노드 종료

노드 종료 (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에서는 GracefulNodeShutdown feature gate로 제어되며 1.21부터 기본 활성화돼요. systemd inhibitor locks를 활용해 노드 종료를 지연시켜요. Windows에서는 WindowsGracefulNodeShutdown feature gate로 제어되며 kubelet이 Windows 서비스로 실행돼야 해요.

  • 구성: shutdownGracePeriod(노드 종료를 지연할 총 시간)와 shutdownGracePeriodCriticalPods(critical pod 종료에 쓸 시간) 두 가지 KubeletConfiguration 옵션으로 구성해요. 기본값은 0이라 활성화하려면 0이 아닌 값으로 설정해야 해요.

노드가 종료 신호를 받으면 kubelet은 노드에 reason: "node is shutting down"NotReady 조건을 설정하고, 스케줄러는 그 노드에 새 Pod를 스케줄링하지 않아요. 정상 종료 중 kubelet은 두 단계로 종료해요.

  1. 일반 Pod 종료
  2. 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 설정으로 끌 수 있어요. 주의해서 사용해야 해요.

더 알아보기 (Learn more)