Automation runbook to create an AMI for an instance and copy it to another region

Automation runbook to create an AMI for an instance and copy it to another region

One of the AWS SAA questions is about designing resilient architectures.

AMI can be copied to another region.

You can copy an Amazon Machine Image (AMI) within or across AWS Regions.

Copy an AMI

This time, we will create an SSM Automation runbook, create an AMI from an existing EC2 instance, and copy this to another region.

Environment

Diagram of Automation runbook to create AMI and copy to another region.

Create an EC2 instance in a private subnet.
The instance will be the latest Amazon Linux 2.

Create an SSM Automation runbook.
The contents of this runbook are as follows

  1. Create an AMI for the instance.
  2. Copy the created AMI to another region.

The region where the EC2 instance is located is ap-northeast-1, and the region where the AMI is copied is us-east-1.

It also creates an association between this runbook and the instance.

CloudFormation template files

The above configuration is built with CloudFormation.
The CloudFormation templates are placed at the following URL

https://github.com/awstut-an-r/awstut-saa/tree/main/01/005

Explanation of key points of template files

(Reference) EC2

Resources:
  Instance:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !Ref InstanceProfile
      ImageId: !Ref ImageId
      InstanceType: !Ref InstanceType
      NetworkInterfaces:
        - DeviceIndex: 0
          SubnetId: !Ref PrivateSubnet
          GroupSet:
            - !Ref InstanceSecurityGroup
      Tags:
        - Key: !Ref TagKey
          Value: !Ref TagValue
Code language: YAML (yaml)

The tag setting is the key point.
This is because SSM association, described below, specifies target instances based on this tag information.

This time, set the tags as follows

  • Tag Name: MyRunbook
  • Tag Value: true

SSM Automation Runbook

Resources:
  CreateAndCopyImageRunbook:
    Type: AWS::SSM::Document
    Properties:
      Content:
        assumeRole: "{{AutomationAssumeRole}}"
        description: Create and Copy AMI to another region.
        schemaVersion: "0.3"
        parameters:
          AutomationAssumeRole:
            type: String
            description: (Optional) The ARN of the role that allows Automation to perform the actions on your behalf.
            default: ""
          DestinationRegion:
            type: String
            description: (Required) The Region to copy image to.
          InstanceId:
            type: String
            description: (Required) The instance ID you want to run commands on.
            default: ""
        mainSteps:
          - name: createImage
            action: aws:createImage
            maxAttempts: 1
            onFailure: Abort
            inputs:
              InstanceId: "{{InstanceId}}"
              ImageName: "{{InstanceId}}_{{global:DATE_TIME}}"
              NoReboot: true
          - name: copyImage
            action: aws:executeScript
            inputs:
              Runtime: python3.8
              Handler: handler
              InputPayload:
                DestinationRegion: "{{DestinationRegion}}"
                InstanceId: "{{InstanceId}}"
                SourceImageId: "{{createImage.ImageId}}"
                SourceRegion: "{{global:REGION}}"
              Script: |-
                import boto3
                import datetime

                def handler(events, context):
                  destination_region = events['DestinationRegion']
                  instance_id = events['InstanceId']
                  source_image_id = events['SourceImageId']
                  source_region = events['SourceRegion']

                  now = datetime.datetime.now()
                  d = now.strftime('%Y-%m-%d_%H.%M.%S')

                  client = boto3.client('ec2', region_name=destination_region)
                  response = client.copy_image(
                    Description='test copy',
                    Name='{instance_id}_{datetime}'.format(instance_id=instance_id, datetime=d),
                    SourceImageId=source_image_id,
                    SourceRegion=source_region
                  )

                  return response
      DocumentFormat: YAML
      DocumentType: Automation
      Name: !Sub "${Prefix}-CreateAndCopyImageRunbook"
      TargetType: /AWS::EC2::Instance
Code language: YAML (yaml)

Create a custom runbook.
For more information on creating runbooks, please see the following pages.

あわせて読みたい
Introduction to Creating SSM Automation Runbooks Using CloudFormation 【Introduction to Creating SSM Automation Runbooks Using CloudFormation】 Many SSM Automation runbooks are currently provided by default. https://docs.aws.am...

The Content property defines the contents of the runbook.

In the parameters data element, specify the parameters for executing this runbook.
In this case, we receive the following three parameters

  • AutomationAssumeRole: ARN of the service role that Autometion will use to run this runbook
  • DestinationRegion: Region to which the AMI will be copied
  • InstanceId: ID of the instance where the AMI will be created

The mainSteps data element describes the process to be executed in the runbook.
This runbook consists of two steps.

Step 1

The first step is to create an AMI from the instance.

AMI creation is done using the aws:createImage action provided by SSM Automation.

https://docs.aws.amazon.com/systems-manager/latest/userguide/automation-action-create.html

Specify the parameters required to run aws:createImage on inputss.
You can check the above page for the parameters that can be given when executing this action, but this time we will set three (InstanceId, ImageName, NoReboot).

When specifying parameters to be passed to ImageName, the automation system variables are referenced.
The date and time of execution can be obtained by using “global:DATE_TIME”.
For details on automation system variables, please refer to the following page.

https://docs.aws.amazon.com/systems-manager/latest/userguide/automation-variables.html

Step 2

The second step is to copy the AMI you just created to another region.

AMI copying is done using the action aws:executeScript provided by SSM Automation.

Runs the Python or PowerShell script provided using the specified runtime and handler.

aws:executeScript – Run a script

Specify the parameters required to run aws:executeScript on inputss.
InputPayload and Script are especially important parameters.

The former specifies parameters to be passed to the script described below.
SourceImageId refers to the ImageId received as a result of the execution of aws:createImage in the first step.
In SourceRegion, refer to the automation system variable global:REGION.
This region is the region where the EC2 instance is created and Automation is executed, i.e., the region from which the AMI is copied.

The Script parameter describes the script to be executed.
In this case, we will specify Python code.
The content of the code to be executed is as follows

  • Receive the variables set in InputPayload.
  • Create a client object for boto3 EC2.
  • Execute the copy_image method of the client object to copy the AMI.
  • Return the result of the method execution.

The key to copying an AMI is to create a client object.
When creating the object, specify the copy destination in the region_name parameter.
This will allow you to copy the AMI to the intended region.

In SSM Automation, if you simply want to copy an AMI, you can also execute the aws:copyImage action.

https://docs.aws.amazon.com/systems-manager/latest/userguide/automation-action-copyimage.html

However, this action allows the source region to be specified, but not the destination region, so it was not used because it did not meet the requirements of this project.

SSM Association

Resources:
  CreateAndCopyImageAssociation:
    Type: AWS::SSM::Association
    Properties:
      AssociationName: !Sub "${Prefix}-CreateAndCopyImageAssociation"
      AutomationTargetParameterName: InstanceId
      Name: !Ref CreateAndCopyImageRunbook
      Parameters:
        AutomationAssumeRole:
          - !GetAtt CreateAndCopyImageRunbookRole.Arn
        DestinationRegion:
          - !Ref DestinationRegion
        InstanceId:
          - "{{RESOURCE_ID}}"
      Targets:
        - Key: !Sub "tag:${TagKey}"
          Values:
            - !Ref TagValue
      WaitForSuccessTimeoutSeconds: !Ref WaitForSuccessTimeoutSeconds
Code language: YAML (yaml)

Associate the aforementioned runbook with an EC2 instance.

For information on how to create SSM associations and run SSM Automation runbooks on EC2 instances, please see the following page.

あわせて読みたい
Create AMI using SSM Automation (one-time/scheduled) 【Create AMI using SSM Automation (one-time/scheduled)】 There are several ways to create an AMI. For example, the following page shows how to create one fro...

In the Targets property, set the tag information so that the aforementioned EC2 instance is the target of the association.

IAM Role for SSM

Resources:
  CreateAndCopyImageRunbookRole:
    Type: AWS::IAM::Role
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - ssm.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole
      Policies:
        - PolicyName: CreateAndCopyImagePolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - iam:PassRole
                Resource:
                  - "*"
Code language: YAML (yaml)

Normally, if no service role is specified, the default service link role (SLR), AWSServiceRoleforAmazonSSM, is used.
In this case, create the service role according to the following official AWS page.

https://docs.aws.amazon.com/systems-manager/latest/userguide/automation-setup-iam.html

In addition, grant the necessary permissions (iam:PassRole) for AMI creation and sharing as an inline policy.

Architecting

Use CloudFormation to build this environment and check its actual behavior.

Create CloudFormation stacks and check the resources in the stacks

Create CloudFormation stacks.
For information on how to create stacks and check each stack, please refer to the following pages.

あわせて読みたい
CloudFormation’s nested stack 【How to build an environment with a nested CloudFormation stack】 Examine nested stacks in CloudFormation. CloudFormation allows you to nest stacks. Nested ...

After reviewing the resources in each stack, information on the main resources created in this case is as follows

  • EC2 instance: i-07bd1e5c166136c88
  • SSM Automation runbook: saa-01-005-CreateAndCopyImageRunbook
  • SSM association: 9954eb73-83f6-4652-aa5b-4e29f78d4cab

Operation Check

Now that you are ready, check each resource from the AWS Management Console.

EC2 Instance

Detail of EC2 1.

The instance is successfully created.
The tag information shows that a tag specifying the target of the association has been set.

SSM Automation Runbook

Check the runbook you have created.

Detail of SSM 1.
Detail of SSM 2.
Detail of SSM 3.

You can see that the runbook has been successfully created.

There are three parameters in this runbook, the contents of which are to copy the AMI of the EC2 instance to another region after it is created.

SSM Association

Check association.

Detail of SSM 4.

You can see that an association has been created for the aforementioned runbook.

Detail of SSM 6.

Parameters for running the runbook.
Specify the IAM role, instance ID, and copy destination region.
Note that the instance ID is a pseudo-parameter.

https://docs.aws.amazon.com/systems-manager/latest/userguide/mw-cli-register-tasks-parameters.html

Detail of SSM 5.

An association is created with an instance that meets the tag criteria.

SSM Automation

Check the execution history of Automation.

Detail of SSM 7.

Automation is started for the instance.

Check the history of Step 1.

Detail of SSM 8.

aws:createImage has been executed and an AMI for the instance has been created.
The ID of the AMI created this time is “ami-011aba43717b3cfcd”.

Then check step 2.

Detail of SSM 9.

The aws:executeScript has been executed and the AMI created in step 1 has been copied to another region.
The ID of the AMI created this time is “ami-056701e3b4d8001d8”.

Check the created AMI.
First is the AMI from which the copy was made.

Detail of EC2 2.

Indeed, an AMI is created in the Tokyo region (ap-northeast-1).

Next is the AMI to copy to.

Detail of EC2 3.

The AMI is indeed copied to the Virginia Region (us-east-1).

Summary

We have shown you how to create an SSM Automation runbook, create an AMI from an existing EC2 instance, and copy this to another region.