Kubernetes - PV Reclaim Policies and Recovery
Over its lifetime, a PV passes through several phases:
Available- no PVC has claimed itBound- a PVC has claimed itReleased- the PVC that claimed it was deleted, but the PV still exists
Every PV has a reclaim policy that determines what happens when its PVC is deleted. The Delete policy removes the PV and its underlying storage, so the PV never reaches Released. The Retain policy keeps the PV and its data in place. The PV moves to Released and an administrator decides what happens to the data next.
This challenge demonstrates both policies using local-path, the built-in provisioner in k3s, and covers two recovery patterns for a Retained PV.
Task 1 - Provision a Volume
The local-path provisioner creates a PV automatically once a pod that uses the PVC gets scheduled to a node. Create a PVC and a pod that mounts it, then confirm the provisioner created a PV.
Steps:
- Create a PVC named
pvc-deletewithout astorageClassNamefield, capacity1Gi, access modeReadWriteOnce - Create a pod named
pod-delete(imagebusybox, commandsleep 3600) mountingpvc-deleteat/data - Confirm the PVC is Bound and note the PV name
Task 2 - Delete Reclaim Policy
The default reclaim policy for local-path is Delete. When a PVC is deleted, the provisioner deletes the PV and the underlying storage directory.
Steps:
- Delete
pod-delete, thenpvc-delete - Verify the PV is also gone
Task 3 - Retain Reclaim Policy
Create a StorageClass with reclaimPolicy: Retain so the PV survives PVC deletion.
Steps:
- Create a StorageClass named
sc-retainwithprovisioner: rancher.io/local-path,volumeBindingMode: WaitForFirstConsumer, andreclaimPolicy: Retain - Create a PVC named
pvc-retainwithstorageClassName: sc-retain, capacity1Gi, access modeReadWriteOnce - Create a pod named
retain-pod(imagebusybox, commandsleep 3600) mountingpvc-retainat/data - Wait for the pod to be Running
- Write
important-datato/data/recover.txtinside the pod (Task 4 recovers it) - Delete the pod first, then the PVC
- Verify the PV is still around in
Releasedstate
Task 4 - Recover the Released PV
After Task 3, the PV is in Released state. The claimRef field still references the deleted PVC and blocks binding to a new claim. Removing claimRef transitions the PV to Available. The new PVC does not name the PV directly. It just requests storageClassName: sc-retain, and Kubernetes matches it to the only Available PV of that class by capacity and access mode. The data on disk is untouched.
Steps:
- Run
kubectl get pvand find the PV inReleasedstate - Run
kubectl edit pv <name>and delete theclaimRefblock fromspec, then save - Confirm the PV transitions to
Available - Create a PVC named
pvc-recoverwithstorageClassName: sc-retain, capacity1Gi, access modeReadWriteOnce - Create a pod named
recover-pod(imagebusybox, commandsleep 3600) mountingpvc-recoverat/data - Read
/data/recover.txtfrom inside the pod and confirm the data is still there
Task 5 - Recover by Creating a New PV
Task 4 patched claimRef on the existing PV object. This time, leave the Released PV alone and create a new PV pointing to the same storage directory. Reuse the sc-retain StorageClass from Task 3, so the new PV keeps the Retain reclaim policy too.
Pin pvc-recover-2 to pv-new directly instead of leaving Kubernetes to match them by class, capacity, and access mode. You already know the exact PV you want, so name it.
Steps:
- Create a PVC named
pvc-retain-2withstorageClassName: sc-retain, capacity1Gi, access modeReadWriteOnce - Create a pod named
pod-retain-2(imagebusybox, commandsleep 3600) mountingpvc-retain-2at/data - Write
important-datato/data/recover.txtinside the pod - Delete
pod-retain-2, thenpvc-retain-2 - Find the Released PV and get its
spec.hostPath.path - Create a PV named
pv-newwithstorageClassName: sc-retain,hostPath.pathset to that directory, capacity1Gi, access modeReadWriteOnce - Create a PVC named
pvc-recover-2withstorageClassName: sc-retain,volumeNameset topv-new, capacity1Gi, access modeReadWriteOnce - Create a pod named
recover-pod-2(imagebusybox, commandsleep 3600) mountingpvc-recover-2at/data - Read
/data/recover.txtfrom insiderecover-pod-2and confirm the data is still there