Cleaning up AMIs

Andreas Wittig – 08 May 2024

Costs are like fingernails. You have to cut them constantly. When working with AWS, cleaning up unused resources is crucial. Otherwise, you will end up with a steadily growing AWS bill and waste money.

Do you build AMIs automatically, for example, with Packer? Learn how to automatically clean up unused AMIs to reduce EBS storage consumption and costs.

How to reduce costs for GitHub Actions?

About a year ago, the tool we used to remove unused AMIs stopped working. As we could not find a working alternative, we started the project aws-amicleaner.

How does the aws-amicleaner command line tool work?

  1. Include AMIs by name or tag.
  2. Exclude AMIs in use, younger than N days, or the newest N images.
  3. Manually confirm the list of AMIs for deletion.
  4. Delete AMIs and linked EBS snapshots.

Examples

Requires Node.js >= 18.

The following example shows how to delete all AMIs in eu-west-1 matching the following conditions:

  • Name starts with amiprefix-
  • Older than five days
  • Not in use by EC2 instances, ASGs, Launch Configurations, and Launch Templates.

Also, keep the newest three images that match the conditions.

npx aws-amicleaner --region eu-west-1 --include-name 'amiprefix-*' --exclude-newest 3 --exclude-days 5 --exclude-in-use --verbose

The following listing shows a typical confirmation screen.

+-----------+-------------+----------------------+--------------------------+---------+-----------------+-------------------------+
| Region | ID | Name | Creation Date | Delete? | Include reasons | Exclude reasons |
+-----------+-------------+----------------------+--------------------------+---------+-----------------+-------------------------+
| eu-west-1 | ami-0a...72 | amiprefix-1685107232 | 2023-05-27T13:32:21.000Z | no | name match | days not passed, newest |
| eu-west-1 | ami-02...3f | amiprefix-1685103569 | 2023-05-27T12:30:50.000Z | no | name match | days not passed, newest |
| eu-west-1 | ami-09...d5 | amiprefix-1685095689 | 2023-05-27T10:19:59.000Z | no | name match | days not passed, newest |
| eu-west-1 | ami-0f...c7 | amiprefix-1685039741 | 2023-05-26T18:47:37.000Z | no | name match | days not passed |
| eu-west-1 | ami-0f...f0 | amiprefix-1685018189 | 2023-05-26T12:49:02.000Z | no | name match | days not passed |
| eu-west-1 | ami-06...a8 | amiprefix-1685015512 | 2023-05-26T12:04:39.000Z | no | name match | days not passed |
| eu-west-1 | ami-04...44 | amiprefix-1684998014 | 2023-05-25T07:14:42.000Z | yes | name match | |
| eu-west-1 | ami-02...6e | amiprefix-1684954911 | 2023-05-24T19:15:37.000Z | yes | name match | |
| eu-west-1 | ami-0e...da | amiprefix-1684952424 | 2023-05-24T18:32:06.000Z | yes | name match | |
| eu-west-1 | ami-0b...54 | amiprefix-1684949922 | 2023-05-24T17:50:26.000Z | yes | name match | |
| eu-west-1 | ami-0b...2c | amiprefix-1684937102 | 2023-05-24T14:17:53.000Z | yes | name match | |
| eu-west-1 | ami-0e...aa | amiprefix-1684915092 | 2023-05-24T08:09:42.000Z | yes | name match | |
+-----------+-------------+----------------------+--------------------------+---------+-----------------+-------------------------+

Do you want to continue and remove 6 AMIs [y/N] ? :

The following example shows how to delete AMIs from all regions that start with eu-west-*, which resolves to eu-west-1, eu-west-2, and eu-west-3 those days. Also, the example filters AMIs by tag key CostCenter and tag value X342-*1111 and the age of 7 days. Besides that the aws-amicleaner keeps the newest five images matching those conditions.

npx aws-amicleaner --region 'eu-west-*' --include-tag-key CostCenter --include-tag-value 'X342-*-1111'

Looking for a way to run the aws-amicleaner in an automated way. Use the --force-delete option to skip the manual approval. We use GitHub Actions to remove unused AMIs once per month.

npx aws-amicleaner --region 'eu-west-*' --include-tag-key CostCenter --include-tag-value 'X342-*-1111' --force-delete

Arguments

Want more? Here is a list of all available arguments supported by aws-amicleaner.

-h, --help            show this help message and exit
--region REGION The AWS region, e.g. us-east-1, arg can be used more than once, wildcard * supported
--include-name INCLUDENAME
The name that must be present, wildcard * supported
--include-tag-key INCLUDETAGKEY
The tag key that must be present
--include-tag-value INCLUDETAGVALUE
The tag value (for the tag key) that must be present, wildcard * supported
--exclude-newest EXCLUDENEWEST
Exclude the newest N AMIs
--exclude-days EXCLUDEDAYS
Exclude AMIs from deletion that are younger than N days
--exclude-in-use, --no-exclude-in-use
Exclude AMIs from deletion that are in use by EC2 instances, ASGs, Launch Configurations, and Launch Templates (default: true)
-f, --force-delete, --no-force-delete
Skip confirmation before deletion (default: false)
--verbose, --no-verbose
Display additional information (default: true)

Summary

The aws-amicleaner is a small but helpfull tool to delete unused AMIs and the corresponding EBS snapshots to reduce costs.

It’s simple to get started (requires Node.js >= 18).

npx aws-amicleaner --help

Andreas Wittig

Andreas Wittig

I’ve been building on AWS since 2012 together with my brother Michael. We are sharing our insights into all things AWS on cloudonaut and have written the book AWS in Action. Besides that, we’re currently working on bucketAV,HyperEnv for GitHub Actions, and marbot.

Here are the contact options for feedback and questions.