Systems Manager Automation enables you to run a sequence of workflows (AWS API calls, provisioning instances, creating buckets, and triggering Lambda functions) through the convenience of a single SSM Automation document.
One of the major benefits you are getting is you no longer need to maintain tooling servers or run scripts locally on your computer. You can automate or schedule most of the maintenance and deployment tasks as a runbook style SSM documents that define the actions to perform.
In this hands-on post, we’ll create a custom AWS SSM Automation document to create an AMI of 1 instance or more and copy the AMI cross regions.
1./ Create a Iam role
1- Navigate to the IAM Console and create a role for System Manager with the below JSON policy. This policy grants the System Manager, the ability to Describe Tags, create and copy Images.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:Describe*", "ec2:CreateSnapshot", "ec2:CopySnapshot", "ec2:CreateTags", "ec2:ModifySnapshotAttribute", "ec2:CreateImage", "ec2:CopyImage", "ec2:RegisterImage" ], "Resource": "*" } ] }
2./ Create SSM Automation Document
1- From the AWS console, select Systems Manager.
2- When you get to the front page of the service, use the left hand panel and go down to the bottom of the menu to select Documents
3- From the main page, select the Create Automation button to build an automation document
4- Enter the name of the automation document and select the Editor option to enter a the document directly into the console
5- Copy the below code:
description: '' schemaVersion: '0.3' assumeRole: '{{ AutomationAssumeRole }}' parameters: InstanceId: type: String description: ' (Required) Target EC2 InstanceId' allowedPattern: '^i-[a-z0-9]{8,17}$' AutomationAssumeRole: type: String description: (Required) The ARN of the role that allows Automation to perform the actions on your behalf. ImagePrefix: type: String description: Choose Prefixes from one of the choices below. allowedValues: - ManualBackup - DEPLOY TargetRegion: type: String description: Region to copy the Ami to default: us-west-2 mainSteps: - name: RecordStartTime action: 'aws:executeScript' inputs: Runtime: python3.8 Handler: script_handler Script: | from datetime import datetime, timezone def script_handler(params: dict, context): return get_current_time().strftime('%Y%m%d_%H%M') def get_current_time(): return datetime.now(timezone.utc) InputPayload: {} outputs: - Name: StartTime Selector: $.Payload Type: String - name: GetInstanceName action: 'aws:executeScript' inputs: Runtime: python3.8 Handler: script_handler Script: | import boto3 def script_handler(events, context): instanceId = events["InstanceId"] ec2 = boto3.client('ec2') tags = ec2.describe_tags( Filters=[{'Name': 'resource-id', 'Values': [instanceId]}])['Tags'] if not tags: return (instanceId) for tag in tags: if (tag['Key']) == "Name": result = tag['Value'] return (result) InputPayload: InstanceId: '{{InstanceId}}' outputs: - Name: result Selector: $.Payload Type: String - name: CreateImage action: 'aws:createImage' inputs: InstanceId: '{{InstanceId}}' ImageName: '{{RecordStartTime.StartTime}}_{{GetInstanceName.result}}_{{ImagePrefix}}' NoReboot: true - name: CreateTagsImage action: 'aws:createTags' maxAttempts: 1 onFailure: Continue inputs: ResourceType: EC2 ResourceIds: - '{{ CreateImage.ImageId }}' Tags: - Key: Name Value: '{{RecordStartTime.StartTime}}_{{GetInstanceName.result}}_{{ImagePrefix}}' - Key: Automation-Id Value: '{{automation:EXECUTION_ID}}' - Key: Owner Value: YallaLabs - Key: SourceInstanceName Value: '{{GetInstanceName.result}}' - Key: Amazon-SSM Value: 'true' - name: CrossRegionImageCopy action: 'aws:executeScript' inputs: Runtime: python3.8 Handler: script_handler Script: | import boto3 def script_handler(events, context): newImageId = events['newImageId'] sourceregion = events['sourceregion'] targetregion = events['targetregion'] creationtime = events['creationtime'] instancename = events['instancename'] imageprefix = events['imageprefix'] ec2 = boto3.client('ec2', region_name=targetregion) result= ec2.copy_image( Name=creationtime + "_" + instancename + "_" + imageprefix, SourceImageId=newImageId, SourceRegion=sourceregion ) new_ami= result['ImageId'] ec2.create_tags( Resources=[new_ami], Tags=[ {'Key': 'Name', 'Value': creationtime + "_" + instancename + "_" + imageprefix}, {'Key': 'CreatedOn', 'Value': str(creationtime)}, {'Key': 'SourceImageId', 'Value': str(newImageId)}, {'Key': 'SourceInstanceName', 'Value': str(instancename)}, {'Key': 'SourceRegion', 'Value': str(sourceregion)} ] ) return (new_ami) InputPayload: newImageId: '{{ CreateImage.ImageId }}' sourceregion: '{{ global:REGION }}' targetregion: '{{ TargetRegion }}' creationtime: '{{RecordStartTime.StartTime}}' instancename: '{{GetInstanceName.result}}' imageprefix: '{{ImagePrefix}}' outputs: - Name: ImageId Selector: $.Payload Type: String
6- Once that’s done click Create Automation
3./ Execute the Automation Document
1- Navigate to Systems Manager > Change Management > Automation
2- Select Execute Automation
3- In Choose document go to Owned by me
4- Pick the one we just created, new Windows will open. Click Execute automation button
5- Fill out the details for Execute automation document
- AutomationAssumeRole: The ARN of the role that allows Automation to perform the actions on your behalf
- InstanceId: Toggle Show Interactive instance picker on and select your instance
- ImagePrefix: Choose a prefix for image, or you can set yours
- TargetRegion: Region to copy the Ami to
6- Select Execute
New window will open to check the status of the currently running automation executions.
Conclusion
In this post, we demonstrated how to create an AMI and copy it to another region using AWS Systems Manager auomation document. You might want to check the following guides: