1. Introduction

A persistent volume mount failure leaves your pod stuck in ContainerCreating indefinitely, with the kubelet unable to attach or mount the storage volume the pod needs. The pod is scheduled, the PVC is bound, but the actual volume can't be made available on the node — and without it, the container won't start.

Mount failures are some of the most infrastructure-specific Kubernetes problems. The root cause depends entirely on the storage backend: AWS EBS, GCE PD, NFS, Ceph, local volumes, and CSI drivers each have their own failure modes. This guide covers the diagnostic approach that works across all backends, followed by fixes for the most common specific scenarios.

2. What a Mount Failure Means

Volume mounting in Kubernetes happens in two phases: attach (the volume is attached to the node at the block device or network level) and mount (the volume is mounted into the container's filesystem). Either phase can fail independently. A failure in the attach phase leaves the pod waiting on the node; a failure in the mount phase means the device is present but can't be formatted or mounted.

3. Common Causes

4. Step-by-Step Diagnosis and Fix

Step 1: Read the pod events

# The error is almost always in the Events section
kubectl describe pod <pod-name> -n <namespace>

# Common mount failure messages:
# "Multi-Attach error for volume ... Volume is already used by pod(s)"
# "Unable to attach or mount volumes: unmounted volumes=[data], unattached volumes=[data]"
# "timed out waiting for the condition"
# "failed to sync <volume>: rpc error: ... No such file or directory"
# "MountVolume.SetUp failed for volume ... (already in use)"

Step 2: Fix multi-attach errors

"># Find which pod is holding the volume
kubectl get volumeattachments
kubectl describe volumeattachment <attachment-name>

# Find the old pod holding the attachment
PV_NAME=$(kubectl get pvc <pvc-name> -n <namespace> -o jsonpath='{.spec.volumeName}')
kubectl get pod -A -o json | jq -r   '.items[] | select(.spec.volumes[]?.persistentVolumeClaim.claimName == "<pvc-name>") | .metadata.name'

# Force-delete the old pod (if it's stuck)
kubectl delete pod <old-pod> -n <namespace> --force --grace-period=0

# If the VolumeAttachment is stuck, delete it manually
kubectl delete volumeattachment <attachment-name>

Step 3: Fix availability zone mismatches

# Check which AZ the PV/volume is in
kubectl get pv <pv-name> -o jsonpath='{.metadata.labels}'
# Look for: topology.kubernetes.io/zone

# Check which AZ the pod scheduled to
kubectl get pod <pod-name> -n <namespace> -o wide
kubectl get node <node-name> -o jsonpath='{.metadata.labels.topology\.kubernetes\.io/zone}'

# Fix: add node affinity to the pod to match the volume's zone
# OR: use a StorageClass with volumeBindingMode: WaitForFirstConsumer
# WaitForFirstConsumer creates the volume in the same zone as the pod

kubectl get storageclass
# Preferred StorageClass config:
# volumeBindingMode: WaitForFirstConsumer

Step 4: Check and fix CSI driver issues

# Check CSI driver pods
kubectl get pods -n kube-system | grep csi

# Check CSI node pods on the affected node
kubectl get pods -n kube-system   --field-selector spec.nodeName=<node-name> | grep csi

# Check CSI driver logs
kubectl logs -n kube-system <csi-node-pod> -c <container-name> --tail=50

# For AWS EBS CSI driver:
kubectl get pods -n kube-system -l app=ebs-csi-node
kubectl logs -n kube-system -l app=ebs-csi-node -c ebs-plugin --tail=50

Step 5: Fix NFS mount failures

# Test NFS connectivity from the node
kubectl debug node/<node-name> -it --image=ubuntu -- bash
mount -t nfs <nfs-server>:<export-path> /mnt/test

# Common NFS issues:
# 1. Server unreachable — check security group / firewall rules for port 2049
# 2. Export not found — check /etc/exports on NFS server
# 3. Permission denied — check NFS export options (no_root_squash vs root_squash)

# Verify NFS packages on node
apt-get install -y nfs-common   # Debian/Ubuntu
yum install -y nfs-utils        # RHEL/Amazon Linux

5. Verification Steps

# Pod should transition from ContainerCreating to Running
kubectl get pod <pod-name> -n <namespace> -w

# Verify the volume is mounted inside the container
kubectl exec -it <pod-name> -n <namespace> -- df -h
# Should show the mounted volume at its expected mountPath

# Check VolumeAttachment is healthy
kubectl get volumeattachments | grep <pv-name>

6. Common Mistakes

7. Prevention Tips

8. FAQ

The pod has been in ContainerCreating for 10 minutes. Is the volume attached?

Check kubectl describe pod — if you see "Waiting for Kubernetes API" or the event shows "AttachVolume.Attach succeeded" followed by nothing, the issue is in the mount phase (not attach). If there's no attach event, the volume hasn't attached yet. For AWS EBS, check the EC2 console to see if the volume is actually attached to the node's instance.

Multi-attach error appears but the old pod is deleted. Why is it still happening?

The VolumeAttachment object persists independently of the pod. Delete it: kubectl get volumeattachments to find the attachment name, then kubectl delete volumeattachment <name>. AWS also maintains its own attachment state — if the instance is unresponsive, the volume may stay "in-use" until AWS force-detaches it (up to 6 minutes).

9. Summary

Error messageCauseFix
Multi-Attach errorVolume attached to old nodeForce-delete old pod; delete VolumeAttachment
Zone mismatchVolume in different AZ than podUse WaitForFirstConsumer StorageClass
CSI driver errorDriver not installed or crashingCheck CSI DaemonSet pods; update driver
NFS mount failedServer unreachable or export issueCheck network, NFS packages, export permissions
PVC still PendingVolume not provisioned yetSee Fix Kubernetes PVC Pending guide

Explore More in This Category

Explore more in this category: Kubernetes guides. Browse all DevOps Compass articles or jump to: Kubernetes, AWS, CI/CD, Containers, Monitoring, Networking.