LearnKubernetes
Kubernetes8. Storage·ADVANCED·5 min read

Advanced Storage Classes

Advanced Storage Classes: Provisioning Models and Binding Behavior

TL;DR

  • Static provisioning: admin manually creates PVs; PVC binds to pre-existing PV (for existing storage, no CSI).
  • Dynamic provisioning: StorageClass auto-creates PV via CSI on PVC creation (responsive, no pre-work).
  • Released PVs: Retain policy keeps PV alive after PVC deletion; claimRef must be manually cleared for reuse (safety against accidental data bind).
  • allowVolumeExpansion: allows PVC size growth; filesystem may need separate resize (resize2fs).
  • volumeBindingMode: Immediate (risky for zone storage) vs WaitForFirstConsumer (safe, defers provisioning until pod scheduled).

Core Concepts

Static vs Dynamic Provisioning

Static: Admin creates PV manually, PVC binds to it. For pre-existing storage or systems without CSI.

Dynamic: StorageClass auto-creates PV on PVC creation. Modern, responsive, standard expectation.

Configuration & Command Reference

Clear claimRef on Released PV for reuse:

kubectl patch pv <pv-name> --type json -p '[{"op": "remove", "path": "/spec/claimRef"}]'

Common Pitfalls

  • Pitfall: Released PV won’t rebind to new PVC. Why: claimRef safety mechanism. Fix: clear claimRef.
  • Pitfall: PVC expanded but filesystem still reports old size. Why: filesystem needs independent resize. Fix: resize2fs on ext4.

Interview Questions

  • Why doesn’t a Released PV automatically rebind to a new PVC? — Tests understanding of data safety.

Static provisioning: an administrator manually creates PV objects ahead of time, describing storage that already exists (an NFS export, a pre-created cloud disk). PVCs then bind to a matching pre-existing PV.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv-manual
spec:
  capacity:
    storage: 100Gi
  accessModes: ["ReadWriteMany"]
  nfs:
    server: nfs.internal.company.com
    path: /exports/shared-data
  persistentVolumeReclaimPolicy: Retain

Dynamic provisioning: a StorageClass with a provisioner (CSI driver) creates both the underlying storage and the PV object automatically, the moment a matching PVC is created — no administrator pre-work needed. This is the default expectation on any modern cloud-managed cluster.

Static provisioning remains necessary for storage systems with no CSI driver, or for pre-existing data you need pods to attach to (migrating an existing NFS share into Kubernetes, for example).


2. Reclaim Policies in Depth

  • Delete — PV and underlying storage are deleted when the PVC is released. Default for most dynamically-provisioned classes.
  • Retain — PV persists in a Released state (not Available) after PVC deletion; the underlying storage and its data are untouched, but the PV must be manually edited (clear claimRef) or deleted+recreated before it can be reused by a new PVC.
  • Recycle — deprecated; performed a basic rm -rf scrub before making the volume Available again. Removed in current Kubernetes versions in favor of dynamic provisioning entirely replacing this use case.
# Reclaim a manually Released PV for reuse
kubectl patch pv nfs-pv-manual --type=json -p '[{"op": "remove", "path": "/spec/claimRef"}]'

3. Volume Binding Modes Revisited

  • Immediate — PV provisioned as soon as PVC is created, before any pod references it. Risky for zone-aware storage (see the classic multi-zone scheduling deadlock).
  • WaitForFirstConsumer — provisioning deferred until a pod actually claims the PVC, guaranteeing the storage lands in the same zone/node topology as the pod that will use it. The clear default choice for any topology-aware backend (EBS, GCE PD, Azure Disk).

4. Volume Expansion

allowVolumeExpansion: true

With this set on the StorageClass, existing PVCs can be resized larger (never smaller) by simply patching spec.resources.requests.storage — the CSI driver handles the underlying resize, and for many (not all) CSI drivers/filesystems, the pod doesn’t even need to restart (FileSystemResizePending condition clears automatically once the filesystem itself is grown, sometimes requiring the pod to at least be running for the final filesystem-level resize step).


5. Hands-on Command Cheat Sheet

Check a StorageClass’s full configuration including reclaim policy and binding mode:

kubectl get storageclass fast-ssd -o yaml

Find which StorageClass is marked as cluster default:

kubectl get sc -o jsonpath='{range .items[?(@.metadata.annotations.storageclass\.kubernetes\.io/is-default-class=="true")]}{.metadata.name}{"\n"}{end}'

Check current PV/PVC binding and phase (Bound/Available/Released):

kubectl get pv,pvc

Watch a volume expansion resize progress:

kubectl get pvc db-data -w
kubectl describe pvc db-data | grep -A3 Conditions

6. Architectural Interview Q&A

Q: A PV shows Released status after its PVC was deleted, but a new PVC that should logically reuse it stays Pending. Why doesn’t Kubernetes automatically rebind it? A: A Released PV still carries the previous claimRef referencing the now-deleted PVC by UID, and Kubernetes deliberately does not automatically clear this or rebind the PV to a different claim — this is a safety mechanism preventing a new, possibly unrelated workload from silently inheriting another application’s data without explicit administrator intent. You must manually clear spec.claimRef (or delete and recreate the PV) before it becomes genuinely Available for a new PVC to bind to.

Q: Why is allowVolumeExpansion alone sometimes not enough to actually see more usable space inside a running pod? A: Volume expansion at the Kubernetes/CSI level resizes the underlying block device or cloud volume, but the filesystem on top of it (ext4, xfs) still needs its own resize operation to actually recognize and use the additional space — for most CSI drivers this filesystem-level resize is triggered automatically as part of the NodeExpandVolume CSI call, but it typically requires the volume to be actively mounted by a running pod for that final step to execute, meaning a completely stopped/unmounted PVC’s expansion can appear to “hang” at the block-device level until a pod actually mounts it again.


7. Common Pitfalls

[!WARNING] Immediate Binding Mode on Zone-Aware Storage Using volumeBindingMode: Immediate (rather than WaitForFirstConsumer) with zone-scoped block storage backends is one of the most common sources of mysterious, hard-to-diagnose “pod stuck Pending forever” incidents — the PV/disk gets provisioned in an essentially random zone before the scheduler has any say, and if the pod’s other constraints later force it into a different zone, the volume can never attach there. Always default to WaitForFirstConsumer for any StorageClass backed by zone-scoped storage unless you have a specific, deliberate reason not to.

🔒 Locked
Sign in and unlock the full syllabus to keep reading.
Sign in to continue
Knowledge check
5 scenario questions on this topic
Take the quiz →
Related in 8. Storage
Kubernetes Persistent Storage
EXPERT