はじめに
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 接続を設定します。
- AWS マネジメントコンソールで対象の Lambda 関数を開き、「設定」タブの「VPC」を選択して「編集」をクリックします。
- RDS が存在する「VPC」を選択します。
- 「サブネット」には、最低でも2つのアベイラビリティゾーン(AZ)にまたがるプライベートサブネットを選択します(冗長性の確保のため)。
- 「セキュリティグループ」には、ステップ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点に集約されます。本記事で紹介した手順とベストプラクティスを参考に、セキュアで可用性の高いサーバーレスシステムを構築してください。