When a Kubernetes PVC Won't Leave Pending — 6 Causes, 5-Minute Diagnostic Guide
You rolled out a deployment, but the Pod is stuck forever in ContainerCreating. You run kubectl get pvc and see this:
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
data-pvc Pending standard 8mSTATUS=Pending has not cleared for several minutes. A lot of people immediately suspect the scheduler—"are we short on node resources?"—but that's a different problem.
⚠️ The previous post, "Kubernetes Pod Pending," covered cases where the scheduler cannot place a Pod on a node—CPU/memory, taints, insufficient nodes, and so on. This post is a storage-only issue: the PV never binds to the PVC, so the volume never attaches. If the real reason the Pod is Pending is the PVC, staring at the Pod will never give you the answer.
This article is a playbook that maps event text → cause → fix command in three steps, so you can pin down which of the six causes matches the message in front of you within five minutes.
1-Minute First Pass: The Four Commands to Run First
Don't overthink it—run these four as-is right now. 90% of the time the answer is already in the Events section of the first command.
# ① 가장 중요 — Events 섹션이 원인을 그대로 알려준다
kubectl describe pvc <pvc-name>
# ② 정적 PV가 존재하는지, 어떤 상태인지
kubectl get pv
# ③ StorageClass 목록과 default 여부 확인
kubectl get sc
# ④ 시간순 전체 이벤트(프로비저너 로그 포착)
kubectl get events --sort-by=.metadata.creationTimestampBranch on the single line printed under Events at the bottom of describe pvc.
| Event text | Jump to cause |
|---|---|
storageclass.storage.k8s.io "xxx" not found | ① StorageClass name typo |
| (no events + empty storageClassName) | ② No default StorageClass |
waiting for first consumer to be created before binding | ③ WaitForFirstConsumer (expected) |
no persistent volumes available for this claim | ④ accessModes/capacity mismatch |
failed to provision volume with StorageClass | ⑤ CSI driver not installed |
... could not find ... topology / zone-related | ⑥ Topology/zone mismatch |
Six-Cause Decision Table (the core of this post)
| # | Event / symptom text | Cause | Check command | Fix command |
|---|---|---|---|---|
| ① | storageclass.storage.k8s.io "fast" not found | storageClassName typo / class does not exist | kubectl get sc | Fix storageClassName in the PVC manifest to the real name and re-apply |
| ② | Pending with no events, storageClassName omitted | No default StorageClass | Confirm (default) in kubectl get sc | kubectl patch storageclass <name> -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' |
| ③ | waiting for first consumer to be created before binding | WaitForFirstConsumer (expected behavior) | kubectl get sc <name> -o yaml | grep volumeBindingMode | Binding happens once you actually create the Pod that mounts the PVC |
| ④ | no persistent volumes available for this claim | accessModes/capacity mismatch (static PV) | kubectl get pv -o wide | Fix PVC accessModes, or use RWX-capable storage (NFS/CephFS) |
| ⑤ | failed to provision volume with StorageClass or infinite Pending | CSI driver/provisioner not installed | kubectl get csidrivers, kubectl get pods -n kube-system | grep csi | Install the CSI driver (EBS/GCE PD, etc.) |
| ⑥ | volume node affinity conflict / zone mismatch | PV lives in a different AZ from the Pod | kubectl get pv -o wide, check the node's topology.kubernetes.io/zone label | Create the PV in the same zone, or use WaitForFirstConsumer for topology-aware provisioning |
① StorageClass name typo
This is the most common case and the fastest to fix. Confirm the real name with kubectl get sc and correct the manifest. Managed clusters use different defaults—EKS gp2/gp3, GKE standard-rwo, AKS default—so if you copy-pasted YAML from another cluster, start here.
② No default StorageClass
A PVC that omits storageClassName entirely uses the cluster's default StorageClass. If there is no default at all, it stays Pending forever.
kubectl get sc
# NAME 옆에 (default)가 없으면 아래로 지정
kubectl patch storageclass standard \
-p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'③ WaitForFirstConsumer — the most commonly misunderstood case
Events:
Normal WaitForFirstConsumer ... waiting for first consumer to be created before bindingThis is not a failure; it is expected behavior. A StorageClass with volumeBindingMode: WaitForFirstConsumer deliberately delays binding until a Pod that uses the PVC is actually scheduled. That prevents the PV and Pod from landing in different zones on a multi-AZ cluster. The fix is to create the Pod that mounts the PVC. Leaving a PVC sitting by itself and wondering why it never binds is extremely common.
④ accessModes mismatch (RWO vs RWX)
no persistent volumes available for this claim appears in static provisioning when no PV matches. A common cause is a PVC requesting ReadWriteMany(RWX) while block storage such as EBS or GCE PD does not support RWX. If you truly need RWX, use file storage such as NFS, CephFS, or EFS.
⑤ CSI driver not installed
This has become one of the most frequent causes. After CSI migration of in-tree volume plugins completed, EBS, GCE PD, and similar volumes require a separately installed CSI driver for dynamic provisioning.
kubectl get csidrivers
kubectl get pods -n kube-system | grep csi
# EKS 예: aws-ebs-csi-driver 애드온 설치 필요⑥ Capacity and zone topology mismatch
Compare the PV's zone from kubectl get pv -o wide with the node's topology.kubernetes.io/zone label. If the PV is in ap-northeast-2a and the Pod is scheduled to 2c, it will never attach. Topology-aware provisioning (WaitForFirstConsumer) is the right answer.
After each change, watch in real time with:
kubectl get pvc -wStatic vs. Dynamic Provisioning — the underlying model
- Static: An admin-created PV binds to a PVC only when
capacity/accessModes/storageClassName/selectorall match. Any mismatch yieldsno persistent volumes available. - Dynamic: The StorageClass plus a provisioner (CSI) automatically creates a PV that fits the PVC. Without a provisioner, it stays Pending.
Immediate binds as soon as the PVC is created (fine for a single zone). WaitForFirstConsumer delays until the Pod is scheduled (the recommended default for multi-AZ).
Minimal YAML trio for reproduction
# 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-pvcA note from the field
In practice, more than half of PVC Pending cases on multi-AZ EKS/GKE are #③ (expected behavior, but nobody created a Pod) and #⑤ (CSI not installed). When you get a new cluster, make a habit of checking kubectl get sc and kubectl get csidrivers before you even launch a Pod—you'll skip this entire class of wasted hours.
Wrap-up: 5-minute diagnostic checklist
kubectl describe pvc→ read the Events linekubectl get sc→ class exists / is default- Check binding mode → if WaitForFirstConsumer, create the Pod first
- Confirm accessModes / capacity / zone match
- Confirm the driver is installed with
kubectl get csidrivers
Prevention tips: Always set a default StorageClass, always specify storageClassName in the manifest, and if you need RWX, pick storage that supports it from the start.
Next post (part 12) preview: When the PVC is Bound but the mount still hangs — fixing Unable to attach or mount volumes / volume node affinity conflict / MountVolume.SetUp failed.
References: official docs
The primary source for the behavior, settings, and errors covered here is the official documentation below. Check it for version-specific options and exact semantics.
FAQ
Q. waiting for first consumer showed up. Is it broken?
A. No. That is expected behavior. Binding happens when you actually create and schedule a Pod that mounts the PVC.
Q. Why do I see no persistent volumes available for this claim?
A. None of the static PVs match the PVC's accessModes/capacity/storageClassName. It is especially common when you request RWX against block storage.
Q. PVC won't bind on EKS. Is the cluster broken?
A. Most of the time the aws-ebs-csi-driver add-on is missing. Check the driver first with kubectl get csidrivers.
Nodelog는 모든 콘텐츠의 내용과 출처를 공개 전에 검토합니다. 환경(OS·버전)에 따라 결과가 달라질 수 있는 기술 정보는 공식 문서와 함께 확인하며, 검토 기준과 정정 원칙은 편집 정책에서 안내합니다. 오류를 발견하시면 이메일로 제보해 주세요 — 확인 후 신속히 정정합니다.
Comments
Be the first to comment.