Creating custom AMIs

Custom AMIs help teams ensure that their agents have all required tools and configurations before instance launch. This prevents instances from reverting to the base image state when agents restart, which would lose any manual changes made during run time.

Custom AMIs can be used with the Elastic CI Stack for AWS by specifying the ImageId parameter. You can use any AMI available to your AWS account. For best results, start with Buildkite's base Packer templates. The Packer templates used to create the default stack images are available in the packer directory of the Elastic CI Stack for AWS repository.

Requirements

To use the Packer templates provided, you will need the following installed on your system:

  • Docker
  • Make
  • AWS CLI

The following AWS IAM permissions are required to build custom AMIs using the provided packer templates:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:AttachVolume",
        "ec2:AuthorizeSecurityGroupIngress",
        "ec2:CopyImage",
        "ec2:CreateImage",
        "ec2:CreateKeyPair",
        "ec2:CreateSecurityGroup",
        "ec2:CreateSnapshot",
        "ec2:CreateTags",
        "ec2:CreateVolume",
        "ec2:DeleteKeyPair",
        "ec2:DeleteSecurityGroup",
        "ec2:DeleteSnapshot",
        "ec2:DeleteVolume",
        "ec2:DeregisterImage",
        "ec2:DescribeImageAttribute",
        "ec2:DescribeImages",
        "ec2:DescribeInstances",
        "ec2:DescribeInstanceStatus",
        "ec2:DescribeRegions",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeSnapshots",
        "ec2:DescribeSubnets",
        "ec2:DescribeTags",
        "ec2:DescribeVolumes",
        "ec2:DetachVolume",
        "ec2:GetPasswordData",
        "ec2:ModifyImageAttribute",
        "ec2:ModifyInstanceAttribute",
        "ec2:ModifySnapshotAttribute",
        "ec2:RegisterImage",
        "ec2:RunInstances",
        "ec2:StopInstances",
        "ec2:TerminateInstances"
      ],
      "Resource": "*"
    }
  ]
}

You'll also benefit from familiarity with:

Creating an image

To create a custom AMI, use the provided Packer templates to build new images with your modifications. First, make your changes to the Packer templates, then run the Makefile in the root directory to begin the build process.

This Makefile provides several build targets, each running Packer in a Docker container:

Command Description

make packer

Build all AMI variants

make packer-linux-amd64.output

Build Amazon Linux 2023 (64-bit x86) AMI only

make packer-linux-arm64.output

Build Amazon Linux 2023 (64-bit ARM, Graviton) AMI only

make packer-windows-amd64.output

Build Windows Server 2019 (64-bit x86) AMI only

By default, all builds target the us-east-1 region and use your default AWS profile. The make command can be prefixed with environment variables to change the behavior of the build.

Variable Default Description

AWS_REGION

us-east-1

Target AWS region for AMI creation

AWS_PROFILE

(system default)

Specific AWS profile to use

PACKER_LOG

(unset)

Enable Packer debug logging (PACKER_LOG=1)

BUILDKITE_BUILD_NUMBER

none

Build identifier passed to Packer

IS_RELEASED

false

Whether this is a release build

ARM64_INSTANCE_TYPE

m7g.xlarge

Instance type for ARM64 builds

AMD64_INSTANCE_TYPE

m7a.xlarge

Instance type for AMD64 builds

WIN64_INSTANCE_TYPE

m7i.xlarge

Instance type for Windows builds

For example, you could build an AMD64 Linux image in the eu-west-1 region using a smaller instance type and a specific AWS profile by running:

AMD64_INSTANCE_TYPE="t3.medium" \
AWS_REGION="eu-west-1" \
AWS_PROFILE="assets-profile" \
make packer-linux-amd64.output

Once your image build is completed, the AMI will be stored in your AWS account and the AMI ID is displayed in your terminal output. You can also find the AMI ID in the corresponding output file (such as packer-linux-amd64.output).