What does the persistentVolumeReclaimPolicy field on a Kubernetes PersistentVolume control, and what actually happens to the data when a PersistentVolumeClaim is deleted under Retain versus Delete?
answer
- Trigger = PVC deletion, nothing else
- Delete = disk and data gone, default from the class
- Retain → Released, data kept, claimRef blocks reuse
- Policy is patchable on a live PV
- Retain ≠ backup; Recycle is dead
basics
~20 sIt decides the volume's fate once its claim is deleted. Delete removes the PersistentVolume object and destroys the backing storage and its data. Retain keeps both: the volume goes to the Released phase with data intact and needs manual cleanup or reuse by an administrator.
solid answer
~50 sThe policy lives on the PersistentVolume and is inherited from the StorageClass's `reclaimPolicy` for dynamically provisioned volumes, defaulting to **Delete**. - **Delete** — deleting the PVC triggers the provisioner to destroy the real disk and remove the PV object. The data is unrecoverable unless you have snapshots or backups. This is the default on every managed cluster, so `kubectl delete namespace` can permanently destroy a database. - **Retain** — the PV survives, moves to `Released`, and keeps the data. It will not bind to a new claim while the stale `claimRef` is present; an administrator either clears `claimRef` to make it `Available`, or deletes the PV object and re-creates it pointing at the same backend volume. The cost is orphaned volumes nobody cleans up. The policy is **editable on an existing PV**, which is the standard emergency move: patch a bound PV to `Retain` before touching anything risky. Legacy `Recycle` (scrub-and-reuse) is deprecated and effectively gone.
code
bash · 10 lines# find the PVs behind a namespace's claims and pin them to Retain
kubectl get pvc -n prod -o jsonpath='{range .items[*]}{.spec.volumeName}{"\n"}{end}' \
| xargs -I{} kubectl patch pv {} \
-p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
# after an accidental PVC deletion: PV is Released, data intact
kubectl get pv
kubectl patch pv pvc-8f3a... --type=json \
-p='[{"op":"remove","path":"/spec/claimRef"}]'
# PV is now Available; create a PVC with spec.volumeName to re-bind itgo deeper
Know the two values and the one-line effect of each, and that Delete is the usual default for dynamically provisioned volumes.
Add that the value is inherited from the StorageClass at provisioning time, that the trigger is claim deletion, and that Released volumes hold data.
Demonstrate the recovery procedure from Released, the pre-risk patch-to-Retain ritual, and the cost and compliance downside of retained orphans.
Set the policy as platform doctrine: which classes retain, who audits orphaned volumes, and how this sits under a real snapshot and backup strategy rather than replacing it.
## What the field decides `spec.persistentVolumeReclaimPolicy` on a PersistentVolume answers exactly one question: when the PersistentVolumeClaim bound to this volume is deleted, what happens to the volume and its contents? Nothing else in Kubernetes triggers it — not deleting a Pod, not deleting a Deployment or StatefulSet, not a rollout. Claim deletion is the trigger. For dynamically provisioned volumes the value is copied from the StorageClass's `reclaimPolicy` at provisioning time, and the default there is `Delete`. For statically created PVs the administrator sets it directly, and the practical default in hand-written manifests should be `Retain`. ## Delete On PVC deletion the PV enters `Released` briefly and the provisioner calls `DeleteVolume` on the driver. The backend destroys the disk; the PV object is then removed. What is gone: - the filesystem and every byte on it, - the cloud resource, so billing stops, - any chance of recovery, unless you have a VolumeSnapshot or an application-level backup taken beforehand. This is the right default for genuinely disposable storage — caches, per-CI-run scratch, dev environments — and it is the one that produces catastrophes when it is the default for a production database. The dangerous shapes are: `kubectl delete namespace`, a GitOps prune that removes a PVC because someone renamed it in git, and a Helm uninstall of a chart whose PVCs are not annotated to survive. In every case, no confirmation is offered and no undo exists. If the delete fails — the driver errors, credentials expired, the disk is still attached — the PV goes to `Failed` and both the object and the backend resource stick around until someone intervenes. ## Retain On PVC deletion, nothing is destroyed. The PV moves to `Released` and stays there indefinitely with the data intact. Two things surprise people: 1. **Released is not Available.** The PV still carries `spec.claimRef` naming the deleted claim (including its UID), and the controller will not rebind it — not even to a new claim with the same namespace and name. To reuse it you either remove `claimRef` (`kubectl patch pv ... --type=json -p '[{"op":"remove","path":"/spec/claimRef"}]'`), which makes it `Available` with the data still on it, or delete the PV object and re-create it referencing the same backend handle. 2. **Nothing cleans up.** Retained volumes accumulate: an ex-namespace's disks keep costing money and keep holding data that may be subject to retention or privacy rules. Retain moves the risk from data loss to data sprawl, so it needs an owner and a periodic audit. Deleting the PV object under Retain does **not** delete the backing disk — that must be removed in the infrastructure separately. ## Recycle The third historical value, `Recycle`, wiped the volume with `rm -rf /thevolume/*` and returned it to `Available`. It is deprecated and unsupported by CSI drivers; the modern equivalent is dynamic provisioning of a fresh volume. Mention it only to dismiss it. ## Operating the choice - **Set `reclaimPolicy: Retain` on a dedicated class** for stateful workloads (`db-retain`, `retain-ssd`) and make production databases use it explicitly. Leave the default class on `Delete` so scratch storage self-cleans. - **Patch before risk.** The policy is mutable on a live PV, so the pre-migration ritual is: find the PVs behind the workload's claims and set them to `Retain`, then do the risky thing. This has saved more clusters than any backup tool. - **Retain is not a backup.** It protects against accidental claim deletion only — not corruption, not ransomware, not a driver bug, not a region failure. Real protection is VolumeSnapshots plus off-cluster backups. - **Static PVs should almost always be Retain**, because their backing storage is usually shared infrastructure that Kubernetes does not own. One more sequencing detail worth knowing: because of the `pvc-protection` finalizer, a PVC in use will not actually delete until the consuming Pods are gone, so the reclaim action fires only after the workload has released the volume — which is exactly why deleting a whole namespace destroys data in a single quiet sweep: the Pods go first, then the claims, then the disks.
- Someone deleted a production PVC on a Retain volume. Walk through recovery.The PV is in Released with the data untouched, so first confirm its phase and note its volume handle. Remove spec.claimRef so it returns to Available, then create a new PVC that pins itself with spec.volumeName set to that PV (matching class, access modes and capacity), and let it bind. Finally point the workload at the new claim and verify the data before letting traffic in.
- Your team wants Retain everywhere so nothing can ever be lost. What is the argument against?Retain converts a data-loss risk into a data-sprawl and cost risk: every deleted namespace leaves orphaned disks that still bill, still hold potentially regulated data, and still count against volume quotas. Nothing reclaims them automatically, so it only works with an owner and an audit process. The usual compromise is Retain on an explicit class for stateful workloads and Delete on the default class, backed by real snapshots.
- Does changing the StorageClass reclaimPolicy affect volumes that already exist?No. The policy is copied onto each PersistentVolume when it is provisioned, so existing PVs keep whatever they were born with. Changing the class only affects volumes created afterwards. To change existing ones you patch persistentVolumeReclaimPolicy on each PV directly, which is allowed on a live, bound volume.
Delete is a shredder attached to the out-tray: file removed, contents destroyed. Retain is a locked archive box — the label says the old owner, so nobody new may open it until an administrator relabels it.
saying these in an interview costs you the question
- Thinking deleting a Pod or Deployment triggers reclamation
- Believing Retain returns the volume to the Available pool automatically
- Treating Retain as a substitute for backups or snapshots
- Assuming deleting a Retain PV object also deletes the cloud disk
- Not knowing the policy can be patched on an existing PersistentVolume