PersistentVolumes left Released, or Available and unclaimed for 7 days
What does ZopNight detect here?
ZopNight flags a Kubernetes PersistentVolume on EKS, GKE or AKS in the `Released` phase, or in `Available` with no `claimRef` once it is 7 days old. Either way, the cloud disk behind it keeps billing for its provisioned size, because EBS, Persistent Disk and Azure managed disks charge whether or not anything mounts them.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-1741 · RC-1841 · RC-1941 |
| Category | orphan |
| Severity | medium |
| Metric | status.phase |
| Threshold | Released, or Available with no claimRef and older than 7 days |
| Evaluation window | 7d |
| Source | ZopNight |
| Permissions used | list persistentvolumes |
Where it applies
The disk keeps billing after the claim is gone
When a claim is deleted, what happens to its volume depends on the reclaim policy. With Delete,
the default for dynamically provisioned volumes, Kubernetes removes both the PV and the cloud
disk. With Retain, the
PersistentVolumes documentation
says the PV stays behind as Released: not available to another claim, because the previous
claimant’s data is still on it. Someone has to reclaim it by hand, and often nobody does.
The disk underneath is billed the whole time. Amazon EBS pricing charges for the GB provisioned per month until you release the storage. Google Cloud prices Persistent Disk by provisioned space, and Azure managed disks are billed hourly by size tier. A retained 500 GiB volume costs the same after its application is deleted as it did while serving traffic.
Listing released and unclaimed volumes
kubectl get pv -o json | jq -r ' .items[] | select(.status.phase == "Released" or (.status.phase == "Available" and .spec.claimRef == null)) | "\(.metadata.name) \(.status.phase) \(.spec.capacity.storage) reclaim=\(.spec.persistentVolumeReclaimPolicy) created=\(.metadata.creationTimestamp)"'kubectl describe pv <name> shows the CSI volume handle, which is the disk ID to look up in the
cloud console.
Two ways a volume qualifies
A volume in Released is flagged straight away; that phase only occurs after a claim was
deleted. A volume in Available is flagged only when it has no claim reference and was created
at least 7 days ago, measured from its creation timestamp. Newly provisioned volumes and static
volumes waiting for their first claim are normal, and the week gives them time. If an Available
volume’s creation time is missing, the rule does not raise a finding.
Volumes it leaves alone
Bound volumes are never flagged, and neither are Available volumes that already carry a claim reference. Claims whose own volume vanished are a different problem, covered by PVC lost its volume.
What the finding reports on cost
The finding includes the volume’s size when ZopNight knows it, but it does not attach a dollar estimate. Multiply the size by your disk type’s per-GB rate to see what reclaiming it is worth.
Reclaiming the volume
- Run
kubectl describe pv <name>and note the claim it last served and the backing disk ID. - Ask the owner whether the data is needed. If it is, snapshot the disk first.
- To reuse the data, delete the PV and create a new PersistentVolume with the same storage asset definition, which is the reuse path the Kubernetes docs describe for retained volumes.
- To discard it, delete the PV. With a
Retainpolicy the cloud disk survives this step, so delete the disk in the provider console or CLI as well. - For future volumes, set
reclaimPolicy: Deleteon classes where retained data is not needed.