its.pkhamre.com

How to Find Unused PVCs in Kubernetes

2026-09-25·3 min read·post

PVCs can remain after their workloads are gone. Kubernetes v1.37 adds an Unused status to PVCs, so you can list claims that no active pods reference.

The Short Answer

Run this command to list unused PVCs across all namespaces. It needs kubectl and jq:

kubectl get pvc -A -o json | jq -r '
  .items[]
  | select(.status.conditions[]? | select(.type == "Unused" and .status == "True"))
  | "\(.metadata.namespace)/\(.metadata.name)"
'

Example output:

payments/archive-data

Each result is shown as namespace/name. The -A flag includes all namespaces. To check one namespace, replace -A with -n <namespace>.

What Kubernetes v1.37 Adds

Kubernetes v1.37 adds the Unused condition through the PersistentVolumeClaimUnusedSinceTime feature. It is Beta and enabled by default. Kubernetes updates the condition as pods start and stop using a claim.

You can inspect the condition on an individual claim with:

kubectl get pvc archive-data -n payments -o yaml

In the output, find type: Unused. The status will be True or False.

Find Claims That Have Been Idle for a While

Each condition has a lastTransitionTime, which records when it last changed. This command lists claims that have been unused for more than 30 days:

kubectl get pvc -A -o json | jq -r '
  .items[]
  | . as $pvc
  | (($pvc.status.conditions // []) | map(select(.type == "Unused" and .status == "True")) | .[0]) as $unused
  | select($unused != null)
  | select((now - ($unused.lastTransitionTime | fromdateiso8601)) > (30 * 86400))
  | "\($pvc.metadata.namespace)/\($pvc.metadata.name) unused since \($unused.lastTransitionTime)"
'

The 30 * 86400 part sets the age limit in seconds. Change 30 to choose a different number of days.

Read the Unused Condition

Unused=True means no non-terminal pods reference the claim. Unused=False means a running or pending pod does. Completed and failed pods do not count. If several pods use a claim, it stays marked in use until they are all gone.

If the condition is missing, check your Kubernetes version and feature settings. A missing condition does not tell you whether a claim is in use.

Important Edge Cases

The condition tracks pod references, not reads or writes to storage. A claim marked unused may still contain data you need or be used again later.

Check the Results Before Cleanup

Treat this list as a starting point. Before deleting a claim, check:

If you are unsure, ask the owner before deleting it.

To check one namespace, add -n and print only the claim name:

kubectl get pvc -n payments -o json | jq -r '
  .items[]
  | select(.status.conditions[]? | select(.type == "Unused" and .status == "True"))
  | .metadata.name
'

You need permission to list PVCs in the namespace. The -A version also requires cluster-wide list permission.

Summary

Filter for Unused=True to find claims that no non-terminal pods reference. Use lastTransitionTime to see how long they have been unused. Check with the owner and protect any data you still need before deleting a claim.

Source