Skip to main content
orphan · kubernetes

PersistentVolumes left Released with their disk still billing

resource types
1
rule IDs covered
3
severity
medium

What does ZopNight detect here?

A PersistentVolume in Released state has lost its claim but kept its underlying cloud disk, which keeps billing at the full provisioned rate. With the default Retain policy nothing reclaims it, and a Released PV cannot rebind even to a matching claim without hand-clearing 1 field, spec.claimRef.

Signal and threshold

How ZopNight evaluates PersistentVolumes left Released with their disk still billing.
Field Value
Rule IDsRC-1741 · RC-1841 · RC-1941
Categoryorphan
Severitymedium
Metricnone — pure configuration read
Sourceinternal/rules/k8s/pv_released.go

Released is not deleted

When a PVC is deleted, its bound PV moves to Released. What happens next depends entirely on the reclaim policy:

  • Retain: the PV stays, the cloud disk stays, and both keep existing until a human intervenes.
  • Delete: the PV and the underlying disk are removed automatically.

Statically-provisioned volumes commonly use Retain, and it is often the correct choice: it means deleting a claim cannot destroy data. The consequence is that the disk keeps billing, forever, at its full provisioned size.

Why these accumulate invisibly

A Released PV is not attached to anything, so it produces no events, no pod failures and no metrics. Nothing in the cluster complains. The only visible trace is on the cloud bill, as an unattached disk that no Kubernetes-facing dashboard shows.

Namespace deletion is the usual multiplier: tearing down an environment removes every PVC in it and leaves a matching set of Released PVs and live disks behind.

A Released volume cannot be reused as-is

This is the part that catches people. A PV in Released state will not bind to a new claim even if the claim matches perfectly; it retains a reference to the deleted claim’s UID.

Reusing it means clearing spec.claimRef manually, at which point you are hand-editing cluster state. Deleting and reprovisioning is usually cleaner unless the data matters.

Grepping the PV list for Released status

Terminal window
kubectl get pv --sort-by=.spec.capacity.storage \
-o custom-columns='NAME:.metadata.name,CAP:.spec.capacity.storage,STATUS:.status.phase,POLICY:.spec.persistentVolumeReclaimPolicy,CLAIM:.spec.claimRef.name' \
| grep Released

Then confirm the disk still exists on the cloud side. The PV object and the disk are separate things, and one can outlive the other.

Before deleting

Snapshot first if there is any doubt. A Retain policy exists because somebody decided this data should survive claim deletion, and that decision may still hold even if the workload is gone.

See it fire on your bill.

Connect an account read-only. The first findings land in minutes.

417 rule families across 353 resource types on 22 platforms. Every threshold, metric, and IAM action is documented on these pages before you grant anything.

417 rule families documented
353 resource types covered
read-only default access level
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·