最近、個人AWSアカウントを活発に利用しており、EC2インスタンス台数が増加してきました。その中で、EC2利用後、ついついインスタンス停止を忘れてしまっており、余計なコストが発生しております。そこでLambdaを利用し、EC2の定期停止設定をしてみました。
LambdaによるEC2定期停止設定の前提
- 対象リージョンはバージニア北部であること(後続のコードを修正することで変更可能)
- 定期停止対象のEC2に対して、タグ[key:EC2Auto_Stop, value:true]が付与済みであること
Lambda実行用IAMポリシー作成
まずはLambda実行用IAMポリシーを作成していきます。
1.IAMコンソール>左ペイン「IAMポリシー」>右上「ポリシーの作成」を押下
2.[アクセス許可を指定]にて、JSONで下記の権限設定を実施し、「次へ」をクリック
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"ec2:Stop*"
],
"Resource": "*"
}
]
}
3.[確認して作成]にて以下のように値を入力し、「ポリシーの作成」をクリック
ポリシー名:EC2AutoStop_Lambda_Policy
説明:EC2AutoStop_Lambda_Policy
一般的に、Lambda用のIAMポリシーを作成する際は下記に留意する
- 最低でもログ出力用にCloudWatch Logsへのアクセス許可が必要となる
- 最小権限の原則
⇛Lambda実行用IAMポリシーは複数のLambda間で共有しないのがベター
Lambda実行用IAMロール作成
前節にて作成したIAMポリシーを使用し、Lambda実行用IAMロールを作成します。
4.IAMコンソール>左ペイン「IAMロール」>右上「ロールを作成」を押下
5.[信頼されたエンティティを選択]にて、Lambdaを選択して「次へ」を押下
6.[許可を追加]にて、EC2AutoStop_Lambda_Policyを選択して「次へ」を押下
7.[名前、確認、および作成」にて以下のように値を入力し、「ロールの作成」をクリック
ロール名:EC2AutoStop_Lambda_Role
説明:EC2AutoStop_Lambda_Role
EC2定期停止用のLambdaを作成
いよいよEC2定期停止用のLambdaを作成です。
8.Lambdaコンソール>左ペイン「関数」>右上「関数の作成」を押下
9.[関数の作成」にて以下の値を入力し、右下「関数の作成」を押下
関数名:EC2AutoStop_Lambda
ランタイム:Python3.12
アーキテクチャ:x86_64
実行ロール:EC2AutoStop_Lambda_Role
10.Lambdaコンソール>左ペイン「関数」>EC2AutoStop_Lambdaを選択
11.[コードソース]タブに移動し、下記の値を入力したのち「Deploy」を押下
import boto3
#定数定義
REGION = 'us-east-1' #定期停止対象EC2のリージョンに応じて変更してください
def lambda_handler(event, context):
#EC2クライアントの作成
ec2 = boto3.client('ec2', region_name=REGION)
#タグ名:EC2Auto_Stop 値:true のEC2インスタンスIdを取得
response = ec2.describe_instances(
Filters=[
{
'Name': 'tag:EC2Auto_Stop',
'Values': [
'true',
],
},
],
)
#print("EC2describeコマンドの出力結果↓")
#print(response)
# インスタンスIDのみ取得
instance_ids = []
for reservation in response["Reservations"]:
for instance in reservation["Instances"]:
instance_ids.append(instance["InstanceId"])
#インスタンスIdの出力
#print("インスタンスIdのみ出力")
#print(instance_ids)
#EC2インスタンス停止処理
for instance_id in instance_ids:
try:
ec2.stop_instances(InstanceIds=[instance_id])
print(f"{instance_id}の停止に成功しました")
except ClientError as errorInstance:
print(f"{instance_id}の停止に失敗しました")
print({errorInstance})
return 0
上記コードは、以下ウェブサイトを参考に記述しました。
【初心者向け】無料でPythonの基本文法を5時間で学ぼう!
https://qiita.com/AI_Academy/items/b97b2178b4d10abe0adb
Boto3 1.35.19 ドキュメント
https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html
12.[設定]タブ>左ペイン「一般設定」>「編集」にて、実行タイムアウトを15分に変更
13.[テスト]タブに移動し、下記スクリーンショットのようにテスト設定を保存
Lambda定期実行用のEventルール作成
最後にLambda定期実行用のEventルールを作成します。
15.EventBridgeコンソール>左ペイン「ルール」>「ルールを作成」を押下
16.[ルールの詳細を定義]にて、下記スクリーンショットのように設定し「続行してルールを作成」を押下
17.[スケジュールを定義]にて、下記スクリーンショットのように設定し「次へ」を押下
18.[ターゲットを選択]にて、下記スクリーンショットのように設定し「次へ」を押下
19.[タグを設定]にて「次へ」を押下
20.[レビューと作成」にて「ルールの作成」を押下
終わり
LambdaでEC2の定期停止設定をしてみました。
自分が忘れっぽいだけかもしれませんが、EC2停止忘れってあるあるだと思っています。
特に個人環境は管理が雑になりがちですので、ちょっとした手間を大事にしたいと思います。