[EC2 RDS Aurora]AWSコスト削減_自動起動・停止機能の作り方(EventBridge+SystemsManagerの自作ランブック)

# はじめに
**【背景】**
コスト削減の為、検証環境にて平日夜間・休日中、
EC2/RDS/Auroraを自動で起動・停止する仕組みを作りました。

**【利用サービス】**
![EC2・RDS自動停止・起動_構成図png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/6fbaf71a-1b06-3732-3db5-0479f22b9478.png)
・SystemsManager(自作ランブック)
　各種運用作業を自動化できるサービスです。
　ランブックとは、運用作業の内容をYAML又はJSONで記述したものになります。
　今回はAWS側で提供している各種起動・停止のランブックを呼び出す形で自作します。
　[ご参考：ランブックについて](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/automation-documents.html)

・EventBridge
　AWSで発生するイベントを検知、又はスケジューリング機能を使用することで、
　様々なAWSサービスの実行トリガーとなるようなサービスです。
　今回はスケジューリング機能を使用して、定刻になったら自作ランブックを実行します。

**【その他考慮事項】**
・起動時
　RDS/Auroraの起動後にEC2を起動する必要があった為、
　RDS/Auroraのステータス遷移を待つステップにて実現しました。

・停止時
　EC2の停止後にRDS/Auroraを停止する必要があった為、
　EC2のステータス遷移を待つステップにて実現しました。

# SystemsManagerの自作ランブック作成
起動・停止の処理は、SystemsManagerの自作ランブックに記載します。
## 起動分

コンソールからSystemsManagerの画面に遷移し、左ペイン内の「ドキュメント」を押下します。
![SSM1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/2d60a12b-837b-b046-b61f-e5a3d31ee198.png)

ドキュメント一覧画面の右上「Create Document」ボタンを押下し、更に「Automation」を押下します。
![SSM2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/2050a04f-e0ee-99c3-251e-4f0ea93636c5.png)

ドキュメントの編集画面にて「名前」欄を入力し、「エディタ」タブ内の「編集」を押下します。
![SSM3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/e34f42f7-b7b1-b05c-d1c0-97e834954f56.png)

恐れることなく「OK」を押下します。
![SSM4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/61e4c3fb-4c23-42cc-bf26-64d789124a5f.png)

ドキュメントエディタにデフォルトでテンプレートが記載されていますが、
全て削除して下記コードをコピペし、右下の「オートメーションを作成する」を押下します。
(ClusterName,DBClusterIdentifier,InstanceIdはサンプルの為、適宜修正してください。)
![SSM6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/af2accd1-539b-9bae-c1f9-201e3a3bb1ef.png)

yaml形式の記述になります。
コードの解説は下記の通りです。
```yaml
description: 'start instance'
schemaVersion: '0.3'
mainSteps:
  - name: StartAuroraCluster
    action: 'aws:executeAutomation'
    inputs:
      DocumentName: AWS-StartStopAuroraCluster
      RuntimeParameters:
        ClusterName: DB1-cluster
        Action: Start
  - name: StartRds
    action: 'aws:executeAutomation'
    inputs:
      DocumentName: AWS-StartRdsInstance
      RuntimeParameters:
        InstanceId: DB2
  - name: WaitForAuroraToStart
    action: 'aws:waitForAwsResourceProperty'
    inputs:
      Service: rds
      Api: DescribeDBClusters
      DBClusterIdentifier: DB1-Cluster
      PropertySelector: '$.DBClusters[0].Status'
      DesiredValues:
        - available
  - name: StartEC2
    action: 'aws:executeAutomation'
    inputs:
      DocumentName: AWS-StartEC2Instance
      RuntimeParameters:
        InstanceId:
           - i-xxxxxxxxxxxxxxxxx
```
「mainSteps:」内に各ステップ(処理)を記載していきます。

- StartAuroraClusterステップ
　'aws:executeAutomation'というアクションを使用して、別のドキュメントを呼出します。
　Auroraを起動する為、AWS側が提供しているドキュメント(AWS-StartStopAuroraCluster)を呼出します。
　RuntimeParameters内に、呼出すドキュメントに必要なパラメーターを記載します。
　必要なパラメーターはAuroraの識別子と、起動・停止の指定になります(起動(Start)を指定しています)。

- StartRdsステップ
　'aws:executeAutomation'というアクションを使用して、別のドキュメントを呼出します。
　RDSを起動する為、AWS側が提供しているドキュメント(AWS-StartRdsInstance)を呼出します。
　RuntimeParameters内に、呼出すドキュメントに必要なパラメーターを記載します。
　必要なパラメーターはRDSの識別子のみになります。

- WaitForAuroraToStartステップ
　'aws:waitForAwsResourceProperty'というアクションを使用して、
　「StartAuroraClusterステップ」で起動したAuroraが利用可能ステータスに遷移するのを待機します。
　　※RDSについてもステータス遷移の監視が必要ですが、
　　　AWS-StartRdsInstance内のステップに組み込まれている為、RDS分については不要になります。

- StartEC2ステップ
　'aws:executeAutomation'というアクションを使用して、別のドキュメントを呼出します。
　EC2を起動する為、AWS側が提供しているドキュメント(AWS-StartEC2Instance)を呼出します。
　RuntimeParameters内に、呼出すドキュメントに必要なパラメーターを記載します。
　必要なパラメーターはEC2のインスタンスIDのみになります。

## 停止分
上記起動分と同様の手順になる為、コードのみ記載します。

```yaml
description: 'stop instance'
schemaVersion: '0.3'
mainSteps:
  - name: StoptEC2
    action: 'aws:executeAutomation'
    inputs:
      DocumentName: AWS-StopEC2Instance
      RuntimeParameters:
        InstanceId:
          - i-xxxxxxxxxxxxxxxxx
  - name: WaitForEC2ToStop
    action: 'aws:waitForAwsResourceProperty'
    inputs:
      Service: ec2
      Api: DescribeInstances
      InstanceIds:
        - i-xxxxxxxxxxxxxxxxx
      PropertySelector: '$.Reservations[0].Instances[0].State.Name'
      DesiredValues:
        - stopped
  - name: StopAuroraCluster
    action: 'aws:executeAutomation'
    inputs:
      DocumentName: AWS-StartStopAuroraCluster
      RuntimeParameters:
        ClusterName: DB1-Cluster
        Action: Stop
  - name: StopRds
    action: 'aws:executeAutomation'
    inputs:
      DocumentName: AWS-StopRdsInstance
      RuntimeParameters:
        InstanceId: DB2
```
「mainSteps:」内に各ステップ(処理)を記載していきます。

- StoptEC2ステップ
　'aws:executeAutomation'というアクションを使用して、別のドキュメントを呼出します。
　EC2を停止する為、AWS側が提供しているドキュメント(AWS-StopEC2Instance)を呼出します。
　RuntimeParameters内に、呼び出すドキュメントに必要なパラメーターを記載します。
　必要なパラメーターはEC2のインスタンスIDのみになります。

- WaitForEC2ToStopステップ
　'aws:waitForAwsResourceProperty'というアクションを使用して、
　「StoptEC2ステップ」で停止したEC2が停止済みステータスに遷移するのを待機します。

- StopAuroraClusterステップ
　'aws:executeAutomation'というアクションを使用して、別のドキュメントを呼出します。
　Auroraを停止する為、AWS側が提供しているドキュメント(AWS-StartStopAuroraCluster)を呼出します。
　RuntimeParameters内に、呼び出すドキュメントに必要なパラメーターを記載します。
　必要なパラメーターはAuroraの識別子と、起動・停止の指定になります(停止(Stop)を指定しています)。

- StopRdsステップ
　'aws:executeAutomation'というアクションを使用して、別のドキュメントを呼出します。
　RDSを停止する為、AWS側が提供しているドキュメント(AWS-StopRdsInstance)を呼出します。
　RuntimeParameters内に、呼び出すドキュメントに必要なパラメーターを記載します。
　必要なパラメーターはRDSの識別子のみになります。

# SystemsManagerの自作ランブックを手動で実行してみる
停止処理を実行する自作ランブックを手動で実行してみます。
（ログインしているIAMユーザーの権限に起動・停止権限がある前提です。）
ドキュメントの一覧画面の「自己所有」タブ内に、先ほど作成した自作ランブックが存在するはずです。
ドキュメントのタイトルである「Stop-Instance」を押下します。
![SSM7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/d863d831-aceb-cbd0-543d-fa63d44a4434.png)

詳細画面の右上の「オートメーションを実行する」を押下します。
![SSM8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/73d41797-3852-83fe-0f0b-6f939af22676.png)

別タブで実行画面が表示されます。
パラメーターの指定はコード内に直書きしていて不要な為、そのまま右下の「実行」を押下します。
![SSM9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/cc383542-b35a-20ce-07d3-332aef467068.png)

実行状況画面にて全てのステップのステータスが"成功"となっていることを確認します。
![SSM10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/e6c6fe44-b90c-44be-d6c7-5a3bc026d137.png)


起動分も上記と同様の手順となる為、実行状況画面のみ記載します。
![SSM11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/183a4124-524b-687c-560c-48fb97cbb11e.png)

# EventBridgeの設定
手動での稼働確認がとれたので、定刻で自動実行するようにEventBridgeの設定をします。

## EventBridge用IAMロール作成
まず、EventBridgeにアタッチするIAMロールを作成します。
コンソールからIAMの画面に遷移し、左ペインの「ポリシー」を押下します。
ポリシー一覧画面にて右上の「ポリシーの作成」を押下します。
![SSM12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/26f6ab44-b4f3-7cea-edf8-ad13a98e846b.png)

ポリシー作成画面にて、「JSON」タブ内の赤枠に下記JSONをコピペします。
![SSM13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/e7e32de1-e706-bee7-2d10-af53a5840f1c.png)
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ec2StartStop",
            "Effect": "Allow",
            "Action": [
                "ec2:RebootInstances",
                "ec2:StartInstances",
                "ec2:StopInstances"
            ],
            "Resource": "*"
        },
        {
            "Sid": "rdsStartStop",
            "Effect": "Allow",
            "Action": [
                "rds:RebootDBCluster",
                "rds:StartDBCluster",
                "rds:StopDBCluster",
                "rds:RebootDBInstance",
                "rds:StopDBInstance",
                "rds:StartDBInstance"
            ],
            "Resource": "*"
        },
        {
            "Sid": "other",
            "Effect": "Allow",
            "Action": [
                "ec2:Describe*",
                "rds:Describe*",
                "cloudwatch:*",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:Encrypt",
                "kms:GenerateDataKey*",
                "kms:DescribeKey",
                "kms:CreateGrant",
                "compute-optimizer:GetEC2InstanceRecommendations",
                "compute-optimizer:GetEnrollmentStatus"
            ],
            "Resource": "*"
        }
    ]
}
```

タグの設定は不要の為、そのまま「次のステップ：確認」ボタンを押下します。
![SSM14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/41b491e7-0551-d436-3fda-f868f2124ec0.png)

「名前」欄を入力し、右下の「ポリシーの作成」を押下します。
![SSM15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/1843e695-9733-3922-9d32-fb60f2074ad2.png)

次にIAMロールを作成します。
IAM画面にて左ペイン内の「ロール」を押下し、右上の「ロールを作成」ボタンを押下します。
![SSM16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/9ec38eb5-00a3-c48b-9da2-dc0acac64957.png)

信頼されたエンティティタイプ「カスタム信頼ポリシー」を選択し、赤枠内に下記JSONをコピペします。
右下の「次へ」ボタンを押下します。
![SSM17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/51ce9ab3-92bd-a7ed-a200-d5a755e7b8e6.png)

```JSON
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "events.amazonaws.com",
                    "ssm.amazonaws.com",
                    "rds.amazonaws.com",
                    "ec2.amazonaws.com"
                ]
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
```

先程作成したIAMポリシーと、AmazonSSMFullAccessを選択し、右下の「次へ」ボタンを押下します。
(SystemsManagerへの操作権限として一番強い権限を付与していますが、
  必要に応じてカスタムポリシー内に権限を絞って記載することをお薦めします。)
![SSM18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/514639a4-1746-1a2f-4924-8498e71bf10e.png)

「ロール名」欄を入力し、右下の「ロールを作成」ボタンを押下します。
EventBridge用のIAMロール作成作業は以上です。
![SSM19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/bae160bf-8c6e-dc4d-e1ea-624111292108.png)

## EventBridgeのルール作成
事前準備(IAMロール作成)が完了したので、自動実行のトリガーとなるEventBridgeのルールを作成します。
コンソールからEventBridgeの画面に遷移し、左ペイン内の「ルール」を押下します。
ルールの一覧画面にて「ルールを作成」ボタンを押下します。
![SSM20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/b6821b1c-6345-84b4-d6c1-33d8e69a81d5.png)

ルール作成画面にて「名前」欄を入力し、ルールタイプは「スケジュール」を選択します。
その後、「次へ」ボタンを押下します。
![SSM21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/67d1444a-aac9-16f6-0ae4-8fb1c7ab2e40.png)


平日夜間、及び、土日は停止しておきたいので、
火曜日～土曜日の24:00に停止処理が実行されるように下記の通り設定し、
左下の「次へ」ボタンを押下します。
　・スケジュールパターン：特定の時刻
　・cron式：(00 15 ? * 2-6 *)
　　※UTC時刻の為、日本時刻(JST)は設定時刻 + 9時間になります(15+9=24時)。
![SSM22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/80cb0cfe-b662-3861-2167-f33799ee02d8.png)

作成したSystemsManagerの自作ランブック(停止)をターゲットに設定し、
作成したIAMロールを使用するように設定します。
その後、右下の「次へ」ボタンを押下します。
![SSM23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/12fe5a12-b6ad-dc2f-247e-4f29d33c7884.png)

タグの設定は不要なので、そのまま右下「次へ」ボタンを押下します。
![SSM24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/52682e91-ee8d-2ff1-409e-38d05d0e66f7.png)

最終確認画面に遷移するので、設定内容を確認し、
右下「ルールの作成」ボタンを押下します(画像割愛)。
以上で停止分のEventBridgeの設定は完了です。
そして、EC2/RDS/Auroraの自動起動・停止機能実装作業も全て完了です。
（起動分は同様の手順になる為、割愛します。）

# 稼働確認
EventBridgeにて設定したスケジュールで自動実行された結果、正常終了しているか確認してみます。
コンソールからSystemsManagerの画面に遷移し、左ペイン内の「自動化」を押下します。
実行状況画面にて作成した処理のステータスが"成功"となっていることを確認します。
![SSM25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/76e98871-f762-a618-68bc-1ac88f2d64d8.png)

# おわりに
皆様のコスト削減の参考になれば幸いです。