RDS自動起動停止をlambdaで

# はじめに
RDSの料金を節約するために夜中に停止して朝起動するジョブを作ります。
# RDSの作成
RDS上でテスト対象となるDBを作成します。

```json:DBの情報
  "DB識別子": "postgres-db"
```

# lambdaの作成
event変数でAction(Start/Stop)と対象のInstanceを取得して、対象DBのステータスを取得したあと起動/停止を行います。

```python:/lambda_function.py
import boto3
region = 'ap-northeast-1'

def lambda_handler(event, context):
    rds = boto3.client('rds', region_name=region)
    action = event["Action"]
    db_instance = event["Instance"]
    
    response = rds.describe_db_instances(DBInstanceIdentifier=db_instance)
    print(
        db_instance, 'is',
        response['DBInstances'][0]['DBInstanceStatus'],'now'
        )

    if action == "Start":
        rds.start_db_instance(DBInstanceIdentifier=db_instance)
        print('started your instance: ' + str(db_instance))
    elif action == "Stop":
        rds.stop_db_instance(DBInstanceIdentifier=db_instance)
        print('stopped your instance: ' + str(db_instance))
    else:
        print('Lamdba function could not be executed.')
```

DB停止用のテストjsonを作成します。

```json:stop-db1
{
  "Action": "Stop",
  "Instance": "postgres-db"
}
```

DB起動用のテストjsonを作成します。


```json:start-db1
{
  "Action": "Start",
  "Instance": "postgres-db"
}
```

lambda関数にrdsアクセス用のIAMロールを付与します。ロールのアクセスポリシーはビジュアルエディタで作成することができます。

```json:start-stop-rds-db
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "rds:DescribeDBInstances",
                "rds:StopDBInstance",
                "rds:StartDBInstance"
            ],
            "Resource": "arn:aws:rds:*:*:db:*"
        }
    ]
}
```

## lambdaのテスト実行

DBの起動と停止をテストしました。どちらも1秒以内にlambdaの処理は終わっていますが、このあと実際にDBが停止や起動するのには数分間くらいかかります。
### DBの停止

```
Test Event Name
stop-db1

Response
null

Function Logs
START RequestId: 45ad5172-4e9e-4a7e-8bf9-6692028cad5f Version: $LATEST
postgres-db is available now
stopped your instance: postgres-db
END RequestId: 45ad5172-4e9e-4a7e-8bf9-6692028cad5f
REPORT RequestId: 45ad5172-4e9e-4a7e-8bf9-6692028cad5f	Duration: 682.01 ms	Billed Duration: 683 ms	Memory Size: 128 MB	Max Memory Used: 68 MB

Request ID
45ad5172-4e9e-4a7e-8bf9-6692028cad5f
```

### DBの起動

```
Test Event Name
start-db1

Response
null

Function Logs
START RequestId: cbb0861c-31e6-46a7-a120-dface73a52e4 Version: $LATEST
postgres-db is stopped now
started your instance: postgres-db
END RequestId: cbb0861c-31e6-46a7-a120-dface73a52e4
REPORT RequestId: cbb0861c-31e6-46a7-a120-dface73a52e4	Duration: 714.55 ms	Billed Duration: 715 ms	Memory Size: 128 MB	Max Memory Used: 67 MB

Request ID
cbb0861c-31e6-46a7-a120-dface73a52e4
```

# EventBridge による自動実行

Amazon EventBridgeはジョブスケジューラのように利用できる製品です。定時実行する場合はルールと呼ばれるジョブネットのようなものを作成して、そこに実行したい処理を乗せることができます。

1. EventBridgeの画面でルールを新規作成します
1. ルール名を入力します。例:Start-RDS
1. パターンは[スケジュール]-[cron式]を選択して、毎日朝8時に起動するように```0 23 ? * * *```と設定しました。ここは日時をGMTで設定するので分かりづらいですが入力した後にローカルタイムで今後の起動スケジュールが表示されるので想定通りに動くか確認できます。
1. ターゲットを作成します。
    1. ターゲットの種類は[Lambda関数]を選択します。
    1. 機能で先ほど作成したLambda関数を選択します。
    1. 入力の設定でJSON形式で引数を渡すことができます。
    ```{"Action": "Start", "Instance": "postgres-db"}```
ここでターゲットを追加できるので、引数だけ変えていくつものRDSを起動することも可能です。
1. 必要ならタグを設定して[作成]ボタンで作成します。
1. 同様に停止のルールも作成します。


# おわりに
RDSは少々オンプレやEC2で構築するのに比べて少々割高なイメージがありますが、利用しない時間に止めておくことでうまくペイできる可能性があると思いました。

# 参考文献

https://qiita.com/YK0214/items/59bc0e5ae89f68af74b3

https://qiita.com/aoi1/items/fe0caaedb036ab79773a