LambdaからVPC内RDSに安全接続!タイムアウトを防ぐ設定手順

はじめに

AWSを実務で利用する際、サーバーレスアーキテクチャの要となる「AWS Lambda」から、リレーショナルデータベースである「Amazon RDS」や「Amazon Aurora」に接続する構成は非常によく使われます。しかし、インフラの初期構築時や運用時に「LambdaからRDSへの接続がタイムアウトする」「設定方法が複雑でセキュリティグループのベストプラクティスがわからない」という課題に直面するエンジニアは少なくありません。

この記事では、初心者から中級者のインフラエンジニア向けに、LambdaからVPC内のRDSに安全に接続するための設定手順と、よくあるタイムアウトを防ぐためのトラブルシューティング、設計ベストプラクティスをステップバイステップで解説します。

前提知識とVPC接続が必要な理由

デフォルト状態の Lambda 関数は、VPC(Virtual Private Cloud)の外側に配置されています。一方、セキュリティの観点から、RDS などのデータベースはパブリックアクセスを無効化し、VPC 内のプライベートサブネットに配置するのが実務における鉄則です。

Lambda からこのプライベートな RDS にアクセスするためには、Lambda 関数を「VPC接続モード(VPC Lambda)」として起動する必要があります。これにより、Lambda に Elastic Network Interface (ENI) が割り当てられ、VPC 内部のプライベートIPアドレスを使って安全にデータベースと通信できるようになります。

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

実務で推奨される、最もセキュアな最小権限の原則に則った設定手順を4つのステップで解説します。

ステップ1:セキュリティグループの作成と設計

LambdaとRDSの間で通信を許可するため、2つのセキュリティグループを作成します。セキュリティグループ同士を「相互参照(ソース指定)」することで、特定のIPアドレスに依存しないセキュアな設計が可能です。

  • Lambda用セキュリティグループ(例: sg-lambda-app
    • インバウンドルール:不要(空にする)
    • アウトバウンドルール:デフォルト(すべてのトラフィックを許可)
  • RDS用セキュリティグループ(例: sg-rds-db
    • インバウンドルール:
      • タイプ:MySQL/Aurora(ポート3306)または PostgreSQL(ポート5432)
      • ソース:sg-lambda-app(Lambda用のセキュリティグループIDを直接指定)
    • アウトバウンドルール:デフォルト(すべてのトラフィックを許可)

ステップ2:Lambda用のIAMロールに権限を追加

Lambda 関数を VPC 内で動作させるには、ENI の作成や削除を行うための権限が必要です。Lambda の実行ロールに、AWS 管理ポリシーである AWSLambdaVPCAccessExecutionRole をアタッチしてください。このポリシーには以下の権限が含まれています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateNetworkInterface",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DeleteNetworkInterface",
                "ec2:AssignPrivateIpAddresses",
                "ec2:UnassignPrivateIpAddresses"
            ],
            "Resource": "*"
        }
    ]
}

ステップ3:Lambda関数のVPC設定

Lambda 関数の設定画面から VPC 接続を設定します。

  1. AWS マネジメントコンソールで対象の Lambda 関数を開き、「設定」タブの「VPC」を選択して「編集」をクリックします。
  2. RDS が存在する「VPC」を選択します。
  3. 「サブネット」には、最低でも2つのアベイラビリティゾーン(AZ)にまたがるプライベートサブネットを選択します(冗長性の確保のため)。
  4. 「セキュリティグループ」には、ステップ1で作成した sg-lambda-app を指定します。

ステップ4:接続確認用コードと外部ライブラリの導入

ここでは Python を使用して、実際に RDS (MySQL) へ接続テストを行うコードを作成します。Python から MySQL に接続するには、外部パッケージである PyMySQL が必要です。

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

Lambda 環境に外部ライブラリを追加するために、ローカル環境で「Lambda レイヤー(Lambda Layer)」を作成してアップロードします。

# ローカル環境(Linux/macOS)での作業手順
mkdir -p python/lib/python3.9/site-packages
pip install pymysql -t python/lib/python3.9/site-packages/
zip -r pymysql-layer.zip python/

# 作成した pymysql-layer.zip を AWS Lambda の「レイヤー」として登録し、対象の関数にアタッチします。

接続確認コード例

import os
import pymysql

# 環境変数からデータベース接続情報を取得
DB_HOST = os.environ['DB_HOST']
DB_USER = os.environ['DB_USER']
DB_PASSWORD = os.environ['DB_PASSWORD']
DB_NAME = os.environ['DB_NAME']

def lambda_handler(event, context):
    try:
        # データベース接続
        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 connection successful. Version: {result[0]}"
            }
    except Exception as e:
        print(f"Error: {e}")
        return {
            "statusCode": 500,
            "body": "Failed to connect to the database."
        }
    finally:
        if 'connection' in locals() and connection.open:
            connection.close()

実務での注意点

実務の現場でインフラエンジニアが陥りがちなトラブルと、その解決策をまとめました。

1. 接続タイムアウト(Timeout)の原因と対策

Lambda からの疎通確認でタイムアウト(または504エラーなど)が発生する場合、原因の9割はネットワーク設計にあります。以下の3点を確認してください。

  • サブネットの選択ミス: Lambda を配置するサブネットは必ず「プライベートサブネット」にしてください。パブリックサブネット(インターネットゲートウェイへのルートを持つサブネット)に配置すると、Lambda はパブリックIPを持たないため、インターネットはおろか同一VPC内の通信でもタイムアウトする仕様になっています。
  • セキュリティグループの設定ミス: RDS 側のインバウンドルールで、Lambda のセキュリティグループからのアクセス(ポート3306/5432など)が正しく許可されているか再確認してください。

2. Lambdaからインターネットへの通信(外部API連携など)

VPC 内に配置した Lambda は、デフォルトでは外部のインターネットと通信できません。もし、Lambda 内から外部の SaaS や API(Slack通知や決済APIなど)を呼び出す必要がある場合は、VPC 内に NAT Gateway を構築し、Lambda が所属するプライベートサブネットのルートテーブルの送信先(0.0.0.0/0)を NAT Gateway に向ける必要があります。

3. データベースのコネクション枯渇問題(RDS Proxyの検討)

Lambda はイベントの発生状況に応じて急激にスケール(同時実行数が増加)します。これにより、Lambda のインスタンスごとにデータベースへのコネクションが確立され、RDS の最大接続上限(max_connections)に達してシステム全体がダウンするリスクがあります。

本番運用では、Lambda と RDS の間に Amazon RDS Proxy を挟むことで、コネクションをプールして効率的に再利用し、急激なスパイクアクセスからデータベースを保護する設計を強く推奨します。

まとめ

Lambda から VPC 内の RDS へ接続する際は、セキュリティグループの相互参照を正しく設計すること、および適切なサブネット(プライベートサブネット)の選択が重要です。

トラブルシューティングの基本は「セキュリティグループの設定」と「ルートテーブルの設定(NAT Gatewayの有無)」の2点に集約されます。本記事で紹介した手順とベストプラクティスを参考に、セキュアで可用性の高いサーバーレスシステムを構築してください。

上部へスクロール