この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、データアナリティクス事業本部の八木です。
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運用を見直してはいかがでしょうか?
以上、八木でした!