Lambda + Amazon EventBridge で特定のタグがついているEC2を自動起動/自動停止させる

こちらの記事とほぼ同じ内容です。
lambda関数でエラー出たので少し改修しました。

https://zenn.dev/creationup2u/articles/0d6274febecaf9

## 主な手順

こちらを目標に進めていきます。
記載を省いてる部分に関してはデフォルトの設定で進めてもらえればと思います。

>『AutoStart』タグに『enable』が入ったインスタンスを平日09時に起動
>『AutoStop』 タグに『enable』が入ったインスタンスを平日18時に停止

1. IAMポリシー作成
2. IAMロール作成
3. Lambda関数作成
4. EventBridgeでルール作成
5. 動作テスト

## IAMポリシー作成

IAMを設定します。
EC2の起動や停止、CloudWatch logsへの書き込み権限などをlambda関数に与えます。

こちらのマネージドポリシーを使用するか、JSONエディタに直接書き込みます。

・AmazonEC2FullAccess
・CloudWatchFullAccess

ポリシー名は任意で

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*",
                "ec2:DescribeInstances"
            ],
            "Resource": "*"
        }
    ]
}
```

## IAMロール作成

ロール名は任意で

先程作成したポリシーをアタッチします。


## Lambda関数作成

[ 関数を作成 ] → [ 一から作成 ]

関数名は任意で

ランタイム：Python 3.8
デフォルトの実行ロール：既存のロールを使用する → 先程作成したロールを指定

コード
```
import boto3

region = 'ap-northeast-1'

def get_target_instance_id(tag_name, tag_value):
    instance_id_list = []
    ec2 = boto3.client('ec2', region_name=region)
    ec2_data = ec2.describe_instances()
    for ec2_reservation in ec2_data['Reservations']:
        for ec2_instance in ec2_reservation['Instances']:
            ec2_tags = ec2_instance.get('Tags', {})
            ec2_tags_dict = {tag['Key']: tag['Value'] for tag in ec2_tags}
            if ec2_tags_dict.get(tag_name, 'NoSuchTag').lower() == tag_value.lower():
                instance_id_list.append(str(ec2_instance['InstanceId']))
    return instance_id_list

def lambda_handler(event, context):
    print("Target instance has Value [ " + event.get('TagValue') + " ] on Tag [ " + event.get('TagName') + " ]")
    target_instances = get_target_instance_id(event.get('TagName'), event.get('TagValue'))
    ec2 = boto3.client('ec2', region_name=region)

    # start EC2
    if event.get('CallType') == 'start':
        ec2.start_instances(InstanceIds=target_instances)
        print('started instances: ' + str(target_instances))

    # stop EC2
    elif event.get('CallType') == 'stop':
        ec2.stop_instances(InstanceIds=target_instances)
        print('stopped instances: ' + str(target_instances))

    # other
    else:
        print("invalid CallType")
        print(event)
```

## EventBridgeでルール作成

起動用、停止用と別々にルールを作成します。
起動用のルール作成後に停止用ルールの作成も行ってもらえればと思います。

Amazon EventBridge のコンパネに移動します。
[ ルール ] → [ ルールを作成 ]

ルール名、説明は任意で

イベントパス：default
ルールタイプ：スケジュール

※ルールタイプを選択後の注意点
右側の [ EventBridge Scheduler で続行 ] ではなく [ 続行してルールを作成 ] をクリックします。
![Amazon EventBridge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070588/7a1d4a9d-beb4-55ee-40ea-b8882c28e9e0.png)

### スケジュール

平日9時に起動させたい場合のスケジュール内容

UTCとJST(日本のタイムゾーン)で9時間の時差があるので UTC 0:00 に起動するように設定しています。
18時に停止させたい場合は9時間前の UTC 09:00 に設定すればOKです。

![スケジュール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070588/36abcb05-67aa-bc3f-6afb-8dc14a66fba9.png)

### ターゲット

ターゲットタイプ：AWSのサービス
ターゲットを選択：lambda関数
機能：先程作成したlambda関数

追加設定
ターゲット入力を設定：[ 定数(JSON テキスト) ]
```
{
  "CallType": "start",
  "TagName": "AutoStart",
  "TagValue": "enable"
}
```
停止用のルール作成時は "CallType" と "TagName" の部分を書き換えてもらえればと
![スクリーンショット 2023-06-19 104034.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070588/64ed3d68-1171-e1de-41ee-21cb523a1802.png)

ルール作成時に自動的にlambda関数に紐づきます。

## 動作テスト

テスト実行で動作確認します。
ここで動作の確認ができたら設定完了です、あとは対象時間帯に自動起動/自動停止を行ってくれます。

対象インスタンスのタグに "AutoStart"、値に "enable" を設定して停止させておきます。

lambda関数コンパネ → 作成したlambda関数 → [ コード ] → Test

イベントJSON
```
{
  "CallType": "start",
  "TagName": "AutoStart",
  "TagValue": "enable"
}
```
一度作成しているので「保存されたイベントを編集」選択してますが、
ここでは「新しいイベントを作成」を選択してもらえればと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070588/64777547-4725-4b68-a9ce-a7a00cd5aa7e.png)

以上です。

これで特定のタグを設定する事で自動起動/自動停止を行ってくれるようになります。
分かりにくい部分指摘してもらえてたら修正します。