임대(Lease)

임대(Lease)

분산 시스템은 공유 리소스를 잠그고 구성원 간 활동을 조정하는 메커니즘인 임대(lease) 를 필요로 하는 경우가 많아요. Kubernetes에서 임대 개념은 coordination.k8s.io API 그룹의 Lease 객체로 표현되며, 노드 하트비트(heartbeat)와 컴포넌트 수준 리더 선출(leader election) 같은 시스템 핵심 기능에 사용돼요.

출처: 문서

본문

노드 하트비트 (Node heartbeats)

Kubernetes는 Lease API를 사용해 kubelet 노드 하트비트를 Kubernetes API 서버에 전달해요. 모든 노드에 대해 kube-node-lease 네임스페이스 안에 이름이 일치하는 Lease 객체가 하나씩 있어요. 내부적으로 모든 kubelet 하트비트는 이 Lease 객체에 대한 업데이트 요청이며, Lease의 spec.renewTime 필드를 갱신해요. Kubernetes 컨트롤 플레인은 이 필드의 타임스탬프를 사용해 노드의 가용성을 판단해요.

자세한 내용은 노드 Lease 객체를 참고해요.

리더 선출 (Leader election)

Kubernetes는 Lease를 사용해 주어진 시점에 컴포넌트의 인스턴스가 하나만 실행되도록 보장하기도 해요. HA 구성에서 kube-controller-manager와 kube-scheduler 같은 컨트롤 플레인 컴포넌트가 이를 사용해요. 이런 구성에서는 컴포넌트 인스턴스 하나만 활발히 실행되고 나머지 인스턴스는 대기(stand-by) 상태로 있어요.

조정된 리더 선출(coordinated leader election) 문서에서 Kubernetes가 Lease API를 기반으로 어떤 컴포넌트 인스턴스가 리더 역할을 할지 선택하는 방법을 배워볼 수 있어요.

kube-controller-manager 종료 시 잠금 해제

ControllerManagerReleaseLeaderElectionLockOnExit 기능 게이트가 활성화되면, kube-controller-manager는 리더 전환 중에 잠금 TTL이 만료될 때까지 기다리지 않고 리더 선출 잠금을 적극적으로 해제해요. 덕분에 새 리더를 더 빨리 선출할 수 있어 리더 전환 지연 시간이 줄어들어요.

API 서버 신원 (API server identity)

Kubernetes v1.26부터 각 kube-apiserver는 Lease API를 사용해 자신의 신원(identity)을 시스템의 나머지 부분에 공개해요. 단독으로는 특별히 유용하지 않지만, 클라이언트가 Kubernetes 컨트롤 플레인을 운영하는 kube-apiserver 인스턴스가 몇 개인지 파악할 수 있는 메커니즘을 제공해요. kube-apiserver 임대가 존재하면 각 kube-apiserver 간 조정이 필요한 미래 기능도 가능해져요.

각 kube-apiserver가 소유한 임대는 kube-system 네임스페이스에서 apiserver-<sha256-hash> 이름의 임대 객체를 확인하거나, 라벨 셀렉터 apiserver.kubernetes.io/identity=kube-apiserver를 사용해 확인할 수 있어요.

kubectl -n kube-system get lease -l apiserver.kubernetes.io/identity=kube-apiserver
NAME                                        HOLDER                                                                           AGE
apiserver-07a5ea9b9b072c4a5f3d1c3702        apiserver-07a5ea9b9b072c4a5f3d1c3702_0c8914f7-0f35-440e-8676-7844977d3a05        5m33s
apiserver-7be9e061c59d368b3ddaf1376e        apiserver-7be9e061c59d368b3ddaf1376e_84f2a85d-37c1-4b14-b6b9-603e62e4896f        4m23s
apiserver-1dfef752bcb36637d2763d1868        apiserver-1dfef752bcb36637d2763d1868_c5ffa286-8a9a-45d4-91e7-61118ed58d2e        4m43s

임대 이름에 사용된 SHA256 해시는 해당 API 서버가 본 OS 호스트 이름을 기반으로 해요. 각 kube-apiserver는 클러스터 안에서 유일한 호스트 이름을 사용하도록 구성해야 해요. 같은 호스트 이름을 사용하는 새 kube-apiserver 인스턴스는 새 Lease 객체를 만드는 대신, 새 holder 신원으로 기존 임대를 인계받아요. kube-apiserver가 사용하는 호스트 이름은 kubernetes.io/hostname 라벨 값으로 확인할 수 있어요.

kubectl -n kube-system get lease apiserver-07a5ea9b9b072c4a5f3d1c3702 -o yaml
apiVersion: coordination.k8s.io/v1
kind: Lease
metadata:
  creationTimestamp: "2023-07-02T13:16:48Z"
  labels:
    apiserver.kubernetes.io/identity: kube-apiserver
    kubernetes.io/hostname: master-1
  name: apiserver-07a5ea9b9b072c4a5f3d1c3702
  namespace: kube-system
  resourceVersion: "334899"
  uid: 90870ab5-1ba9-4523-b215-e4d4e662acb1
spec:
  holderIdentity: apiserver-07a5ea9b9b072c4a5f3d1c3702_0c8914f7-0f35-440e-8676-7844977d3a05
  leaseDurationSeconds: 3600
  renewTime: "2023-07-04T21:58:48.065888Z"

더 이상 존재하지 않는 kube-apiserver의 만료된 임대는 1시간 후에 새 kube-apiserver가 가비지 컬렉션으로 정리해요.

API 서버 신원 임대는 APIServerIdentity 기능 게이트를 비활성화하면 끌 수 있어요.

워크로드

자체 워크로드도 Lease를 자기 방식대로 정의해서 사용할 수 있어요. 예를 들어, 주(primary) 또는 리더 구성원이 동료가 하지 않는 연산을 수행하는 사용자 정의 컨트롤러를 실행한다고 해봐요. 컨트롤러 복제본들이 Kubernetes API를 이용해 조정하면서 리더를 선택(또는 선출)하도록 Lease를 정의해요.

Lease를 사용한다면, 제품이나 컴포넌트와 명확히 연결되는 이름을 정하는 것이 좋은 습관이에요. 예를 들어 Example Foo라는 컴포넌트가 있다면 example-foo라는 Lease 이름을 사용하는 식이에요.

클러스터 운영자나 다른 최종 사용자가 컴포넌트의 여러 인스턴스를 배포할 수 있다면, 이름 접두사를 선택하고 (Deployment 이름의 해시 같은) 충돌을 피할 메커니즘을 골라야 해요.

다른 소프트웨어 제품끼리 충돌하지 않는다는 같은 결과를 달성한다면 다른 접근 방식을 사용해도 괜찮아요.

더 알아보기 (Learn more)