7.6 Deprecating and Deregistering Old AMIs
Right, let’s talk about digital housekeeping. You’ve been diligently creating AMIs for every deployment, every patch, every “oh god please work” moment. That’s smart. But now your AWS account looks like my first apartment—cluttered with old, mysterious artifacts that seemed like a good idea at the time. An unmanaged collection of AMIs isn’t just untidy; it’s a security risk, a source of confusion, and a fantastic way to accidentally launch a three-year-old kernel with twelve known CVEs. Let’s clean up.
Deregistering an AMI is the act of telling AWS, “Hey, forget this image definition ever existed.” It’s like removing a book from the library’s catalog. Crucially, and this is the part everyone messes up at least once, it does not delete the underlying snapshot(s). The AMI is just a pointer, a set of metadata. The actual blocks of data that make up your root volume and any additional EBS volumes? Those live on in Snapshotsville, happily accruing storage charges.
The Deregistration Dance (It’s a Solo Act)
Deregistering an AMI is simple and irreversible. There’s no “Are you really sure?” dialog box from AWS. You click the button, it’s gone. So let’s get it right. First, find the AMI ID you want to axe. The AWS CLI is your friend here.
# List all AMIs you own, sorted by creation date (so the oldest are at the top)
aws ec2 describe-images --owners self --query 'Images[*].[ImageId,Name,CreationDate]' --output text | sort -k3
Found the culprit? Note its ID. Now, deregister it.
# Say goodbye to ami-1234567890abcdef0
aws ec2 deregister-image --image-id ami-1234567890abcdef0
Poof. The AMI is no longer available for launch. Any existing EC2 instances already running from this AMI are completely unaffected—they’re running from a launch-time copy of the blocks, not the AMI itself. But the snapshots are still there, laughing at you from the billing page.
Finding and Deleting the Orphaned Snapshots
This is the real work. An AMI can be composed of multiple snapshots (one per EBS volume mapped in the block device mapping). You need to find them all and nuke them. The easiest way to find the snapshots linked to a specific AMI is to describe the AMI before you deregister it.
# Get the snapshot IDs for a given AMI before you deregister it
aws ec2 describe-images --image-ids ami-1234567890abcdef0 --query 'Images[0].BlockDeviceMappings[*].Ebs.SnapshotId' --output text
This will output something like snap-0a1b2c3d4e5f6g7h8 snap-0z9y8x7w6v5u4t3s2. Write these down. Now you can deregister the AMI and then delete the snapshots.
# Deregister the AMI
aws ec2 deregister-image --image-id ami-1234567890abcdef0
# Delete the snapshots (be VERY sure these are the right IDs)
aws ec2 delete-snapshot --snapshot-id snap-0a1b2c3d4e5f6g7h8
aws ec2 delete-snapshot --snapshot-id snap-0z9y8x7w6v5u4t3s2
If you’ve already deregistered the AMI and forgot to note the snapshots, you’re in for a bad time. Your only option is to trawl through all your snapshots, looking at the description field for clues. Some third-party tools can help, but it’s a mess. Learn from our collective pain: always get the snapshot IDs first.
Automating the Cleanup (Because You’re Not a Robot)
Doing this manually is for chumps and masochists. You need a strategy. My preferred method is to use tags. When you create an AMI, tag it with an expiration date.
# Create an AMI and tag it with a 'RetireOn' date
aws ec2 create-image --instance-id i-1234567890abcdef0 --name "MyApp-v1.2.3" --description "Post-security-patch baseline"
aws ec2 create-tags --resources ami-9876543210abcdef0 --tags Key=RetireOn,Value=2024-12-01
Now, you can write a simple script (run it via a Lambda on a Schedule, because this is AWS and we over-engineer everything) that finds all AMIs with a RetireOn tag in the past, grabs their snapshots, and obliterates the whole lot.
#!/bin/bash
# Example script logic (pseudo-code heavy, don't just run this)
TODAY=$(date +%Y-%m-%d)
# Find all AMIs with a RetireOn tag less than or equal to today
EXPIRED_AMIS=$(aws ec2 describe-images --owners self --filters "Name=tag:RetireOn,Values=*" --query "Images[?to_string(Tags[?Key=='RetireOn'].Value) <= '$TODAY'].ImageId" --output text)
for AMI in $EXPIRED_AMIS; do
echo "Processing expired AMI: $AMI"
# Get its snapshots
SNAPSHOTS=$(aws ec2 describe-images --image-ids $AMI --query "Images[0].BlockDeviceMappings[*].Ebs.SnapshotId" --output text)
# Deregister the AMI
aws ec2 deregister-image --image-id $AMI
# Delete each snapshot
for SNAP in $SNAPSHOTS; do
echo "Deleting snapshot: $SNAP"
aws ec2 delete-snapshot --snapshot-id $SNAP
done
done
The “But What If…” Edge Cases
- Shared AMIs: If you’ve shared an AMI with another AWS account, you must first make it private again before you can deregister it. Use
aws ec2 modify-image-attributeto remove launch permissions. The other account will no longer be able to use it, obviously. - Running Instances: You cannot deregister an AMI that’s currently being used to launch an instance. This isn’t a common issue, but if you have a slow-starting instance or an Auto Scaling group that’s mid-scaling action, you might hit this. Wait for the launch to complete or fail.
- AMI Copies: If you copied an AMI to another region, remember that the copy creates a new AMI with new underlying snapshots in the destination region. Deregistering the source AMI does nothing to the copy. You have to repeat this whole process in every region you’ve polluted. You’re welcome.
The bottom line is this: deregistration is easy, but proper cleanup is a discipline. Tag your AMIs, automate the deletion, and for the love of all that is holy, don’t forget the snapshots. Your future self, reviewing the monthly bill, will thank you.