When working with AWS EC2, deleting an AMI (Amazon Machine Image) requires more than just deregistering the image. The complete process involves:
- Deregistering the AMI itself
- Deleting the associated EBS snapshots
- Cleaning up any related resources
Here's the complete workflow to properly delete an EC2 AMI:
1. First, identify the AMI and its snapshots
aws ec2 describe-images --image-ids ami-1234567890abcdef0
This will return details including the snapshot IDs associated with the AMI.
2. Deregister the AMI
aws ec2 deregister-image --image-id ami-1234567890abcdef0
3. Delete the associated snapshots
The snapshots won't be automatically deleted when you deregister the AMI. You need to delete them separately:
aws ec2 delete-snapshot --snapshot-id snap-1234567890abcdef0
For frequent AMI management, consider this bash script:
#!/bin/bash
AMI_ID="ami-1234567890abcdef0"
# Get snapshot IDs
SNAPSHOTS=$(aws ec2 describe-images --image-ids $AMI_ID \
--query 'Images[0].BlockDeviceMappings[].Ebs.SnapshotId' \
--output text)
# Deregister AMI
aws ec2 deregister-image --image-id $AMI_ID
# Delete snapshots
for SNAPSHOT in $SNAPSHOTS; do
aws ec2 delete-snapshot --snapshot-id $SNAPSHOT
done
echo "AMI $AMI_ID and associated snapshots deleted successfully"
- Verify the AMI isn't being used before deletion
- Check IAM permissions (needs ec2:DeregisterImage and ec2:DeleteSnapshot)
- AMI deletion is irreversible
- Snapshots may take time to delete depending on size
Error: "UnauthorizedOperation"
Fix: Ensure your IAM policy includes ec2:DeleteSnapshot and ec2:DeregisterImage permissions
Error: "InvalidAMIID.Unavailable"
Fix: The AMI may already be deregistered - verify its status first
When working with AWS EC2 instances, you'll often need to manage AMIs (Amazon Machine Images). While creating AMIs is straightforward using ec2-create-image
, the deletion process requires more attention because AMIs consist of multiple components that need proper cleanup.
A common mistake is using only the aws ec2 deregister-image
command, which only removes the AMI registration but leaves underlying EBS snapshots untouched. This leads to:
- Orphaned snapshots consuming storage
- Unnecessary storage costs
- Cluttered AWS resources
Here's the proper way to delete an AMI and its associated snapshots:
# First, get the snapshot IDs associated with the AMI
aws ec2 describe-images --image-ids ami-12345678 --query "Images[0].BlockDeviceMappings[].Ebs.SnapshotId" --output text
# Deregister the AMI
aws ec2 deregister-image --image-id ami-12345678
# Delete each associated snapshot
aws ec2 delete-snapshot --snapshot-id snap-1234567890abcdef0
For regular maintenance, you might want to automate this process:
#!/bin/bash
AMI_ID=$1
# Get snapshot IDs
SNAPSHOT_IDS=$(aws ec2 describe-images --image-ids $AMI_ID \
--query "Images[0].BlockDeviceMappings[].Ebs.SnapshotId" \
--output text)
# Deregister AMI
aws ec2 deregister-image --image-id $AMI_ID
# Delete snapshots
for SNAPSHOT_ID in $SNAPSHOT_IDS
do
aws ec2 delete-snapshot --snapshot-id $SNAPSHOT_ID
echo "Deleted snapshot: $SNAPSHOT_ID"
done
echo "AMI $AMI_ID and its snapshots have been completely removed"
- Verify the AMI isn't being used before deletion
- Check AWS regions if you're working across multiple regions
- Consider creating backups before deletion if the AMI is critical
- Monitor AWS Billing to confirm storage costs decrease
For enterprise environments, consider setting up a Lambda function triggered by CloudWatch Events to periodically clean up old AMIs:
import boto3
import datetime
def lambda_handler(event, context):
ec2 = boto3.client('ec2')
# Get all AMIs older than 30 days
amis = ec2.describe_images(Filters=[{'Name': 'owner-id', 'Values': ['YOUR_ACCOUNT_ID']}])
for ami in amis['Images']:
creation_date = datetime.datetime.strptime(ami['CreationDate'], '%Y-%m-%dT%H:%M:%S.%fZ')
if (datetime.datetime.now() - creation_date).days > 30:
# Deregister AMI and delete snapshots
snapshot_ids = [bdm['Ebs']['SnapshotId'] for bdm in ami['BlockDeviceMappings'] if 'Ebs' in bdm]
ec2.deregister_image(ImageId=ami['ImageId'])
for snapshot_id in snapshot_ids:
ec2.delete_snapshot(SnapshotId=snapshot_id)
return {'statusCode': 200, 'body': 'AMI cleanup completed'}