PersistentVolumeClaims (PVCs) are a normal part of stateful Kubernetes workloads. Applications use PVCs to request persistent storage, while PersistentVolumes (PVs) provide the actual storage resource.
The problem is that PVCs can remain after the workload that created them has been removed.
Over time, a cluster can accumulate:
Unused PVCs
Orphaned PersistentVolumes
Old application storage
Failed deployments
Test environment data
Storage resources that continue consuming capacity
Kubernetes does not automatically know whether a PVC is still important to an administrator simply because it is no longer attached to a running application.
That makes identifying unused storage an operational task.
Understanding the PVC Relationship
A simplified Kubernetes storage model looks like this:
Pod
|
v
PersistentVolumeClaim
|
v
PersistentVolume
|
v
Storage BackendA pod can mount a PVC:
apiVersion: v1
kind: Pod
metadata:
name: storage-demo
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: app-data
mountPath: /data
volumes:
- name: app-data
persistentVolumeClaim:
claimName: app-dataThe pod references the PVC through:
claimName: app-dataThe PVC then represents the application's request for persistent storage.
What Makes a PVC "Unused"?
An unused PVC does not necessarily mean it is safe to delete.
A claim might be:
Currently mounted by a pod
Used by a StatefulSet
Temporarily detached
Waiting for a workload to restart
Retained intentionally for recovery
Part of a backup or migration process
Truly orphaned
Therefore, "not currently mounted" and "safe to delete" are not the same thing.
A useful investigation should combine Kubernetes resource information with application ownership and operational context.
Step 1: List PVCs
Start by viewing claims across namespaces:
kubectl get pvc -AFor a specific namespace:
kubectl get pvc -n productionA typical result may look like:
NAME STATUS VOLUME CAPACITY ACCESS MODES AGE
app-data Bound pvc-abc123 20Gi RWO 45d
database-data Bound pvc-def456 100Gi RWO 90d
old-test-data Bound pvc-ghi789 50Gi RWO 180dThe AGE field can help identify old resources, but age alone is not evidence that a claim is unused.
Step 2: Check the PVC Details
Inspect a suspicious claim:
kubectl describe pvc old-test-data -n productionThis provides information such as:
Namespace
Status
Storage class
Requested capacity
Bound volume
Events
Access modes
You can also retrieve the object as YAML:
kubectl get pvc old-test-data \
-n production \
-o yamlThe YAML is useful when investigating metadata such as labels, annotations, and ownership information.
Step 3: Find Pods Using a PVC
A PVC is commonly consumed by a pod through its volumes definition.
You can inspect pods in a namespace:
kubectl get pods -n production -o yamlThen search for:
persistentVolumeClaim:
claimName: old-test-dataFor a single namespace, this provides direct evidence that a pod currently references the claim.
For larger environments, automate the search rather than manually checking hundreds of pods.
Finding PVC References with JSONPath
You can inspect pod volumes using JSONPath:
kubectl get pods -n production \
-o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{range .spec.volumes[*]}{.persistentVolumeClaim.claimName}{" "}{end}{"\n"}{end}'This produces output similar to:
api-7c8f9d app-data
worker-55fd21
database-0 database-dataYou can compare these references with the PVC list.
A claim that does not appear in current pod volume references deserves further investigation.
Step 4: Check StatefulSets
Stateful applications require additional care.
For example:
kubectl get statefulsets -AA StatefulSet can use volumeClaimTemplates to create PVCs for individual replicas.
Example:
volumeClaimTemplates:
- metadata:
name: database-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100GiA generated PVC may have a name such as:
database-data-database-0Deleting such a claim without understanding the StatefulSet's storage design can result in data loss.
Step 5: Check Deployments and Jobs
Not all storage users are long-running applications.
Review:
kubectl get deployments -A
kubectl get jobs -A
kubectl get cronjobs -ATemporary workloads can create storage that remains after the workload finishes.
This is particularly common in:
Data processing
CI workloads
Batch jobs
Testing environments
Migration tasks
Step 6: Inspect the PersistentVolume
A PVC normally binds to a PersistentVolume.
Find the associated PV:
kubectl get pvc old-test-data \
-n production \
-o jsonpath='{.spec.volumeName}'Then inspect it:
kubectl describe pv <volume-name>Check:
Status
Claim reference
Storage class
Reclaim policy
Capacity
Storage backend
The reclaim policy is particularly important.
Understanding Reclaim Policies
A PersistentVolume can have a reclaim policy such as:
Retain
DeleteThe policy determines what happens to the underlying storage after the claim is released.
A Retain policy is intentionally conservative because the storage may need manual cleanup or recovery.
A Delete policy can remove the associated storage resource when the claim is deleted, depending on the storage provisioner.
Therefore, never treat PVC deletion as a simple metadata cleanup operation.
Step 7: Check Storage Classes
Find the storage class:
kubectl get storageclassThen inspect it:
kubectl describe storageclass <storage-class>Storage classes can define how persistent storage is provisioned.
Understanding the storage class helps determine what deleting a PVC could mean for the underlying infrastructure.
A Safer Investigation Workflow
A useful process is:
List PVCs
|
v
Identify old or suspicious claims
|
v
Check current pod references
|
v
Check StatefulSets and workloads
|
v
Inspect the PV
|
v
Check reclaim policy
|
v
Check application ownership
|
v
Confirm backups / retention requirements
|
v
Delete only after validationThis is safer than deleting claims based solely on their age.
Automating PVC Investigation
For larger clusters, manually inspecting every claim is inefficient.
A script can first list claims:
kubectl get pvc -A \
-o custom-columns=\
NAMESPACE:.metadata.namespace,\
NAME:.metadata.name,\
STATUS:.status.phase,\
VOLUME:.spec.volumeNameYou can then investigate candidates based on namespace, labels, workload ownership, or age.
For example:
kubectl get pvc -A \
--sort-by=.metadata.creationTimestampThis sorts claims by creation time and makes older resources easier to review.
Remember that this is an investigation aid, not an automated deletion mechanism.
Labels Can Make Cleanup Easier
Good resource metadata makes storage management much easier.
For example:
metadata:
labels:
app: reporting
environment: staging
owner: data-teamLater, administrators can identify resources using:
kubectl get pvc \
-n staging \
-l environment=stagingConsistent labels are especially useful in environments containing many teams and applications.
Common Mistakes
Deleting Based Only on Age
An old PVC may contain important production data.
Assuming Bound Means Actively Used
Bound indicates that the claim is associated with a PV. It does not by itself prove that a running pod is currently using it.
Ignoring StatefulSets
Stateful workloads often have storage lifecycle behavior that differs from ordinary deployments.
Forgetting the Reclaim Policy
Deleting a PVC can have consequences beyond the Kubernetes object itself.
Cleaning Up Without Backups
Before removing important storage, verify that the data is either disposable or covered by an appropriate backup and recovery process.
Using Force Deletion as a Cleanup Strategy
Force deletion should not be used simply because a resource appears difficult to remove.
First determine why Kubernetes is retaining it.
Production Best Practices
Use Labels Consistently
Identify application, environment, team, and ownership.
Document Storage Ownership
Teams should know which workloads own persistent storage.
Review Old Claims Regularly
Periodic review can prevent storage resources from accumulating indefinitely.
Monitor Storage Capacity
Unused claims are only one part of storage management. Monitor actual capacity and utilization as well.
Protect Stateful Data
Treat database and stateful application PVCs differently from temporary test storage.
Establish a Retention Policy
Define how long storage should remain after an application is retired.
Advantages of Regular PVC Audits
Regular storage reviews can provide several benefits:
Benefit | Impact |
|---|---|
Reduced storage waste | Fewer unnecessary resources |
Better visibility | Easier cluster administration |
Clear ownership | Faster troubleshooting |
Improved capacity planning | Better understanding of storage demand |
Safer cleanup | Less accidental deletion |
Easier cost management | Fewer unnecessary storage resources |
Risks of Aggressive Cleanup
Cleanup without sufficient validation can cause:
Permanent data loss
Application outages
Failed recovery operations
Broken StatefulSets
Unexpected storage deletion
Difficult incident recovery
The cost of an incorrectly deleted production database PVC can be significantly greater than the storage cost of keeping an old claim temporarily.
A Practical PVC Review Checklist
Before deleting a PVC, verify:
[ ] PVC namespace identified
[ ] PVC ownership identified
[ ] Current pod references checked
[ ] StatefulSets checked
[ ] Jobs and CronJobs checked
[ ] Associated PV inspected
[ ] Storage class identified
[ ] Reclaim policy checked
[ ] Backup status verified
[ ] Data retention requirements checked
[ ] Application owner contacted when necessary
[ ] Deletion impact understood
[ ] Rollback or recovery plan availableSummary
Finding unused PVCs in Kubernetes is not simply a matter of locating old claims.
A PVC can remain important even when no pod is currently mounting it. Stateful workloads, backups, retention policies, and persistent storage configuration all need to be considered before cleanup.
Start with kubectl get pvc, inspect suspicious claims, identify current workload references, check StatefulSets, examine the associated PersistentVolume, and understand the reclaim policy.
For production clusters, the safest approach is to treat PVC cleanup as a controlled storage-management process rather than an automated deletion task.
The goal is not to delete as many unused PVCs as possible. The goal is to confidently identify storage that is genuinely no longer required without putting persistent application data at risk.

Join the conversation! Your thoughts help the community grow.