노드 종료
노드 종료 (Node Shutdowns)
Kubernetes 클러스터에서 노드는 계획된 정상 종료(graceful) 방식으로, 또는 정전 같은 외부 요인으로 예상치 못하게 종료될 수 있어요. 노드 종료 전에 drain 하지 않으면 워크로드가 실패할 수 있어요. 노드 종료는 정상(graceful) 또는 비정상(non-graceful) 으로 나뉘어요.
주의: Debian의
unattended-upgrades패키지는 기본 설정에서 graceful node shutdown과 충돌해요.shutdownGracePeriod가 30초보다 크면 kubelet이 shutdown 이벤트를 제대로 처리하는 데 필요한 lock을 얻지 못해요./etc/systemd/logind.conf.d/unattended-upgrades-logind-maxdelay.conf를/dev/null로 심볼릭 링크하면 일부 구성을 비활성화할 수 있어요.
정상 노드 종료 (Graceful node shutdown)
kubelet이 노드 시스템 종료를 감지하면 노드에서 실행 중인 Pod를 종료해요. kubelet은 노드 종료 중 새 Pod를 수용하지 않아요.
-
활성화: Linux에서는
GracefulNodeShutdownfeature gate로 제어되며 1.21부터 기본 활성화돼요. systemd inhibitor locks를 활용해 노드 종료를 지연시켜요. Windows에서는WindowsGracefulNodeShutdownfeature gate로 제어되며 kubelet이 Windows 서비스로 실행돼야 해요. -
구성:
shutdownGracePeriod(노드 종료를 지연할 총 시간)와shutdownGracePeriodCriticalPods(critical pod 종료에 쓸 시간) 두 가지KubeletConfiguration옵션으로 구성해요. 기본값은 0이라 활성화하려면 0이 아닌 값으로 설정해야 해요.
노드가 종료 신호를 받으면 kubelet은 노드에 reason: "node is shutting down"의 NotReady 조건을 설정하고, 스케줄러는 그 노드에 새 Pod를 스케줄링하지 않아요. 정상 종료 중 kubelet은 두 단계로 종료해요.
- 일반 Pod 종료
- critical pod 종료
예를 들어 shutdownGracePeriod=30s, shutdownGracePeriodCriticalPods=10s라면, 처음 20초(30-10)는 일반 Pod, 마지막 10초는 critical pod 종료에 씁니다.
Pod 우선순위 기반 정상 노드 종료
FEATURE STATE: Kubernetes v1.24 [beta](기본 활성화)
Pod의 PriorityClass를 존중해 종료 순서를 명시적으로 정의할 수 있어요. shutdownGracePeriodByPodPriority 설정으로 우선순위 값별 종료 시간을 지정하죠.
shutdownGracePeriodByPodPriority:
- priority: 100000
shutdownGracePeriodSeconds: 10
- priority: 10000
shutdownGracePeriodSeconds: 180
- priority: 1000
shutdownGracePeriodSeconds: 120
- priority: 0
shutdownGracePeriodSeconds: 60
이 설정은 priority >= 100000인 Pod는 10초, >= 10000이고 < 100000인 Pod는 180초, >= 1000이고 < 10000인 Pod는 120초, 나머지는 60초를 부여해요. 그 구간에 Pod가 없으면 kubelet은 바로 다음 우선순위 구간으로 건너뜁니다.
비정상 노드 종료 처리 (Non-graceful node shutdown)
FEATURE STATE: Kubernetes v1.28 [stable](기본 활성화)
kubelet의 Node Shutdown Manager가 감지하지 못한 종료가 발생하면, StatefulSet에 속한 Pod는 종료된 노드에서 terminating 상태로 고착되고 새 노드로 이동하지 못해요. 이 문제를 완화하려면 사용자가 node.kubernetes.io/out-of-service taint(NoExecute 또는 NoSchedule)를 수동으로 추가해 노드를 서비스 중단 상태로 표시할 수 있어요. 그러면 매칭되는 toleration이 없는 Pod는 강제 삭제되고, 즉시 볼륨 detach 작업이 일어나 다른 노드에서 빠르게 복구될 수 있어요.
주의: taint를 추가하기 전에 노드가 실제로 종료/전원 꺼짐 상태인지 확인하고(재시작 중이 아닌지), Pod가 새 노드로 이동한 뒤에는 taint를 직접 제거해야 해요.
강제 스토리지 detach (Forced storage detach on timeout)
Pod 삭제가 6분간 성공하지 못하면, 그 시점에 노드가 비정상이라면 kubelet이 볼륨을 강제 detach 해요. 이는 CSI 스펙을 위반할 수 있고 데이터 손상을 초래할 수 있어요. disable-force-detach-on-timeout 설정으로 끌 수 있어요. 주의해서 사용해야 해요.