EventBridgeスケジューラを使ってEC2の定期起動/停止を行う方法
こんにちは、データアナリティクス事業本部の八木です。
EC2が必要なのは一部の時間帯だけ。。。使わない時間は停止してコスト削減したいな。。。といった悩みをお持ちの方、いるのではないでしょうか?
数分の実行であればLambda、数時間の実行であればECSタスクに乗り換えるという手段もありますが、既存処理を移植しにくい、作業工数を取れないといった場合もあるかと思います。
そんな時に思い当たるのがEC2の定期起動/停止ではないでしょうか。
EC2の定期起動/停止方法として、従来はEC2のEventBridge + Lambda1や、EventBridge + Systems Manager2を利用する構成がとられてきました。
しかし前者の手法はLambdaのコードを書く必要があったり、後者の手法ではEC2がSSMサービスに通信可能でなければいけないなどの課題がありました。
(追記:SSMのAWS-StartEC2Instanceドキュメントでは、インスタンスはSSM管理下である必要はないため、SSMサービスへの通信は必要ありませんでした。)
そんな中、EventBridgeの新機能、EventBridgeスケジューラが登場しました!!!
EventBridgeから直接EC2の起動/停止が行えたら楽なのになーと思っていたのですが、まさにこれが可能になりました。
EventBridgeスケジューラは、スケジュール実行のEventBridgeルールのほぼ上位互換的な機能となっており、EventBridgeルールでは実行できなかったEC2の起動/停止アクションができるようになりました。
今回はこの機能を利用して、EC2の定期起動/停止をしてみます。
やってみた
前提
- 停止済みのEC2インスタンスが存在する
EventBridgeスケジューラ用IAMロールの作成
まず、EventBridgeスケジューラが利用するIAMロールを作成します。このロールはEC2の起動/停止アクションを許可します。
IAMロールの作成画面で信頼されたエンティティタイプに「カスタム信頼ポリシー」を選択し、以下のJSONを入力します。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "scheduler.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
ポリシー選択では、EC2フルアクセスを許可します。(実際はec2:StartInstances
とec2:StopInstances
の権限があれば十分です。)
定期起動のEventBridgeスケジューラ作成
EC2インスタンスを起動するEventBridgeスケジューラを作成します。
EventBridgeのコンソール→スケジュール→スケジュールの作成と進みます。
スケジュールのパターンで定期的なスケジュールを作成します。今回は1日回実行を行うように設定しました。
続いてターゲットAPIで「Amazon EC2」→「StartInstances」を選択します。
入力の項目ではStartInstancesのAPIリクエストパラメータ3を指定します。
以下のように起動を行うEC2インスタンスのIDを指定します。(複数指定可能です)
{ "InstanceIds": [ "i-yyyyyyyyyyyyyy" ] }
IAMロールは先に作成したロールを指定します。
以上で設定は完了です。
指定した時間にEC2を確認してみると、EC2が起動し始めていました。
CloudTrailも確認してみると、インスタンスのステータスがstoppedからpendingに変わり、起動されたことがわかります。
{ "eventVersion": "1.08", "userIdentity": { "type": "AssumedRole", "principalId": "AROAxxxxxxxxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxx", "arn": "arn:aws:sts::123456789012:assumed-role/ec2-scheduler/xxxxxxxxxxxxxxxx", "accountId": "123456789012", "accessKeyId": "ASIAxxxxxxxxxxxxx", "sessionContext": { "sessionIssuer": { "type": "Role", "principalId": "AROAxxxxxxxxxxxxxxxx", "arn": "arn:aws:iam::123456789012:role/ec2-scheduler", "accountId": "123456789012", "userName": "ec2-scheduler" }, "webIdFederationData": {}, "attributes": { "creationDate": "2023-01-25T03:54:44Z", "mfaAuthenticated": "false" } } }, "eventTime": "2023-01-25T03:55:15Z", "eventSource": "ec2.amazonaws.com", "eventName": "StartInstances", "awsRegion": "ap-northeast-1", "sourceIPAddress": "54.150.111.13", "userAgent": "AmazonEventBridgeScheduler, aws-sdk-java/2.19.14 Linux/4.14.301-224.520.amzn2.x86_64 OpenJDK_64-Bit_Server_VM/11.0.17+11-LTS Java/11.0.17 kotlin/1.3.72-release-468 (1.3.72) vendor/Amazon.com_Inc. md/internal exec-env/AWS_ECS_FARGATE io/async http/NettyNio cfg/retry-mode/legacy", "requestParameters": { "instancesSet": { "items": [ { "instanceId": "i-yyyyyyyyyyyyyy" } ] } }, "responseElements": { "requestId": "caa45bfb-32e0-4410-9a44-65337b5e9be7", "instancesSet": { "items": [ { "instanceId": "i-yyyyyyyyyyyyyy", "currentState": { "code": 0, "name": "pending" }, "previousState": { "code": 80, "name": "stopped" } } ] } }, "requestID": "caa45bfb-32e0-4410-9a44-65337b5e9be7", "eventID": "48c04297-345a-4e6d-bbf3-a166ea5bd540", "readOnly": false, "eventType": "AwsApiCall", "managementEvent": true, "recipientAccountId": "123456789012", "eventCategory": "Management", "tlsDetails": { "tlsVersion": "TLSv1.2", "cipherSuite": "ECDHE-RSA-AES128-GCM-SHA256", "clientProvidedHostHeader": "ec2.ap-northeast-1.amazonaws.com" } }
定期停止のEventBridgeスケジューラ作成
続いてEC2インスタンスの停止を行うEventBridgeスケジューラを作成します。
起動の時と同様、cronでスケジュールを登録しました。
ターゲットAPIで「Amazon EC2」→「StopInstances」を選択します。
入力にはStopInstancesのAPIリクエストパラメータ4を入力します。
以下のように停止を行うEC2インスタンスのIDを指定します。(複数指定可能です)
{ "InstanceIds": [ "i-yyyyyyyyyyyyyy" ] }
IAMロールには起動の時と同様のIAMロールを指定しました。
以上でスケジューラの設定は完了です。
指定時間にEC2インスタンスを確認すると、停止済みになっていました。想定通りにインスタンスが停止したようです。
CloudTrailのログを確認しても、期待通りにインスタンスの停止リクエストが記録されていました。
{ "eventVersion": "1.08", "userIdentity": { "type": "AssumedRole", "principalId": "AROAxxxxxxxxxxxxxxxxxxxx", "arn": "arn:aws:sts::123456789012:assumed-role/ec2-scheduler/xxxxxxxxxxxxxxxxxxxx", "accountId": "123456789012", "accessKeyId": "ASIAxxxxxxxxxxxxxxxxxxxx", "sessionContext": { "sessionIssuer": { "type": "Role", "principalId": "AROAxxxxxxxxxxxxxxxxxxxx", "arn": "arn:aws:iam::123456789012:role/ec2-scheduler", "accountId": "123456789012", "userName": "ec2-scheduler" }, "webIdFederationData": {}, "attributes": { "creationDate": "2023-01-25T05:04:54Z", "mfaAuthenticated": "false" } } }, "eventTime": "2023-01-25T05:05:21Z", "eventSource": "ec2.amazonaws.com", "eventName": "StopInstances", "awsRegion": "ap-northeast-1", "sourceIPAddress": "54.150.111.13", "userAgent": "AmazonEventBridgeScheduler, aws-sdk-java/2.19.14 Linux/4.14.301-224.520.amzn2.x86_64 OpenJDK_64-Bit_Server_VM/11.0.17+11-LTS Java/11.0.17 kotlin/1.3.72-release-468 (1.3.72) vendor/Amazon.com_Inc. md/internal exec-env/AWS_ECS_FARGATE io/async http/NettyNio cfg/retry-mode/legacy", "requestParameters": { "instancesSet": { "items": [ { "instanceId": "i-yyyyyyyyyyyyyy" } ] }, "force": false }, "responseElements": { "requestId": "aed457a8-b15a-4b67-91d4-b1bb16d79b66", "instancesSet": { "items": [ { "instanceId": "i-yyyyyyyyyyyyyy", "currentState": { "code": 64, "name": "stopping" }, "previousState": { "code": 16, "name": "running" } } ] } }, "requestID": "aed457a8-b15a-4b67-91d4-b1bb16d79b66", "eventID": "2bd2eca7-f6f8-4edc-b6a0-e3ca83b702d6", "readOnly": false, "eventType": "AwsApiCall", "managementEvent": true, "recipientAccountId": "123456789012", "eventCategory": "Management", "tlsDetails": { "tlsVersion": "TLSv1.2", "cipherSuite": "ECDHE-RSA-AES128-GCM-SHA256", "clientProvidedHostHeader": "ec2.ap-northeast-1.amazonaws.com" } }
最後に
今回はEventBridgeスケジューラによるEC2インスタンスの定期起動/停止方法をご紹介しました。
従来はLambdaなどを組み合わせる必要がありましたが、EventBridge単体で出来るようになったのが嬉しいポイントです。
ぜひこの機会に常時起動のEC2運用を見直してはいかがでしょうか?
以上、八木でした!