Skip to content

Module - AMI Housekeeper

This module deploys a Lambda function responsible for deleting outdated AMIs. You can specify various criteria for the deletion process. Please note that the creation of AMIs is not within the scope of this project; the Lambda's role is solely to remove old ones. To avoid potential conflicts, it is recommended to deploy this module only once.

By default, the Lambda will scan all launch templates and assume that only the default version is in use. Any other AMIs referenced in the launch templates will be considered outdated and subject to deletion. Additionally, the module can search for AMIs referenced in AWS Systems Manager (SSM). When you set ssmParameterNames to *ami-id, the module will regard all AMIs referenced in SSM as in use, sparing them from deletion.

You can further refine the deletion process by applying AMI filters, such as those based on tags. The module also offers a 'dry run' option, allowing you to test the Lambda's behavior before executing actual deletions.

Usages

The module can be activated via the main module by setting enable_ami_housekeeper to true. Or invoking the module directly.

module "ami_housekeeper" {
  source = "path to module"

  prefix = "my-prefix"

  ami_cleanup_config = {
    ssmParameterNames = ["*/ami-id"]
    minimumDaysOld    = 30
    filters = [
      {
        Name   = "tag:Packer"
        Values = ["true"]
      }
    ]
    dryRun = true
  }

  log_level = "debug"
}

Development

Lambda Function

The Lambda function is written in TypeScript and requires Node and yarn. Sources are located in [https://github.com/philips-labs/terraform-aws-github-runner/tree/main/lambdas].

Install

cd lambdas
yarn install

Test

Test are implemented with Jest, calls to AWS and GitHub are mocked.

yarn run test

Package

To compile all TypeScript/JavaScript sources in a single file ncc is used.

yarn run dist

Requirements

Name Version
terraform >= 1.3.0
aws ~> 5.27

Providers

Name Version
aws ~> 5.27

Modules

No modules.

Resources

Name Type
aws_cloudwatch_event_rule.ami_housekeeper resource
aws_cloudwatch_event_target.ami_housekeeper resource
aws_cloudwatch_log_group.ami_housekeeper resource
aws_iam_role.ami_housekeeper resource
aws_iam_role_policy.ami_housekeeper resource
aws_iam_role_policy.ami_housekeeper_xray resource
aws_iam_role_policy.lambda_logging resource
aws_iam_role_policy_attachment.ami_housekeeper_vpc_execution_role resource
aws_lambda_function.ami_housekeeper resource
aws_lambda_permission.ami_housekeeper resource
aws_iam_policy_document.lambda_assume_role_policy data source
aws_iam_policy_document.lambda_xray data source

Inputs

Name Description Type Default Required
aws_partition (optional) partition for the base arn if not 'aws' string "aws" no
cleanup_config Configuration for AMI cleanup.

amiFilters - Filters to use when searching for AMIs to cleanup. Default filter for images owned by the account and that are available.
dryRun - If true, no AMIs will be deregistered. Default false.
launchTemplateNames - Launch template names to use when searching for AMIs to cleanup. Default no launch templates.
maxItems - The maximum numer of AMI's tha will be queried for cleanup. Default no maximum.
minimumDaysOld - Minimum number of days old an AMI must be to be considered for cleanup. Default 30.
ssmParameterNames - SSM parameter names to use when searching for AMIs to cleanup. This parameter should be set when using SSM to configure the AMI to use. Default no SSM parameters.
object({
amiFilters = optional(list(object({
Name = string
Values = list(string)
})),
[{
Name : "state",
Values : ["available"],
},
{
Name : "image-type",
Values : ["machine"],
}]
)
dryRun = optional(bool, false)
launchTemplateNames = optional(list(string))
maxItems = optional(number)
minimumDaysOld = optional(number, 30)
ssmParameterNames = optional(list(string))
})
{} no
lambda_architecture AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86_64' functions. string "arm64" no
lambda_memory_size Memory size linit in MB of the lambda. number 256 no
lambda_principals (Optional) add extra principals to the role created for execution of the lambda, e.g. for local testing.
list(object({
type = string
identifiers = list(string)
}))
[] no
lambda_runtime AWS Lambda runtime. string "nodejs20.x" no
lambda_s3_bucket S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. string null no
lambda_s3_key S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas. string null no
lambda_s3_object_version S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket. string null no
lambda_schedule_expression Scheduler expression for action runner binary syncer. string "rate(1 day)" no
lambda_security_group_ids List of security group IDs associated with the Lambda function. list(string) [] no
lambda_subnet_ids List of subnets in which the action runners will be launched, the subnets needs to be subnets in the vpc_id. list(string) [] no
lambda_timeout Time out of the lambda in seconds. number 60 no
lambda_zip File location of the lambda zip file. string null no
log_level Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'. string "info" no
logging_kms_key_id Specifies the kms key id to encrypt the logs with string null no
logging_retention_in_days Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. number 180 no
prefix The prefix used for naming resources string "github-actions" no
role_path The path that will be added to the role, if not set the environment name will be used. string null no
role_permissions_boundary Permissions boundary that will be added to the created role for the lambda. string null no
state_event_rule_ami_housekeeper State of the rule. string "ENABLED" no
tags Map of tags that will be added to created resources. By default resources will be tagged with name and environment. map(string) {} no
tracing_config Configuration for lambda tracing.
object({
mode = optional(string, null)
capture_http_requests = optional(bool, false)
capture_error = optional(bool, false)
})
{} no

Outputs

Name Description
lambda n/a
lambda_log_group n/a
lambda_role n/a