The Retained Volume
Someone deleted a database deployment by accident. The good news: the data is still on disk. In the next few minutes you'll reconnect it the way the CKA exam expects.
🎥 Watch the video: https://www.youtube.com/watch?v=0GvawTDSyiU
This is a CKA Storage walkthrough. Every command below is real output from a live cluster, and you can reproduce the whole thing yourself (scripts at the end).
The scenario
A MariaDB deployment in the mariadb namespace was deleted. Its volume uses the Retain reclaim policy, so the data survived. Your task: create a claim for that volume, point the deployment at it, apply, and verify the pod is running with no restarts.
- MariaDB Deployment in namespace mariadb was deleted
- Its PV uses Retain, so the data is still there
- Create a PVC bound to that PV
- Re-wire the Deployment, apply, and verify
How storage binding works
Storage in Kubernetes is a chain. A Deployment mounts a persistent volume claim. The claim binds to a persistent volume, which is the actual disk. Delete the claim and the deployment, and with Retain the volume keeps the data, waiting for a new claim to pick it back up.
Reproduce symptom
First, confirm the symptom. The mariadb namespace has no deployment and no pods. The workload is simply gone.
$ kubectl -n mariadb get deploy,pods
No resources found in mariadb namespace.
Confirm the data survived
Now the good news. The persistent volume still exists, its reclaim policy is Retain, and it is Available. That Retain policy is why your data outlived the deployment.
$ kubectl get pv mariadb
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
mariadb 250Mi RWO Retain Available <unset> 10h
Create the claim
Create a file, mariadb-pvc.yaml. Two details matter: an empty storage class name, so Kubernetes binds the existing volume instead of provisioning a new one, and a volume name that points straight at the PV. Apply it, and it binds immediately.
$ cat mariadb-pvc.yaml
...
metadata:
name: mariadb
namespace: mariadb
spec:
accessModes:
- ReadWriteOnce
# Must match the PV: empty class (static, no dynamic provisioning) and an explicit
# volumeName so it binds to the retained "mariadb" PV rather than a new one.
storageClassName: ""
volumeName: mariadb
resources:
requests:
storage: 250Mi
$ kubectl apply -f mariadb-pvc.yaml
persistentvolumeclaim/mariadb created
$ kubectl -n mariadb get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
mariadb Bound mariadb 250Mi RWO <unset> 1s
Verify
Apply the wired deployment, and prove it. The pod is Running with zero restarts, on top of the original data. The deployment is recovered.
$ kubectl apply -f mariadb-deployment.yaml
deployment.apps/mariadb created
$ kubectl -n mariadb get pods
NAME READY STATUS RESTARTS AGE
mariadb-68cd856df4-jx6mm 1/1 Running 0 0s
Exam tips
A few traps to remember. Use an empty storage class name to force a static bind, or the cluster's default provisioner will hand you a brand new empty volume. After you delete a claim, a Retain volume goes to Released, not Available; clear its claimRef to make it bindable again. And always confirm the claim is Bound before you expect the pod to start.
- storageClassName "" = static bind (avoid the default provisioner)
- volumeName targets a specific PV
- Retain PV goes Released after PVC delete; clear claimRef to rebind
- Confirm PVC is Bound before expecting the pod to run
Recap
- Retain preserves data past the claim's life
- Re-bind: PVC with empty class + volumeName
- Wire the Deployment, then verify Bound + Running
- Subscribe + dev.to writeup
Reproduce this yourself
The entire scenario is scripted on a throwaway kind cluster:
git clone <repo> && cd learning/scenarios/scenario2-retained-pv-recovery
./setup.sh # creates the cluster AND arms it (namespace + retained PV, deployment gone)
# solve it by hand, or:
./solution.sh # apply the answer key and verify recovery
If this helped, subscribe to The Cyber SideKick on YouTube for more CKA drills, and grab the newsletter at https://thecybersidekick.beehiiv.com.
Top comments (0)