쿠버네티스(Kubernetes) 클러스터를 운영하다 보면 가장 자주 마주치는 문제 중 하나가 바로 Pod가 ‘Pending‘ 상태에서 멈춰버리는 현상입니다. 분명히 yaml 파일도 제대로 작성했고 kubectl apply도 성공했는데 왜 Pod가 계속 대기 상태에 머물러 있는지 이해하기 어려울 때가 있습니다. 오늘은 쿠버네티스 Pod의 Pending 상태가 발생하는 주요 원인들과 해결 방법을 정리해보겠습니다.
1. Pod ‘Pending’ 상태의 정확한 의미
쿠버네티스에서 Pod는 생성부터 종료까지 여러 단계의 라이프사이클을 거칩니다. ‘Pending’ 상태는 Pod가 쿠버네티스 시스템에 의해 승인되었지만, 아직 어떤 노드에도 스케줄링되지 않은 상태를 의미합니다.
정상적인 경우라면 Pod는 몇 초에서 1분 이내에 Pending 상태를 벗어나 Running 상태로 전환됩니다. 하지만 1분 이상 Pending 상태가 지속된다면 이는 명백한 문제 상황으로 봐야 합니다.
Pod의 주요 상태는 다음과 같습니다:
- Pending: 스케줄링 대기 상태
- Running: 최소 하나의 컨테이너가 실행 중
- Succeeded: 모든 컨테이너가 성공적으로 종료
- Failed: 하나 이상의 컨테이너가 오류로 종료
- Unknown: Pod 상태를 확인할 수 없음
2. Pod Pending 상태의 주요 원인 분석
2.1 리소스 부족 (가장 흔한 원인)
클러스터 내 노드들의 CPU나 메모리가 부족한 경우입니다. Pod가 요청하는 리소스보다 사용 가능한 리소스가 적을 때 발생합니다.
2.2 노드 선택 조건 불만족
NodeSelector, Taints/Tolerations, Affinity 규칙 등으로 인해 Pod가 배치될 수 있는 노드가 없는 경우입니다.
2.3 이미지 풀 문제
컨테이너 이미지를 다운로드할 수 없거나, 잘못된 이미지 이름이 지정된 경우입니다.
2.4 PVC(Persistent Volume Claim) 문제
Pod가 요구하는 스토리지 볼륨을 할당할 수 없는 경우입니다.
2.5 노드 상태 문제
노드가 unschedulable 상태이거나 유지보수를 위해 cordon된 경우입니다.
3. 문제 진단을 위한 체계적 접근법
3.1 기본 상태 확인
먼저 전체 Pod 상태를 확인합니다:
# 모든 네임스페이스의 Pending 상태 Pod 조회
kubectl get pods --all-namespaces --field-selector=status.phase=Pending
# 특정 네임스페이스의 Pod 상태 확인
kubectl get pods -n your-namespace
3.2 상세 정보 확인
Pod의 상세 정보를 통해 정확한 문제 원인을 파악합니다:
# Pod 상세 정보 확인 (가장 중요한 명령어)
kubectl describe pod <pod-name> -n <namespace>
describe 명령어의 출력에서 특히 주목해야 할 부분은 Events 섹션입니다. 여기서 FailedScheduling 메시지를 통해 구체적인 실패 이유를 확인할 수 있습니다.
3.3 클러스터 이벤트 확인
# 클러스터 전체 이벤트 확인
kubectl get events --sort-by=.metadata.creationTimestamp
# 특정 네임스페이스의 이벤트만 확인
kubectl get events -n <namespace>
3.4 노드 상태 확인
# 노드 리소스 사용량 확인
kubectl top nodes
# 노드 상세 정보 확인
kubectl describe nodes
4. 원인별 구체적인 해결 방법
4.1 리소스 부족 문제 해결
증상 확인:
Warning FailedScheduling: 0/3 nodes are available: 3 Insufficient cpu
해결 방법:
- Pod의 리소스 요청량 조정
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
- 불필요한 Pod 제거
# 사용하지 않는 Pod 삭제
kubectl delete pod <pod-name> -n <namespace>
# Deployment 스케일 다운
kubectl scale deployment <deployment-name> --replicas=2
- 노드 추가 또는 리소스 확장
# 클러스터 오토스케일러 활성화 확인
kubectl get deployment -n kube-system cluster-autoscaler
4.2 NodeSelector 문제 해결
증상 확인:
Warning FailedScheduling: 0/3 nodes are available: 3 node(s) didn't match node selector
해결 방법:
- 노드 라벨 확인
kubectl get nodes --show-labels
- NodeSelector 수정 또는 제거
spec:
nodeSelector:
kubernetes.io/os: linux # 실제 존재하는 라벨로 수정
4.3 Taints/Tolerations 문제 해결
증상 확인:
Warning FailedScheduling: 0/3 nodes are available: 3 node(s) had taints that the pod didn't tolerate
해결 방법:
- 노드의 Taint 확인
kubectl describe node <node-name> | grep -i taint
- Toleration 추가
spec:
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
- Taint 제거 (필요시)
kubectl taint nodes <node-name> key1=value1:NoSchedule-
4.4 이미지 풀 문제 해결
증상 확인:
Warning Failed: Failed to pull image "wrong-image-name:latest"
해결 방법:
- 이미지 이름 확인 및 수정
# 이미지 직접 풀 테스트
docker pull <image-name>
- ImagePullSecrets 설정 (private registry 사용시)
spec:
imagePullSecrets:
- name: regcred
4.5 PVC 문제 해결
증상 확인:
Warning FailedScheduling: pod has unbound immediate PersistentVolumeClaims
해결 방법:
- PVC 상태 확인
kubectl get pvc -n <namespace>
kubectl describe pvc <pvc-name>
- StorageClass 확인 및 수정
kubectl get storageclass
4.6 노드 상태 문제 해결
해결 방법:
- Cordon된 노드 해제
kubectl uncordon <node-name>
- 노드 상태 확인 및 복구
kubectl get nodes
kubectl describe node <node-name>
5. Pending 이슈 예방 및 모니터링 방법
5.1 리소스 관리 모범 사례
- LimitRange 설정으로 기본값 지정
apiVersion: v1
kind: LimitRange
metadata:
name: default-limit-range
spec:
limits:
- default:
memory: "512Mi"
cpu: "500m"
defaultRequest:
memory: "256Mi"
cpu: "250m"
type: Container
- ResourceQuota로 네임스페이스별 리소스 제한
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
spec:
hard:
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
5.2 모니터링 및 알림 설정
# 정기적인 클러스터 상태 확인
kubectl top nodes
kubectl top pods --all-namespaces
# Pending Pod 자동 모니터링 스크립트
kubectl get pods --all-namespaces --field-selector=status.phase=Pending
5.3 Pod Priority 및 Preemption 활용
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000
globalDefault: false
description: "High priority class for critical workloads"
6. 실제 자주 사용하는 유용한 명령어 모음
# Pod 상태별 카운트 확인
kubectl get pods --all-namespaces | awk '{print $4}' | sort | uniq -c
# 특정 노드의 Pod 목록 확인
kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=<node-name>
# 리소스 사용량 기준 Pod 정렬
kubectl top pods --all-namespaces --sort-by=memory
# 클러스터 전체 리소스 현황
kubectl describe nodes | grep -A 5 "Allocated resources"
# YAML 형태로 Pod 정보 확인
kubectl get pod <pod-name> -o yaml
Pod의 Pending 상태 문제는 쿠버네티스 운영에서 피할 수 없는 이슈입니다. 하지만 체계적인 접근을 통해 원인을 정확히 파악하고 해결한다면 충분히 극복할 수 있는 문제이기도 합니다. 가장 중요한 것은 kubectl describe pod
명령어를 통한 정확한 진단입니다. Events 섹션의 메시지를 주의 깊게 읽고, 그에 맞는 해결책을 적용하는 것이 핵심입니다. 또한 사전 예방을 위해 적절한 리소스 제한과 모니터링 체계를 구축하는 것도 중요합니다. 정기적인 클러스터 상태 점검을 통해 문제를 미리 발견하고 대응할 수 있도록 준비해두시길 추천드립니다.
관련 태그: kubernetes, 쿠버네티스, pod, pending, 스케줄링, 트러블슈팅, kubectl, 컨테이너, 오케스트레이션, devops, 클러스터, 리소스관리, 노드, 도커, k8s