Kubernetes
Persistent Volume
PV Deletion
Cloud Native
DevOps

Kubernetes How do I delete PV in the correct manner

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Deleting a PersistentVolume in Kubernetes is not just a kubectl delete pv operation. The correct process depends on whether the volume is still claimed, what the reclaim policy is, and whether you want to keep or destroy the underlying storage.

Start With the PVC, Not the PV

A PersistentVolume, or PV, is the cluster-side storage object. A PersistentVolumeClaim, or PVC, is the workload-side request for that storage. In a normal lifecycle, the PVC is the object you delete first.

If a PV is still bound to a claim, deleting the PV directly often leaves the claim stuck or triggers confusing controller behavior. Start by checking the current state:

bash
kubectl get pvc
kubectl get pv
kubectl describe pv my-volume

If the PV shows STATUS=Bound, find the claim name and namespace from kubectl describe pv. Then remove the workload that is actively using the claim, or update it so it no longer mounts that storage. After that, delete the PVC:

bash
kubectl delete pvc app-data -n production

At this point the PV usually moves from Bound to Released. What happens next depends on the reclaim policy.

Understand the Reclaim Policy

The reclaim policy controls what Kubernetes should do after the claim is deleted.

Delete means the backing storage should be removed automatically if the provisioner supports that behavior. This is common with dynamically provisioned cloud disks.

Retain means the PV object stays around and the underlying storage is kept. This is safer when the data matters, but it also means cleanup is partly manual.

You can inspect the policy like this:

bash
kubectl get pv my-volume -o jsonpath='{.spec.persistentVolumeReclaimPolicy}'
echo

If the policy is Retain, deleting the PVC does not wipe the disk. You may need to inspect the cloud volume, NFS export, or local path yourself before removing the PV object.

Safe Deletion Sequence

A practical deletion flow looks like this:

  1. Stop pods that are still writing to the PVC.
  2. Delete the PVC.
  3. Wait for the PV to enter Released or disappear automatically.
  4. If the PV remains, inspect its reclaim policy and any finalizers.
  5. Delete the PV only after you know whether the backing storage should survive.

Example session:

bash
1kubectl scale deployment web --replicas=0 -n production
2kubectl delete pvc app-data -n production
3kubectl get pv my-volume -w
4kubectl delete pv my-volume

That final delete is appropriate when the volume is no longer needed or when the underlying disk has already been handled.

When Finalizers Block Removal

Sometimes a PV or PVC stays in Terminating. This usually means a controller finalizer is still present because Kubernetes is waiting for a detach, cleanup, or provisioner action.

Inspect the object:

bash
kubectl get pv my-volume -o yaml

If the storage backend is healthy, the finalizer often clears on its own. If it does not, investigate the CSI driver, cloud provider logs, or node attach state before forcing anything. Removing finalizers manually is possible, but it should be a last resort because it can orphan real storage.

Static Versus Dynamic Volumes

Statically created PVs often point to infrastructure that Kubernetes does not fully manage. For example, an NFS share or a pre-created cloud disk may remain even after the PV object is gone. In that case, deleting only the Kubernetes object does not actually reclaim capacity.

Dynamically provisioned PVs are usually safer to delete because the storage class and CSI driver know how to clean up the backing resource. Even then, verify the reclaim policy instead of assuming deletion is automatic.

Here is a minimal PV example showing the key field:

yaml
1apiVersion: v1
2kind: PersistentVolume
3metadata:
4  name: my-volume
5spec:
6  capacity:
7    storage: 10Gi
8  accessModes:
9    - ReadWriteOnce
10  persistentVolumeReclaimPolicy: Retain
11  hostPath:
12    path: /data/demo

With Retain, the path or disk survives until you clean it up deliberately.

Common Pitfalls

Deleting the PV before the PVC is the most common mistake. Kubernetes is designed around claim-driven storage, so removing the volume first often creates stuck resources.

Another mistake is assuming kubectl delete pv always deletes the real disk. That only happens when the reclaim policy and provisioner support it.

A third issue is forcing finalizer removal without checking the storage backend. That may hide the symptom while leaving an attached or billable resource behind.

Summary

  • Delete the PVC before deleting the PV in normal workflows.
  • Check whether the PV is Bound, Released, or already deleting.
  • Inspect persistentVolumeReclaimPolicy before deciding what cleanup should happen.
  • 'Delete usually removes storage automatically; Retain usually requires manual cleanup.'
  • Treat stuck finalizers as a storage-controller problem first, not a patch-it-away problem.

Course illustration
Course illustration