Persistent Volumes and Storage¶
Overview¶
Claim storage with a PVC against a StorageClass, mount it in a Pod, and explain PV vs PVC vs CSI.
PVC is the app’s request; PV is the provisioned volume; StorageClass selects a provisioner (CSI). Dynamic provisioning creates PVs automatically on most clouds and kind (local-path / rancher).
This is a core tutorial in Module 7 · Storage of the REBASH Academy Kubernetes for Cloud & DevOps Engineers series — written for Cloud, DevOps, Platform, and SRE engineers.
Prerequisites¶
Learning Objectives¶
By the end of this tutorial, you will be able to:
- Create PVC + Pod mount
- List StorageClasses
- Contrast access modes (RWO/RWX)
- Outline CSI role
Architecture¶
This topic’s control points and relationships are shown below.
Theory¶
What it is¶
Kubernetes storage separates what the app asks for from what the cluster provides. A PersistentVolumeClaim (PVC) is the app’s request (size, access mode). A PersistentVolume (PV) is the actual volume. A StorageClass names a provisioner — usually a CSI (Container Storage Interface) driver — so PVs can be created dynamically. Ephemeral Volumes (emptyDir, config/secret mounts) die with the Pod; PVCs outlive Pods when configured to.
Why it matters¶
Databases, queues, and ML artefacts need data that survives Pod restarts and reschedules. Cloud disks, NFS, and local path provisioners all plug in through the same PV/PVC model. Understanding access modes and reclaim policy prevents “volume already attached” and accidental data loss during delete.
How it works (mental model)¶
- Admin (or platform) installs CSI drivers and defines StorageClasses.
- User creates a PVC referencing a StorageClass (or the default).
- The provisioner creates a PV and binds it to the PVC.
- A Pod mounts the PVC; kubelet attaches/mounts via CSI.
- On Pod delete, the PVC/PV remain unless reclaim policy and delete workflows remove them.
StatefulSets often use volumeClaimTemplates so each ordinal gets its own PVC.
Key concepts / comparisons¶
| Object | Role |
|---|---|
| Volume (Pod field) | Mount into containers |
| PVC | Claim for durable storage |
| PV | Provisioned volume |
| StorageClass | Provisioner + parameters |
| CSI | Standard driver interface |
| Access mode | Meaning |
|---|---|
| ReadWriteOnce (RWO) | One node writer (typical disks) |
| ReadOnlyMany (ROX) | Many nodes read-only |
| ReadWriteMany (RWX) | Many nodes read-write (NFS-like) |
Common pitfalls¶
- Pending PVC because no default StorageClass or provisioner is broken.
- Scheduling Pods with RWO volumes onto different nodes after a move — attach conflicts.
- Deleting PVCs in production without backups; reclaim policy
Deletedestroys the backend. - Using emptyDir for data you thought was persistent.
- Assuming every cluster has RWX — many cloud disks are RWO only.
Hands-on Lab¶
Create a workspace for this tutorial.
Focus: Claim storage with a PersistentVolumeClaim using the default StorageClass
Step 1 – Create a PVC and mount it¶
kubectl create namespace rebash-lab
kubectl get storageclass
cat > pvc.yaml <<'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data
namespace: rebash-lab
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
name: writer
namespace: rebash-lab
spec:
containers:
- name: app
image: busybox:1.36
command: ["sh", "-c", "echo hello-storage > /data/msg.txt; sleep 3600"]
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: data
EOF
kubectl apply -f pvc.yaml
Step 2 – Wait for Bound and read the file¶
kubectl -n rebash-lab get pvc data -w &
WPID=$!; sleep 8; kill $WPID 2>/dev/null || true
kubectl -n rebash-lab get pvc,pv
kubectl -n rebash-lab wait --for=condition=Ready pod/writer --timeout=120s || kubectl -n rebash-lab describe pod writer
kubectl -n rebash-lab exec writer -- cat /data/msg.txt
Final step – Cleanup note¶
kubectl delete namespace rebash-lab --ignore-not-found
# Workspace kept for notes; remove with: rm -rf "$(pwd)" when finished
Validation¶
- Lab commands run under
~/rebash-k8s/module-07/ - You can explain each Theory section in your own words
- You used modern tooling where it applies to this topic
- You can describe one production failure mode for this topic
Code Walkthrough¶
Production practice for Persistent Volumes and Storage always combines:
- Inspect before you change (status, plan, logs, dry-run)
- Prefer reversible, documented changes (Git, IaC, drop-ins, version pins)
- Capture evidence (command output, pipeline logs) for handovers
- Prefer current tools and APIs over legacy shortcuts
- Least privilege — escalate credentials only when required
Keep runbooks short enough to follow under pressure. Automate checks; keep humans for judgement.
Security Considerations¶
- Treat credentials and tokens for kubernetes as privileged — never commit them
- Prefer short-lived auth (OIDC, roles, SSO) over long-lived keys
- Validate blast radius before apply/deploy/delete operations
- Restrict who can approve production changes
- Collect audit logs; limit who can read sensitive traces
Common Mistakes¶
Pending PVC because no default StorageClass or provisioner is broken.
Validate assumptions against the Theory section and official docs before changing production.
Scheduling Pods with RWO volumes onto different nodes after a move — attach conflicts.
Lab shortcuts (open security groups, admin roles, skip approvals) must not ship unchanged.
Changing production without a rollback path
Always know how to revert (previous artefact, prior release, state rollback, DNS failback).
Best Practices¶
- Encode Persistent Volumes and Storage changes as code and review them in pull requests
- Pin versions (images, modules, actions, provider plugins)
- Separate environments with clear promotion gates
- Alert on symptoms with runbooks attached
- Destroy lab resources; tag everything with owner and expiry where possible
Troubleshooting¶
| Symptom | Likely cause | Fix |
|---|---|---|
| Auth / permission denied | Wrong identity, policy, or scope | Check caller identity, roles, and least-privilege policies |
| Timeout / no route | Network, DNS, security group, or endpoint | Trace path, DNS, and allow-lists before retrying |
| Drift / unexpected plan | Manual change or wrong state/workspace | Reconcile desired vs actual; avoid click-ops on managed resources |
| Pipeline/job red | Flaky step, cache, or missing secret | Read failing step logs; bisect recent workflow/config changes |
| Cost spike | Idle load balancer, NAT, oversized compute | Inventory billable resources; stop/delete labs promptly |
Summary¶
Persistent Volumes and Storage is essential for Cloud and DevOps engineers working with kubernetes. Practise the lab until the inspection and change path is muscle memory, then continue the track.
Interview Questions¶
- What is the relationship between PersistentVolume, PersistentVolumeClaim, and StorageClass?
- What does the Bound phase on a PVC mean?
- What is the difference between ReadWriteOnce and ReadWriteMany?
- What data-loss risks exist when deleting PVCs, and how do reclaim policies affect them?
- Why are StatefulSets often paired with volumeClaimTemplates?
Sample answer — question 2
Bound means a PV has been allocated to the claim and is ready to mount. Until Bound, Pods needing the volume may stay Pending.
Sample answer — question 4
Deleting a PVC can delete underlying storage depending on reclaim policy (Delete vs Retain). Snapshot and backup strategies matter before destructive cleanup in production.