LabHub
배우기 러닝패스 코스

CRD 와 오퍼레이터 · 조정이 두 번 일어났다 · 실습

조정이 두 번 일어났다 — 임차 만료와 인수, 그리고 사고 진단

LabHub 에서 이어서 보기

목표

Lease 의 다섯 필드를 직접 다루며 갱신·만료·인수를 만들어 보고, 리더 선출에 필요한 최소 권한을 맞춘 뒤, 리더가 둘일 때 실제로 무슨 일이 생기는지 필드 관리자 충돌로 증명하고 운영 점검표로 묶는다.

왜 중요한가

오퍼레이터를 두 개 이상 띄우는 이유는 가용성이다. 그런데 조정 루프는 클러스터 상태를 바꾸는 코드라 동시에 둘이 돌면 안 된다. 그래서 쿠버네티스는 아주 작은 오브젝트 하나에 '지금 누가 리더인가' 를 적어 두고, 리더가 주기적으로 갱신하며 살아 있음을 알린다. 여기서 중요한 것은 이 오브젝트에 '만료됨' 같은 필드가 없다는 사실이다. 살아 있는지는 renewTime + leaseDurationSeconds 를 지금과 견주는 계산으로 정해지고, 그 계산은 각 인스턴스가 자기 시계로 한다. 시계가 어긋나거나 API 서버 응답이 늦으면 두 인스턴스가 동시에 자기가 리더라고 믿는 구간이 생긴다. 그 구간에 두 조정 루프가 같은 자원을 만들려 하면 무슨 일이 생기는지, 그리고 그 흔적을 어디서 찾는지가 이 실습의 주제다.

단계

1. 네임스페이스 op-leader 를 만들고 /root/op-leader/lease-widget.yamlcoordination.k8s.io/v1 Lease widget-operator 를 쓰세요 — holderIdentitywidget-operator-0, leaseDurationSeconds 는 15, acquireTimerenewTime 은 지금 시각, leaseTransitions 는 0 입니다. 적용한 뒤 kubectl -n op-leader get lease widget-operator -o yaml 출력을 /root/op-leader/lease-initial.yaml 에 저장하세요.
2. 리더가 하는 일을 손으로 세 번 해 보세요 — renewTime 만 지금 시각으로 갱신하는 patch 를 1초 간격으로 세 번 돌리고, 그때마다 갱신된 renewTime/root/op-leader/renew-log.txt 에 한 줄씩 남깁니다(세 줄). holderIdentityleaseTransitions 는 건드리지 않습니다.
3. 두 개의 임차를 더 만드세요 — /root/op-leader/lease-stale.yamlstale-operator(holder stale-operator-0, leaseDurationSeconds 15, renewTime10분 전으로), /root/op-leader/lease-fresh.yamlfresh-operator(holder fresh-operator-0, leaseDurationSeconds 86400, renewTime 은 지금)입니다. /root/op-leader/leases.tsv<임차이름><탭><기대: EXPIRED 또는 LIVE> 두 줄을 적고, /root/op-leader/expiry.sh 가 각 임차의 renewTime + leaseDurationSeconds 를 지금과 견줘 분류한 뒤 맞으면 OK …, 틀리면 MISMATCH … 를 표준출력에만 찍고 한 줄이라도 틀리면 0 이 아닌 코드로 끝나게 하세요. 출력을 /root/op-leader/expiry.txt 에 저장합니다.
4. widget-operator 임차를 다른 인스턴스가 가져갔다고 보고 한 번의 patch 로 네 값을 바꾸세요 — holderIdentitywidget-operator-1 로, acquireTimerenewTime 을 지금 시각으로, leaseTransitions 를 1 로. /root/op-leader/takeover.txt 에 네 줄을 남기세요 — before-holder=, after-holder=, before-transitions=, after-transitions=.
5. 초 단위 시각으로 갱신을 시도해 보세요 — renewTime2026-01-01T00:00:00Z 처럼 소수점 없는 값으로 patch 합니다. 결과를 /root/op-leader/microtime-error.txt 에 모으세요 — 첫 줄은 patch-rc=<종료 코드> 이고 그 아래에 서버가 낸 문장을 그대로 붙입니다.
6. /root/op-leader/rbac.yaml 에 세 오브젝트를 담아 적용하세요 — ServiceAccount widget-operator, Role leader-election(coordination.k8s.io 그룹의 leasesget·create·update 만), 그리고 둘을 잇는 RoleBinding leader-election. 그다음 kubectl auth can-i <동사> leases.coordination.k8s.io --as=system:serviceaccount:op-leader:widget-operator -n op-leaderget·create·update·delete 네 번 돌려 결과를 /root/op-leader/rbac-check.txt<동사>=<yes 또는 no> 네 줄로 저장하세요.
7. 두 인스턴스가 동시에 자기가 리더라고 믿는 상황을 재현하세요 — /root/op-leader/child-a.yaml 에 ConfigMap order-1(네임스페이스 op-leader, data.phaseA)을 쓰고 kubectl apply --server-side --field-manager=widget-operator-0 로 적용합니다. 그다음 /root/op-leader/child-b.yaml 에 같은 이름의 ConfigMap 을 data.phaseB 로 써서 --field-manager=widget-operator-1 로 적용해 보세요. 결과를 /root/op-leader/split-brain.txt 에 모으세요 — apply-b-rc=<종료 코드>, 서버가 낸 문장, 그리고 마지막 줄에 final-phase=<지금 값>.
8. /root/op-leader/lease-audit.sh 를 만드세요 — op-leader 의 모든 임차를 <이름> holder=<홀더> transitions=<전환 횟수> duration=<임차 길이> 한 줄씩 정렬해 표준출력에만 찍습니다(나이나 시각은 넣지 않습니다). 출력을 /root/op-leader/lease-audit.txt 에 저장하고, /root/op-leader/runbook.txt 에 운영 규칙을 적으세요 — --leader-elect-lease-duration·--leader-elect-renew-deadline·--leader-elect-retry-period 세 값의 이름이 모두 나와야 하고, 갱신 기한이 임차 길이보다 짧아야 하는 이유와 전환 횟수가 계속 늘 때 무엇을 의심할지가 들어가야 합니다.

참고

단계 8개

  1. 임차 한 장이 리더를 정한다
  2. 리더는 쉬지 않고 갱신한다
  3. 살아 있는지는 계산으로 정한다
  4. 인수는 전환 횟수로 드러난다
  5. 시각 형식 하나가 갱신을 막는다
  6. 리더 선출에 필요한 최소 권한
  7. 리더가 둘이면 같은 필드를 놓고 싸운다
  8. 점검표와 운영 규칙으로 묶는다