Containers

Creating custom Amazon Machine Images with the ECS-optimized AMI Build Recipes

Customers running their container workloads on Amazon Elastic Container Service (Amazon ECS) have a choice of AWS Fargate and also using Elastic Compute Cloud (EC2) instances with the Amazon ECS-optimized AMI. One of the requests (issue #176) that our customers submitted, was to allow them to create their own ECS Amazon Machine Image (AMI).

Today we released the ECS-optimized AMI Build Recipes as an open source project. The build scripts uses a HashiCorp packer recipe to build the AMI.

Use cases

Building your own custom ECS AMI unlocks a number of use cases:

  1. Smaller AMI’s. In order to reduce their EBS volume costs, some of our customers would like to create smaller EBS volumes for their ECS instances.
  2. Pre-installed software on ECS container instances. Some of our customers have requirements for certain software or packages to be installed on their instances in the cloud (for example monitoring or security agents). With this recipe, they can now package their software into their own AMI, for faster provisioning and standardization.
  3. Pre-cached containers. For our customers that are looking for even faster ECS task launch times, they can now pre-populate a docker image on their ECS instances, hereby reducing the initial image pull time from a container registry to the instance. This is beneficial when the image sizes are especially large.

Architecture

The diagram below describes the build process.

ECS AMI scripts architecture

  1. A new EC2 instance is provisioned with an SSH key pair and appropriate security group rule (by default packer creates a rule that allows SSH traffic from 0.0.0.0/0, this can be customized).
  2. Software is installed on the EC2 instance and configuration changes are made to the operating system. This includes the relevant ECS software packages and their dependencies.
  3. The instance goes through a “generalization“ process to clean out any unique information before being packaged.
  4. The instance is stopped and an AMI is created from the instance with the relevant tagging information applied.
  5. The resources created during the process are then removed (the EC2 instance is terminated and the security group and key pair are deleted).

Prerequisites

Process

First, you will need to clone the Amazon ECS AMI github repository to your local environment and change to the amazon-ecs-ami directory.

git clone https://github.com/aws/amazon-ecs-ami
cd amazon-ecs-ami

For the purposes of this blog post we are going to build an Amazon Linux 2 AMI in the us-east-1 AWS region, although this can be used in any of the AWS regions.

The scripts support building an AMI for the following architectures:

  • al1 – Amazon Linux 64-bit (x86)
  • al2 – Amazon Linux 2 64-bit (x86)
  • al2arm – Amazon Linux 2 64-bit (Arm)
  • al2gpu – Amazon Linux 2 GPU-optimized
  • al2inf – Amazon Linux 2 (Inferentia)

Run the make command (REGION is mandatory).

REGION=us-east-1 make al2

The script downloads the appropriate version of packer and the Packer Plugin Amazon to your environment.
It uses global defaults which are in variables.pkr.hcl and for each architecture there are additional defaults in a specific settings file for that architecture, in our case al2.pkr.hcl. All of these defaults can be customized based on your specific needs and requirements.

The EC2 instance is launched in the default VPC in us-east-1. A new key pair and security group are created specifically for this build.

Once the instance is up and running and accessible through SSH, the process continues by going through several steps of installing software and modifying settings on the instance. The progress will displayed in the console.

Below is an overview of the operations performed on the instance:

  • Changes are made to the Message of the Day (MOTD) banner
  • Docker is installed
  • The ecs-init package is installed
  • The AWS Systems Manager Agent (SSM Agent) is installed to enable the ecs exec feature
  • Adds the ec2-user to the docker Unix group
  • Ensure that the ecs, amazon-ecs-volume-plugin, and amazon-ssm-agent services are launched at startup
  • Removes specific information from the instance

You can find a comprehensive list of all the changes made on the github repository.

The instance is then stopped, and the recipe creates an AMI (and backing snapshot) from the instance.

Once the process is complete, the recipe then terminates the EC2 instance and removes the security group and key pair.

Disconnected environments (air-gapped)

The scripts executed in the recipe download a number of packages and software from repositories that are located outside of the VPC where the instance runs. Some customers have stringent security requirements, which prohibits unfettered internet access for software downloads. The recipe also accommodates such requirements.

For such use cases, you need to set the variable to true in the relevant location in variables.pkr.hcl

variable "air_gapped" {
  type = string
  description = "If this build is for an air-gapped region, set to 'true'"
  default = "true"
}

All the other software packages that you wish to install, will need to be downloaded and stored in the additional-packages directory. Once they are placed there, the recipe will copy them to the instance and install them on the instance.

Clean Up

To remove the resources created during this post you will need to the deregister the AMI and remove the snapshot.
Run the following commands:

AMI_ID=$(aws ec2 describe-images \
  --filters "Name=tag:Name,Values='Packer Builder'" \
  --query 'Images[*].[ImageId]' \
  --region us-east-1 \
  --output text)

SNAPSHOT_ID=$(aws ec2 describe-images \
  --filters "Name=tag:Name,Values='Packer Builder'" \
  --query 'Images[].BlockDeviceMappings[].Ebs.SnapshotId' \
  --region us-east-1 \
  --output text)

aws ec2 deregister-image --image-id $AMI_ID --region us-east-1
aws ec2 delete-snapshot --snapshot-id $SNAPSHOT_ID --region us-east-1

Conclusion

In this post, we discussed the details of how you can use the ECS-optimized AMI Build Recipes, the resources that are created during the process, and how you can further customize the scripts for your own specific requirements.

The ECS-optimized AMI Build Recipes are an open source and a collaborative community project, and I would like to welcome you to get involved and provide your feedback. Check out our Amazon ECS AMI github repository for discussion via issues and submit your contributions via pull requests.

Maish Saidel-Keesing

Maish Saidel-Keesing

Maish Saidel-Keesing is a Senior Enterprise Developer Advocate in the Container Services team. Maish lives in Israel with his wife and 3 daughters and focuses on improving customer experience with everything related to containers in the cloud. You can always reach out to him on Twitter (@maishsk).