The persistent volume controller failed to bind a requested persistent volume claim to an available persistent volume, leaving the PVC in a "Pending" state.

The most common culprit is a mismatch between the storageClassName specified in your PersistentVolumeClaim (PVC) and the storageClassName available on your PersistentVolumes (PVs) or provisionable by your storage provisioner.

Diagnosis:

  1. Check the PVC’s events for detailed error messages.

    kubectl describe pvc <your-pvc-name> -n <your-namespace>
    

    Look for events indicating "provisioning failed" or "no persistent volumes found."

  2. List all available StorageClasses.

    kubectl get storageclass
    

    Verify that the storageClassName in your PVC exactly matches one of the names listed here.

Fix: Ensure your PVC definition uses a storageClassName that is present in the output of kubectl get storageclass. For example, if kubectl get storageclass shows gp2 and fast-ssd, your PVC should have storageClassName: gp2 or storageClassName: fast-ssd. This matches the PVC’s request to the specific type of storage available or provisionable.

Another frequent cause is the absence of any matching PersistentVolumes (PVs) or a provisioner that can dynamically create one for the requested PVC.

Diagnosis:

  1. If you are using pre-provisioned PVs, check if any exist that match the PVC’s requirements (size, access modes, storageClassName).

    kubectl get pv
    

    Look for PVs with Status: Available that meet the PVC’s resources.requests.storage and accessModes.

  2. If you expect dynamic provisioning, check the status of your storage provisioner (e.g., CSI driver pods).

    kubectl get pods -n kube-system | grep csi # or similar for your provisioner
    

    Ensure the provisioner pods are running and healthy.

Fix: If using pre-provisioned PVs, create a PV that satisfies the PVC’s requirements. For example, to create a PV for 10Gi of standard storage with ReadWriteOnce access:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-manual-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  storageClassName: standard # Must match PVC's storageClassName
  hostPath: # Example for local storage, replace with your actual storage type
    path: "/mnt/data/my-pv"

This explicitly makes storage available to the cluster. If dynamic provisioning is expected, ensure your CSI driver or storage provisioner is correctly deployed and configured, and its pods are running.

Incorrect accessModes in the PVC or available PVs can also block binding.

Diagnosis:

  1. Examine the accessModes requested by your PVC.

    # Your PVC definition
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: my-pvc
    spec:
      accessModes:
        - ReadWriteOnce # e.g., RWO, RMA, RWX
      resources:
        requests:
          storage: 5Gi
      storageClassName: standard
    
  2. Check the accessModes of any available PVs or what your provisioner can offer.

    kubectl get pv -o wide # Look at Access Modes column for available PVs
    # Or for dynamic provisioning, consult your storage provider's documentation
    

Fix: Ensure at least one available PV has an accessMode that is compatible with your PVC’s requested accessModes. For example, if your PVC requests ReadWriteOnce and ReadOnlyMany, and an available PV only supports ReadWriteOnce, it can still bind. However, if your PVC requests ReadWriteOnce and no PV supports it, it will remain pending. Adjust either the PVC’s request or the PV’s capability. For instance, if your PVC needs ReadWriteMany and your underlying storage (like NFS) supports it, ensure the PV definition or provisioner configuration reflects this.

Insufficient capacity is a straightforward but common reason.

Diagnosis:

  1. Check the requested storage size in your PVC.

    # Your PVC definition
    spec:
      resources:
        requests:
          storage: 50Gi # This is the request
    
  2. Check the capacity of all available PVs or the limits of your dynamic provisioner.

    kubectl get pv -o wide # Look at CAPACITY column for available PVs
    

Fix: If using pre-provisioned PVs, ensure there is an available PV with capacity.storage greater than or equal to the PVC’s resources.requests.storage. If your provisioner has limits, you might need to increase them or ensure the provisioner is configured to create volumes of the requested size. For example, to satisfy a 50Gi request, you’d need an available PV with at least 50Gi capacity.

The volumeBindingMode: WaitForFirstConsumer setting in your StorageClass can delay binding until a Pod using the PVC is scheduled. If the Pod cannot be scheduled (e.g., due to node affinity, taints, or resource constraints), the PVC will remain Pending.

Diagnosis:

  1. Inspect your StorageClass definition.

    kubectl get storageclass <your-storageclass-name> -o yaml
    

    Look for volumeBindingMode: WaitForFirstConsumer.

  2. If this setting is enabled, check the events of the Pod that is supposed to consume the PVC.

    kubectl describe pod <your-pod-name> -n <your-namespace>
    

    Look for scheduling failures.

Fix: If volumeBindingMode: WaitForFirstConsumer is set and the Pod is unschedulable, resolve the Pod’s scheduling issues. Alternatively, you can change the volumeBindingMode in the StorageClass to Immediate (if your storage provider supports it and it’s appropriate for your use case) to allow the PVC to bind as soon as a suitable PV is found, regardless of Pod scheduling.

# In your StorageClass
volumeBindingMode: Immediate

This allows the PVC to be bound to a PV before a pod is scheduled, decoupling the two processes.

Sometimes, issues with the underlying storage provider or its CSI driver can prevent provisioning.

Diagnosis:

  1. Check the logs of your CSI driver pods.

    kubectl logs <csi-driver-pod-name> -n <csi-driver-namespace>
    

    Look for errors related to creating or attaching volumes.

  2. Check the status of your storage cluster (e.g., cloud provider dashboard, on-premises storage system).

Fix: Address any errors reported in the CSI driver logs or issues within your storage system. This might involve restarting CSI driver pods, adjusting storage system configurations, or contacting your cloud provider’s support. A common fix is restarting the CSI controller or node plugin pods if they appear unhealthy.

If you’ve fixed a PVC stuck in Pending, the next error you’ll likely encounter is the Pod failing to start because the volume cannot be mounted.

Want structured learning?

Take the full Kubernetes course →