Kubernetes Pod Pending 상태, 더 이상 추측하지 마세요: 7가지 원인과 실시간 진단 가이드
쿠버네티스(Kubernetes) 환경에서 서비스를 운영하는 엔지니어라면 누구나 한 번쯤 'Pod가 Pending 상태로 멈춰있는' 경험을 했을 것입니다. 배포는 성공적으로 보였고, 애플리케이션 로그도 정상적으로 보이지만, 서비스 트래픽은 들어오지 않습니다. 이 Pending 상태는 마치 시스템의 심장이 멈춘 듯한 불안감을 주며, 장애 대응의 골든타임을 앗아갑니다.
Pending 상태는 단순히 '아직 시작하지 않았다'는 의미를 넘어, 쿠버네티스 스케줄러가 Pod를 원하는 노드에 배치하는 과정에서 어떤 제약 조건에 걸렸는지를 알려주는 중요한 신호입니다. 이 글은 막연한 추측에 의존하는 대신, 체계적인 진단 프로세스를 통해 Pending 상태의 근본 원인을 7가지 시나리오로 나누어 분석하고, 현장에서 즉시 적용 가능한 실전 가이드를 제공합니다.
1단계: 상태의 비밀을 파헤치는 마법의 명령어, kubectl describe
Pod가 Pending 상태일 때 가장 먼저 해야 할 일은 감(感)에 의존하는 것이 아니라, 시스템이 기록한 '이벤트(Events)' 로그를 확인하는 것입니다. 이 로그에는 스케줄러가 어떤 이유로 Pod 배치를 거부했는지에 대한 결정적인 단서가 담겨 있습니다.
kubectl describe pod [pod-name] -n [namespace]이 명령어의 출력 중 Events: 섹션을 집중적으로 살펴보세요. 여기에 FailedScheduling, Insufficient CPU, 또는 Node(s) had taint {key: value} that the Pod cannot tolerate와 같은 명확한 에러 메시지가 기록되어 있습니다. 이 이벤트 메시지가 바로 우리가 해결해야 할 문제의 첫 번째 단서입니다.
2단계: Pod Pending 진단 3단계 체크리스트 (진단 흐름도)
Pod가 Pending 상태일 때, 원인을 찾기 위해 무작정 모든 설정을 뒤지는 것은 비효율적입니다. 다음의 3단계 논리적 흐름에 따라 점검하는 것이 가장 빠르고 정확합니다.
| 단계 | 점검 영역 | 주요 원인 | 확인 명령어/로그 |
|---|---|---|---|
| 1단계 | 리소스 제약 (Resource) | 노드에 할당 가능한 CPU/Memory 부족 | kubectl describe pod의 Events, Insufficient... 메시지 |
| 2단계 | 정책 충돌 (Policy) | Taint와 Toleration 매칭 실패 | kubectl describe node 및 Pod Spec 확인 |
| 3단계 | 스케줄링 제약 (Scheduling) | Node Selector, Affinity, PriorityClass 불일치 | kubectl describe pod의 Node-Selectors 섹션 |
이 순서대로 점검하면, 대부분의 Pending 문제는 1~2단계에서 해결됩니다.
3단계: 리소스 부족 문제 (Resource Constraints) 진단
가장 흔한 원인 중 하나는 노드의 물리적/논리적 자원 부족입니다. Pod가 요청한 리소스(Requests)를 현재 클러스터의 어느 노드도 감당할 수 없을 때 발생합니다.
🚨 핵심 에러 메시지 예시:
Events:
Type Reason From Message
---- ------ ---- -------
Warning Failed kube-scheduler Pod cannot be scheduled: insufficient cpu이 메시지는 스케줄러가 Pod가 요청한 CPU 자원을 현재 클러스터의 모든 노드에서 찾을 수 없다는 의미입니다.
💡 해결 방안:
- Scale Down: 불필요한 Pod를 삭제하거나, 배포된 Pod의 개수를 줄입니다.
- Resource Request 조정: Pod Spec에서
requests값을 현재 노드 상황에 맞게 하향 조정합니다. - Cluster Autoscaler 확인: 클라우드 환경이라면, 노드 부족 시 자동으로 노드를 증설하는 Autoscaler가 제대로 동작하는지 확인해야 합니다.
4단계: 정책 충돌 문제 (Taints & Tolerations)
쿠버네티스에서 가장 까다롭지만 중요한 개념이 바로 Taint와 Toleration입니다. Taint는 노드에 '이 노드는 특정 용도로만 사용해야 한다'는 표식(제약)을 붙이는 것이고, Toleration은 Pod가 '이런 제약 조건이 있어도 괜찮다'고 허락하는 것입니다.
❌ 잘못된 시나리오:
만약 특정 노드(Node-A)에 dedicated=gpu:NoSchedule이라는 Taint가 걸려있는데, 해당 Pod가 이 Taint를 무시하겠다는 toleration을 명시하지 않았다면, 스케줄러는 이 Pod를 Node-A에 배치하는 것을 거부합니다.
✅ 해결 스니펫 (Pod Spec 수정):
Pod가 Taint를 무시하고 해당 노드에 배치되도록 하려면, Pod의 spec에 다음을 추가해야 합니다.
spec:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"5단계: 스케줄링 제약 문제 (Affinity & Selector)
Pod가 특정 노드 그룹에만 배포되도록 제한하는 경우(Node Affinity, Node Selector), 해당 조건을 만족하는 노드가 클러스터에 존재하지 않으면 Pending 상태가 됩니다.
- Node Selector: Pod가 반드시 특정 레이블을 가진 노드에만 배포되도록 지정합니다. (가장 단순한 제한)
- Node Affinity: 더 복잡한 조건(예: 특정 레이블을 가진 노드 중 3개 이상에서만 배포)을 지정할 때 사용합니다.
만약 NodeSelector를 사용했는데, 해당 레이블을 가진 노드가 하나도 없다면, Pod는 영원히 Pending 상태에 머무르게 됩니다. kubectl get nodes --show-labels로 노드의 실제 레이블을 먼저 확인하는 습관이 중요합니다.
🛠️ 실무자가 경험한 팁: 장애 대응의 자동화 관점
실제 운영 환경에서는 사람이 수동으로 kubectl describe를 반복하는 것 자체가 병목이 됩니다. 저는 최근 GitOps 워크플로우를 구축하면서, Pod가 Pending 상태가 되면 자동으로 알림(Alerting)을 발생시키고, 해당 Pod의 describe 결과를 캡처하여 Jira 티켓에 첨부하는 프로세스를 구축하는 것을 강력히 추천합니다. 즉, 장애 대응을 '수동 진단'에서 '자동화된 관측 가능성(Observability)'으로 전환해야 합니다.
💡 최종 점검: Pod Pending 문제 해결 체크리스트
- [필수]
kubectl describe pod [pod-name]을 실행하여Events섹션을 확인한다. (가장 먼저 볼 곳) - 리소스 확인: CPU/Memory 요청 및 제한(Requests/Limits)이 너무 크거나 누락되지 않았는지 확인한다.
- 정책 확인: 네임스페이스에
LimitRange나ResourceQuota같은 제한 정책이 걸려있지 않은지 확인한다. - 정책 확인:
PodDisruptionBudget이나PodAntiAffinity같은 스케줄링 제약 조건이 충돌을 일으키지 않는지 확인한다.
이 체크리스트를 통해 대부분의 스케줄링 문제를 해결할 수 있습니다.
이 글은 AI 에이전트가 1차 초안을 작성한 뒤, 사람 편집자가 사실관계·출처·톤과 맥락을 검토하여 발행했습니다. 오류나 부정확한 내용이 확인되면 24시간 이내에 정정합니다.
댓글
불러오는 중...