노드 유지 관리

KubernetesBeginner
지금 연습하기

소개

운영 환경의 Kubernetes 에서는 노드 유지 관리가 필요한 경우가 많습니다. 이때 중요한 점은 불필요하게 워크로드를 중단하지 않는 것입니다.

노드를 호텔 객실, Pod 를 투숙객이라고 생각해 보겠습니다. 객실을 개조하거나 유지 관리해야 할 때, 투숙객이 자는 중에 갑자기 들어갈 수는 없습니다. 정중하고 안전한 절차가 필요합니다.

이 실습에서는 노드 유지 관리를 위한 표준 작업 흐름을 배웁니다.

  • Cordon(방해 금지): 문에“새 투숙객을 받지 않음”이라는 표지판을 붙입니다. 호텔 (스케줄러) 은 이 객실에 새 투숙객을 배정하지 않습니다.
  • Drain(축출): 기존 투숙객에게 정중하게 나가도록 요청하고, 이용 가능한 다른 객실로 이동시킵니다.
  • 유지 관리: 필요한 작업 (개조) 을 수행합니다.
  • Uncordon(개방): 표지판을 제거하고 다시 스케줄링을 허용합니다.

이 실습에서는 로컬 Minikube 클러스터를 사용해 이 과정을 시뮬레이션합니다.

노드 Cordon 설정

유지 관리를 시작하기 전에 Kubernetes 스케줄러가 작업 대상 노드에 새 Pod 를 배치하지 않도록 해야 합니다. 이 과정을“cordon 설정”이라고 합니다. 호텔 객실 문에“방해 금지”또는“사용 중지”표지판을 붙이는 것과 같습니다.

이는 종료가 아니라 스케줄링 결정입니다. Cordon 이 설정된 노드도 정상 상태일 수 있으며 기존 Pod 를 계속 실행할 수 있습니다. Kubernetes 는 해당 노드를 새 배치를 위한 대상으로만 사용할 수 없다고 표시합니다. 따라서 통제된 방식으로 유지 관리를 시작할 수 있습니다.

먼저 노드 이름을 확인합니다. 다음 명령을 실행합니다.

kubectl get nodes

Ready 상태의 노드 하나가 표시되어야 합니다 (예: minikube).

노드를 스케줄링 불가 상태로 표시하려면 cordon 명령을 사용합니다. 명령 치환 $()을 사용해 노드 이름을 자동으로 가져옵니다.

kubectl cordon $(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')

이제 노드 상태를 다시 확인합니다.

kubectl get nodes

상태가 Ready,SchedulingDisabled로 변경되어야 합니다. 이는 노드에 cordon 이 설정되었음을 의미합니다. 이 노드에는 새 Pod 가 스케줄링되지 않지만 기존 Pod 는 계속 실행됩니다.

노드 Drain 수행

Cordon 은 새 Pod 의 배치만 중지합니다. 객실에는 여전히 실행 중인 애플리케이션 (투숙객) 이 있습니다. 이들을 안전하게 제거하려면 drain 명령을 사용합니다.

이 명령은 Pod 를 축출합니다. 그러면 Kubernetes 는 필요한 복제본 수인 2 개가 충족되지 않았음을 확인하고, 다른 이용 가능한 노드에 새 대체 Pod 를 만들려고 합니다.

여기서 **축출 (evict)**이라는 단어가 중요합니다. Drain 은 Pod 를 강제로 중단하는 작업이 아닙니다. Kubernetes 를 이해하는 방식으로 워크로드가 종료되도록 요청하므로, 컨트롤러가 워크로드를 대체하고 종료 규칙도 준수할 수 있습니다. 따라서 노드에서 임의의 프로세스를 직접 삭제하는 것보다 drain이 안전합니다.

Drain 명령을 실행합니다. 이 환경에서 축출을 강제로 수행하려면 몇 가지 옵션을 추가해야 합니다.

  • --ignore-daemonsets: 일부 시스템 Pod(DaemonSet) 는 노드에 고정되어 이동할 수 없습니다. 이러한 Pod 는 무시합니다.
  • --delete-emptydir-data: Pod 가 로컬 임시 스토리지를 사용하는 경우 drain 과정에서 해당 데이터가 삭제됩니다. 이 삭제를 인지하고 승인합니다.
  • --force: ReplicationController, ReplicaSet, Job, DaemonSet 또는 StatefulSet 이 관리하지 않는 Pod(예: Minikube 의 storage-provisioner) 를 삭제할 때 필요합니다.
kubectl drain $(kubectl get nodes -o jsonpath='{.items[0].metadata.name}') --ignore-daemonsets --delete-emptydir-data --force

Pod 가 축출되고 있음을 나타내는 출력이 표시됩니다.

참고: 이 단일 노드 Minikube 실습에서는 유일한 노드를 drain 하면 Pod 가 축출된 후 Pending 상태가 됩니다. 이동할“호텔의 다른 객실”이 없기 때문입니다. 실제 다중 노드 클러스터에서는 Pod 가 정상 상태인 다른 노드로 즉시 이동합니다.

상태 확인

노드를 drain 한 후에는 애플리케이션에 어떤 일이 발생했는지 확인해야 합니다.

이 확인 단계는 클러스터 관리에서 중요한 습관을 익히게 합니다. 유지 관리 명령을 실행한 뒤 바로 끝내지 마십시오. 항상 워크로드 관점에서 스케줄링 결과를 확인해야 합니다. 애플리케이션이 의도한 위치에 배치되었을 때만 유지 관리 작업이 성공한 것입니다.

Pod 상태를 확인합니다.

kubectl get pods

앞서 설명한 것처럼 Pod 가 Pending 상태로 표시될 가능성이 높습니다.

Pod 가 Pending 상태인 이유를 확인하기 위해 Kubernetes 에 정보를 요청합니다. Pod 하나를 설명합니다.

kubectl describe pod $(kubectl get pods -o jsonpath='{.items[0].metadata.name}')

출력 하단의 Events 섹션을 찾습니다. 다음과 비슷한 메시지가 표시되어야 합니다.

0/1 nodes are available: 1 node(s) are unschedulable.

이는 drain 이 성공했음을 확인해 줍니다. 스케줄러는 Pod 를 실행하려고 하지만, 사용 가능한 유일한 노드에 설정한“방해 금지”표지를 따릅니다.

노드 Uncordon 수행

이제“개조”(OS 업그레이드 또는 유지 관리) 를 완료했다고 가정해 보겠습니다. 객실을 다시 열고 노드를 서비스에 복귀시킬 시간입니다.

uncordon은 스케줄링 차단만 제거합니다. Pod 를 즉시 노드에 강제로 배치하지는 않습니다. 대신 스케줄러에 이 노드를 다시 배치 대상으로 사용할 수 있다고 알리고, 이후 정상적인 조정 작업이 이어집니다.

이를 위해 uncordon 명령을 사용합니다. 이 명령은“방해 금지”표지를 제거합니다.

kubectl uncordon $(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')

이제 노드 상태를 확인합니다.

kubectl get nodes

상태가 Ready로 돌아와야 합니다 (SchedulingDisabled 태그가 사라집니다).

마지막으로 Pod 를 다시 확인합니다. 노드가 다시 사용 가능해졌으므로 Kubernetes 스케줄러는 이제 Pending 상태인 Pod 를 이 노드에 배치해야 합니다.

kubectl get pods

Pod 상태가 Pending에서 ContainerCreating으로 바뀐 다음 최종적으로 Running이 되는 것을 확인할 수 있습니다.

요약

이 실습에서는 Kubernetes 노드 유지 관리를 안전하게 수행하는 전체 수명 주기를 연습했습니다. 다음 방법을 배웠습니다.

  1. 노드를 스케줄링 불가 상태로 표시하도록 Cordon을 설정합니다 (방해 금지).
  2. 실행 중인 워크로드를 안전하게 축출하도록 노드를 Drain합니다.
  3. 노드를 다시 서비스에 복귀시키도록 Uncordon을 수행합니다.

이 명령은 시스템 관리자가 높은 가용성을 유지하는 데 필수적입니다. 애플리케이션의 다운타임을 유발하지 않고 인프라를 복구할 수 있게 해 줍니다 (물론 다중 노드 클러스터에서 가능합니다!).