DEV Community

The Cyber Sidekick
The Cyber Sidekick

Posted on

Recover a deleted Deployment from a Retain-policy volume (CKA Storage)

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.
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)