Amazon EventBridgeのスケジュール機能を利用した、リソースの自動起動/停止

## この記事は何？
AWSのEvent Bridgeのスケジュール機能の使用メモです。

## EventBridgeのスケジュール機能とは
Event Bridgeのルール機能の中にあったスケジュール設定部分が、単独機能として実装されたものです。
単独機能になったことで、LambdaやSSMAutomation等と連携せずに直接ターゲットAPIを利用してリソースを操作できるようになったようです。

現在は、Event Bridgeのルール作成の際に、ルールタイプで「スケジュール」を選択すると、スケジュール機能へ誘導される感じにもなっています。
![Amazon_EventBridge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438093/08b82e3c-89ee-cc7f-a369-ecfaff254e8e.png)

## 実際に設定してみる
以下ケースをサンプルに設定してみます。

:::note info
<ケース１>
・2台のEC2を毎日AM9:00〜PM7:00のみ起動し、それ以外の時間は停止させる。
:::
構成は以下のように、EventBridgeに対象リソースの操作権限を付与すればOKです。

<img width="400" alt="スクリーンショット 2023-06-23 8.26.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438093/6da67540-f472-5cd0-599b-5d571453b18c.png">


### 1.IAMロールの作成
EventBridge SchedulerにEC2の停止/起動の権限を付与するIAMロールを作成します。

#### カスタム信頼ポリシー

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "scheduler.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

```
【参考ドキュメント】

https://docs.aws.amazon.com/scheduler/latest/UserGuide/setting-up.html#setting-up-execution-role

#### IAMポリシー

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:StopInstances",
                "ec2:StartInstances"
            ],
            "Resource": "*"
        }
    ]
}
```

### 2.EventBridge Schedulerの作成
EC2の停止と起動の2つのSchedulerを作成します。
cron指定時間とターゲットAPI以外は同じ内容になります。
| 項目 | 設定内容 |
|:-|:-:|
| スケジュール名 | ec2-automation-stop<br>ec2-automation-start|
|頻度|定期的なスケジュール|
|スケジュールの種類|cron ベースのスケジュール|
|フレックスタイムウィンドウ(※1)|オフ|
|cron 式|0 19 * * ? *<br>0 9 * * ? *|
|タイムゾーン|Asia/Tokyo|
|サービスタイプ|EC2|
|ターゲットAPI|StopInstances<br>StartInstances|
|ダーゲットリソース(※2)|Jsonフォーマットで作成|
|アクセス許可|手順1で作成したIAMロール|

(※1)フレックスタイムウィンドウ
時間指定することで、その時間枠内でスケジュールが実行されます。
例えば、15分を選択すると19:00~19:15の間で実行されるイメージです。

(※2)ターゲットリソース

```json
{
  "InstanceIds": [
    "i-xxxxxxxxxxxxxxxxx",
    "i-xxxxxxxxxxxxxxxxx"
  ]
}
```

設定は以上です。
あとはCloudTrailのイベント履歴でスケジュールどおりの挙動になっていればOKです。

##


:::note info
<ケース2>
RDSの一時停止を継続させる。　
:::
RDSの一時停止（1週間で自動起動される）をScheduler機能で継続させます。
ただし、実際には起動したRDSを再度停止させる処理になりますので、完全に停止状態が継続するものではありません。

設定パターンはいくつかあると思いますが、ケース1と同様に停止と起動の2つのSchedulerを設定すると、起動時間を短時間に抑えられます。

停止アクションのみでは、不要な起動時間が発生してしまう形になります。

例えば、以下のように毎日9時にRDSを停止させるスケジュールを設定したとします。
![Amazon_EventBridge_Scheduler.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438093/d8d35636-252c-3a46-b897-31cf2d31dc00.png)

初回の6/18の停止アクションは問題ありません。ただし、RDS停止は数分かかるため、1週間後（6/25）は9:05分頃にRDSが起動されます。
そのため、6/25の9:00時点では、まだ起動されないRDSに対して停止アクションが実行されますが、この場合の処理は無効になります。

<img width="400" alt="スクリーンショット 2023-06-28 8.14.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438093/2477e60d-38d4-e672-faa1-023082a6b0f7.png">

スケジュール機能では失敗したアクションを再試行させる仕様はありますが、この無効処理はアクション失敗と判断されず再試行されません。

その結果、次にRDSが停止されるのは翌朝9時になってしまい1日不要に起動させることになります。
もし停止アクションを1週間毎に実行する場合は、1週間起動された状態になってしまいます。

そのため、RDSの自動起動に合わせて停止アクションを設定するのではなく、自動起動前のステップとして起動アクションを行います。これにより、停止アクションを有効なものにし、スケジュールが正しく機能するようにします。

設定内容はケース１と同様で、IAMポリシーにはRDS停止アクションを設定します。
※DBClusterはAuroraの場合に使用
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "rds:StartDBInstance"
                "rds:StopDBInstance"
                "rds:StartDBCluster"
                "rds:StopDBCluster"
            ],
            "Resource": "*"
        }
    ]
}
```
あとはターゲットAPIとターゲットリソースをRDS用に設定するだけです。
| 項目 | 設定内容 |
|:-|:-:|
| スケジュール名 | rds-automation-stop<br>rds-automation-start|
|頻度|定期的なスケジュール|
|スケジュールの種類|cron ベースのスケジュール|
|フレックスタイムウィンドウ|オフ|
|cron 式(※1)|0 9 ? * Sun *<br>5 9 ? * Sun *|
|タイムゾーン|Asia/Tokyo|
|サービスタイプ|RDS|
|ターゲットAPI|StartDBInstance<br>StopDBInstance<br>StartDBCluster(Aurora)<br>StopDBCluster(Aurora)|
|ダーゲットリソース(※2)|Jsonフォーマットで作成|
|アクセス許可|手順1で作成したIAMロール|

(※1)cron 式
毎週日曜日の9:00(起動)、9:05（停止）させる場合


(※2)ターゲットリソース

```json
{
  "DbInstanceIdentifier": "DB識別子"
  "DbClusterIdentifier": "DB識別子"  　## Auroraの場合
}

```

RDSの起動時間の料金については、1時間未満のDBインスタンス時間であれば10分を最小料金として、秒単位の請求になるため、起動から10分以内であればどのタイミングで停止しても請求金額は同じです。

https://aws.amazon.com/jp/about-aws/whats-new/2019/04/aws-rds-per-second-billing/


一点補足として、コスト削減目的でRDSを停止させる場合、停止状態でもRDSの料金は別途発生しますのでご注意ください。
以下ドキュメントのとおり、停止することでインスタンス自体は課金はされませんが、ストレージは停止/起動の状態に関係なく課金されます。

> DB インスタンスが停止していても、プロビジョニング済みストレージ (プロビジョンド IOPS を含む) に対して課金されます。また、指定された保持ウィンドウ内の手動スナップショットや自動バックアップを含むバックアップストレージに対しても課金されます。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_StopInstance.html

> DB クラスターの停止中は、指定された保持期間内のクラスターストレージ、手動のスナップショット、および自動化されたバックアップストレージに対してのみ課金されます。DB インスタンス時間に対しては請求されません。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/aurora-cluster-stop-start.html

以上。