Find and Delete Unattached EBS Volumes Safely
An unattached EBS volume bills for its full provisioned size. Find them, prove nobody needs them, then delete.
An EBS volume that is not attached to anything sits in the available state and keeps billing for its provisioned storage. EBS volumes cannot be stopped or paused; the only way to stop the charge is to delete the volume, optionally keeping a snapshot. This procedure finds them, identifies an owner, preserves anything uncertain, and deletes.
Why they pile up
Whether a volume survives its instance depends on the DeleteOnTermination flag, and the default is not the same everywhere. From the EC2 documentation:
| Volume | Attached | Method | Default on termination |
|---|---|---|---|
| Root | At launch | Console or CLI | Delete |
| Root | After launch | Console or CLI | Preserve |
| Data | At launch | Console | Preserve |
| Data | At launch | CLI | Delete |
| Data | After launch | Console or CLI | Preserve |
A preserved volume continues to incur charges after its instance is gone, which is how a volume ends up billing with no instance to explain it.
1. List every unattached volume
aws ec2 describe-volumes \ --filters Name=status,Values=available \ --query "Volumes[].{id:VolumeId,sizeGiB:Size,type:VolumeType,created:CreateTime,az:AvailabilityZone,tags:Tags}" \ --output tableRun it per Region. available is the volume state for “not attached”; in-use means attached.
2. Work out who detached it and when
describe-volumes does not record when a volume was detached. CloudTrail does, for the last 90 days:
aws cloudtrail lookup-events \ --lookup-attributes AttributeKey=ResourceName,AttributeValue=vol-0123456789abcdef0Look for DetachVolume or TerminateInstances events and the user identity on them. Volumes tagged kubernetes.io/... were provisioned by a CSI driver for a persistent volume claim; leave those to the cluster owner, because deleting one strands the workload that expects it. If CloudTrail has nothing and there is no owner tag, ask the account owner before step 4.
3. Snapshot anything you are unsure about
aws ec2 create-snapshot --volume-id vol-0123456789abcdef0 \ --description "pre-delete copy of vol-0123456789abcdef0, ticket OPS-4411"# Use the SnapshotId returned by the create-snapshot command above.aws ec2 wait snapshot-completed --snapshot-ids snap-0fedcba9876543210If the snapshot is only a just-in-case copy, move it to the archive tier, which AWS positions for snapshots you plan to keep 90 days or longer and rarely access, at a lower storage price than the standard tier. Archiving converts the incremental snapshot to a full one, and it must be restored to the standard tier before use.
aws ec2 modify-snapshot-tier --snapshot-id snap-0fedcba9876543210 --storage-tier archive4. Delete
aws ec2 delete-volume --volume-id vol-0123456789abcdef0After deletion the data is gone and the volume cannot be attached anywhere. The one safety net is Recycle Bin: if a retention rule matches the volume, it goes to the Recycle Bin instead of being deleted immediately. Check your Recycle Bin rules before relying on that.
Console path for the same steps: EC2, Volumes, filter Volume state = Available, select the volume, Actions, Create snapshot, then Actions, Delete volume.
5. Stop new ones appearing
Check DeleteOnTermination on data volumes of running instances, and set it where the data does not need to outlive the instance:
aws ec2 describe-instances --instance-ids i-0abc1234def567890 \ --query "Reservations[].Instances[].BlockDeviceMappings[].{device:DeviceName,volume:Ebs.VolumeId,deleteOnTermination:Ebs.DeleteOnTermination}"Permissions
ec2:DescribeVolumes, ec2:CreateSnapshot, ec2:ModifySnapshotTier, ec2:DeleteVolume, plus cloudtrail:LookupEvents for step 2.
Verify
Re-run the step 1 query. The deleted IDs should be absent, and describe-snapshots --snapshot-ids should still return any copies you kept.
In ZopNight
ZopNight’s orphaned EBS volume rule files an available volume under the orphan category once the volume is at least 7 days old (AWS exposes no detach time, so this mainly skips volumes still being provisioned), skips volumes carrying Kubernetes CSI tags, and prices the saving as the volume’s full cost. From the recommendation, the remediation wizard can run a delete: it checks preconditions, asks for admin approval when a non-admin starts a destructive operation, executes, then validates. The blast radius view lists connected resources and their impact class before anyone approves. Resource notes are on the EBS volume page, and cloud waste covers the wider category.