4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

RDS Proxyを作成して、lambdaで利用する

Last updated at Posted at 2021-12-03

概要

RDS Proxyをセットアップする手順を記載する

なぜRDS Proxyを使わないといけないか

LambdaからRDSへのアクセスはアンチパターンと言われています。(調べるまで知りませんでした)
その理由は、Lambdaはリクエストごとに起動し、その都度RDSに対してコネクションを張ろうとするため、
コネクション上限を超えたLambdaからのアクセスはエラーとなってしまうためです。
Lambda起動の頻度が高いほどコネクションが多くなってしまうのですね。。。

lambdaが終了しても、コネクションが残ってしまい、接続数の上限に達してしまう

参考

AWS

RDS Proxyについての記事

lambdaのコードをzipで圧縮してアップロード

前提

RDSにインスタンスとテーブルは作成されていること

[検証用] RDSにインスタンスを作成し、テーブルの作成手順

※ 起動の手順は省略

MySQL

CREATE DATABASE stream_test;

USE stream_test;

CREATE TABLE `fruits` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `fruits` (name) VALUES ('orange'), ('apple');

PostgreSQL

CREATE DATABASE stream_test;

\c stream_test;

CREATE TABLE "fruits" (
  "id" SERIAL,
  "name" varchar(255) NOT NULL DEFAULT ''
);

INSERT INTO "fruits" (name) VALUES ('strawberry'), ('banana');

手順

  1. シークレットマネージャーを登録する
  2. RDS Proxyを登録する
  3. Policyを作成する
  4. lambdaを登録する
  5. テストを実行する

シークレットマネージャーを登録する

RDS Proxyで利用されるuserとpasswordをシークレットマネージャーに登録

  • ユーザー名
  • パスワード
  • データベース

RDS Proxyを登録する

  • プロキシ識別子: 任意
  • エンジンの互換性: 任意
  • Transport Layer Security が必要: PostgreSQLの場合は必須
  • データベース: 任意(PostgreSQLは、version 10 もしくは 11のみ対応)
  • Secrets Manager シークレット: 前述のシークレット
  • IAM ロール: IAMロールを作成
  • IAM 認証: 無効(SSMを利用するので、無効)
  • サブネット : (変更しない)

Policyを作成する

LambdaからRDS Proxyを参照できるPolicyを作成する

  • タグ(任意)
    • キー: Name
    • 値 - オプション: 任意
  • 名前: 任意(前述のタグと同じもの推奨)
  • 説明: 任意( ex: Secret manager available in lambda )

JSON

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetResourcePolicy",
                "secretsmanager:GetSecretValue",
                "secretsmanager:DescribeSecret",
                "secretsmanager:ListSecretVersionIds"
            ],
            "Resource": [
                "{secretのARN}"
            ]
        }
    ]
}

lambdaを登録する

"一から作成" を選択

  • 関数名: 任意
  • ランタイム: Python3.8 (他の言語、バージョンでも良いが、今回利用するレイヤーが、3.8向けのものです)

レイヤーの追加

Python3.8に対応したレイヤーを探して使う(2021年12月3日時点で、3.9向けのものは、このリポジトリでは準備されていない)
PostgreSQLを利用したので、 psycopg2 を利用

今回は、こちらを参照

arn:aws:lambda:ap-northeast-1:770693421928:layer:Klayers-python38-aws-psycopg2:1

以下は他のサイトで見つけた psycopg2

arn:aws:lambda:ap-northeast-1:898466741470:layer:psycopg2-py38:1

設定

  • 一般設定

    • タイムアウト: 30秒(任意です)
  • IAMロール

    • ポリシーの追加
    • 前述で作成したPolcy
    • AWSLambdaVPCAccessExecutionRole

※ kinesisを利用する場合は、AmazonKinesisFullAccessを追加

  • VPC

    • VPC: RDSのあるVPC
    • サブネット: 全て選択
    • セキュリティグループ: RDS Proxyと同じもの
  • データベースプロキシ

    • 既存のデータベースプロキシの選択: 前述のRDS Proxy
  • データベースプロキシ追加後、IAMロール

    • RDS ProxyのPolicyがあるか確認
    • ex) AWSLambdaRDSProxyExecutionRole-12345678-1234-1234-1234-123456789012

lambda登録

import json
import os
import sys
import boto3
import psycopg2
import base64


# PostgreSQL Connection
def connect():
    ENDPOINT="{前述のRDS Proxyのエンドポイント}"
    PORT="5432"
    USR="{前述のRDS Proxyに登録したユーザ}"
    REGION="ap-northeast-1"
    DATABASE="{任意のデータベース名}"

    client = boto3.client('rds')
    token = client.generate_db_auth_token(DBHostname=ENDPOINT, Port=PORT, DBUsername=USR, Region=REGION)
    con = psycopg2.connect(host=ENDPOINT, database=DATABASE, user=USR, password=token)

    return con


# EXECUTE SELECT
def select_execute(con, sql, values):
    print(sql)
    with con.cursor() as cur:
        cur.execute(sql, values)
        records = cur.fetchall()

    return records


def lambda_handler(event, context):
    con = connect()

    sql = 'SELECT COUNT(1) AS count FROM fruits'
    records = select_execute(con, sql, [])

    return {
        'statusCode': 200,
        'body': f"calllog_id: {records[0][0]}"
    }

テストを実行する

fruitsの個数が表示されれば、正常に完了です。

Test Event Name
test1

Response
{
  "statusCode": 200,
  "body": "fruits count: 2"
}

Function Logs
START RequestId: 6f6d853f-e213-41e4-a75c-fc6f1a927238 Version: $LATEST
SELECT COUNT(1) AS count FROM fruits
END RequestId: 6f6d853f-e213-41e4-a75c-fc6f1a927238
REPORT RequestId: 6f6d853f-e213-41e4-a75c-fc6f1a927238	Duration: 1437.65 ms	Billed Duration: 1438 ms	Memory Size: 128 MB	Max Memory Used: 74 MB	Init Duration: 330.97 ms

Request ID
6f6d853f-e213-41e4-a75c-fc6f1a927238

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?