Lambda編の記事ではPythonのコードをLambdaに登録してCloudWatchEventsから呼び出してEC2起動/停止のスケジューリングを実現しました。一昔前まではこの手法が王道だったようですが、現在はコードを書かずともCloudWatchEvents + SystemsManager(SSM)の組み合わせでできちゃいます。こちらの方法も試してみました。
IAMロールの作成
あらかじめIAMのメニューからロール、ポリシーを作成します。以下の権限が必要となります。
- CloudWatchからSSMのオートメーションを実行するための権限
- CloudWatchからEC2を停止/起動するための権限
ロール作成時、信頼されたエンティティはCloudWatch Eventsを選択し、以下のポリシーで作成します。
まず、ssm:StartAutomationExecution
でSSMAutomationの実行権限を与えていて、対象のドキュメントをEC2停止/起動に限定しています。<account_id>
の箇所は適宜読み替えてください。$DEFAULT
はバージョン指定です。
次に、EC2停止/起動の権限を付与しています。ec2:DescribeInstanceStatus
は起動/停止後のステータスチェックに使われているようです。この権限がなくともEC2の起動/停止はされますが、SSMAutomationの実行結果は「失敗」となるので付与しておきます。
※ポリシーの定義が面倒な場合はAmazonSSMAutomationRole
の管理ポリシーを利用しても良いかと思います。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:StartAutomationExecution"
],
"Resource": [
"arn:aws:ssm:ap-northeast-1:<account_id>:automation-definition/AWS-StartEC2Instance:$DEFAULT",
"arn:aws:ssm:ap-northeast-1:<account_id>:automation-definition/AWS-StopEC2Instance:$DEFAULT"
]
},
{
"Effect": "Allow",
"Action": [
"ec2:StartInstances",
"ec2:StopInstances",
"ec2:DescribeInstanceStatus"
],
"Resource": "*"
}
]
}
CloudWatch Eventsにスケジュールを登録
Lambda編と違うのはターゲットの選択です。種類は「SSMAutomation」を選択して、AWS-StartEC2Instance
またはAWS-StopEC2Instance
のドキュメントを選択します。あとは、対象のEC2のインスタンスID、あらかじめ作成したIAMロールを選択すればOKです。(cronのスケジュールは適当です)
ちなみに、ドキュメントのパラメータ指定にあるAutomationAssumeRole
は、SSMがドキュメントを実行する場合の権限を個別に割り当てたい場合に利用するようです。(※後述)
実行結果を確認
Systems Manger → 自動化の画面から履歴を確認することができます。
エラーになった場合は、実行IDをクリックして中身を確認してみましょう。
CloudWatch Eventsにスケジュールしたのにそもそも履歴が出ない場合は、おそらくSSMAutomationの実行権限が不足していますので、IAM設定を見直しましょう。
まとめ
今回はCloudWatchEvents + SystemsManagerでEC2自動起動・自動停止を試してみました。コードを書く必要がなく、簡単に設定できるのでとても便利ですね。個人的には、IAMの理解が深まった検証になりました。
簡単に設定できてコスト削減に直結しますので、積極的に使っていきたいですね。前回のLambda編と合わせて参考になれば幸いです。
AutomationAssumeRoleを指定する理由
2021/4/20追記
AutomationAssumeRole
を指定する意味がよくわからなかったのでサポートに問い合わせてみました。
公式ドキュメントだと以下のページが参考になります。
委任管理者を使用して、オートメーションを実行する
ランブックの詳細リファレンス - AWS-StartEC2Instance
まとめると次のようになります。
-
AutomationAssumeRole
を指定しない場合、Systems Manager オートメーションはこのドキュメントを実行するユーザーのアクセス許可を使用する -
AWSとしては
AutomationAssumeRole
を指定して(権限を分けて)実行することを推奨している -
AutomationAssumeRole
に指定するロールの権限は管理ポリシーのAmazonSSMAutomationRole
が推奨されている
つまり、AutomationAssumeRole
を利用して権限を分離し、最小にすることがベストプラクティスとなっています。AutomationAssumeRole
を指定しない場合、CloudWatch Eventsには本来必要のないEC2起動/停止の権限を割り当てていることとなり管理上わかりづらくなるためです。
CloudWatch Eventsのロールには、SSMAutomationにPassRoleする権限が必要なので注意。
PassRoleについては以下の記事が参考になります。
IAM ロールの PassRole と AssumeRole をもう二度と忘れないために絵を描いてみた
冒頭のポリシーからEC2関連を削除してPassRole
を追加しています。パスするロールはssm.amazonaws.com
を信頼したものを管理ポリシーと同じ名前で作成しました。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:StartAutomationExecution"
],
"Resource": [
"arn:aws:ssm:ap-northeast-1:<account_id>:automation-definition/AWS-StartEC2Instance:$DEFAULT",
"arn:aws:ssm:ap-northeast-1:<account_id>:automation-definition/AWS-StopEC2Instance:$DEFAULT"
]
},
{
"Effect": "Allow",
"Action": [
"iam:PassRole"
],
"Resource": "arn:aws:iam::<account_id>:role/AmazonSSMAutomationRole",
"Condition": {
"StringLikeIfExists": {
"iam:PassedToService": "ssm.amazonaws.com"
}
}
}
]
}
CloudWatch Eventsのルールで指定するAutomationAssumeRole
にはIAMロールのARNを入力すればOKです。
参考リンク
CloudWatch Events と Systems Manager で EC2の起動/停止をスケジュール化する
IAM ロールの PassRole と AssumeRole をもう二度と忘れないために絵を描いてみた