How data actually persists in a cluster that's designed to treat everything as disposable — provisioning models, the CSI plugin architecture, running stateful workloads correctly, and backing all of it up before you need to.
Five layers sit between "a pod wants a disk" and "a disk is actually attached." Understand them top to bottom before you touch a StatefulSet in production.
🔴 PV / PVC
PersistentVolume
PersistentVolumeClaim
Access Modes
Reclaim Policy
Binding Controller
🟠 StorageClass
Provisioner
Parameters
volumeBindingMode
allowVolumeExpansion
Default Class
🔵 CSI Driver
Controller Plugin
Node Plugin
external-provisioner
external-attacher
node-driver-registrar
🟢 StatefulSet
Stable Pod Identity
Headless Service
Ordered Deploy/Scale
volumeClaimTemplates
PVC Retention Policy
🟣 Backup / DR
VolumeSnapshotClass
VolumeSnapshot
Velero
Cross-Region Replication
RPO / RTO Targets
Deep-Dive
STORAGE REFERENCE
Click any layer to explore concepts, YAML, and production-tested guidance.
PERSISTENTVOLUME & PERSISTENTVOLUMECLAIM
The abstraction that decouples "where the disk lives" from "what pod uses it"
3 Concepts
📦
Static vs Dynamic Provisioning
A PV is a cluster resource representing actual storage. A PVC is a namespaced request for that storage. How the PV gets created is the whole story.
Must KnowProvisioning
Must Know▾
Static: admin pre-creates the PV
pv-static.yaml
apiVersion: v1
kind: PersistentVolume
metadata: {name: pv-billing-logs}
spec:
capacity: {storage: 50Gi}
accessModes: [ReadWriteOnce]
persistentVolumeReclaimPolicy: Retain
nfs: {server: 10.20.4.5, path: /export/billing}
Static Provisioning
🔵Admin creates the PV up front (NFS export, pre-carved LUN, existing disk)
🔵A matching PVC binds to it — no provisioner call involved
🟢Good for: NFS shares, pre-existing SAN LUNs, migration scenarios
Dynamic Provisioning
1
PVC references a storageClassName instead of an existing PV
2
The CSI external-provisioner sidecar watches for unbound PVCs
3
It calls the backend API (EBS, Ceph, etc.) and creates the PV automatically
4
This is the default in almost every production cluster today
🔐
Access Modes
Access modes describe how many nodes can mount the volume simultaneously — not a permissions system. Getting this wrong causes multi-attach errors.
ImportantBinding
Important▾
The Four Access Modes
Mode
Meaning
Typical Backend
RWO
ReadWriteOnce — one node, read-write
EBS, Azure Disk, GCE PD
ROX
ReadOnlyMany — many nodes, read-only
NFS, CephFS
RWX
ReadWriteMany — many nodes, read-write
NFS, CephFS, EFS, Azure Files
RWOP
ReadWriteOncePod — single pod (K8s 1.22+), stricter than RWO
CSI drivers supporting block-mode RWOP
Common Mistake
1
Requesting RWX on EBS/Azure Disk — these block-storage backends only support RWO. Use EFS/Azure Files/CephFS instead.
2
Scaling a Deployment with an RWO PVC beyond 1 replica → new pod stuck Pending with a multi-attach error since two nodes can't mount the same RWO volume.
♻️
Reclaim Policy & PVC Lifecycle
What happens to the underlying disk once the PVC is deleted — the single most consequential setting for data safety.
Data Safety
Recommended▾
Reclaim Policies
🔴Delete (default for dynamic): backend volume is destroyed when the PVC is deleted — irreversible
🔵Retain: PV becomes Released, data stays, needs manual admin cleanup/reclaim before reuse
🟢Recycle (deprecated): basic rm -rf scrub — don't use it
PVC Binding Lifecycle
1
PVC created → Pending
2
Matching PV found/provisioned → Bound
3
PVC deleted → PV becomes Released (Retain) or is destroyed (Delete)
4
Set persistentVolumeReclaimPolicy: Retain on anything holding data you can't regenerate
STORAGECLASSES & DYNAMIC PROVISIONING
The template that tells Kubernetes how to provision a volume on demand
3 Concepts
⚙️
Defining a StorageClass
A StorageClass names a provisioner and passes it backend-specific parameters. PVCs reference the class by name — that's the entire contract.