発端
使わないEC2を日次で停止させておきたい。ただ、タグをいちいち指定するのもめんどくさいから、問答無用でアカウント内の全EC2を停止させたい。
停止させる方法をぐぐってみたが、意外と出てこない
やりたい事(要件)
- タグを指定しないで全EC2を停止させる
- 起動はさせない
- EventBridgeSchedulerを使ってトリガーさせる
- 簡単に実装したい
EC2を停止させる方法
EC2を指定させる方法を列挙します。
- SSM Automation
- Lambda
- SSM Resource Scheduler
- AWS Instance Scheduler
要件に合うものは・・・
- SSM Automation
→ できそう。 - Lambda
→ コードを実装するのが面倒だができそう。 - SSM Resource Scheduler
→ 起動がセットになってるのでダメ。(自動起動はしたくない) - AWS Instance Scheduler
→ 同上
結局選んだのは
結果的にLambdaで実装しました。理由としてはLambdaで実装すると結構スリムに作れる&Lambdaのコンソールからトリガー、ロールにアクセスできるので管理が楽そうだったからです。
コードの実装に関してはChatGPTにお願いすると一瞬で出力してくれました。ナニトゾナニトゾ
実装
1.Lambda関数の作成
以下のソースコードでLambda関数を作成しました。
ランタイムはPython3.13です。作成後にタイムアウト時間を1分に変更してください。
デフォルトの3秒のままだと実行がタイムアウトして停止が実行されませんでした。
import boto3
def lambda_handler(event, context):
# EC2クライアントを作成
ec2 = boto3.client('ec2')
all_instance_ids = []
instance_id = ""
try:
# 停止したいインスタンスのIDを指定
response = ec2.describe_instances()
# reservationsからInstancesリストを取り出す
instances_list = response.get('Reservations', [])
for reservation in instances_list:
for instance in reservation.get('Instances', []):
instance_id = instance.get('InstanceId')
# インスタンスを停止
response = ec2.stop_instances(InstanceIds=[instance_id])
print(f"Stopping EC2 instance: {instance_id}")
print(f"Response: {response}")
return {
'statusCode': 200,
'body': f'Successfully initiated stop for instance'
}
except Exception as e:
print(f"Error stopping instance {instance_id}: {str(e)}")
return {
'statusCode': 500,
'body': f'Error stopping instance {instance_id}: {str(e)}'
}
2.実行ロールの変更
作成された実行ロールのままではEC2を停止させるポリシーが不足しているので、対応したポリシーを追加します。
具体的にはLambdaの実行ロールに対して以下のポリシーを追加しました。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "StopEC2InMyAccount",
"Effect": "Allow",
"Action": "ec2:StopInstances",
"Resource": "arn:aws:ec2:*:<アカウントID>:instance/*"
},
{
"Sid": "ListUpEC2InstanceID",
"Effect": "Allow",
"Action": "ec2:DescribeInstances",
"Resource": "*"
}
]
}
3.トリガーの追加
Lambdaコンソールからトリガーを追加します。
こんな感じで作りました。毎日の21:00JSTにトリガーが起動する設定です。
まとめ
現在存在している方法が大体インスタンスのタグを指定するか直接インスタンスIDを指定して停止させる方法ばかりなので、Lambdaでの方法が一番シンプルに作成できるのではないかと思います。
もっといい方法があったらコメントをお願いします!