KubernetesLIII · Storage Failure ModesStorage failure modes
Volume expansion failures — when growing a PVC does not work
What you'll learn
- Diagnose volume expansion failures
- Identify the causes: StorageClass setting, CSI driver, filesystem, quota
- Apply the production fixes for each cause
- Validate expansion before declaring it complete
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
Volume expansion is the operation of growing a PVC’s capacity. The operation has multiple stages; each can fail independently. This lesson walks the failure modes and the diagnostic patterns.
The expansion lifecycle
sequenceDiagram
participant U as User
participant API as API server
participant CSI as CSI controller
participant K as kubelet
U->>API: edit PVC: requests.storage 100Gi -> 200Gi
API->>CSI: ControllerExpandVolume (volumeHandle, newSize)
CSI-->>API: volume expanded
API->>K: NodeExpandVolume (volumePath, newSize)
K->>K: resize filesystem (resize2fs / xfs_growfs)
K-->>API: filesystem resized
API-->>U: PVC status: capacity 200Gi
The stages:
- API server: accepts the edit (if
allowVolumeExpansion: trueon the StorageClass). - CSI controller: calls
ControllerExpandVolumeto grow the underlying volume. - kubelet: calls
NodeExpandVolumeto resize the filesystem.
Each stage has its own failure modes.
Cause 1: StorageClass does not allow expansion
The most common cause:
# StorageClass without allowVolumeExpansion
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: db-default
provisioner: ebs.csi.aws.com
parameters:
type: gp3
# allowVolumeExpansion: true <-- missing
The user edits the PVC:
kubectl edit pvc data
# Change spec.resources.requests.storage from 100Gi to 200Gi
The API server rejects the edit:
# The PVC's spec.resources.requests.storage is unchanged
kubectl get pvc data -o jsonpath='{.spec.resources.requests.storage}'
# 100Gi
The fix: set allowVolumeExpansion: true on the
StorageClass. Note that this change applies to new PVCs;
existing PVCs are unaffected. To grow an existing PVC on
a StorageClass without allowVolumeExpansion, you must
recreate the PVC (with a snapshot and restore).
Cause 2: CSI driver does not support expansion
The StorageClass allows expansion; the API server accepts the edit; the CSI driver returns an error:
kubectl describe pvc data
# Events:
# Warning VolumeResizeFailed ... rpc error: code = Unimplemented
# desc = controller expand not supported
The fix: update the CSI driver to a version that
supports ControllerExpandVolume. Or use a different
StorageClass with a driver that supports expansion.
Cause 3: backend quota exceeded
The CSI driver attempts to expand the underlying volume
(e.g., call ec2:ModifyVolume), but the backend’s
quota is exceeded:
kubectl describe pvc data
# Events:
# Warning VolumeResizeFailed ... exceeded quota: storage-gigabytes
The fix: reduce the PVC’s request, or request a quota increase from the cloud provider.
Cause 4: filesystem cannot resize online
The CSI controller succeeds; the kubelet attempts to resize the filesystem; the filesystem cannot be resized online:
kubectl describe pvc data
# Events:
# Warning VolumeResizeFailed ... fs resize failed: device busy
The causes:
- The filesystem is busy (a process is using it).
- The filesystem does not support online resize (some older filesystems).
- The kernel’s online resize module is not loaded.
The fix: stop the workload (offline expansion), or use a filesystem that supports online resize (ext4, xfs).
Cause 5: new size smaller than current
The user accidentally reduced the PVC’s capacity request:
kubectl edit pvc data
# Change spec.resources.requests.storage from 200Gi to 100Gi
The API server rejects the edit:
# The PVC's spec.resources.requests.storage is unchanged
kubectl get pvc data -o jsonpath='{.spec.resources.requests.storage}'
# 200Gi
The fix: ensure the new request is greater than the current size. Volume expansion cannot shrink.
The diagnostic ladder
flowchart TD
A[Expansion fails] --> B[kubectl describe pvc]
B --> C{Event message?}
C -->|allowVolumeExpansion| D[Fix StorageClass]
C -->|Unimplemented| E[Update CSI driver]
C -->|quota| F[Reduce or request quota]
C -->|fs resize| G[Stop workload or use online-resize fs]
C -->|smaller| H[Increase size]
The production fix
For each cause:
| Cause | Production fix |
|---|---|
| StorageClass missing allowVolumeExpansion | Update the StorageClass (applies to new PVCs) |
| CSI driver does not support expansion | Update the driver or use a different driver |
| Backend quota exceeded | Reduce request or request quota increase |
| Filesystem cannot resize online | Use offline expansion or a different filesystem |
| New size smaller | Increase the request |
Quiz
Knowledge check · 4 questions
Q1. A user tries to expand a PVC from 100 GB to 200 GB. The edit is accepted, but the events show `VolumeResizeFailed: rpc error: code = Unimplemented`. What is the fix?
Q2. Updating `allowVolumeExpansion: true` on a StorageClass applies to existing PVCs.
Q3. Your team's database PVC is at 95% capacity. The user tries to expand. The expansion fails with `fs resize failed`. Walk through the diagnostic.
PostgreSQL PVC at 95% capacity. User edits PVC from 100 GB to 200 GB. The CSI controller succeeds (volume expanded to 200 GB). The kubelet fails at filesystem resize with `fs resize failed`.
Q4. Explain why volume expansion is a one-way operation and what the production discipline is.
Passing score: 75%. Answers are checked in this browser.
Production discipline
allowVolumeExpansion: trueon production StorageClasses. Databases grow; the StorageClass must allow it.- Validate expansion on staging. A failed expansion can leave the workload in a degraded state.
- Snapshot before expansion. There is no rollback; the snapshot is the safety net.
- Verify the application sees the new capacity. Some applications cache the size; a refresh is required.
- Use a filesystem that supports online resize. ext4 and xfs do; older filesystems may not.