はじめに
サーバーレスアーキテクチャを構築する際、AWS LambdaからAmazon RDS(あるいはAurora)に接続する構成はよく使われます。しかし、アクセスが急増するとLambdaの並行数が一気に増え、データベース(DB)の最大コネクション数を超過して接続エラーが発生することがあります。本記事では、この問題を根本的に解決する「RDS Proxy」の導入方法と、具体的な設定手順をステップバイステップで解説します。
前提知識とRDS Proxyが必要な理由
通常のEC2やECSなどの常駐型アプリケーションと異なり、Lambdaはリクエストごとにインスタンスが起動・終了する一時的な実行環境です。各LambdaインスタンスがDB接続(コネクション)を確立し、処理終了後も一定時間保持されるため、アクセス集中時に接続数が簡単に枯渇してしまいます。
RDS Proxyを中間に配置することで、以下のメリットが得られます:
- コネクションプール: Lambdaからの接続をプールし、背後のDB接続を効率的に使い回すため、DBの負荷を大幅に軽減します。
- フェイルオーバーの高速化: DBのマルチAZ切り替え時のダウンタイムを大幅に短縮します。
- セキュリティ向上: IAMデータベース認証を利用して、Lambdaから安全に接続できます。
具体的な設定手順・設計方法
ここでは、VPC環境内に構築されたAurora PostgreSQLに、RDS Proxyを経由してLambdaから接続する手順を解説します。
ステップ1:Secrets Managerでの認証情報の登録
RDS ProxyはDBのユーザー情報をAWS Secrets Managerから安全に取得します。
- AWSマネジメントコンソールで「Secrets Manager」を開き、「新しいシークレットを保存する」をクリックします。
- シークレットのタイプで「Amazon RDS データベースの資格情報」を選択し、ユーザー名とパスワードを入力します。
- 対象のRDS/Auroraデータベースを選択し、シークレットを保存します(例:
my-db-secret)。
ステップ2:RDS Proxy用のIAMロールの作成
RDS ProxyがSecrets Managerから認証情報を読み取るためのIAMロールを作成します。信頼ポリシーに rds.amazonaws.com を指定し、以下のIAMポリシーをアタッチします。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:my-db-secret-xxxxxx"
}
]
}
ステップ3:RDS Proxyの作成
- RDSコンソールの「プロキシ」メニューから「プロキシを作成」をクリックします。
- エンジンファミリー(PostgreSQLまたはMySQL)を選択し、対象のDBクラスターを紐付けます。
- 「認証」セクションで、ステップ1で作成したSecrets Managerのシークレットと、ステップ2で作成したIAMロールを選択します。
- プロキシを作成すると、エンドポイント(例:
my-proxy.proxy-xxxxxx.ap-northeast-1.rds.amazonaws.com)が生成されます。これを控えておきます。
ステップ4:Lambda関数の作成と外部ライブラリの導入
PythonのLambda関数からRDS Proxy経由で接続するコードを記述します。PostgreSQLへの接続には psycopg2-binary ライブラリを使用します。
【重要】外部ライブラリの導入手順:
AWS Lambdaの標準実行環境には psycopg2 が含まれていないため、Lambdaレイヤーとしてアップロードする必要があります。ローカルのLinux環境やDocker環境等で以下のコマンドを実行し、ZIPを作成してLambdaレイヤーに登録してください。
mkdir python
pip install psycopg2-binary -t python/
zip -r psycopg2-layer.zip python/
作成した psycopg2-layer.zip をLambdaコンソールから「レイヤー」として登録し、対象のLambda関数にアタッチします。
Lambdaコード例(Python):
import os
import psycopg2
def lambda_handler(event, context):
try:
# 環境変数からRDS Proxyのエンドポイント等を取得
conn = psycopg2.connect(
host=os.environ['DB_PROXY_HOST'],
database=os.environ['DB_NAME'],
user=os.environ['DB_USER'],
password=os.environ['DB_PASSWORD'],
connect_timeout=5
)
with conn.cursor() as cur:
cur.execute("SELECT NOW();")
result = cur.fetchone()
print(f"Database Time: {result}")
conn.close()
return {"statusCode": 200, "body": "Success"}
except Exception as e:
print(f"Error: {e}")
return {"statusCode": 500, "body": "Connection Failed"}
実務での注意点
- ピン留め(Pinning)現象に注意: プリペアドステートメント(Prepared Statements)の使用や、セッションの一時テーブル作成などを行うと、RDS Proxyが特定のコネクションを固定(ピン留め)してしまい、コネクションプールが効率的に機能しなくなる場合があります。クエリの設計段階で注意が必要です。
- コスト: RDS Proxyは、プロキシが稼働するデータベースインスタンスのvCPU数に応じて1時間あたりで課金されます。検証環境など、不要な時間帯はインスタンスを停止するなどのコスト管理を徹底しましょう。
まとめ
LambdaとRDSを組み合わせるモダンなサーバーレス開発において、RDS Proxyは接続負荷問題を解決するための強力なソリューションです。設定は一見複雑に見えますが、本記事の手順に従うことで安全に導入できます。突発的なバーストトラフィックに耐えられる、堅牢なシステムを構築しましょう。