A PersistentVolumeClaim separates storage lifetime from a recreated Pod; it does not guarantee data recovery. A PersistentVolume describes storage, a claim requests it, and controllers arrange binding or provisioning. Recovery still depends on backing storage, usable topology and backups.
Claims and volumes have separate lifetimes. Finalizers can postpone deletion, while reclaim policy controls the released storage. Review both before maintenance: mistakes can cause persistent Terminating states, unintended data loss or retained storage bills.
The claim, the volume, and the binding
Ordinary matching checks capacity, access modes, storage class, volumeMode, selectors and existing ownership. An unmatched claim can remain Pending; inspect its events and StorageClass rather than assuming a single cause. Binding is not proof of usable topology: explicitly naming a PV can bind despite conflicting node affinity. Scheduling and mounting still have to succeed.
accessModes has no default. ReadWriteOnce permits read-write mounting on one node, potentially by several Pods there; it is not single-Pod exclusivity. ReadWriteOncePod provides that constraint for supported CSI volumes. Access modes alone do not enforce write protection after mounting. Immediate starts binding or provisioning without waiting for a consumer, risking unusable placement for topology-constrained storage. Supported WaitForFirstConsumer provisioning coordinates storage with a consuming Pod’s scheduling constraints before placement completes.
The deletion order and the finalizer
A usual retirement sequence is Pod, claim, then volume. Deleting an in-use claim records deletionTimestamp, but kubernetes.io/pvc-protection can postpone removal. In Kubernetes v1.34.0, the ordinary PVC-reference check counts Pods assigned to a node; an unscheduled Pod reference alone does not hold protection. This is a controller reference check, not a live mount probe. A stuck Terminating claim therefore needs inspection of scheduled consumers, controller progress and other finalizers.
The same protection exists in the other direction. A PersistentVolume carries kubernetes.io/pv-protection, so deleting a volume that is bound to a claim is postponed until it is no longer bound. That ordering delays an accidental deletion; a deletionTimestamp cannot simply be cancelled. This explains why a volume can seem to ignore a delete for as long as its claim exists.
Reclaim policy: Delete or Retain
When the claim is finally gone the volume is released, and the reclaim policy takes over. With a supporting storage plugin, Delete reclaims the PV and backing asset asynchronously; removal is not an atomic or immediate guarantee. Retain keeps the PV object, marks it Released, and deliberately does not make it available for a new claim, because the previous claimant’s data is still on it — reclamation becomes a manual sequence: verify ownership and backups, then deliberately reclaim, reuse or delete storage according to the provider’s procedure.
Dynamically provisioned volumes inherit the policy from their StorageClass, whose default is Delete. Whether that default fits a database depends on retention and recovery requirements. It is easy to overlook: nothing in the PVC or pod spec mentions the policy, so the decision lives in a cluster-scoped object nobody reviewing the workload ever sees.
When it breaks
The classic failure is the claim that will not die. Someone deletes a PVC, sees Terminating, and waits — while a pod somewhere still mounts it, usually a StatefulSet that was never scaled down or a pod stuck on an unreachable node. Nothing errors, nothing times out, and the PVC blocks the storage behind it. Find the pod rather than deleting the finalizer by hand; bypassing protection can permit premature storage deletion while a workload still uses it.
The second failure is the Retain orphan. The claim is gone, the pods are gone, the namespace may be gone, and a Released PV plus its storage asset remain for deliberate reclamation. Retention may be intentional; without inventory alerts it is easy to miss and the volume does not appear in any workload’s list. The inverse mistake is just as quiet: a class whose default Delete policy was never overridden, discovered only when someone tries to recover data that the reclaim already removed.
Check it quickly
Look at both sides of the binding, and at what holds the claim:
kubectl get pvc -A -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name,STATUS:.status.phase,VOLUME:.spec.volumeName,CLASS:.spec.storageClassName
kubectl get pv -o custom-columns=NAME:.metadata.name,STATUS:.status.phase,POLICY:.spec.persistentVolumeReclaimPolicy,CLAIM:.spec.claimRef.name
kubectl get pvc data -o jsonpath='{.metadata.finalizers}{"\n"}'
kubectl get pods -A -o json | jq -r '.items[] | select(.spec.volumes[]?.persistentVolumeClaim.claimName=="data") | "\(.metadata.namespace)/\(.metadata.name)"'
These retained diagnostics were not rerun here. Protection indicates cleanup is pending; it does not prove the controller is healthy or a Pod still exists. The fourth command finds all claims named data across namespaces, so match the target namespace before treating a Pod as a consumer. Released plus Retain calls for an ownership and recovery decision, not automatic deletion; the old claimRef may remain.
Sources
- Persistent Volumes, binding, access modes, reclaim policies,
Releasedstate and the pvc/pv protection finalizers, checked 2026-10-15. - Storage Classes, dynamic provisioning,
reclaimPolicy, andvolumeBindingMode, checked 2026-10-15. - Persistent Volumes (v1.34), v1.34 prebinding, access-mode limits and supported reclaim behavior, checked 2026-10-18.
- PVC protection implementation, v1.34.0 podUsesPVC node-assignment and explicit-reference checks, checked 2026-10-18.