Troubleshooting Kubernetes Persistent Volume Claim (PVC) Stuck in Pending Status on Alpine Linux
Resolve Kubernetes PVCs stuck in pending on Alpine Linux nodes. Covers StorageClass, CSI driver, and configuration issues, providing step-by-step solutions for robust storage.
Resolve Kubernetes PVCs stuck in pending on Alpine Linux nodes. Covers StorageClass, CSI driver, and configuration issues, providing step-by-step solutions for robust storage.
A Kubernetes Persistent Volume Claim (PVC) stuck in Pending status is a common and often frustrating issue for DevOps engineers and system administrators managing containerized applications. This problem indicates that Kubernetes cannot find or provision a suitable Persistent Volume (PV) to fulfill the storage request made by your application. When this occurs on Alpine Linux worker nodes, it can introduce specific challenges due to Alpine's minimalist design and differences in package management and system initialization compared to more common distributions like Ubuntu or CentOS. This guide provides a comprehensive, highly technical approach to diagnosing and resolving PVCs stuck in Pending on Alpine Linux-based Kubernetes clusters.
Symptom & Error Signature
When a Persistent Volume Claim (PVC) is stuck in Pending, your associated Pods will typically remain in a Pending state as well, unable to start because their required storage is unavailable. You'll observe this symptom through kubectl commands:
PVC Status:
kubectl get pvc -n my-app-namespaceNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE my-data-pvc Pending standard 5mPod Status:
kubectl get pod -n my-app-namespaceNAME READY STATUS RESTARTS AGE my-app-deployment-xxxx-yyyy 0/1 Pending 0 5mThe pod's description will often show a warning about not being able to mount the volume:
kubectl describe pod my-app-deployment-xxxx-yyyy -n my-app-namespace... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 5m default-scheduler 0/3 nodes are available: 3 persistentvolumeclaims "my-data-pvc" not found.(Note: The
persistentvolumeclaims "my-data-pvc" not foundmessage in the pod events indicates the scheduler couldn't even bind the PVC, let alone mount it. The more common PVC pending message is below.)Detailed PVC Events (Crucial for Diagnosis): The most critical information comes from describing the PVC itself, specifically the
Eventssection:kubectl describe pvc my-data-pvc -n my-app-namespaceName: my-data-pvc Namespace: my-app-namespace StorageClass: standard Status: Pending Volume: Labels: <none> Annotations: volume.beta.kubernetes.io/storage-provisioner: example.com/csi-driver Finalizers: [kubernetes.io/pvc-protection] Capacity: Access Modes: VolumeMode: Filesystem Mounted By: <none> Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning ProvisioningFailed 20s (x3 over 1m) standard-provisioner failed to provision volume with StorageClass "standard": rpc error: code = Internal desc = volume creation failed: could not connect to storage backend Normal ExternalProvisioning 20s (x3 over 1m) persistentvolume-controller waiting for a volume to be created, either by an external provisioner or manually created by an administrator.Or, for static provisioning:
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal WaitForFirstConsumer 20s persistentvolume-controller waiting for first consumer to be created before binding Normal FailedBinding 10s persistentvolume-controller no persistent volumes available for this claim and no storage class is set
Root Cause Analysis
A PVC gets stuck in Pending when the Kubernetes control plane cannot find or provision a suitable Persistent Volume (PV) to bind to the PVC. This can stem from several underlying issues, often amplified or nuanced when using Alpine Linux for worker nodes:
Missing or Misconfigured StorageClass:
- No Default StorageClass: If the PVC doesn't specify a
storageClassNameand no default StorageClass is defined cluster-wide, dynamic provisioning cannot occur. - Non-existent StorageClass: The
storageClassNamespecified in the PVC does not exist. - Misconfigured StorageClass: The specified StorageClass is pointing to a non-existent or improperly configured CSI (Container Storage Interface) driver, or its parameters (e.g.,
provisioner,parameters) are incorrect.
- No Default StorageClass: If the PVC doesn't specify a
No Available Persistent Volume (PV) for Static Provisioning:
- If the PVC is meant to bind to a pre-created (statically provisioned) PV, there might be no PV with matching criteria (e.g.,
storageClassName,capacity,accessModes,labels,nodeSelector). - All suitable PVs might already be bound to other PVCs.
- If the PVC is meant to bind to a pre-created (statically provisioned) PV, there might be no PV with matching criteria (e.g.,
CSI Driver Issues:
- Driver Not Installed or Healthy: The CSI driver (e.g., NFS CSI, iSCSI CSI, Ceph CSI) responsible for dynamic provisioning is not deployed, or its pods (provisioner, attacher, node driver) are not running correctly or are in an unhealthy state (e.g.,
CrashLoopBackOff,Pending). - Underlying Storage Connectivity/Configuration: This is where Alpine Linux characteristics become critical.
- Missing Host Utilities/Kernel Modules on Alpine Nodes: The CSI node driver or the Kubelet itself requires specific host utilities or kernel modules to mount the volume (e.g.,
nfs-utilsfor NFS,open-iscsifor iSCSI,xfsprogsfor XFS filesystems). Alpine's minimal install often lacks these by default. - Network/Firewall Issues: Alpine worker nodes cannot reach the external storage array or server due to network segmentation, firewall rules, or DNS resolution problems.
- Incorrect CSI Driver Configuration: The CSI driver itself has incorrect credentials, IP addresses, paths, or other parameters needed to interact with the external storage system.
- Missing Host Utilities/Kernel Modules on Alpine Nodes: The CSI node driver or the Kubelet itself requires specific host utilities or kernel modules to mount the volume (e.g.,
- Driver Not Installed or Healthy: The CSI driver (e.g., NFS CSI, iSCSI CSI, Ceph CSI) responsible for dynamic provisioning is not deployed, or its pods (provisioner, attacher, node driver) are not running correctly or are in an unhealthy state (e.g.,
Access Mode Mismatch: The PVC requests
accessModes(e.g.,ReadWriteOnce,ReadWriteMany,ReadOnlyMany) that are incompatible with what the available PVs offer or what the StorageClass's provisioner can support for the underlying storage.Insufficient Capacity: There are no available PVs, or the StorageClass provisioner cannot allocate enough storage to meet the PVC's
requests.storagespecification.RBAC Permissions: While less common for the
Pendingstatus itself (more for failing provisioners), the CSI provisioner's ServiceAccount might lack the necessary Kubernetes RBAC permissions to create PersistentVolume objects or interact with the storage API.
Step-by-Step Resolution
This section outlines a methodical approach to troubleshoot and resolve PVCs stuck in Pending status, with specific considerations for Alpine Linux worker nodes.
1. Inspect the PVC and Related Events
Start by gathering detailed information about the problematic PVC and any associated Pods. The Events section of the PVC description is your primary diagnostic tool.
Get PVC Details:
kubectl describe pvc my-data-pvc -n my-app-namespaceCarefully examine the
Status,Volume,StorageClass, and especially theEventssection.- If
EventsshowFailedBindingorno persistent volumes available for this claim, it points to an issue with static provisioning or a missing StorageClass. - If
EventsshowProvisioningFailed(e.g.,failed to provision volume with StorageClass "standard": rpc error: code = Internal desc = volume creation failed), it indicates a problem with dynamic provisioning via the CSI driver. The error message here is crucial.
- If
Check Related Pods (if any):
kubectl describe pod my-app-deployment-xxxx-yyyy -n my-app-namespaceLook for scheduling errors related to the PVC.
2. Verify StorageClass Configuration
If your cluster relies on dynamic provisioning (which is almost always recommended), ensure your StorageClass is correctly defined and operational.
Check PVC's StorageClass: Note the
StorageClassname fromkubectl describe pvc my-data-pvc. If it's empty, and no default StorageClass is defined, this is a major clue.List All StorageClasses:
kubectl get scNAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE standard (default) example.com/csi-driver Delete Immediate true 2d fast-ssd another.com/fast-csi Retain WaitForFirstConsumer false 1wEnsure the StorageClass referenced by your PVC exists. If your PVC did not specify a
storageClassName, verify that a default StorageClass (marked with(default)) exists and is functional.Inspect StorageClass Details:
kubectl describe sc standardName: standard IsDefaultClass: Yes Annotations: storageclass.kubernetes.io/is-default-class=true Provisioner: example.com/csi-driver Parameters: <none> MountOptions: <none> AllowVolumeExpansion: True ReclaimPolicy: Delete VolumeBindingMode: Immediate Events: <none>Verify the
Provisionerfield matches the actual CSI driver deployed in your cluster. If theProvisioneris incorrect or theParametersare misconfigured for your storage backend, the PVC will remain pending.If you don't have a StorageClass or if the
Provisioneris unknown, you need to deploy a CSI driver for your chosen storage backend (e.g., NFS CSI, iSCSI CSI, local-path provisioner, cloud provider CSI). Refer to your storage vendor's documentation for Kubernetes CSI deployment.
3. Troubleshoot CSI Driver (Dynamic Provisioning)
If a StorageClass is correctly defined but PVCs are still pending with ProvisioningFailed errors, the issue likely lies within the CSI driver.
Identify CSI Driver Pods: Typically, CSI driver components run as Pods, often in the
kube-systemnamespace or a dedicated namespace (e.g.,csi-nfs-driver).kubectl get pod -n kube-system -l app=csi-nfs-controller # Example for NFS CSI kubectl get pod -n csi-driver-namespaceLook for pods with names like
csi-provisioner,csi-attacher,csi-node, or specific driver names. Ensure all relevant pods areRunningandREADY.Examine CSI Driver Pod Logs: The logs of the CSI provisioner pod are crucial for understanding why volume creation failed.
kubectl logs csi-nfs-controller-provisioner-xxxx -n csi-driver-namespace kubectl describe pod csi-nfs-controller-provisioner-xxxx -n csi-driver-namespaceLook for errors related to API calls, network connectivity to the storage backend, authentication failures, or capacity issues.
Alpine Node Specific Checks for CSI Connectivity: If the CSI driver logs indicate issues connecting to the storage backend or mounting volumes, you'll need to investigate the Alpine worker nodes directly.
Making direct changes to worker nodes, especially installing packages, can be ephemeral in dynamically scaled clusters or overwritten during node upgrades. For production, consider using custom Alpine images that include necessary tools or ensuring your CSI driver pods include these tools.
SSH to an Alpine Worker Node: Identify a worker node where the problematic pod might schedule or where the CSI node driver is running.
ssh root@<alpine-worker-node-ip>Check for NFS Utilities (if using NFS CSI): Alpine uses
apkfor package management.apk info nfs-utilsIf not installed, install it:
apk add nfs-utilsTest connectivity to your NFS server:
showmount -e <nfs-server-ip> # Attempt a manual mount to confirm mkdir -p /mnt/test-nfs mount -t nfs <nfs-server-ip>:/<path/to/share> /mnt/test-nfs df -h /mnt/test-nfs umount /mnt/test-nfsFirewall on Alpine: Alpine uses
iptablesornftables. Ensure no rules are blocking NFS ports (2049, 111).iptables -L -n | grep -E "2049|111" # Basic checkCheck for iSCSI Utilities (if using iSCSI CSI):
apk info open-iscsiIf not installed, install it:
apk add open-iscsiEnsure the iSCSI daemon is running and enabled on boot:
rc-service iscsid status rc-service iscsid start rc-update add iscsid default # Add to default runlevel for persistenceCheck iSCSI initiator name and discover targets:
cat /etc/iscsi/initiatorname.iscsi iscsiadm -m discovery -t st -p <iscsi-target-ip>Firewall on Alpine: Check for blocks on iSCSI port 3260.
Other CSI Drivers: Consult the specific CSI driver documentation for any host-level requirements on Alpine Linux and adapt the
apkcommands accordingly. Missing system dependencies are a very common cause on Alpine.
4. Review Persistent Volume (PV) Availability (Static Provisioning)
If you are using static provisioning (i.e., you manually create PVs) or if dynamic provisioning is failing, check for available PVs.
List All PVs:
kubectl get pvNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE my-manual-pv 10Gi RWO Retain Available 2h bound-pv-1 5Gi RWO Delete Bound my-app-namespace/other-pvc standard 1dDescribe PVs to find a match:
kubectl describe pv my-manual-pvLook for an
AvailablePV that matches the PVC's requirements:- Capacity: Must be greater than or equal to the PVC's requested storage.
- Access Modes: Must be compatible (e.g.,
RWOforReadWriteOnce,RWXforReadWriteMany). storageClassName: If the PVC specifies one, the PV must either have the samestorageClassNameor both PVC and PV omit it for a default binding.- Labels/NodeSelector: If the PVC has specific
selectorornodeSelectorrequirements (less common for basic PVCs), the PV must satisfy them.
Create or Adjust PV: If no suitable PV is
Available, you may need to:- Create a new PV that matches the PVC's criteria.
- Adjust an existing
AvailablePV's configuration to match.
Example of a static NFS PV manifest:
apiVersion: v1 kind: PersistentVolume metadata: name: my-nfs-pv spec: capacity: storage: 10Gi accessModes: - ReadWriteMany # Or ReadWriteOnce, ReadOnlyMany persistentVolumeReclaimPolicy: Retain storageClassName: "" # Important: set to empty string or remove if PVC also omits storageClassName nfs: path: /exports/my-data server: 192.168.1.100 mountOptions: - hard - nfsvers=4.1
5. Check Access Mode Compatibility
Ensure the accessModes requested by your PVC are supported by the underlying storage and match the available PVs or what the CSI driver can provision.
Review PVC Access Modes:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-data-pvc spec: accessModes: - ReadWriteOnce # Could be ReadWriteMany, ReadOnlyMany resources: requests: storage: 10Gi storageClassName: standardIf your application requires multiple pods on different nodes to write to the same volume, you must use
ReadWriteMany. If you're usingReadWriteOncebut the underlying storage only offersReadWriteMany, it generally won't bind. The reverse (requestingReadWriteManywhen onlyReadWriteOnceis available) will definitely prevent binding.Not all storage backends support all access modes. For instance,
hostPathPVs are typicallyReadWriteOnce(limited to the node they are on), while many distributed file systems (NFS, CephFS) supportReadWriteMany. Block storage (iSCSI, cloud disks) typically only supportsReadWriteOncefor a single attachment.
6. Examine for RBAC Permissions Issues
If CSI driver logs show Permission Denied or similar errors related to Kubernetes API access, check the RBAC setup for the CSI driver's ServiceAccount.
- Identify CSI Provisioner ServiceAccount:
Look at the CSI provisioner pod's YAML to determine its
serviceAccountName.kubectl get pod csi-nfs-controller-provisioner-xxxx -n csi-driver-namespace -o yaml | grep serviceAccountName - Inspect Roles/ClusterRoles and Bindings:
Check the
RoleorClusterRoleand correspondingRoleBindingorClusterRoleBindingfor that ServiceAccount. Ensure it has permissions toget,list,watch,create,update,patch,deletepersistentvolumesandstorageclasses, and potentially other resources depending on the driver.
This setup is usually part of the CSI driver's deployment manifest, so verify it matches the vendor's recommendations.kubectl get clusterrole # List cluster roles kubectl get clusterrolebinding # List cluster role bindings
7. Clean Up and Reapply
After making configuration changes to StorageClasses, PVs, or CSI drivers, it's often necessary to clean up and reapply your PVC and potentially your Pods.
Delete the PVC:
kubectl delete pvc my-data-pvc -n my-app-namespaceWait until the PVC is fully deleted (
kubectl get pvcshould no longer list it).Reapply the PVC:
kubectl apply -f my-pvc.yaml -n my-app-namespaceMonitor its status:
kubectl get pvc my-data-pvc -n my-app-namespace kubectl describe pvc my-data-pvc -n my-app-namespaceDelete and Recreate Dependent Pods/Deployments: If the PVC was previously referenced by a Pod or Deployment, you will likely need to delete and recreate them to pick up the newly bound volume.
kubectl delete deploy my-app-deployment -n my-app-namespace kubectl apply -f my-app-deployment.yaml -n my-app-namespace
8. Advanced: Debugging Node-Specific Mount Failures
Even if a PVC successfully binds to a PV, the pod might still fail to start if the worker node (Alpine in this case) cannot actually mount the volume. This would manifest as the PVC being Bound but the Pod remaining Pending or entering CrashLoopBackOff with mount errors.
Identify Pod's Node:
kubectl get pod my-app-deployment-xxxx-yyyy -n my-app-namespace -o wideNote the
NODEwhere the pod is scheduled.SSH to the Alpine Worker Node:
ssh root@<alpine-worker-node-ip>Check Kernel Messages:
dmesg | tail -n 50Look for errors related to
NFS,iSCSI,XFS,ext4, or generic mount failures.Check System Logs (OpenRC): Alpine typically uses OpenRC. Relevant logs might be found in
/var/log/messagesor accessed viajournalctlif configured.grep -i "mount" /var/log/messagesOr, if
rsyslogis installed:rc-service rsyslog statusVerify Volume Mounts: Check if the volume is listed as mounted on the node by the
kubeletor CSI node driver.mount | grep <volume-identifier> # e.g., grep /var/lib/kubelet/pods/<pod-uid>/volumes
By systematically working through these steps, from PVC inspection to Alpine node-specific checks and CSI driver diagnostics, you can effectively pinpoint and resolve Kubernetes Persistent Volume Claims stuck in Pending status.
Our Production Verification Guarantee
Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.