【AWS構築】EventBridge + Lambdaで毎日決まった時間にEC2を自動停止させる

# 背景

コスト削減のため、深夜帯で起動する必要性がないEC2は自動で停止をEventBridgeで行う。

:::note warn
本来EventBridgeだけでEC2の停止のスケジュールは可能ですが、タグでフィルターができないためLambda構成としております。
:::

## ゴール
20時で『PowerManagement』タグが付いているEC2を自動で停止させる


## EventBridge

### イベントバス作成
イベントバスとは、イベントの発生源とターゲットの仲介役となる設定。
イベントバス内でJsonを評価するなどしてターゲットの送信先を選ぶなどが可能
だが今回はcron式のため、ほとんど使わないが作成だけはしておく。

●イベントバスに関するドキュメント
https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-event-bus.html

左ペインから「イベントバス」選択⇒「イベントバス」作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/abbad6d1-c456-436e-9ad3-27bdaac90502.png)

暗号化やリソースベースポリシーは設定しない
リソース間で連携させる場合には、EventBridgeに対して別のAWSリソースへのアクセスを許可する必要性がある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/ca3fba00-568e-4f2f-b847-b862fe5a5bff.png)


## スケジュールグループ作成
スケジュールのタスク実行を行うためにはスケジュールグループを作成する
「test_schedulegroup」という名前のスケジュールグループを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/6a6e42fe-a71e-494a-b7b8-15c771708d21.png)

次にスケジュールグループにスケジュールを設定する

「名前」：任意
「スケジュールグループ」は先ほどのスケジュールグループ選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/6b1ddf88-2f78-4cc4-bc06-727d955877a9.png)

「定期的なスケジュール」を選択
「タイムゾーン」に「Asia/Tokyo」⇒「cron式」を入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/4d825fd9-ba5b-4f4b-99ac-673614b94d0b.png)

タイムゾーンを日本にしているため、UTC時間を日本時間に変換する必要などはありません。
```
cron(0 20 * * ? *)
```

次にターゲットで「Lambda」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/021051a9-215c-4783-b575-2322b94c8184.png)

Lambda関数はまだ作成していないので「新しい関数を作成」を選択⇒Python3.3のLambda関数
一旦関数の中身については後から作成するのでコードは適当で保存してください
ペイロードは空白でOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/587206ea-df20-4638-b065-82dc8cb9ce5c.png)


「スケジュールの有効化」をオン（画像はオフになってますがオンで良い）
「スケジュール完了後のアクション」をNONE
他はデフォルトでおｋ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/9df1c4b0-0186-41f9-b568-58cda2532aa3.png)

上記設定が完了し、作成を選択します（少し時間がかかる）

↓作成されました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/ca1b4ffb-437c-43a1-b9ad-eb215a3bf992.png)

    
## Lambda関数作成
続いて、EC2を起動するLambda関数を作ります。

### EC2の情報取得する関数
boto3はPythonのAWSのSDK

下記がアカウント内のEC2を全て取得するコード

```python
import boto3
ec2 = boto3.client('ec2')
def lambda_handler(event, context):
    response = ec2.describe_instances()
```

下記がEC2を停止するコード
```python
instance_ids = ["<インスタンスID>"]
response = ec2.stop_instances(InstanceIds=instance_ids)
```

:::note
ec2.stop_instancesの引数は配列にしないとエラー出るみたい。。。
:::

上二つを組み合わせて今回はVPC情報とタグ情報とEC2の状態でEC2をフィルターし、インスタンスを停止するLambda関数を作成します。

```Python
import boto3
ec2 = boto3.client('ec2')

def lambda_handler(event, context):
    vpc_id = "<VPCのID>"
    Filters = [
        {'Name': 'vpc-id', 'Values': [vpc_id]},
        {'Name': 'tag:PowerManagement', 'Values': ['ON']},
        {'Name': 'instance-state-name', 'Values': ['running']}
    ]
    response = ec2.describe_instances(Filters=Filters)

    # インスタンス停止処理
    instance_ids = []
    for reservation in response['Reservations']:
        for instance in reservation['Instances']:
            instance_ids.append(instance['InstanceId'])
    
    result = ec2.stop_instances(InstanceIds=instance_ids)
    print(f"停止処理結果: {result}")
```


作成したLambda関数に上記コードを張り付けて保存します。
Lambda関数の保存には、左下の「Deploy」をクリックします。
コードにエラーがなければ正常に更新されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/680656ca-21b4-4bb1-a450-704855e4ce0e.png)


## Lambdaをテスト

対象のVPC内にPowerManagementというキーでONというvalueを持つタグを持つEC2を立ち上げます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/7e381cd0-0174-485d-bc48-f3e08d5e923a.png)

「テスト」タブを開いて「テスト」をクリックします。（入力は必要ない関数のため、Jsonは書き換え不要）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/765fbf04-3fd1-41d3-a5f4-146141e68692.png)

また、「テスト」が完了するとpythonのprint文の出力などがCloudWatchLogsに出力されています。
ちなみに、resultの中身はこんな感じです。（APIの結果が返ってきてます）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/cdc72a92-cf5e-4027-9d57-35ebf92542fb.png)


Lambda起動後はEC2が停止されており、成功しております。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/b017712a-abf4-4d0b-a350-ac3123433d5d.png)