EC2インスタンスを切り忘れることが多く、さすがにちょっと自分に嫌気がさしてきたので、強制的に停止させる仕組みを作ることにしました。
なお、タイトルは0時としていますが、任意の時間(曜日、特定日・・・)を選択可能です。
前提条件
今回やりたいことは以下になります。
- 毎日0時になったら、もしEC2インスタンスが停止していなければ停止させる
- 停止対象のEC2インスタンスが複数ある
調べたところ、EC2インスタンスが1つだけの場合だと Systems Manager によりサクッと停止処理を実現できそうなのですが、複数のEC2インスタンスを停止させるとなると Lambda を使用しないと難しそうです。(Systems Manager の停止処理のイベントを複数定義する方法もありますが・・・)
ということで、上記条件を満たして毎日0時に自動停止する方法の備忘録します。
概要
使用するAWSサービス
今回の条件を実現するために必要なサービスは以下の通りでした。
- IAM
- Lambda
- EventBridge
仕組みのイメージ
EventBridge によりスケジュールイベントを発行
↓
Lambdaをコール
↓
LambdaからEC2インスタンスの停止処理
参考サイト
実行手順
大まかな流れは以下の感じです。
- LambdaがEC2インスタンスを停止できるように、Lambda用のIAMロール作成
- EC2インスタンスを停止させるためのLambda関数を作成
- IAMロールもアタッチ
- EventBridgeにてスケジュールイベントを設定し、Lambdaをコールするように設定
Lambda用のIAMロールの作成
ポリシーの作成
IAMのサービス画面に行き、下記の通りポリシー作成を選択します。
作成画面では、「JSON」タブを選択し、下記の JSON を直入力します。
(下記、公式より抜粋)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"ec2:Start*",
"ec2:Stop*"
],
"Resource": "*"
}
]
}
画面をそのまま進めて作成します。(名前は任意のものでよいです)
IAMロールの作成
IAMのサービス画面に行き、下記の通りロール作成を選択します。
Lambdaを選択します。
ポリシーの選択では、先ほど作成したポリシーのみを選択します。
以降は、画面をそのまま進めて作成します。(名前は任意のものでよいです)
EC2インスタンスを停止させるための Lambda の作成
Lambdaのサービス画面に行き、下記の通り「関数の作成」を選択します。
次画面で以下の通り、入力します。
ロールは、先ほど作成したものを選択します。
関数の作成については、下記のように入力します。
EventBridgeから呼ばれる際の引数でリージョンやインスタンスの配列、開始か停止かのフラグを与えるようにしています。
import boto3
# event引数で以下を渡されることとする
# 'Region':リージョン名
# 'Instances':インスタンスIDの配列(複数インスタンス可能)
# 'Action':Start or Stop
def lambda_handler(event, context):
region = event['Region']
instances = event['Instances']
ec2 = boto3.client('ec2', region_name=region)
if event['Action'] == 'start':
ec2.start_instances(InstanceIds=instances)
elif event['Action'] == 'stop':
ec2.stop_instances(InstanceIds=instances)
上記入力したら、「Deploy」ボタンを押します。
ここで、関数の作成は完了ですが、追加設定やテストをしておきます。
タイムアウトを変更
デフォルトではタイムアウトが3秒になっているみたいなので、ちょっとシビアです。
ケースバイケースですが、一応30秒とかにしてみます。
下記の通り、画面そのままで「設定」タブを選択し、編集ボタンを押します。
任意の秒数に変更して保存します。
Lambda関数の動作確認
続いていったん動作確認しておきます。
以下の画面で「Test」ボタンを押します。
下記のような画面が出てくるので、下記の通り入力します。
テストに入力するJSONは以下。
{
"Action": "stop",
"Region": "ap-northeast-1",
"Instances": ["i-xxxxx", "i-xxxxx", "i-xxxxx"] // インスタンスIDの配列
}
下記の通り、Testボタンを押してテストを実行してみます。
うまくいけば、指定したインスタンスが全て停止になっているはずです。
EventBridgeにLambda関数を登録する
EventBridgeのサービス画面に行き、「EventBridgeスケジュール」を選択し、「スケジュールを作成」を押します。
スケジュール名には任意の名前を入力します。
スケジュールのパターンについては、下記の通り「定期的なスケジュール」を選択→「cronベースのスケジュール」を選択します。
cron式は、0 15 ? * * *
としていますが、「分」と「時間」のところは任意のものでよいです。
(注意:UCT時間になっている場合があります)
ターゲットの選択は Lambda を選択します。
再試行ポリシーはいったん無効でいいと思います。
以降はそのまま進んでスケジュール作成完了です。
以上で、目的達成です。
コメント