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 @twitter2025 AWS Community Builder / 2024 Japan AWS All Certifications Engineer
Recommends
こちらもおすすめ
-
「AWS請求代行・活用支援サービス」で技術とおサイフの安心を同時に実現
2016.6.1
-
約65%のコスト削減!AWS開発環境を見直すコスト最適化で無駄を排除
2023.12.19
-
Oracle を BYOL で使う時の AWS 仮想コアの話
2015.7.15
Special Topics
注目記事はこちら
データ分析入門
これから始めるBigQuery基礎知識
2024.02.28

AWSの料金が 10 %割引になる!
『AWSの請求代行リセールサービス』
2024.07.16

