[Amazon Web Services]LambdaでEC2の定期停止設定してみた

最近、個人AWSアカウントを活発に利用しており、EC2インスタンス台数が増加してきました。その中で、EC2利用後、ついついインスタンス停止を忘れてしまっており、余計なコストが発生しております。そこでLambdaを利用し、EC2の定期停止設定をしてみました。

## LambdaによるEC2定期停止設定の前提
\- 対象リージョンはバージニア北部であること（後続のコードを修正することで変更可能）
\- 定期停止対象のEC2に対して、タグ[key：EC2Auto_Stop, value：true]が付与済みであること

## Lambda実行用IAMポリシー作成
まずはLambda実行用IAMポリシーを作成していきます。

1.IAMコンソール＞左ペイン「IAMポリシー」＞右上「ポリシーの作成」を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822026/42b71a15-5695-5df1-aacb-5d218c1d4421.png)

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 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822026/73f5151b-bf76-01c1-2b04-508e0df02a0f.png)

:::note info
一般的に、Lambda用のIAMポリシーを作成する際は下記に留意する
\- 最低でもログ出力用にCloudWatch Logsへのアクセス許可が必要となる
\- 最小権限の原則
⇛Lambda実行用IAMポリシーは複数のLambda間で共有しないのがベター
:::

## Lambda実行用IAMロール作成
前節にて作成したIAMポリシーを使用し、Lambda実行用IAMロールを作成します。

4.IAMコンソール＞左ペイン「IAMロール」＞右上「ロールを作成」を押下

5.[信頼されたエンティティを選択]にて、Lambdaを選択して「次へ」を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822026/f0a31518-39ff-7f12-4bbb-50915dbb77fd.png)

6.[許可を追加]にて、EC2AutoStop_Lambda_Policyを選択して「次へ」を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822026/fc25bb6e-6971-8b56-3488-4c728696c317.png)

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
~~~

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822026/1c626050-4020-0ffa-aef1-0ea131346a4d.png)

:::note info
上記コードは、以下ウェブサイトを参考に記述しました。

【初心者向け】無料で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.[テスト]タブに移動し、下記スクリーンショットのようにテスト設定を保存
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822026/8509db31-adc9-2bbb-5049-9ce189470950.png)

14.テスト実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822026/4371166f-5dc6-2a52-bd8a-d7f85281b241.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822026/f2a11011-baba-4f0c-85cf-5e508a8fa496.png)

## Lambda定期実行用のEventルール作成
最後にLambda定期実行用のEventルールを作成します。

15.EventBridgeコンソール＞左ペイン「ルール」＞「ルールを作成」を押下

16.[ルールの詳細を定義]にて、下記スクリーンショットのように設定し「続行してルールを作成」を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822026/234d0076-d4c8-3bc6-8cab-42bfb2f3c971.png)

17.[スケジュールを定義]にて、下記スクリーンショットのように設定し「次へ」を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822026/0adbd577-934e-9755-fcf4-e6f07f201a6f.png)

18.[ターゲットを選択]にて、下記スクリーンショットのように設定し「次へ」を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822026/d8d48716-2974-60c0-6790-904a8ec8400c.png)

19.[タグを設定]にて「次へ」を押下

20.[レビューと作成」にて「ルールの作成」を押下

## 終わり
LambdaでEC2の定期停止設定をしてみました。
自分が忘れっぽいだけかもしれませんが、EC2停止忘れってあるあるだと思っています。
特に個人環境は管理が雑になりがちですので、ちょっとした手間を大事にしたいと思います。