LabHub
배우기 러닝패스 코스

쿠버네티스 운영 실무 · 노드에 문제가 생긴 뒤의 5분 · 실습

아무도 drain 을 치지 않았는데 파드가 사라졌다

LabHub 에서 이어서 보기

목표

NoSchedule 과 NoExecute 가 이미 떠 있는 파드에 각각 무엇을 하는지 실제 축출로 확인하고, tolerationSeconds 가 정하는 축출 시각을 파드마다 계산해 표로 만든 뒤, 상태를 가진 워크로드에 줄 값을 근거와 함께 정한다.

왜 중요한가

운영자가 불려 나가는 사고의 절반은 아무도 명령을 치지 않았는데 파드가 움직인 경우다. 노드가 하트비트를 멈추면 노드 컨트롤러가 node.kubernetes.io/not-ready 또는 node.kubernetes.io/unreachable 테인트를 NoExecute 로 붙이고, 그 순간부터 각 파드의 tolerationSeconds 가 시계를 돌린다. 문제는 이 값을 적은 적이 없는 팀이 대부분이라는 것이다. 적지 않으면 어드미션이 300초를 넣어 준다 — 즉 모든 워크로드가 5분 뒤에 옮긴다는 같은 정책을 쓰고 있다. 스테이트리스 프런트엔드에는 너무 길고, 로컬 상태가 큰 데이터 워크로드에는 너무 짧다. 이 값을 이해하고 워크로드마다 고르는 것이 노드 사고 대응의 절반이다.

단계

1. 네임스페이스 ops-evict 를 만들고, /root/ops-eviction/web.yaml 에 Deployment web 을 쓰세요 — 레플리카 3, 라벨 app: web, 이미지 nginx:1.27.3, 그리고 nodeSelectorkubernetes.io/hostname: lab-node-0 에만 앉게 합니다. 적용하고 파드 3개가 모두 Running 이 될 때까지 기다리세요.
2. web 파드에는 톨러레이션을 한 줄도 적지 않았습니다. 그런데 실제 오브젝트에는 붙어 있습니다. web 파드 아무거나 하나를 골라 -o json 으로 확인하고, 그 톨러레이션들을 /root/ops-eviction/default-tolerations.tsv<키><효과><tolerationSeconds> 한 줄씩, 키 이름 오름차순으로 저장하세요. 다른 줄은 넣지 마세요.
3. /root/ops-eviction/brittle.yaml/root/ops-eviction/patient.yaml 에 파드 두 개를 쓰세요. 둘 다 네임스페이스 ops-evict, 이미지 nginx:1.27.3, nodeSelectorkubernetes.io/hostname: lab-node-1 입니다. 두 파드는 톨러레이션의 효과만 다릅니다 — brittle 은 라벨 role: brittle 이고 키 maintoperator: Exists·effect: NoSchedule 로 견디는 톨러레이션 하나(tolerationSeconds 없음), patient 은 라벨 role: patient 이고 키 maintoperator: Exists·effect: NoExecute·tolerationSeconds: 3600 으로 견디는 톨러레이션 하나입니다. 둘 다 적용해 lab-node-1 에서 Running 이 되게 하세요.
4. lab-node-1 에 테인트 maint=planned:NoSchedule 을 거세요. 그다음 /root/ops-eviction/noschedule.tsvbrittlepatient 의 지금 상태를 <파드이름><노드이름><phase> 한 줄씩, 파드 이름 오름차순으로 저장하세요.
5. 같은 노드 lab-node-1 에 테인트 maint=planned:NoExecute 를 더 거세요. brittle 이 사라질 때까지 고정 sleep 이 아니라 조건을 기다리는 반복문으로 기다린 뒤, 결과를 /root/ops-eviction/noexecute.tsv 에 두 줄로 저장하세요 — brittlegone, patientRunning 입니다.
6. /root/ops-eviction/shortwait.yaml/root/ops-eviction/longwait.yaml 을 쓰세요. 둘 다 네임스페이스 ops-evict, 이미지 nginx:1.27.3, nodeSelectorkubernetes.io/hostname: lab-node-2 입니다. 두 파드 모두 키 linkdownoperator: Exists·effect: NoExecute 로 견디되, shortwaittolerationSeconds: 20, longwaittolerationSeconds: 3600 입니다. 라벨은 각각 role: shortwait, role: longwait 입니다. 둘 다 lab-node-2 에서 Running 이 되게 하세요.
7. 링크가 끊긴 상황을 흉내 냅니다 — lab-node-2 에 테인트 linkdown=yes:NoExecute 를 거세요. shortwait 이 사라질 때까지 조건 반복문으로 기다린 뒤 /root/ops-eviction/partition.tsv 에 두 줄로 저장하세요 — shortwaitgone, longwaitRunning 입니다.
8. 먼저 /root/ops-eviction/forever.yaml 에 파드 forever 를 만드세요 — 네임스페이스 ops-evict, 라벨 role: forever, 이미지 nginx:1.27.3, nodeSelectorkubernetes.io/hostname: lab-node-0, 톨러레이션은 키를 적지 않고 operator: Exists·effect: NoExecute 하나뿐입니다(tolerationSeconds 없음). 그다음 /root/ops-eviction/evict-plan.sh 를 만드세요 — ops-evict 의 모든 파드를 읽어 파드마다 linkdownNoExecute 를 몇 초 견디는지 <파드이름><값> 으로 표준출력에만 찍습니다. 값은 견디는 톨러레이션이 없으면 0, 있지만 tolerationSeconds 가 없으면 never, 있으면 그 초입니다. 출력은 파드 이름 오름차순이어야 합니다. 그 출력을 /root/ops-eviction/evict-plan.tsv 에 저장하세요.
9. 네임스페이스 ops-ledger 를 만들고 /root/ops-eviction/ledger.yaml 에 Deployment ledger 를 쓰세요 — 네임스페이스 ops-ledger, 레플리카 2, 라벨 app: ledger, 이미지 nginx:1.27.3. 이 워크로드는 노드 로컬 상태가 커서 짧은 단절에는 버티는 편이 낫습니다. node.kubernetes.io/not-readynode.kubernetes.io/unreachable 두 키를 operator: Exists·effect: NoExecute 로 견디되, 두 톨러레이션의 tolerationSeconds 를 같은 값으로, 900 이상 3600 이하로 정하세요. 적용해 파드 2개가 Running 이 되게 한 뒤 /root/ops-eviction/decision.tsv 에 두 줄을 쓰세요 — tolerationSeconds<고른 값>, reason<40자 이상의 근거 한 문장>.

참고

단계 9개

  1. 건드리지 않을 노드에 비교군을 세운다
  2. 아무도 적지 않은 톨러레이션이 이미 붙어 있다
  3. 같은 노드에, 견디는 시간만 다른 파드 둘
  4. NoSchedule 은 이미 떠 있는 파드를 건드리지 않는다
  5. NoExecute 를 걸면 정말로 사라진다
  6. 네트워크가 끊겼을 때를 대비한 파드 둘
  7. 노드가 응답을 멈춘 것처럼 만들고 시각을 잰다
  8. 축출 시각표를 기계가 계산하게 한다
  9. 상태를 가진 워크로드에 줄 값을 정하고 근거를 남긴다