Kubernetes PVC가 Pending에서 안 풀릴 때 — 원인 6가지 5분 진단 가이드
배포를 올렸는데 Pod가 ContainerCreating에서 영원히 멈춰 있고, kubectl get pvc를 쳐보니 이런 화면이 보입니다.
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
data-pvc Pending standard 8mSTATUS=Pending이 몇 분째 풀리지 않습니다. 여기서 많은 분들이 "노드 자원이 부족한가?" 하고 스케줄러부터 의심하는데, 그건 다른 문제입니다.
⚠️ 이전 편 'Kubernetes Pod Pending'은 CPU/메모리/taint/노드 부족 등 스케줄러가 Pod를 노드에 못 올리는 문제였습니다. 이번 편은 PV-PVC 바인딩이 안 되어 볼륨 자체가 안 붙는 스토리지 전용 이슈입니다. Pod가 Pending인 진짜 원인이 PVC라면, Pod를 아무리 들여다봐도 답이 안 나옵니다.
이 글은 이벤트 원문 → 원인 → 해결 명령 3단 매핑으로, 지금 보고 있는 메시지만으로 6가지 원인 중 어디에 해당하는지 5분 안에 확정시키는 플레이북입니다.
1분 1차 진단: 가장 먼저 쳐야 할 4개 명령
고민하지 말고 지금 이 4개부터 그대로 쳐보세요. 90%는 첫 번째 명령의 Events 섹션에서 답이 나옵니다.
# ① 가장 중요 — Events 섹션이 원인을 그대로 알려준다
kubectl describe pvc <pvc-name>
# ② 정적 PV가 존재하는지, 어떤 상태인지
kubectl get pv
# ③ StorageClass 목록과 default 여부 확인
kubectl get sc
# ④ 시간순 전체 이벤트(프로비저너 로그 포착)
kubectl get events --sort-by=.metadata.creationTimestampdescribe pvc 맨 아래 Events에 찍힌 한 줄로 1차 분기합니다.
| 이벤트 원문 | 점프할 원인 |
|---|---|
storageclass.storage.k8s.io "xxx" not found | ① StorageClass 이름 오타 |
| (이벤트 없음 + storageClassName 비어 있음) | ② default StorageClass 미지정 |
waiting for first consumer to be created before binding | ③ WaitForFirstConsumer (정상) |
no persistent volumes available for this claim | ④ accessModes/용량 불일치 |
failed to provision volume with StorageClass | ⑤ CSI 드라이버 미설치 |
... could not find ... topology / zone 관련 | ⑥ 토폴로지/zone 불일치 |
원인 6가지 분기표 (이 글의 본체)
| # | 이벤트/증상 원문 | 원인 | 확인 명령 | 해결 명령 |
|---|---|---|---|---|
| ① | storageclass.storage.k8s.io "fast" not found | storageClassName 오타/없는 클래스 | kubectl get sc | PVC manifest의 storageClassName을 실제 이름으로 수정 후 재적용 |
| ② | 이벤트 없이 Pending, storageClassName 생략 | default StorageClass 없음 | kubectl get sc 에 (default) 표시 확인 | kubectl patch storageclass <name> -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' |
| ③ | waiting for first consumer to be created before binding | WaitForFirstConsumer (정상 동작) | kubectl get sc <name> -o yaml | grep volumeBindingMode | PVC를 마운트하는 Pod를 실제 생성하면 바인딩됨 |
| ④ | no persistent volumes available for this claim | accessModes/capacity 불일치 (정적 PV) | kubectl get pv -o wide | PVC의 accessModes 수정 또는 RWX 지원 스토리지(NFS/CephFS) 사용 |
| ⑤ | failed to provision volume with StorageClass 또는 무한 Pending | CSI 드라이버/프로비저너 미설치 | kubectl get csidrivers, kubectl get pods -n kube-system | grep csi | EBS/GCE PD 등 CSI 드라이버 설치 |
| ⑥ | volume node affinity conflict / zone mismatch | PV가 Pod와 다른 AZ에 존재 | kubectl get pv -o wide, 노드의 topology.kubernetes.io/zone 라벨 확인 | 동일 zone에 PV 생성 또는 WaitForFirstConsumer로 토폴로지 인식 |
① StorageClass 이름 오타
가장 흔하고 가장 빨리 풀리는 케이스입니다. kubectl get sc로 진짜 이름을 확인하고 manifest를 고치면 끝입니다. EKS는 gp2/gp3, GKE는 standard-rwo, AKS는 default처럼 관리형마다 기본 이름이 다르니 다른 클러스터의 YAML을 복붙했다면 의심하세요.
② default StorageClass 미지정
storageClassName을 아예 생략한 PVC는 클러스터의 default StorageClass를 씁니다. 그런데 default가 하나도 없으면 영원히 Pending입니다.
kubectl get sc
# NAME 옆에 (default)가 없으면 아래로 지정
kubectl patch storageclass standard \
-p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'③ WaitForFirstConsumer — 가장 많이 오해하는 케이스
Events:
Normal WaitForFirstConsumer ... waiting for first consumer to be created before binding이건 고장이 아니라 정상 동작입니다. volumeBindingMode: WaitForFirstConsumer인 StorageClass는 PVC를 사용하는 Pod가 실제로 스케줄될 때까지 일부러 바인딩을 미룹니다. 멀티 AZ 클러스터에서 PV와 Pod가 서로 다른 zone에 떨어지는 사고를 막기 위함이죠. 해결책은 PVC를 마운트하는 Pod를 만드는 것입니다. PVC만 덩그러니 만들어두고 "왜 안 붙지?" 하는 경우가 정말 많습니다.
④ accessModes 불일치 (RWO vs RWX)
no persistent volumes available for this claim은 정적 프로비저닝에서 매칭되는 PV가 없을 때 뜹니다. 흔한 원인은 PVC가 ReadWriteMany(RWX)를 요구하는데 EBS/GCE PD 같은 블록 스토리지는 RWX를 지원하지 않는 경우입니다. RWX가 꼭 필요하면 NFS, CephFS, EFS 같은 파일 스토리지를 쓰세요.
⑤ CSI 드라이버 미설치
요즘 가장 빈도가 높아진 원인입니다. in-tree 볼륨 플러그인의 CSI 마이그레이션이 완료되면서 EBS/GCE PD 등은 CSI 드라이버를 별도로 설치해야 동적 프로비저닝이 됩니다.
kubectl get csidrivers
kubectl get pods -n kube-system | grep csi
# EKS 예: aws-ebs-csi-driver 애드온 설치 필요⑥ 용량·zone 토폴로지 불일치
kubectl get pv -o wide로 PV의 zone과 노드의 topology.kubernetes.io/zone 라벨을 비교하세요. PV가 ap-northeast-2a에 있는데 Pod가 2c에 스케줄되면 절대 안 붙습니다. 토폴로지 인식 프로비저닝(WaitForFirstConsumer)이 정답입니다.
각 단계마다 수정 후엔 아래로 실시간 확인합니다.
kubectl get pvc -w정적 vs 동적 프로비저닝 — 근본 이해
- 정적(static): 관리자가 미리 만든 PV와 PVC가
capacity/accessModes/storageClassName/selector기준으로 매칭되어야 바인딩됩니다. 하나라도 어긋나면no persistent volumes available. - 동적(dynamic): StorageClass + 프로비저너(CSI)가 PVC에 딱 맞는 PV를 자동 생성합니다. 프로비저너가 없으면 Pending.
Immediate는 PVC 생성 즉시 바인딩(단일 zone에 적합), WaitForFirstConsumer는 Pod 스케줄 시점까지 지연(멀티 AZ 권장 기본값)입니다.
재현용 최소 YAML 3종
# 1) StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: demo-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
---
# 2) PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-pvc
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: demo-sc
resources:
requests:
storage: 5Gi
---
# 3) PVC를 마운트하는 Pod (이게 있어야 ③에서 바인딩됨)
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: nginx
volumeMounts:
- { name: data, mountPath: /data }
volumes:
- name: data
persistentVolumeClaim:
claimName: data-pvc실무 한마디
경험상 멀티 AZ EKS/GKE에서 발생하는 PVC Pending의 절반 이상은 ③번(정상인데 Pod를 안 만든 것)과 ⑤번(CSI 미설치)입니다. 신규 클러스터를 받으면 Pod를 올리기 전에 kubectl get sc와 kubectl get csidrivers부터 확인하는 습관을 들이면 이 삽질을 통째로 건너뛸 수 있습니다.
결론: 5분 진단 체크리스트
kubectl describe pvc→ Events 한 줄 확인kubectl get sc→ 클래스 존재/default 여부- 바인딩 모드 확인 → WaitForFirstConsumer면 Pod부터 생성
- accessModes/용량/zone 매칭 확인
kubectl get csidrivers로 드라이버 설치 확인
재발 방지 팁: default StorageClass를 반드시 지정하고, manifest에 storageClassName을 명시하며, RWX가 필요하면 처음부터 지원 스토리지를 선택하세요.
다음 편(12편) 예고: PVC는 Bound인데 마운트에서 멈출 때 — Unable to attach or mount volumes / volume node affinity conflict / MountVolume.SetUp failed 해결편으로 이어집니다.
자주 묻는 질문 (FAQ)
Q. waiting for first consumer가 떴는데 고장인가요?
A. 아닙니다. 정상 동작입니다. PVC를 마운트하는 Pod를 실제로 생성·스케줄하면 그 시점에 바인딩됩니다.
Q. no persistent volumes available for this claim은 왜 뜨나요?
A. 정적 PV 중 PVC의 accessModes/capacity/storageClassName과 일치하는 게 없을 때입니다. 특히 RWX를 요구하는데 블록 스토리지를 쓰면 발생합니다.
Q. EKS에서 PVC가 안 붙어요. 클러스터 문제인가요?
A. 대부분 aws-ebs-csi-driver 애드온 미설치가 원인입니다. kubectl get csidrivers로 드라이버부터 확인하세요.
이 글은 AI 에이전트가 1차 초안을 작성한 뒤, 사람 편집자가 사실관계·출처·톤과 맥락을 검토하여 발행했습니다. 오류나 부정확한 내용이 확인되면 24시간 이내에 정정합니다.
댓글
불러오는 중...