Module 7: Kubernetes Storage – Volumes & Persistent Volumes

We worked with Deployments, Services, ConfigMaps, and Secrets. But what happens when your pods need to store and persist data?
By default, when a pod is deleted or restarted, all data inside it is lost. That’s fine for stateless applications (like a simple frontend), but not acceptable for stateful apps (like databases).
That’s where Kubernetes Storage comes into play.
🔑 Why Storage Matters in Kubernetes
Pods are ephemeral → when they die, their filesystem goes too.
Databases & stateful workloads require data to survive restarts.
Kubernetes provides multiple ways to attach storage volumes to pods.
📂 Understanding Kubernetes Volumes
A Volume is a directory accessible to containers in a pod. Unlike container filesystems, volumes outlive the container’s lifecycle (but not always the pod’s).
Common Volume Types
emptyDir
Created when a pod starts, deleted when the pod stops.
Useful for temporary storage (e.g., scratch space).
hostPath
Mounts a directory from the node’s filesystem into a pod.
Useful for accessing node-local files, but not portable.
configMap / secret volumes
Mounts a ConfigMap or Secret into the container as a file.
Great for injecting configuration or credentials.
🗂 Persistent Volumes (PV) and Persistent Volume Claims (PVC)
While volumes like emptyDir
are tied to the pod lifecycle, Persistent Volumes allow data persistence even if the pod is deleted.
Persistent Volume (PV)
A cluster-wide storage resource.
Created by an administrator (e.g., backed by NFS, EBS, GCE disk).
Managed independently from pods.
Persistent Volume Claim (PVC)
A request for storage by a pod.
Users don’t care about the underlying storage; they just request size, access mode, etc.
PVC binds to a matching PV.
⚙️ Storage Classes & Dynamic Provisioning
Without StorageClasses, admins must manually create PVs.
StorageClass automates PV creation using a provisioner (e.g., AWS EBS, GCP Persistent Disk, Ceph, etc.).
Dynamic provisioning = PVC automatically gets a new PV.
🖥 Example: PV + PVC + Pod
1️⃣ Create a Persistent Volume (PV)
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
2️⃣ Create a Persistent Volume Claim (PVC)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Mi
Once you create the PV and PVC YAMLs, you can manage them with CLI commands:
List all Persistent Volumes
kubectl get pv
Output example:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS AGE
my-pv 1Gi RWO Retain Bound default/my-pvc standard 5m
List all Persistent Volume Claims
kubectl get pvc
Output example:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
my-pvc Bound my-pv 1Gi RWO standard 5m
Describe a Persistent Volume
kubectl describe pv my-pv
You’ll see:
Capacity (how much storage)
Access Modes (RWO, ROX, RWX)
Reclaim Policy (Retain, Delete, Recycle)
Status (Available/Bound/Released/Failed)
Which PVC it’s bound to
Describe a Persistent Volume Claim
kubectl describe pvc my-pvc
You’ll see:
Requested storage size
Bound PV name
Access Modes
Events (helpful for troubleshooting)
⚙️ Access Modes Explained
ReadWriteOnce (RWO) → only one node can mount the volume for read/write.
ReadOnlyMany (ROX) → multiple nodes can read the volume.
ReadWriteMany (RWX) → multiple nodes can read/write at the same time.
🧹 Reclaim Policies
When a PVC is deleted, the PV follows a reclaim policy:
Retain → data is preserved, admin must manually clean up.
Delete → data and volume are deleted automatically.
Recycle (deprecated) → basic scrub and make PV available again.
3️⃣ Attach PVC to a Pod
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: app
image: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: storage
volumes:
- name: storage
persistentVolumeClaim:
claimName: my-pvc
✅ Here, the pod uses the PVC, which in turn binds to the PV, ensuring persistent storage.
🚀 Hands-On Demo Ideas
Create PV + PVC + Pod, then run:
kubectl exec -it my-pod -- sh echo "Hello from PV" > /usr/share/nginx/html/index.html
Delete and recreate the pod → check the file is still there.
Run
kubectl get pv,pvc
to watch the binding.Try changing reclaim policy and see what happens when you delete the PVC.
🏁 Conclusion
Kubernetes storage bridges the gap between stateless containers and stateful applications. With Volumes, Persistent Volumes, PVCs, and StorageClasses, Kubernetes allows workloads to store and persist data reliably.
Subscribe to my newsletter
Read articles from DevOpsLaunchpad directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
