はじめに
EC2インスタンスの自動起動停止は、2016年頃はLambdaFunctionを使って実現してました。
LambdaFunctionが出たばかりで楽しくて書いてみたんですけど、まじめに実現しようとすると仕組みが複雑化したり、バグがでたりすることなどが少し悩みでした。
その後SystemManagerのオートメーションが発表され、CloudWatchEventsからSSM Automationの組み込みのドキュメントを使って実現していました。
バグで動かないなんてことも無くなったのでよかったのですが、対象とするEC2インスタンスが増えてくると自動停止・起動対象のEC2インスタンスIDをCloudWatchEventsのパラメータに設定するのが厳しくなってきました。
さてどうしたか
ゴリゴリ書かずにAWSの機能だけでタグベースで自動起動・停止を実現できないかを考えていたのですが、AutomationActionにexecuteAwsApiが指定できるようになって実現できるようになりました。
AWS Systems Manager の新しい Automation アクションの使い方を紹介
https://aws.amazon.com/jp/blogs/news/onica-demonstrates-uses-for-new-aws-systems-manager-automation-actions/
つまり、CloudWatch EventsからSSM Automation Document(AWS-StopEC2Instance、AWS-StartEC2Instance)を呼び出すときにはインスタンスIDが必須になるのですが、ドキュメントを自分で作ることでタグやリソースグループを指定して起動停止できるようになります。
早速やってみます。
ドキュメントの作成
SystemManagerの画面を開き、左メニューのドキュメント→「Create automation」を選びます。
名前に「StopEC2InstancesUsingTags_StopTime」と入力し、「コンテンツ」→「Edit」をクリックします。
警告がでますがそのまま進み以下のyamlをコピペします。
タグ Key:StopTime, Value:8pm~11pmをAWS-StopEC2Instanceドキュメントに引数として渡してあげるように記載されています。
description: StopEC2Instances Using Tags:StopTime
schemaVersion: "0.3"
assumeRole: "{{ AutomationAssumeRole }}"
parameters:
StopTime:
type: String
default: 8pm
description: (Required) 8pm,9pm,10pm,11pm
allowedValues:
- 8pm
- 9pm
- 10pm
- 11pm
AutomationAssumeRole:
type: String
description: (Optional) The ARN of the role that allows Automation to perform the actions on your behalf.
default: ""
mainSteps:
- name: StopEC2Instances
action: aws:executeAwsApi
inputs:
Service: ssm
Api: StartAutomationExecution
DocumentName: AWS-StopEC2Instance
TargetParameterName: "InstanceId"
Targets:
-
Key: tag:StopTime
Values:
- "{{ StopTime }}"
これでドキュメントの作成は完成です。
動作確認してみる
対象のEC2インスタンスのタグにStopTime:8pmというタグを付与します。
先ほど作ったドキュメントStopEC2InstancesUsingTags_StopTimeを開き、オートメーションの実行をクリックします。
入力パラメータに8pmを指定して、実行します。
実行の状況はこのように見えます。
StopEC2InstancesUsingTagsが成功すると、組み込みドキュメントであるAWS-StopEC2Instanceが起動しているのが確認できます。
EC2インスタンスが停止したことをマネジメントコンソールで確認しましょう。
CloudWatchEventでスケジューリングする
午後8時に8pmタグが指定されたEC2インスタンスを停止するようにCloudWatchEventsに設定してみます。
ポイントは「SSM Automation」に先ほど指定したドキュメントを指定してください。
Automationの失敗を通知する
これもCloudWatchEventsで設定します。
Automationのイベントが変更されたタイミングでFailed,Timeout,CancelledになったときにSNSを使って通知します。
CloudWatchEventsは複数設定した場合でもこの通知設定は一つで問題ありません。
時間ごとに設定しないといけないのは少し面倒ですけどしょうがないですね・・・。
自動起動バージョン
念のため貼っておきます。
description: StartEC2Instances Using Tags:StartTime
schemaVersion: "0.3"
assumeRole: "{{ AutomationAssumeRole }}"
parameters:
StartTime:
type: String
default: 8am
description: (Required) 7am,8am,9am
allowedValues:
- 7am
- 8am
- 9am
AutomationAssumeRole:
type: String
description: (Optional) The ARN of the role that allows Automation to perform the actions on your behalf.
default: ""
mainSteps:
- name: StartEC2Instances
action: aws:executeAwsApi
inputs:
Service: ssm
Api: StartAutomationExecution
DocumentName: AWS-StartEC2Instance
TargetParameterName: "InstanceId"
Targets:
-
Key: tag:StartTime
Values:
- "{{ StartTime }}"
さいごに
AWS Systems Manager の新しい Automation アクションexecuteAwsApiがサポートされたことでより柔軟にアクションが指定できるようになりました。同じようにEC2の起動や、RDSの停止というアクションも実現可能ですしリソースグループを指定した停止も実現できるようになります。
参考までにリソースグループを指定する場合のドキュメントを張っておきます。
SystemManagerの画面でリソースグループを作成後、リソースグループ名を指定することでリソースグループまとめて停止が可能になります。
---
description: Exec AWS-StopEC2Instances
schemaVersion: "0.3"
assumeRole: "{{ AutomationAssumeRole }}"
parameters:
ResourceGroupName:
type: String
description: (Required) ResourceGroup Name 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: StopEC2Instances
action: aws:executeAwsApi
inputs:
Service: ssm
Api: StartAutomationExecution
DocumentName: AWS-StopEC2Instance
TargetParameterName: "InstanceId"
Targets:
-
Key: ResourceGroup
Values:
- "{{ ResourceGroupName }}"