2018年版：lambdaでRDSを自動起動・停止

# きっかけ
久しぶりにlambdaを触ろうと思ったら記憶はないし昔と大分違っているので改めて記事にまとめます

# やりたいこと
ある時刻になったらRDSを自動起動・停止したいです。

# lambdaとは
https://aws.amazon.com/jp/lambda/

サーバーレスでコードを実行できるサービス。
サーバーがいらないのでサーバーを立てるよりやすい！
色々制約がありますが、今回は1日1回自動でRDSを停止させるだけなので、特に気にしません。
ちょくちょくアップデートされているようで、2018年にまた色々と変わったようです。そのためタイトルに「2018年版」とつけました。

# lambda実行に必要な操作
lambdaを実行できる状態にするには以下の操作が必要です。

-  ロールの作成
-  lambdaの実装
-  デプロイ

今回は上記の操作を経てlambdaを実行できる状態を作り、cloudwatchで定期的にlambdaを実行します。

## ロールの作成

lambdaを実行する為のロールを作成する必要があります。

## ロールについての簡単な説明
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_terms-and-concepts.html
ロールやポリシーに関する説明はドキュメントを参照してください。

ここではlambdaに必要なロールについて説明します。

lambda実行時に他のリソースを操作する場合、lambda関数に他のリソースのアクセス権をつけてあげる必要があります。
必要なアクセス権をロールとして定義し、lambda実行時にロールを指定してあげることで他のリソースを操作可能にします。

今回の場合lambdaにはRDSを起動・停止してもらいたいので、RDS起動・停止を許可するロールを作成し、付与します。

## ロール作成手順

1. IAMのコンソールからポリシーを作成する画面を開く
![iam_policy.png](https://qiita-image-store.s3.amazonaws.com/0/210944/bcbf515c-1d4f-4aa3-3b4f-b99ae12fb03e.png)

2. JSONタブを開き、以下のJSONをコピペする
![json.png](https://qiita-image-store.s3.amazonaws.com/0/210944/78c8d637-4367-166c-041e-09b342ed6992.png)

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

3.「Review Policy」をクリック。適当な名前を指定し、「Create Policy」をクリック。

# lambda関数の実装

## boto3を使用する

AWSのリソースを操作する為にpython3の[boto3](https://github.com/boto/boto3)というライブラリを使用します。

そのため、lambdaの実装はpython3で行います。

使い方は[ドキュメント](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html#using-boto-3)にあるとおり、とても簡単です。
以下の実装をローカルで動かせばDBを停止させることができます。（あらかじめboto3のインストールが必要です)

```
import boto3

dbinstance = 'testdb'

# 使用したいサービスを指定する
client = boto3.client('rds')
# 行いたい操作を実行
response = client.stop_db_instance(DBInstanceIdentifier=dbinstance)
print(response)
```

## lambdaの実装ルール

lambda実装時には[ハンドラー](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/python-programming-model-handler-types.html)を実装する必要があります。

lambda実行時にこのハンドラー関数が呼び出されます。

ハンドラーは以下の形で記載します。

```
def handler_name(event, context): 
    ...
    return some_value
```

eventやcontextとありますが、今回はlambdaにパラメータを渡す必要がないので省略します。詳しくはドキュメントを参照してください。

先ほどboto3を用いた実装をこのハンドラーで指定すると以下の実装になります。

```
import boto3


def lambda_handler(event, context):
    dbinstance = 'testdb'
    client = boto3.client('rds')
    response = client.stop_db_instance(DBInstanceIdentifier=dbinstance)
    print(response)
    return 0
```

まあ簡単！

# lambda関数をデプロイする

いくつかデプロイ方法がありますが、今回はすぐ動かしたいのでコードのコピペをします。

1. lambdaのダッシュボードから「関数の作成」をクリックする
<img width="1113" alt="スクリーンショット 2018-10-11 23.32.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/210944/c2eec0cd-fd81-f9a7-1762-3fbdaec9e255.png">


2. 「一から作成」を選択し、以下の値を選択する
ランタイム：Python3.6
ロール：既存のロールを選択
既存のロール：ロールの作成ステップで作成したロール
<img width="1078" alt="スクリーンショット 2018-10-11 23.32.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/210944/be0e7233-e022-3264-1344-1eff96b4213a.png">

3. 「関数の作成」をクリックする

4. lambda関数の実装ステップの実装を「関数コード」にコピペする

<img width="1071" alt="スクリーンショット 2018-10-11 23.40.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/210944/6be42ca7-3403-d39e-c7e2-c5bf41b7f657.png">
5. 右上の「保存」をクリックして完成！

# Cloudwatchで定期実行

## CloudWatchとは

AWSのリソースをモニタリングできるサービスです。
請求額を超えそうになったら通知したり、リソースを監視して何かあったら通知したりできます。
今回はこのCloudWatchのイベントを利用して定期的にlambdaを実行したいと思います。

## イベントを登録する

1.  CloudWatchのイベント画面を開きます
![cloudwatch.png](https://qiita-image-store.s3.amazonaws.com/0/210944/b4a06cb6-07be-55a1-7271-7a68d9f84945.png)

2. 「ルールの作成」をクリックする
![rule.png](https://qiita-image-store.s3.amazonaws.com/0/210944/3ba95d45-fee8-50a3-e79d-de6d572c2f9b.png)

3. 「スケジュール」、「Cron式」を選択し、[ドキュメント](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html)に基づき設定したい条件を書く
![schedule.png](https://qiita-image-store.s3.amazonaws.com/0/210944/bbaf398f-3ffa-6b92-18c9-0cc048f92e95.png)

※式を入力する際の注意事項
![checkpoint.png](https://qiita-image-store.s3.amazonaws.com/0/210944/c02f0d61-229c-71c6-cd3c-839e37aebd32.png)
<b>・上のキャプチャを見ていただければわかりますが、GMTで指定してください
・cron 式の日フィールドと曜日フィールドを同時に指定することはできません。一方のフィールドに値 (または *) を指定する場合、もう一方のフィールドで ? (疑問符) を使用する必要があります。</b>
linuxのcron設定の感覚でやると「パラメータ間違ってるよ！！！」と出てきてしまうので注意してください。

5.「ターゲットの追加」をクリックし、先ほど作成したtestdbを選択する

6.「設定の詳細」をクリックし、適当な名前を付けて「ルールの作成」

あとは時間まで待つ･･･

![rds.png](https://qiita-image-store.s3.amazonaws.com/0/210944/1756b15a-1150-0d99-cf7f-e06244e91db6.png)

testdbが停止中になっています。
無事lambdaが動きましたね！