Haru Utils

SCHEDULING & STORAGE

Kubernetes Pending·PVC·Node NotReady 장애

Pending Pod의 scheduler 이벤트를 시작점으로 리소스·taint·affinity, PVC 바인딩, Node Ready·Pressure 상태를 분리하고 데이터 손실 없는 조치만 선택합니다.
Pod PendingFailedSchedulingunbound immediate PersistentVolumeClaimsPVC PendingNode NotReadyDiskPressure MemoryPressure
환경Kubernetes v1.35·v1.36·v1.37 · CSI/PersistentVolume · Linux worker Node
분류컨테이너
검토일2026-09-02
진행5단계 · 조회 우선

SAFE OPERATING BOUNDARY

중단·복구 기준부터 확인하세요

STOP CONDITIONS

여기서는 멈추세요

  • Bound PVC 삭제, finalizer 강제 제거, PV reclaimPolicy 변경이 필요해 보이면 데이터 소유자와 스토리지 담당자 승인 전 중단합니다.
  • control plane 다수 Node가 NotReady이거나 etcd/API 응답도 불안정하면 개별 workload 조치 대신 클러스터 장애 절차로 전환합니다.
  • 현재 cordon 이유, workload disruption budget, 스토리지 백업 상태를 모르면 drain·uncordon·재부팅을 실행하지 않습니다.
ROLLBACK

복구 기준

workload 변경은 적용 전 백업 manifest와 정상 Git revision으로 복원하고 rollout을 검증합니다. PVC/PV는 삭제로 롤백하지 않으며 storageClass·reclaimPolicy·실데이터 백업을 확인한 공급자 복구 절차를 따릅니다. uncordon한 Node에 문제가 재발하면 새 배치를 멈출지 운영 영향과 PDB를 확인해 승인받습니다.

ESCALATION PACK

담당자에게 전달할 자료

  • FailedScheduling 원문과 Pod request·selector·affinity·toleration, Node allocatable·taint
  • PVC·StorageClass·PV 상태와 CSI Warning 이벤트, 실제 데이터 백업·reclaimPolicy 정보
  • Node conditions·lease·kubelet/containerd 로그와 변경 전후 Pod Ready·PVC Bound 결과
2026년 9월 2일 기준 upstream 공식 문서와 현재 지원 버전을 대조했습니다. 먼저 읽기 전용 명령으로 사실을 확인하고, 변경 명령은 영향·백업·복구 경로를 확인한 뒤 승인된 대상에만 적용하세요. <...> 자리표시자는 승인된 리터럴 값으로 직접 치환하고 외부 입력으로 shell 명령을 조립하거나 eval하지 마세요.

BEFORE YOU START

이런 증상에서 시작합니다

  • Pod가 Pending 상태에서 Node에 배치되지 않음
  • 이벤트에 FailedScheduling 또는 Insufficient cpu/memory가 표시됨
  • PVC STATUS가 Pending이고 Pod가 unbound claim을 기다림
  • Node STATUS가 NotReady이거나 DiskPressure·MemoryPressure가 True임

CHECK THE BRANCH

놓치기 쉬운 원인 분기

01

Insufficient cpu·memory 또는 too many pods인 경우

scheduler는 현재 사용량이 아니라 request와 Node allocatable을 기준으로 배치합니다. request 축소·증설 전 실제 요구량과 namespace quota, DaemonSet 점유량을 함께 확인합니다.

02

taint·affinity·selector 불일치인 경우

Node의 장애 taint를 임의 제거하지 않습니다. workload가 요구한 selector·affinity·topology와 Node label, 허용된 toleration이 의도한 정책인지 소스에서 비교합니다.

03

PVC가 Pending인 경우

StorageClass 존재, default 여부, accessModes·용량·volumeBindingMode, CSI provisioner 이벤트를 확인합니다. PVC 삭제나 finalizer 제거는 영구 데이터 손실로 이어질 수 있습니다.

04

Node Ready가 False 또는 Unknown인 경우

False는 kubelet이 비정상 상태를 보고한 경우, Unknown은 control plane이 heartbeat를 받지 못한 경우일 수 있습니다. cordon/uncordon보다 kubelet·runtime·네트워크·압박 조건을 먼저 복구합니다.

FOLLOW THE FLOW

순서대로 확인하기

1
조회시스템을 변경하지 않는 확인 단계

1분 점검: Pod·PVC·Node·이벤트 한눈에 보기

같은 namespace의 Pod와 PVC, 클러스터 Node 조건, 최근 Warning 이벤트를 시간순으로 확인해 첫 분기를 정합니다.

Pending Pod와 배치 Node
kubectl get pods -n <NAMESPACE> -o wide --field-selector=status.phase=Pending
namespace PVC·StorageClass
kubectl get pvc -n <NAMESPACE>
kubectl get storageclass
PV는 cluster-scoped이므로 namespace PVC와 함께 전체 조회하지 않습니다.
PVC가 참조하는 승인된 단일 PV
kubectl get pvc -n <NAMESPACE> <PVC> -o jsonpath='{.spec.volumeName}{"\n"}'
kubectl get pv <BOUND_PV> -o custom-columns='NAME:.metadata.name,STATUS:.status.phase,CLASS:.spec.storageClassName,CAPACITY:.spec.capacity.storage,CLAIM:.spec.claimRef.name'
첫 명령에서 확인한 정확한 PV 이름을 <BOUND_PV>에 넣고 cluster-scoped 조회 권한을 승인받은 경우에만 실행합니다. 전체 PV 목록을 외부 공유하지 않습니다.
Node 상태
kubectl get nodes -o wide
최근 Warning 이벤트
kubectl events -n <NAMESPACE> --types=Warning
결과 읽기

FailedScheduling 메시지가 리소스, taint/affinity, unbound PVC 중 어디를 가리키는지 확인하고 Node NotReady가 동시에 발생했는지 봅니다.

다음 판단

한 번에 여러 조건을 바꾸지 말고 scheduler·storage·node 중 주원인 분기로 이동합니다.

2
조회시스템을 변경하지 않는 확인 단계

Scheduler 제약과 request 확인

Pod 이벤트와 spec, Node allocatable·taint를 비교합니다. 실제 CPU 사용량만 보고 request를 임의 축소하지 않습니다.

Pod 상세와 FailedScheduling
kubectl events -n <NAMESPACE> --for pod/<POD> --types=Warning
이벤트 메시지의 workload 이름·Node·PVC 등 내부 식별정보는 외부 공유 전 마스킹합니다.
request·selector·affinity·toleration
kubectl get pod -n <NAMESPACE> <POD> -o jsonpath='{range .spec.containers[*]}{.name}{" requests="}{.resources.requests}{"\n"}{end}{"nodeSelector="}{.spec.nodeSelector}{"\naffinity="}{.spec.affinity}{"\ntolerations="}{.spec.tolerations}{"\n"}'
전체 YAML 대신 스케줄링 진단 필드만 조회합니다. label 값과 topology 정보는 내부 자산 정보일 수 있어 외부 공유 전 마스킹합니다.
Node allocatable·taint·조건
kubectl get nodes -o custom-columns='NAME:.metadata.name,CPU:.status.allocatable.cpu,MEMORY:.status.allocatable.memory,PODS:.status.allocatable.pods,TAINTS:.spec.taints[*].key'
필요한 수용량과 taint key만 조회합니다. Node 이름도 내부 자산 정보이므로 외부 공유 전에 마스킹합니다.
결과 읽기

Insufficient는 request 대비 allocatable 부족, untolerated taint는 정책 불일치, node affinity/selector는 적합한 label의 Node 부재를 뜻합니다.

다음 판단

용량 증설, workload request 조정, label/affinity 수정 중 원인에 맞는 하나만 변경안으로 준비합니다.

3
조회시스템을 변경하지 않는 확인 단계

PVC·StorageClass·CSI 이벤트 확인

PVC와 StorageClass 설정, PV 바인딩 조건, CSI controller 이벤트를 조회합니다. Secret이나 VolumeAttachment를 강제로 지우지 않습니다.

PVC 상세 이벤트
kubectl describe pvc -n <NAMESPACE> <PVC>
describe 출력에는 annotation·스토리지 식별자·이벤트가 포함될 수 있습니다. 제한된 터미널에서 확인하고 외부 공유 전 마스킹합니다.
PVC 요구조건
kubectl get pvc -n <NAMESPACE> <PVC> -o jsonpath='{.spec.storageClassName}{" "}{.spec.accessModes}{" requested="}{.spec.resources.requests.storage}{" volume="}{.spec.volumeName}{"\n"}'
StorageClass 바인딩 정책
kubectl get storageclass <STORAGE_CLASS> -o jsonpath='{.provisioner}{" binding="}{.volumeBindingMode}{" reclaim="}{.reclaimPolicy}{" expansion="}{.allowVolumeExpansion}{"\n"}'
전체 YAML의 provider parameter·내부 식별자를 출력하지 않고 바인딩 판단에 필요한 필드만 조회합니다.
스토리지 관련 Warning 이벤트
kubectl events -n <NAMESPACE> --types=Warning | grep -E 'PersistentVolume|Provisioning|AttachVolume|MountVolume|<PVC>'
결과 읽기

no provisioner·quota·access mode 불일치인지, WaitForFirstConsumer라서 Pod 스케줄과 함께 지연되는 정상 흐름인지 구분합니다.

다음 판단

기존 Bound PVC는 삭제·재생성하지 말고 CSI와 스토리지 제공자의 복구 절차를 확인합니다.

4
주의서버 부하나 권한을 고려할 단계

Node Ready·Pressure와 kubelet 확인

NotReady Node에서 조건·lease와 kubelet/containerd 로그를 확인합니다. drain·reboot·runtime 재시작은 이 진단 단계에서 수행하지 않습니다.

Node 조건과 taint
kubectl get node <NODE> -o jsonpath='{range .status.conditions[*]}{.type}{"="}{.status}{" reason="}{.reason}{" message="}{.message}{"\n"}{end}{"taints="}{.spec.taints}{"\n"}'
Node lease heartbeat
kubectl get lease -n kube-node-lease <NODE> -o jsonpath='{.spec.holderIdentity}{" renewTime="}{.spec.renewTime}{"\n"}'
전체 YAML 대신 holder와 갱신 시각만 조회하며 Node 식별자는 외부 공유 전 마스킹합니다.
Node 로컬 서비스 로그
sudo systemctl status kubelet.service containerd.service --no-pager -l
sudo journalctl -u kubelet.service -u containerd.service --since '-20 min' --no-pager
Node 디스크·메모리
df -hT / /var
free -h
결과 읽기

Ready Unknown과 lease 정지는 네트워크·kubelet 중단, Ready False와 Pressure True는 노드 자원·runtime 문제 가능성이 큽니다.

다음 판단

노드 원인을 먼저 복구하고 Ready True가 안정적으로 유지된 뒤 스케줄링 상태를 다시 봅니다.

5
변경데이터·서비스 상태가 달라질 수 있는 단계

검토된 한 가지 수정 적용 후 바인딩·배치 검증

이 단계는 workload·스토리지·Node 스케줄 상태를 바꿀 수 있습니다. PVC 삭제·finalizer 제거·강제 drain은 제시하지 않으며, 소스 관리된 수정만 diff 후 적용합니다.

변경 단계입니다. 실행 전 대상 이름과 경로, 서비스 중단 영향, 복구 방법을 다시 확인하세요.
현재 workload·PVC 메타데이터 백업
install -d -m 0700 "<APPROVED_BACKUP_PATH>"
umask 077
kubectl get deployment -n <NAMESPACE> <DEPLOYMENT> -o yaml > "<APPROVED_BACKUP_PATH>/deployment.before-scheduling-fix.yaml"
kubectl get pvc -n <NAMESPACE> <PVC> -o yaml > "<APPROVED_BACKUP_PATH>/pvc.before-scheduling-fix.yaml"
chmod 0600 "<APPROVED_BACKUP_PATH>/deployment.before-scheduling-fix.yaml" "<APPROVED_BACKUP_PATH>/pvc.before-scheduling-fix.yaml"
stat -Lc '%a %U:%G %n' "<APPROVED_BACKUP_PATH>/deployment.before-scheduling-fix.yaml" "<APPROVED_BACKUP_PATH>/pvc.before-scheduling-fix.yaml"
Deployment에는 literal env.value·annotation·내부 URL, PVC에는 storageClass·volumeName·annotation이 포함될 수 있습니다. 전용 0700 디렉터리와 0600 파일에서만 보관하고 원문을 외부에 공유하지 않습니다.
변경 미리보기
kubectl diff --server-side -f <REVIEWED_FIX.yaml>
승인된 manifest 적용
kubectl apply --server-side -f <REVIEWED_FIX.yaml>
request·affinity·PVC 정의를 동시에 바꾸지 않습니다. 기존 Bound PVC 교체는 스토리지 백업·복원 계획 없이는 실행하지 않습니다.
복구된 Node만 스케줄 허용
kubectl uncordon <NODE>
작업 전 수동 cordon 상태였고 Node Ready=True, Pressure=False이며 운영 승인까지 받은 경우에만 실행합니다. 장애 taint를 직접 제거하지 않습니다.
최종 배치·바인딩 확인
kubectl get pod,pvc -n <NAMESPACE> -o wide
kubectl get node <NODE>
kubectl events -n <NAMESPACE> --types=Warning
결과 읽기

Pod가 Running/Ready, PVC가 Bound, Node가 Ready이고 같은 Warning 이벤트가 다시 발생하지 않아야 합니다. 하나라도 불명확하면 복구 완료로 판정하지 않습니다.

다음 판단

실패하면 manifest는 백업·정상 Git revision으로 복원하고 uncordon은 다시 cordon할지 운영 영향에 따라 승인받습니다. 재발 방지를 위해 request 기준 용량, CSI 경보, Node Ready·Pressure와 PVC Pending 지속시간 알림을 둡니다.

PRIMARY REFERENCES

공식 문서

배포판과 버전에 따라 옵션·로그 위치가 다를 수 있습니다. 실행 전 서버의 --help와 로컬 매뉴얼을 함께 확인하세요.

도구 빠른 검색

최근 사용한 도구를 다시 열거나, 이름과 기능으로 검색하세요.

검색어와 도구의 입력·결과는 저장하지 않습니다.

↑↓ 이동 · Enter 열기 · Esc 닫기