소개
운영 환경의 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 노드 유지 관리를 안전하게 수행하는 전체 수명 주기를 연습했습니다. 다음 방법을 배웠습니다.
- 노드를 스케줄링 불가 상태로 표시하도록 Cordon을 설정합니다 (방해 금지).
- 실행 중인 워크로드를 안전하게 축출하도록 노드를 Drain합니다.
- 노드를 다시 서비스에 복귀시키도록 Uncordon을 수행합니다.
이 명령은 시스템 관리자가 높은 가용성을 유지하는 데 필수적입니다. 애플리케이션의 다운타임을 유발하지 않고 인프라를 복구할 수 있게 해 줍니다 (물론 다중 노드 클러스터에서 가능합니다!).


