EC2を停止してからAMIを取得する自動パイプラインを【AWS Systems Manager Automation】で実装してみた
はじめに
こんにちは、YUJIです。
最近、「EC2のバックアップ取得を自動化したいが、静止点確保のためにEC2を停止が必要で、どうすれば良いかわからない。」
という旨のお問い合わせを、複数同時にいただいているのを見ました。
上記のご要望を叶えるために
- AWS Systems Manager Automationで一貫して処理できないか
- cronで日時指定して自動実行できるように、Amazon EventBridge RulesでAutomationを自動実行できないか
という所を目標に、実験してみます。
記事のターゲット
タイトルでEC2を停止してからAMIを取得しようとしているところから、お察しの通り
「簡単に静止点を確保した上で、AMIを取得したい。しかも自動で。」
という要望を持っている方向けの記事です。
静止点の確保だけで言えば
例えば、Windowsなら専用コンポーネントをEC2にインストールした上で
AWS BackupでVSSスナップショットを有効にする等、様々なアプローチがあります。
が、この記事ではもっと分かりやすく簡単に
EC2を止める→AMIを取得する→止めたEC2を開始する
というフローで実現したいと思います。
引用するjsonやyamlが長すぎて、この記事自体やたらボリュームがあって複雑そうに見えてしまうかもしれませんが
コピペして各リソースを作ってしまえば、実装は簡単です!
※あくまでも概念実証での実験なので、実際の挙動は検証環境等を使って確かめてください。
前提知識
・AWS Systems Manager Automationの概要を理解していること。
この記事のハンズオンを経験いただくと、スムーズに内容が入ってくると思います。
今回は下記のようなAutomationを作って、EventBridge Schedulerで自動実行させます。
ステップ1 EC2を停止する
ステップ2 EC2を強制停止する(ステップ1の失敗時のみ実行)
ステップ3 AMIを取得する
ステップ4 停止したEC2のNameタグを取得する
ステップ5 AMIにNameタグを付与する
ステップ6 停止したインスタンスを開始する
実装するだけなら、ステップ4とステップ5は必要無いです。
…が、NameタグがついてないAMIって気持ち悪いと思いませんか?僕は思います。
事前準備
EC2
対象のEC2に、AmazonSSMManagedInstanceCoreのポリシーが付いたIAMロールがアタッチされていること。
もしEC2をプライベートサブネットに設置する場合は
NATゲートウェイやVPCエンドポイントなどを使い、外部と443ポートでのアウトバウンド通信が可能であること。
Automation用のロール
信頼ポリシー
{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": "ssm.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
許可ポリシー ※内容を一部修正しました(2024/6/24)
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:DescribeInstances", "ec2:DescribeInstanceStatus", "ec2:StartInstances", "ec2:StopInstances", "ec2:DescribeImages", "ec2:CreateImage", "ec2:DescribeTags", "ec2:CreateTags" ], "Resource": "*" } ] }
Eventbridge用のロール
信頼ポリシー
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "events.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
許可ポリシー
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssm:StartAutomationExecution", "ssm:DescribeAutomationExecutions" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "ec2:DescribeInstances", "ec2:StopInstances", "ec2:StartInstances", "ec2:CreateImage", "ec2:CreateTags" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "iam:PassRole" ], "Resource": "*", "Condition": { "StringEqualsIfExists": { "iam:PassedToService": "ssm.amazonaws.com" } } } ]
紹介用に、権限はある程度広めでとっています。
気になる方は、対象リソースを*(ワイルドカード)とするのではなく、明示的に指定するなどカスタマイズしてみてください。
実装
Automation ランブックの作成
ランブックの作成ページに移動します。
次に、左上の鉛筆マークを押して、ランブックをお好きな名前に編集したら
[{ }コード] タブを選択して、表示された赤枠の編集部分に下記のyamlをペーストします。
description: |- # 概要 ステップ1 EC2を停止する ステップ2 EC2を強制停止する(ステップ1の失敗時のみ実行) ステップ3 AMIを取得する ステップ4 停止したEC2のNameタグを取得する ステップ5 AMIにNameタグを付与する ステップ6 停止したインスタンスを開始する schemaVersion: '0.3' assumeRole: '{{ AutomationAssumeRole }}' parameters: InstanceId: type: String description: (Required) EC2 Instance to stop AutomationAssumeRole: type: String description: (Optional) The ARN of the role that allows Automation to perform the actions on your behalf. default: '' mainSteps: - name: stopInstance action: aws:changeInstanceState nextStep: CreateAMI isEnd: false onFailure: step:forceStopInstance inputs: InstanceIds: - '{{ InstanceId }}' DesiredState: stopped - name: forceStopInstance action: aws:changeInstanceState nextStep: CreateAMI isEnd: false inputs: InstanceIds: - '{{ InstanceId }}' CheckStateOnly: false DesiredState: stopped Force: true - name: CreateAMI action: aws:createImage nextStep: getInstanceName isEnd: false inputs: InstanceId: '{{ InstanceId }}' ImageName: '{{ InstanceId }}-{{ global:DATE_TIME }}' outputs: - Name: CreatedImageId Selector: $.ImageId Type: String - name: getInstanceName action: aws:executeScript nextStep: taggingAMI isEnd: false inputs: Runtime: python3.8 Handler: handler Script: | import boto3 def handler(event, context): ec2 = boto3.client('ec2') response = ec2.describe_instances(InstanceIds=[event['InstanceId']]) tags = response['Reservations'][0]['Instances'][0]['Tags'] for tag in tags: if tag['Key'] == 'Name': return {'InstanceName': tag['Value']} InputPayload: InstanceId: '{{ InstanceId }}' outputs: - Name: InstanceName Selector: $.Payload.InstanceName Type: String - name: taggingAMI action: aws:createTags nextStep: startInstance isEnd: false inputs: ResourceIds: - '{{ CreateAMI.CreatedImageId }}' Tags: - Key: Name Value: '{{ getInstanceName.InstanceName }}-{{ global:DATE_TIME }}' - name: startInstance action: aws:changeInstanceState isEnd: true inputs: InstanceIds: - '{{ InstanceId }}' DesiredState: running
EventBridge ルールの作成
まずはルールの作成画面へ移動します。
ステップ1
ルール名:お好きなルール名
ルールタイプ:スケジュール
を設定し、続行してルールを作成するをクリック
ステップ2
お好みのスケジュールパターンで、Automationを動かしたい時間を設定します。
Amazon EventBridge cron 式のリファレンス
https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-cron-expressions.html
画像では、特定の時刻の実行を選び
毎日12:20(UTC) = 21:20(JST)でAutomationを動かすように、cron式を埋めています。
ステップ3
下記のように設定値を埋めていきます。
項目 | 設定値 |
---|---|
ターゲットタイプ | AWSのサービス |
ドキュメント | [Automation ランブックの作成]で作成済みのドキュメント |
InstanceID | 対象のインスタンスID(i-xxxxxxxxxxx) |
AutomationAssumeRole | 事前準備で作成したAutomation用のロール |
実行ロール | 既存のロールを使用 |
ロール名 | 事前準備で作成したEventbridge用のロール |
ステップ4
ルールにタグを付与できます。
スキップしても問題ありません。
ステップ5
ここまでで設定した内容が表示されるので、各項目が合っているかどうかを確認しましょう。
動作確認
※インスタンスの停止が伴うので、ターゲットのインスンタンスIDは間違っていないかどうかは確認しましょう
試しに、直近の時刻に走るよう、ルールのスケジュールを編集してみましょう。
今回は日本時間の毎日15:05にスケジュールしてみます。
UTC表記で紛らわしいですが、15:05(JST)にAutomationが発火していることが確認できます。
呼び出しのラグがあるので、秒単位では少し誤差がありますね。
実行されたAutomationの詳細を確認すると
・EC2の停止のリクエストを行い、ステータスが[停止中]から、[停止済み]になる
・AMIの取得を開始、AMIが利用可能になる
・AMIへNameタグをつける
・EC2を再度開始する
までの一貫した処理が、正常に行われていることが確認できます。
※停止が成功しているので、強制停止のステップは実行されません。
実際にAMIを見に行ってみると、ちゃんと居ました。
ただし、変数:global:DATE_TIMEがUTCを見に行ってるため、UTCの時刻でタグ付けされてしまってますね。
スクリプトとステップが複雑化してしまうので、NameタグにおいてのJSTへの変換は今回は行いません。
Automationが実行結果で「Success」と言っているので
疑う余地はあまり無いですが、EC2がちゃんと起動し直されていることも確認できます。
これで、「EC2の停止→停止済みのEC2からAMIを取得→EC2の開始」のフローを一貫して行うAutomationを
事前のスケジュール通りに、自動で行えるようになりました。
まとめ
以上、AWS Systems Manager AutomationとEventBridgeで
静止点の確保+AMI取得の自動化までを紹介してみました。
Automationのステップを編集すれば
「StartBackupJobのAPIを叩いてバックアップ処理自体はAWS Backup経由にする」など
カスタマイズは効くはずなので、是非要件に合わせて色々と試してみてください!
今回の記事が参考になれば幸いです。
最後まで読んでいただき、ありがとうございました。
テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!
Follow @twitter2023年9月に入社 邦ロックとVtuber好き
Recommends
こちらもおすすめ
-
AWSとWordPressで企業Webサイトを構築する
2019.5.16
-
atop コマンドを用いて Amazon EC2 の障害原因を切り分けよう!
2024.5.30
Special Topics
注目記事はこちら
データ分析入門
これから始めるBigQuery基礎知識
2024.02.28
AWSの料金が 10 %割引になる!
『AWSの請求代行リセールサービス』
2024.07.16