AWS RDS Proxyを設定しLambdaの接続を最適化する手順

はじめに

サーバーレスアーキテクチャにおいて、AWS LambdaからAmazon RDS(またはAurora)への接続は、実務で非常によくあるユースケースです。しかし、Lambdaが急激にスケールアウトした際、データベースの最大接続数(コネクション数)の上限に達し、接続エラーが発生することが多々あります。この課題を解決するのが「Amazon RDS Proxy」です。本記事では、LambdaからRDS Proxy経由で安全かつ効率的にデータベースへ接続する設定手順と、実務における設計のベストプラクティスを解説します。

前提知識/必要な理由

  • 接続のプーリング:データベース接続をプールして再利用し、RDSのメモリとCPU負荷を軽減します。
  • 自動フェイルオーバーの高速化:マルチAZ構成において、フェイルオーバー時の接続切り替え時間を大幅に短縮します。
  • セキュリティの向上:IAM認証やAWS Secrets Managerと連携し、データベースの認証情報をセキュアに管理できます。

具体的な設定手順・設計方法

以下は、RDS PostgreSQL/MySQLを対象としたRDS Proxyの設定ステップです。

ステップ1:Secrets Managerでのデータベース認証情報の作成

RDS Proxyはデータベースの認証情報をAWS Secrets Managerから安全に取得します。

  • AWSマネジメントコンソールで「Secrets Manager」を開き、「新しいシークレットを保存する」をクリックします。
  • 「RDSデータベースの資格情報」を選択し、ユーザー名とパスワードを入力します。
  • 対象のデータベースインスタンスを選択し、シークレットに名前を付けて保存します(例:rds/db-credentials)。

ステップ2:RDS Proxyの作成

次に、データベースとLambdaを中継するプロキシを作成します。

  • RDSコンソールの「プロキシ」メニューから「プロキシの作成」をクリックします。
  • プロキシ名を設定し、エンジンの種類(MySQLまたはPostgreSQL)を選択します。
  • 「接続」セクションで、対象のデータベース(RDSまたはAurora)を選択します。
  • 「認証」セクションで、ステップ1で作成したSecrets Managerのシークレットを選択します。
  • IAMロールを新規作成するか、既存のロールを選択してプロキシがシークレットにアクセスできるようにします。

ステップ3:Lambda用IAMロールの設定とネットワーク設計

Lambda関数がRDS Proxyに接続するためには、同一のVPC内に配置し、適切なセキュリティグループを設定する必要があります。

  • セキュリティグループの設定:RDS Proxyのセキュリティグループにて、Lambdaのセキュリティグループからのインバウンド接続(ポート3306または5432)を許可します。
  • LambdaのIAMポリシー:Lambda関数の実行ロールに、RDS Proxyへの接続アクションを許可するポリシーを付与します。

ステップ4:Lambda関数の作成と実装

ここでは、Pythonを使用してRDS Proxy経由でMySQLに接続するLambda関数のコード例を示します。外部ライブラリとして PyMySQL を使用します。

【補足】外部ライブラリ(PyMySQL)の導入手順

Lambda環境には標準で PyMySQL が含まれていないため、以下の手順でローカルでパッケージングしてアップロードするか、Lambdaレイヤーを使用してください。

# ローカルの作業ディレクトリでライブラリをインストール
mkdir python
pip install pymysql -t python/
zip -r pymysql-layer.zip python/
# 作成したzipファイルをLambdaレイヤーに登録し、関数に適用します。

Lambda関数の実装コード

接続先ホスト(DB_HOST)には、データベースのエンドポイントではなく、RDS Proxyのエンドポイントを指定します。

import os
import pymysql

# 環境変数から接続情報を取得
DB_HOST = os.environ['DB_HOST'] # RDS Proxyのエンドポイント
DB_USER = os.environ['DB_USER']
DB_PASSWORD = os.environ['DB_PASSWORD']
DB_NAME = os.environ['DB_NAME']

def lambda_handler(event, context):
    connection = None
    try:
        # RDS Proxy経由でのデータベース接続
        connection = pymysql.connect(
            host=DB_HOST,
            user=DB_USER,
            password=DB_PASSWORD,
            database=DB_NAME,
            connect_timeout=5
        )
        with connection.cursor() as cursor:
            cursor.execute("SELECT VERSION()")
            result = cursor.fetchone()
            return {
                'statusCode': 200,
                'body': f"Database version: {result[0]}"
            }
    except Exception as e:
        print(f"Error: {e}")
        return {
            'statusCode': 500,
            'body': "Database connection failed"
        }
    finally:
        if connection:
            connection.close()

実務での注意点

  • ピン留め(Pinning)の回避:トランザクション内で一時テーブルの使用や一部のセッション状態の変更を行うと、RDS Proxyは「ピン留め」と呼ばれる状態になり、特定のLambdaコンテナにコネクションが固定されます。これにより、プーリングの効果が著しく低下するため、不要なセッションの変更は避けてください。
  • 追加コストの発生:RDS Proxyは、処理したデータの容量やプロキシが動作するデータベースインスタンスのvCPU数に基づいた課金が発生します。アクセスが少ない小規模なシステムでは、導入費用がメリットを上回る可能性があるため、コスト試算を事前に行いましょう。
  • サブネットの選定:RDS Proxyは少なくとも2つのアベイラビリティーゾーン(AZ)のサブネットに関連付ける必要があります。データベース本体と同じサブネット群を選択してください。

まとめ

Amazon RDS Proxyは、サーバーレス構成におけるリレーショナルデータベースへの接続負荷を軽減するための非常に強力なソリューションです。Secrets Managerと強固に連携し、Lambdaの急激なスケーリングにもデータベースを守りつつ安定したシステム構成を実現できます。本記事の手順に沿って、安全かつスケーラブルなインフラを構築してください。

上部へスクロール