インスタンスのAMIを作成して別リージョンにコピーするAutomationランブック
AWS SAAの出題範囲の1つである、弾力性に優れたアーキテクチャの設計に関する内容です。
AMIは別リージョンにコピーすることができます。
AWS リージョン内またはリージョンをまたいで Amazon マシンイメージ (AMI) をコピーできます。
AMI のコピー
今回はSSM Automationランブックを作成して、既存のEC2インスタンスからAMIを作成し、これを別リージョンにコピーします。
構築する環境
プライベートサブネット内にEC2インスタンスを作成します。
インスタンスは最新のAmazon Linux 2とします。
SSM Automationランブックを作成します。
このランブックの内容は以下の通りです。
- インスタンスのAMIを作成する。
- 作成したAMIを別リージョンにコピーする。
EC2インスタンスが設置されているリージョンはap-northeast-1、AMIをコピーするリージョンはus-east-1とします。
このランブックとインスタンスの関連付けも作成します。
CloudFormationテンプレートファイル
上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。
https://github.com/awstut-an-r/awstut-saa/tree/main/01/005
テンプレートファイルのポイント解説
(参考)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)
タグ設定がポイントです。
後述のSSM関連付けでは、このタグ情報に基づいて対象のインスタンスを指定するためです。
今回は以下の通りにタグを設定します。
- タグ名:MyRunbook
- タグの値:true
SSM Automationランブック
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)
カスタムランブックを作成します。
ランブックの作成については、以下のページをご確認ください。
Contentプロパティでランブックの中身を定義します。
parametersデータエレメントで、このランブックを実行するためのパラメータを指定します。
今回は以下の3つのパラメータを受け取ります。
- AutomationAssumeRole:Autometionがこのランブックを実行するために使用するサービスロールのARN
- DestinationRegion:AMIのコピー先のリージョン
- InstanceId:AMIを作成するインスタンスのID
mainStepsデータエレメントにランブックで実行する処理を記載します。
このランブックは2つのステップで構成されています。
1ステップ目
1つ目のステップはインスタンスからAMIを作成します。
AMIの作成はSSM Automationが提供するaws:createImageアクションを使用します。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/automation-action-create.html
inputsにaws:createImageを実行するために必要なパラメータを指定します。
このアクションを実行する際に与えることができるパラメータについては、上記のページを確認できますが、今回は3つ(InstanceId, ImageName, NoReboot)を設定します。
なおImageNameに渡すパラメータを指定する際に、オートメーションシステム変数を参照しています。
「global:DATE_TIME」で実行時の日時を取得することができます。
オートメーションシステム変数の詳細につきましては、以下のページをご確認ください。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/automation-variables.html
2ステップ目
2つ目のステップでは、先ほど作成したAMIを別リージョンにコピーします。
AMIのコピーはSSM Automationが提供するアクションaws:executeScriptを使用します。
指定されたランタイムとハンドラを使用して、提供された Python または PowerShell スクリプトを実行します。
aws:executeScript – スクリプトを実行する
inputsにaws:executeScriptを実行するために必要なパラメータを指定します。
特にInputPayloadとScriptが重要なパラメータです。
前者は後述のスクリプトに渡すパラメータを指定するものです。
SourceImageIdでは、1ステップ目のaws:createImageの実行結果として受け取れるImageIdを参照します。
SourceRegionでは、オートメーションシステム変数global:REGIONを参照します。
このリージョンは、EC2インスタンスが生成され、かつAutomationが実行されるリージョン、つまりAMIのコピー元リージョンです。
Scriptパラメータに実行するスクリプトを記述します。
今回はPythonコードを指定します。
実行するコードの内容は以下の通りです。
- InputPayloadで設定した変数を受け取る。
- boto3のEC2用クライアントオブジェクトを作成する。
- クライアントオブジェクトのcopy_imageメソッドを実行して、AMIをコピーする。
- メソッドの実行結果を返す。
AMIをコピーする上で、クライアントオブジェクトの作成がポイントです。
オブジェクトを作成する際に、region_nameパラメータにコピー先を指定します。
これでAMIを目的にリージョンにコピーすることができます。
なおSSM Automationにおいて、単純にAMIのコピーしたい場合は、aws:copyImageアクションを実行する方法もあります。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/automation-action-copyimage.html
ただこのアクションでは、コピー元リージョンは指定できますが、コピー先リージョンが指定できないため、今回の要件とは合わなかったため、使用しておりません。
SSM関連付け
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)
先述のランブックとEC2インスタンスを関連付けます。
SSM関連付けを作成して、EC2インスタンスに対してSSM Automationランブックを実行するため方法については、以下のページをご確認ください。
Targetsプロパティで、先述のEC2インスタンスが関連付けの対象となるように、タグ情報を設定します。
SSM用IAMロール
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)
通常、サービスロールを指定しない場合は、デフォルトのサービスリンクロール(SLR)であるAWSServiceRoleforAmazonSSMが使用されます。
今回は以下のAWS公式ページに従って、サービスロールを作成します。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/automation-setup-iam.html
さらにAMIの作成および共有に必要な権限(iam:PassRole)を、インラインポリシーとして付与します。
環境構築
CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。
CloudFormationスタックを作成し、スタック内のリソースを確認する
CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。
各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。
- EC2インスタンス:i-07bd1e5c166136c88
- SSM Automationランブック:saa-01-005-CreateAndCopyImageRunbook
- SSM関連付け:9954eb73-83f6-4652-aa5b-4e29f78d4cab
動作確認
準備が整いましたので、AWS Management Consoleから各リソースを確認します。
EC2インスタンス
正常にインスタンスが作成されています。
タグ情報を見ると、関連付けの対象を指定するタグが設定されていることがわかります。
SSM Automationランブック
作成したランブックを確認します。
ランブックが正常に作成されていることがわかります。
このランブックには3つのパラメータが存在し、EC2インスタンスのAMIを作成後、別リージョンにコピーする内容です。
SSM関連付け
関連付けを確認します。
先述のランブックに対する関連付けが作成されていることがわかります。
ランブックを実行するためのパラメータです。
IAMロール、インスタンスID、コピー先リージョンを指定します。
なおインスタンスIDは疑似パラメータを使用しています。
タグ条件を満たしているインスタンスと関連付けが作成されています。
SSM Automation
Automationの実行履歴を確認します。
インスタンスに対してAutomationが開始されています。
ステップ1の履歴を確認します。
aws:createImageが実行されて、インスタンスのAMIが作成されました。
今回作成されたAMIのIDは「ami-011aba43717b3cfcd」です。
続いてステップ2を確認します。
aws:executeScriptが実行されて、ステップ1で作成したAMIが別リージョンにコピーされました。
今回作成されたAMIのIDは「ami-056701e3b4d8001d8」です。
作成されたAMIを確認します。
まずコピー元のAMIです。
確かに東京リージョン(ap-northeast-1)にAMIが作成されています。
続いてコピー先のAMIです。
確かにバージニアリージョン(us-east-1)にAMIがコピーされています。
まとめ
SSM Automationランブックを作成して、既存のEC2インスタンスからAMIを作成し、これを別リージョンにコピーする方法をご紹介しました。