Unattached EBS volumes in the available state for at least 7 days
What does ZopNight detect here?
ZopNight flags an Amazon EBS volume in the `available` state, attached to nothing, once it has existed for at least 7 days and is not managed by Kubernetes. AWS charges for provisioned storage until the volume is deleted, so the saving is the volume's full monthly cost, including any provisioned IOPS and throughput.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-002 |
| Category | orphan |
| Severity | low |
| Metric | none — pure configuration read |
| Threshold | available (unattached), 7+ days old |
| Evaluation window | 7d |
| Source | ZopNight |
| Permissions used | ec2:DescribeVolumes · ec2:DescribeSnapshots |
Where it applies
Detaching a volume does not stop the bill
Amazon EBS pricing charges volume storage by the GB you provision per month until you release it, with extra charges for IOPS and throughput above the baseline on types that support them. The detach guide is direct about it: after you detach a volume you are still charged for its storage, and you must delete it to stop the charges.
Volumes end up unattached when instances are terminated with data volumes set to be preserved, when someone detaches a disk for a quick fix, or when a test environment is torn down unevenly.
Listing unattached volumes
aws ec2 describe-volumes --filters Name=status,Values=available \ --query 'Volumes[].[VolumeId,Size,VolumeType,CreateTime,Tags]' --output tableLook at the tags before anything else. The
EBS CSI driver’s tagging docs
list ebs.csi.aws.com/cluster and CSIVolumeName as tags it adds to every volume it creates;
volumes like that belong to a Kubernetes cluster and should be handled through it, not the EC2
console.
Three checks before a finding
- The volume’s state is
available, meaning it is not attached to any instance. - It does not look Kubernetes-managed: no name starting
pvc-orkubernetes-dynamic-pvc-, and nokubernetes.io/created-for/pvc/name,kubernetes.io/cluster/orKubernetesClustertag. Deleting a volume that backs a persistent volume claim would strand the pod that needs it. - When ZopNight has the volume’s creation time, the volume must be at least 7 days old, which keeps volumes still being provisioned or migrated out of the list.
Cases handled elsewhere or left out
AWS exposes no detach timestamp, so the 7 days count from creation; an old volume detached yesterday can still qualify, which is why the fix steps start with a check. A volume that backs a released Kubernetes persistent volume in a cluster whose node group has been abandoned is counted under EKS Abandoned Node Group instead, so the same cost is not reported twice. Volumes with no price are skipped.
The full volume cost comes back
saving = the volume's monthly cost (storage + provisioned IOPS + provisioned throughput)cost after fix = 0Removing an unattached volume
- Check the volume’s tags and recent CloudTrail
DetachVolumeevents to see who detached it and when. - Snapshot it if the data may be needed:
aws ec2 create-snapshot --volume-id vol-0123456789abcdef0. - Delete it with
aws ec2 delete-volume --volume-id vol-0123456789abcdef0.