VPC内のLambdaを用いたAuroraからの情報取得

# やりたいこと
ユーザーの登録状況など、日ごとに情報を取得したいことがあります。取得したいデータがVPC内部のPrivate SubnetのAuroraにある場合、従来は内部にインスタンスを立てて取得する必要が以前はありました。しかし、結構前からLambdaをVPC内に立てることが可能になったので、このような要件の場合もLambdaを利用できるようになりました。

今回はVPC内にLambdaを動作させて、RDS内部の情報を定期的に取得するLambda関数を作成します。

# 想定構成
VPCのPrivate Subnet内部にRDSとLambdaが配置されます。Lambdaは1日に一度動作してAuroraから情報を取得し、S3にCSVファイルとして保存します。

<img width="356" alt="スクリーンショット 2017-07-22 20.21.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/8a98e264-0ecb-4676-b73d-3dfa295b7525.png">

# 必要な設定
RDSから情報を取得するVPC内のLambdaを作成する上でまず、以下の3点については既に用意されていると想定します。

* Amazzon Aurora
* VPC、Public Subnet、Private Subnetなどの設定

## IAMロールの作成
VPC内でLambdaを動作させるためにAWSLambdaVPCAccessExecutionRoleポリシーが必要となります。このポリシーを含んだIAMロールを作成します。

<img width="720" alt="スクリーンショット 2017-07-22 20.43.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/cfd5c190-0ab7-638d-904e-204b282d7158.png">

## セキュリティグループ
Auroraにはセキュリティグループが設定されていると思います。AuroraにアクセスするためにAuroraに設定されているセキュリティグループのインバウンドにこれから動作させるLambdaのセキュリティグループを追加する必要があります。

# Lambda関数の作成
VPC内のLambdaを作成していきます。Lambda関数の作成で"Blank Function"を選択します。
<img width="501" alt="スクリーンショット 2017-07-23 11.21.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/e369c88b-55ab-3321-7e43-d60fd338b852.png">
トリガーは後でCloudWatchイベントを設定しますので、次へを選択。
<img width="744" alt="スクリーンショット 2017-07-23 11.21.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/24d816d1-9f59-f0db-4b44-8d3d3e6dbc80.png">
Lambda関数名を適当に選択してpython2.7を選択します。
<img width="550" alt="スクリーンショット 2017-07-23 11.22.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/20ac167e-858a-5817-ee93-e80bbcda6b16.png">
先ほど作成したIAMロールを選択します。バッチ処理でデータベースからデータを取得してCSVファイルを作成する想定なので、タイムアウト時間を長く設定しておきます。
<img width="546" alt="スクリーンショット 2017-07-23 11.23.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/48be1791-63e0-b64a-dccd-6dce37981ffe.png">
詳細設定でVPCを選択します。Lambdaも通常のインスタンスと同様に可用性の観点からアベイラビリティゾーンそれぞれのプライベートサブネットを選択します。Auroraに接続するために先ほど設定したセキュリティグループを選択します。
<img width="646" alt="スクリーンショット 2017-07-23 11.24.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/94c4d69b-007e-2957-f5e2-363890a9a77d.png">

# Lambda関数の実装
## 事前準備
pymysqlというライブラリを利用しますので、working directoryを作成してそこにpymysqlをインストールしておきます。

```bash
$ pip install pymysql -t .
DistutilsOptionError: must supply either home or prefix/exec-prefix -- not both
```
しかし上記のようなエラーが発生します。これはMacの環境でbrewを使ってPythonをインストールしている場合に起こる問題で、ホームディレクトリに.pydistutils.cfgという名前のファイルを作成し以下を記述すれば問題は解決されます。

```bash
[install]
prefix=
```
## コード
app.pyには以下のようなコードを記述します。MySQLとの接続は、パフォーマンスの観点からlambda_handler関数外で行います。

```py
import sys
import logging
import pymysql

RDS_HOST="XXXX"
NAME="XXXX"
PASSWORD="XXXX"
DB_NAME="XXXX"

logger = logging.getLogger()
logger.setLevel(logging.INFO)

try:
    conn = pymysql.connect(RDS_HOST, user=NAME, passwd=PASSWORD, db=DB_NAME, connect_timeout=5)
except:
    logger.error("ERROR: Unexpected error: Could not connect to MySql instance.")
    sys.exit()

def lambda_handler(event, context):
    results = []
    with conn.cursor() as cur:
        cur.execute('select * from tablename')
        for row in cur:
            results.append(row)
    return results
```
## コードのデプロイ
zipファイルに固めてAWSコンソールを利用してアップロードします。

```bash
$ zip -r upload.zip *
```

# CloudWatchイベント
24時間に1度データを集計するためにLambdaを起動するためのCloudWatchイベントを事前に作成する必要があります。毎日0時(UTC: 日本時間午前9時)にデータを取得するように設定します。

# Link
http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/vpc-rds.html