AWS - Clean up left over EBS volumes
Sometimes you mess up and forget to have EC2 instances delete their volumes on termination. When this happens you may need to clean them up. If you have a list of the AMI IDs that were used in each region, here is a script that lets you find volumes using the AMI snapshot ids that are no longer mounted and need to be cleaned up.
ebs_cleanup.py
import boto3 import botocore.exceptions as boto_exc AMI_MAP = { "us-east-1":"ami-0123456789abcef12", "us-east-2":"ami-0123456789abcef13", "us-west-1":"ami-0123456789abcef14", "us-west-2":"ami-0123456789abcef15", } def get_snapshot_from_id(client, ami_id): resp = client.describe_images( ImageIds=[ami_id] ) return resp["Images"][0]["BlockDeviceMappings"][0]["Ebs"]["SnapshotId"] session = boto3.Session() ec2 = session.client("ec2") count = 0 for region in ec2.describe_regions()["Regions"]: region_name = region["RegionName"] if region_name not in AMI_MAP: print(f"Skipping unsupported region {region_name}") continue print(f"Cleaning up {region_name}") ec2client = session.client("ec2", region_name=region_name) snapshot_id = get_snapshot_from_id(ec2client, AMI_MAP[region_name]) paginator = ec2client.get_paginator("describe_volumes") pages = paginator.paginate( Filters=[ { 'Name': 'status', 'Values': ['available'] }, { 'Name': 'snapshot-id', 'Values': [snapshot_id], }, ] ) volumes_to_delete = [] for page in pages: volumes_to_delete.extend([ volume["VolumeId"] for volume in page["Volumes"] if not volume["Attachments"] ]) if len(volumes_to_delete) == 0: print(f"No volumes to remove for {region_name}") continue count = count + len(volumes_to_delete) for volume in volumes_to_delete: print(f"Deleting {volume}") try: ec2client.delete_volume(VolumeId=volume, DryRun=False) except boto_exc.ClientError as e: if 'DryRunOperation' not in str(e): raise if count > 0: print(f"Deleted {count} unattached volumes")