PersistentVolumes & StorageClasses
Understand the Kubernetes storage layer: PVs, PVCs, and dynamic provisioning.
Time: ~10 minutes Difficulty: Intermediate
What You Will Learn
Section titled “What You Will Learn”- PersistentVolume (PV): a piece of storage in the cluster
- PersistentVolumeClaim (PVC): a request for storage by a pod
- StorageClass: dynamic provisioning without pre-creating PVs
- Access modes: ReadWriteOnce, ReadOnlyMany, ReadWriteMany
- Reclaim policies: Retain vs Delete
- Data persistence across pod restarts
Deploy
Section titled “Deploy”Check available StorageClasses
Section titled “Check available StorageClasses”kubectl get storageclassesMinikube provides a standard StorageClass backed by hostPath.
Static provisioning (manual PV)
Section titled “Static provisioning (manual PV)”Navigate to the demo directory:
cd demos/persistent-volumeskubectl apply -f manifests/namespace.yamlkubectl apply -f manifests/static-pv.yamlCheck the PV and PVC:
kubectl get pvkubectl get pvc -n storage-demoThe PVC should be Bound to the PV.
Dynamic provisioning (automatic PV)
Section titled “Dynamic provisioning (automatic PV)”kubectl apply -f manifests/dynamic-pvc.yamlkubectl get pvc -n storage-demokubectl get pvA new PV is automatically created by the standard StorageClass and bound to the PVC.
Use the Storage
Section titled “Use the Storage”Write data
Section titled “Write data”kubectl apply -f manifests/writer-pod.yamlkubectl logs writer -n storage-demo -fThe writer appends a log entry every 5 seconds to /data/log.txt on the PVC.
Delete the writer and verify data persists
Section titled “Delete the writer and verify data persists”kubectl delete pod writer -n storage-demo
# Data is still on the PVCkubectl run verify --rm -it --image=busybox:1.36 -n storage-demo \ --overrides='{"spec":{"volumes":[{"name":"d","persistentVolumeClaim":{"claimName":"dynamic-pvc"}}],"containers":[{"name":"v","image":"busybox:1.36","command":["cat","/data/log.txt"],"volumeMounts":[{"name":"d","mountPath":"/data"}]}]}}'The data survives pod deletion because it lives on the PVC, not in the container.
Read data with the reader pod
Section titled “Read data with the reader pod”kubectl apply -f manifests/reader-pod.yamlkubectl logs reader -n storage-demoWhat is Happening
Section titled “What is Happening”manifests/ namespace.yaml # storage-demo namespace static-pv.yaml # Manual PV (hostPath) + PVC with label selector dynamic-pvc.yaml # PVC using standard StorageClass (PV auto-created) writer-pod.yaml # Writes to dynamic-pvc reader-pod.yaml # Reads from manual-pvcStorage hierarchy:
StorageClass (how to provision) | vPersistentVolume (a piece of storage) | v (bound)PersistentVolumeClaim (a request for storage) | v (mounted)PodAccess modes:
| Mode | Short | Description |
|---|---|---|
| ReadWriteOnce | RWO | One node can mount read-write |
| ReadOnlyMany | ROX | Many nodes can mount read-only |
| ReadWriteMany | RWX | Many nodes can mount read-write |
Reclaim policies:
| Policy | What Happens When PVC Is Deleted |
|---|---|
| Retain | PV keeps data, admin must clean up manually |
| Delete | PV and underlying storage are deleted |
| Recycle | Deprecated. Was rm -rf /volume/* |
Experiment
Section titled “Experiment”-
Check what backing storage the dynamic PV uses:
Terminal window kubectl get pv -o widekubectl describe pv <pv-name> -
Delete the PVC and check the PV reclaim behavior:
Terminal window kubectl delete pvc dynamic-pvc -n storage-demokubectl get pvDynamic PVs with
Deletepolicy are removed. Static PVs withRetainstay. -
List StorageClass details:
Terminal window kubectl describe storageclass standard
Cleanup
Section titled “Cleanup”kubectl delete namespace storage-demokubectl delete pv manual-pv --ignore-not-foundFurther Reading
Section titled “Further Reading”See docs/deep-dive.md for a detailed explanation of CSI drivers, volume snapshots, volume expansion, topology-aware provisioning, and production storage patterns.
Next Step
Section titled “Next Step”Move on to Vault to learn production secret management with HashiCorp Vault.