This error occurs when a PersistentVolumeClaim (PVC) cannot find a matching PersistentVolume (PV) to bind to. Common causes include mismatched access modes, storage class issues, or no available volumes. The fix involves ensuring your PVC and PV specifications align correctly.
When Kubernetes reports "PersistentVolumeClaim is not bound," it means your PVC is stuck in a Pending state because it cannot find a suitable PersistentVolume to claim. This is a blocking issue—any pods depending on this PVC will not start until the binding succeeds. The PVC-to-PV binding process requires several criteria to match: storage capacity, access modes (ReadWriteOnce, ReadWriteMany, ReadOnlyMany), storage class, and optionally label selectors. If any of these don't align, Kubernetes cannot complete the binding. In clusters with dynamic provisioning enabled, a StorageClass provisioner automatically creates PVs when PVCs are submitted. If dynamic provisioning fails or isn't configured, you'll need to manually create matching PVs or troubleshoot the provisioner.
First, inspect your PVC status and events to understand why binding failed:
kubectl get pvc -n <namespace>
kubectl describe pvc <pvc-name> -n <namespace>Look at the Events section for messages like "no persistent volumes available" or specific mismatch details. Also list available PVs:
kubectl get pv
kubectl describe pv <pv-name>Ensure your PVC and PV use compatible access modes. They must match exactly:
# PV access modes
spec:
accessModes:
- ReadWriteOnce # Must match PVC
# PVC access modes
spec:
accessModes:
- ReadWriteOnce # Must match PVCommon modes: ReadWriteOnce (single node), ReadWriteMany (multiple nodes), ReadOnlyMany (read-only multi-node).
Verify both PVC and PV reference the same storage class:
kubectl get storageclass
kubectl describe storageclass <name>For static provisioning, ensure PV has matching storageClassName:
# PV
spec:
storageClassName: manual
# PVC
spec:
storageClassName: manualFor dynamic provisioning, verify the provisioner pod is running:
kubectl get pods -n kube-system | grep -E 'provisioner|csi'PV capacity must be greater than or equal to PVC request:
# PV must have enough capacity
spec:
capacity:
storage: 10Gi
# PVC request must be <= PV capacity
spec:
resources:
requests:
storage: 5Gi # OK: 5Gi <= 10GiIf no PV has sufficient capacity, create a larger one or reduce your PVC request.
If a PV shows status "Released," it cannot be reused until reset. For Retain reclaim policy:
# Check PV status
kubectl get pv
# If Released, you have two options:
# Option 1: Delete and recreate the PV
kubectl delete pv <pv-name>
# Then recreate with same spec
# Option 2: Remove claimRef to make it Available again
kubectl patch pv <pv-name> -p '{"spec":{"claimRef": null}}'Warning: Option 2 may leave orphaned data on the volume.
If using WaitForFirstConsumer binding mode, the PVC stays Pending until a pod using it is scheduled:
kubectl get storageclass <name> -o yaml | grep volumeBindingModeThis is expected behavior for topology-aware storage. Create a pod that uses the PVC to trigger binding:
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: test
image: busybox
command: ["sleep", "3600"]
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: your-pvc-nameIf no suitable PV exists, create one that matches your PVC:
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
storageClassName: manual
persistentVolumeReclaimPolicy: Retain
hostPath: # For local testing only
path: /mnt/dataApply and verify binding:
kubectl apply -f pv.yaml
kubectl get pvc # Should now show BoundCloud Provider Considerations:
- AWS EKS: Ensure the EBS CSI driver is installed and has proper IAM permissions. Check kubectl get pods -n kube-system -l app=ebs-csi-controller.
- GKE: Verify the Compute Engine persistent disk CSI driver is enabled. Regional PVs must match pod scheduling zones.
- AKS: Check Azure Disk or Azure File CSI driver status. Verify storage account quotas and regional availability.
Local Development:
- Minikube: Use minikube addons enable storage-provisioner for automatic provisioning.
- Kind: Requires manual StorageClass setup or the local-path-provisioner.
- Docker Desktop: Limited to hostPath volumes for local development.
Topology and Affinity:
When using WaitForFirstConsumer, the volume is provisioned in the same zone as the first pod. This prevents cross-zone mounting issues but means PVC binding depends on pod scheduling. Use kubectl describe pvc to see waiting status.
Pre-binding PVs:
For explicit PV-to-PVC mapping, use spec.volumeName in PVC and spec.claimRef in PV. The claimRef must include namespace:
spec:
claimRef:
namespace: my-namespace
name: my-pvcFailed to connect to server: connection refused (HTTP/2)
How to fix "HTTP/2 connection refused" error in Kubernetes
missing request for cpu in container
How to fix "missing request for cpu in container" in Kubernetes HPA
error: invalid configuration
How to fix "error: invalid configuration" in Kubernetes
etcdserver: cluster ID mismatch
How to fix "etcdserver: cluster ID mismatch" in Kubernetes
running with swap on is not supported
How to fix "running with swap on is not supported" in kubeadm