Automate EC2 AMI Build and Deployment with AWS Systems Manager

Consider a typical EC2-based application fronted by a load balancer with a number of EC2 instances in an auto-scaling group behind it. The application in this case is baked into the AMI of the instances. Every time a new app release is needed, a new AMI must be built.

The infrastructure is deployed using CloudFormation. The CloudFormation template accepts the AMI ID as a parameter. Every time a new AMI is built, the stack is updated manually with the new AMI ID. CloudFormation then gracefully decommissions the instances with the old AMI and deploys replacement instances with the new AMI.

This article describes a way to automate this entire workflow using Systems Manager. The automation will start by building the AMI and then go on to update the CloudFormation stack as well.

All this will be done using an Automation Document in Systems Manager. The document will have these steps:

  • Create AMI by starting an image pipeline in EC2 image builder.
  • Wait for the AMI to be built.
  • Fetch the ID of the new AMI.
  • Update CloudFormation stack with new AMI ID.
  • Wait for stack update.

Many of these steps aren’t natively supported by Systems Manager documents but SSM documents can invoke any AWS API directly. We’ll use this feature to accomplish many of the steps!

EC2 Image Builder Pipeline

Before we can write the SSM document, we need a pipeline that will build the AMI. EC2 Image Builder is another service that lets us create such pipelines. Perform the first 3 steps of the following article to create the pipeline, then return here to build the SSM document:

Automate EC2 AMI Builds Triggered by Code Pushed to AWS CodeCommit Repositories

Systems Manager Automation Document

Let’s start writing the document. Go to console.aws.amazon.com/systems-manager/documents/create-document#documentType=Automation, provide a name for the document, scroll down to Step 1 in the Builder section, and let’s start building the document, one step at a time.

Start Image Pipeline

The first step is to invoke the StartImagePipelineExecution API of the ImageBuilder service. For this, fill in the Step 1 form as shown below:

The equivalent SSM document YAML is auto-generated by the UI:

name: StartImagePipelineExecution
action: 'aws:executeAwsApi'
inputs:
  Service: imagebuilder
  Api: StartImagePipelineExecution
  imagePipelineArn: Provide ARN of the Image Pipeline here.
outputs:
- Type: String
  Name: imageARN
  Selector: $.imageBuildVersionArn

Wait for Image State = Available

Add Step 2 to wait for the image build to complete:

The equivalent YAML is generated:

name: WaitForImageStateAvailable
action: 'aws:waitForAwsResourceProperty'
inputs:
  Service: imagebuilder
  Api: GetImage
  imageBuildVersionArn: '{{ StartImagePipelineExecution.imageARN }}'
  PropertySelector: image.state.status
  DesiredValues:
  - AVAILABLE

Get AMI ID

Get the ID of the newly built AMI:

YAML:

name: GetAMI_ID
action: 'aws:executeAwsApi'
inputs:
  Service: imagebuilder
  Api: GetImage
  imageBuildVersionArn: '{{ StartImagePipelineExecution.imageARN }}'
outputs:
- Selector: '$.image.outputResources.amis[0].image'
  Type: String
  Name: AMI_ID

Update CloudFormation Stack

Next, update the existing CloudFormation stack:

name: UpdateCloudFormationStack
action: 'aws:executeAwsApi'
inputs:
  Service: cloudformation
  Api: UpdateStack
  StackName: Provide your stack name here.
  UsePreviousTemplate: true
  Parameters:
  - ParameterKey: AMI_ID
    ParameterValue: '{{ GetAMI_ID.AMI_ID }}'
  Capabilities:
  - CAPABILITY_IAM

Wait for CloudFormation

name: WaitForCloudFormationUpdateComplete
action: 'aws:waitForAwsResourceProperty'
inputs:
  Service: cloudformation
  Api: DescribeStacks
  StackName: Your stack name.
  PropertySelector: 'Stacks[0].StackStatus'
  DesiredValues:
  - UPDATE_COMPLETE

Conclusion

Finally, click the ‘Create automation’ button to create this automation document. You can now run this document whenever a new deployment is needed!

About the Author ✍🏻

Harish KM is a Principal DevOps Engineer at QloudX & a top-ranked AWS Ambassador since 2020. 👨🏻‍💻

With over a decade of industry experience as everything from a full-stack engineer to a cloud architect, Harish has built many world-class solutions for clients around the world! 👷🏻‍♂️

With over 20 certifications in cloud (AWS, Azure, GCP), containers (Kubernetes, Docker) & DevOps (Terraform, Ansible, Jenkins), Harish is an expert in a multitude of technologies. 📚

These days, his focus is on the fascinating world of DevOps & how it can transform the way we do things! 🚀

Leave a Reply

Your email address will not be published. Required fields are marked *