LambdaからプライベートサブネットのRDSに接続できない — VPC設定の正しい理解と診断手順

「Lambda関数からRDSに接続しようとしたら、タイムアウトが返ってくる。セキュリティグループは開いているはずなのに」——この症状で詰まるエンジニアは多い。原因の大半はVPC設定の誤解にある。LambdaをプライベートサブネットのRDSに接続するには、Lambda自身もVPC内に配置する必要があり、その設定には正確なサブネットとセキュリティグループの指定が必要だ。

TL;DR — Lambda × プライベートRDS 接続チェックリスト

確認項目正しい状態
LambdaのVPC設定VPC・サブネット・セキュリティグループが明示的に指定されている
LambdaのサブネットRDSと同じVPC内のプライベートサブネット(複数AZ推奨)
RDSのセキュリティグループLambdaのSGからのインバウンドを許可するルールが存在する
LambdaのIAMロールVPC ENI作成権限(AWSLambdaVPCAccessExecutionRole)が付与されている
インターネットアクセス(必要な場合)NATゲートウェイ経由でのルーティングが設定されている

なぜLambdaにVPC設定が必要なのか — 接続の仕組み

デフォルト状態のLambda関数はAWSが管理するVPC内で動作しており、ユーザーのVPCリソース(RDS、ElastiCacheなど)には直接到達できない。プライベートサブネットに置かれたRDSはパブリックインターネットからアクセス不可能なため、Lambda側もそのVPCに参加する必要がある。

Lambda関数にVPC設定を行うと、AWSはHyperplane ENI(Elastic Network Interface)をユーザー指定のサブネットに作成し、Lambda実行環境をそのVPCに論理的に接続する。この仕組みにより、Lambda関数はRDSと同じネットワークセグメントから通信できるようになる。

graph LR subgraph AWSManaged["AWSマネージドVPC"] LambdaDefault["Lambda (VPC設定なし)"] end subgraph UserVPC["ユーザーVPC"] subgraph PublicSubnet["パブリックサブネット"] NAT["NATゲートウェイ"] end subgraph PrivateSubnetA["プライベートサブネット A"] ENI["Hyperplane ENI"] LambdaVPC["Lambda (VPC設定あり)"] end subgraph PrivateSubnetB["プライベートサブネット B"] RDS["RDS インスタンス"] end SGLambda["Lambda SG"] SGRDS["RDS SG (Lambda SGからの インバウンド許可)"] end LambdaDefault -. "到達不可" .-> RDS LambdaVPC -- "ENI経由" --> ENI ENI -- "VPC内ローカルルート" --> RDS SGLambda -- "参照" --> SGRDS LambdaVPC -. "インターネット必要時" .-> NAT
  1. デフォルトLambda(VPC設定なし): AWSマネージドVPCで動作。ユーザーVPCのプライベートリソースには到達不可。
  2. VPC設定済みLambda: 指定サブネットにHyperplane ENIが作成され、Lambda実行環境がユーザーVPCに接続される。
  3. セキュリティグループ: LambdaのSGはENIにアタッチされ、RDSのSGはそのSGからのインバウンドを許可する。
  4. プライベートサブネット: RDSはインターネットゲートウェイへのルートを持たないサブネットに配置されている。

Lambda VPC接続 — 正しい設定手順

Step 1: LambdaのVPC設定を確認・追加する

まずLambda関数に現在VPC設定があるかを確認する。VPC設定が存在しない場合、どれだけセキュリティグループを調整しても接続は成立しない。これが最初に確認すべき理由は、他のすべての診断がこの前提の上に成り立つからだ。

# Lambda関数のVPC設定を確認する
aws lambda get-function-configuration \
  --function-name your-function-name \
  --query 'VpcConfig'

レスポンスの VpcId が空文字列の場合、Lambda関数はVPC外で動作している。以下のコマンドでVPC設定を追加する。

# LambdaにVPC設定を追加する
aws lambda update-function-configuration \
  --function-name your-function-name \
  --vpc-config SubnetIds=subnet-xxxxxxxxxxxxxxxxx,subnet-yyyyyyyyyyyyyyyyy,SecurityGroupIds=sg-xxxxxxxxxxxxxxxxx

サブネットは複数AZにまたがるプライベートサブネットを指定する。単一AZのみ指定した場合、そのAZで障害が発生するとLambdaが起動できなくなる。

Step 2: セキュリティグループのルールを検証する

VPC設定が正しくても、セキュリティグループのルールが不正確だと接続は失敗する。よくある誤りは「RDSのSGでCIDRブロックを許可しているが、LambdaのSGを参照していない」パターンだ。IPアドレスベースの許可はENIのIPが変わる可能性があるため、SGベースの参照が推奨される。

# RDSのセキュリティグループのインバウンドルールを確認する
aws ec2 describe-security-groups \
  --group-ids sg-rds-security-group-id \
  --query 'SecurityGroups[*].IpPermissions'

RDSのSGに以下のようなルールが存在することを確認する。LambdaのSGをソースとして直接参照するルールが最も確実だ。

# RDSのセキュリティグループにLambdaのSGからのインバウンドを許可するルールを追加する
aws ec2 authorize-security-group-ingress \
  --group-id sg-rds-security-group-id \
  --protocol tcp \
  --port 5432 \
  --source-group sg-lambda-security-group-id

ポート番号はRDSエンジンに合わせて変更する(MySQL/Aurora MySQL: 3306、PostgreSQL/Aurora PostgreSQL: 5432)。

Step 3: LambdaのIAMロールにVPCアクセス権限があるかを確認する

VPC設定とSGが正しくても、LambdaのIAMロールにENI作成権限がなければデプロイ時にエラーが発生する。この権限不足はLambda関数の実行時ではなく、設定更新時や関数の初回起動時に表面化するため、接続問題と混同されやすい。

# LambdaのIAMロールにアタッチされているポリシーを確認する
aws iam list-attached-role-policies \
  --role-name your-lambda-execution-role-name

AWSマネージドポリシー AWSLambdaVPCAccessExecutionRole がアタッチされていることを確認する。存在しない場合は以下で追加する。

# VPCアクセス実行ロールポリシーをアタッチする
aws iam attach-role-policy \
  --role-name your-lambda-execution-role-name \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole

Step 4: サブネットのルートテーブルを確認する

LambdaをVPC内に配置しても、Lambdaが配置されたサブネットのルートテーブルが正しく構成されていないと、RDSへのパケットが届かない。特にRDSが別のサブネットにある場合、同一VPC内であればローカルルートで到達できるはずだが、誤ったルートテーブルの設定が干渉することがある。

# Lambdaが配置されているサブネットのルートテーブルを確認する
aws ec2 describe-route-tables \
  --filters Name=association.subnet-id,Values=subnet-lambda-subnet-id \
  --query 'RouteTables[*].Routes'

同一VPC内の通信はローカルルート(local)で処理される。このルートはデフォルトで存在し、削除できない。RDSへの接続に外部インターネットは不要なため、NATゲートウェイへのルートがなくてもVPC内通信は成立する。

Step 5: RDSのエンドポイントとポートを確認する

ネットワーク層が正しく設定されていても、接続先のエンドポイントやポートが誤っていれば接続は失敗する。アプリケーションコードのハードコードされた値と実際のRDS設定が一致しているかを確認する。

# RDSインスタンスのエンドポイントとポートを確認する
aws rds describe-db-instances \
  --db-instance-identifier your-db-instance-identifier \
  --query 'DBInstances[*].{Endpoint:Endpoint.Address,Port:Endpoint.Port,VpcId:DBSubnetGroup.VpcId}'

よくある誤診断パターン — 実際の障害から

「セキュリティグループのアウトバウンドルールをすべて許可にしたのに接続できない」という報告が来たことがある。確認してみると、LambdaのVPC設定自体が存在しなかった。アウトバウンドルールを見直す前に、そもそもLambdaがVPCに参加しているかを確認するのが先だ。

セキュリティグループはファイアウォールのルールセットだが、そのルールが適用されるのはENIが存在する場合のみだ。LambdaにVPC設定がなければENIは作成されず、SGのルールは意味を持たない。

もう一つの典型的な誤診断は「RDSのSGでインバウンドを0.0.0.0/0で開放したら接続できた。だからSGの問題だった」という結論だ。これは正しくない。実際の原因はLambdaのSGをソースとして指定していなかったことであり、全開放は問題の回避であって解決ではない。本番環境では必ずLambdaのSGを明示的に参照するルールに絞り込む。

graph TD Start(["Lambda タイムアウト発生"]) --> Check1{"LambdaにVPC設定 が存在するか?"} Check1 -- "なし" --> Misdiag1["誤診断: SGのアウトバウンド ルールを確認してしまう"] Misdiag1 --> Fix1["正しい対処: VPC設定を追加する"] Check1 -- "あり" --> Check2{"RDSのSGに Lambda SGからの インバウンドルールがあるか?"} Check2 -- "なし" --> Misdiag2["誤診断: RDS SGを 0.0.0.0/0で全開放してしまう"] Misdiag2 --> Fix2["正しい対処: Lambda SGを ソースとして明示的に指定する"] Check2 -- "あり" --> Check3{"IAMロールに VPCアクセス権限があるか?"} Check3 -- "なし" --> Fix3["AWSLambdaVPCAccessExecutionRole をアタッチする"] Check3 -- "あり" --> Fix4["RDSエンドポイント・ポート・ 認証情報を確認する"] Fix1 --> Success(["接続成功"]) Fix2 --> Success Fix3 --> Success Fix4 --> Success
  1. タイムアウト発生: Lambda関数がRDS接続でタイムアウト。エラーログにはネットワーク到達不能を示すメッセージが出る。
  2. 誤診断1 — SGのアウトバウンド: LambdaのSGアウトバウンドルールを確認するが、VPC設定自体がないため無意味。
  3. 誤診断2 — RDSのSG全開放: 全開放で接続できるが、これはセキュリティホールを作るだけで根本解決ではない。
  4. 正しい診断: LambdaのVPC設定追加 → LambdaのSGをRDSのSGインバウンドルールに追加 → 最小権限で接続成功。

Lambdaがインターネットアクセスも必要な場合

LambdaをVPC内に配置すると、デフォルトではインターネットへのアクセスができなくなる。外部APIの呼び出しやAWSサービスへのアクセス(VPCエンドポイントがない場合)が必要な場合は、NATゲートウェイをパブリックサブネットに配置し、プライベートサブネットのルートテーブルにNATゲートウェイへのデフォルトルートを追加する必要がある。

AWSサービス(S3、DynamoDB、Secrets Managerなど)へのアクセスはVPCエンドポイントを使用することでNATゲートウェイなしに実現できる。RDSの認証情報をSecrets Managerで管理している場合は、Secrets Manager用のVPCエンドポイントを作成することを検討する。

# Secrets Manager用のVPCエンドポイントを確認する
aws ec2 describe-vpc-endpoints \
  --filters Name=vpc-id,Values=vpc-xxxxxxxxxxxxxxxxx \
            Name=service-name,Values=com.amazonaws.us-east-1.secretsmanager \
  --query 'VpcEndpoints[*].{State:State,ServiceName:ServiceName}'

IAMポリシー — 最小権限での設定例

Lambda実行ロールに必要な権限を最小限に絞った例を示す。VPCアクセスに必要なENI操作権限はAWSマネージドポリシーで付与し、RDS接続に必要な認証情報取得権限は別途付与する。

🔽 Lambda実行ロール IAMポリシー例(クリックして展開)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "CloudWatchLogs",
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/your-function-name:*"
    },
    {
      "Sid": "SecretsManagerAccess",
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetSecretValue"
      ],
      "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:your-rds-secret-name-*"
    }
  ]
}

VPC ENI操作権限(ec2:CreateNetworkInterfaceec2:DescribeNetworkInterfacesec2:DeleteNetworkInterface)は AWSLambdaVPCAccessExecutionRole マネージドポリシーで付与する。これらをインラインポリシーで手動定義する場合、Resource: "*" が必要になるため、マネージドポリシーの使用が実用的だ。

LambdaからプライベートRDSへの接続 — 診断フローまとめ

graph TD A(["Lambda → RDS 接続失敗"]) --> B{"LambdaのVpcId が空か?"} B -- "空" --> C["Step1: VPC設定を追加 サブネット + SG を指定"] B -- "設定済み" --> D{"サブネットはRDSと 同じVPC内か?"} D -- "No" --> E["正しいVPCの サブネットを指定し直す"] D -- "Yes" --> F{"RDSのSGに Lambda SGからの インバウンドルールがあるか?"} F -- "No" --> G["Step2: RDS SGに Lambda SGをソースとする インバウンドルールを追加"] F -- "Yes" --> H{"IAMロールに VPCAccessExecutionRole があるか?"} H -- "No" --> I["Step3: マネージドポリシーを IAMロールにアタッチ"] H -- "Yes" --> J["Step4: RDSエンドポイント ポート・認証情報を確認"] C --> K(["接続確認"]) E --> K G --> K I --> K J --> K
  1. LambdaのVPC設定が存在するかを最初に確認する。存在しなければ追加が必須。
  2. VPC設定がある場合、サブネットがRDSと同じVPC内のプライベートサブネットかを確認する。
  3. RDSのSGにLambdaのSGからのインバウンドルールが存在するかを確認する。
  4. LambdaのIAMロールにVPCアクセス実行ロールポリシーがアタッチされているかを確認する。
  5. すべて正しい場合、RDSのエンドポイント・ポート・認証情報をアプリケーションコードで確認する。

まとめ — LambdaとプライベートRDS接続の要点

LambdaからプライベートサブネットのRDSに接続するには、Lambda自身をVPC内に配置することが前提条件だ。VPC設定(サブネットとセキュリティグループ)の明示的な指定、RDSのSGへのインバウンドルール追加、IAMロールへのVPCアクセス権限付与——この3点が揃って初めて接続が成立する。タイムアウトが発生したらまずLambdaのVPC設定の有無を確認し、その後セキュリティグループのルールを検証する順序で診断を進めると効率的だ。

詳細な設定手順については AWS Lambda VPC設定公式ドキュメント を参照すること。

用語集

用語説明
Hyperplane ENILambda VPC接続で使用されるAWS管理のElastic Network Interface。複数のLambda実行環境で共有される。
プライベートサブネットインターネットゲートウェイへの直接ルートを持たないサブネット。外部からの直接アクセスを遮断する。
セキュリティグループ(SG)ENIレベルで動作するステートフルなファイアウォール。インバウンド・アウトバウンドルールを定義する。
VPCエンドポイントインターネットを経由せずにAWSサービスへプライベート接続するための仕組み。
NATゲートウェイプライベートサブネット内のリソースがインターネットへアウトバウンド通信するためのマネージドサービス。

Related Posts

コメント

このブログの人気の投稿

SQS Visibility Timeoutの完全解説:メッセージ二重処理の原因と対策

EC2 SSH接続タイムアウトの原因と修正方法 — セキュリティグループのインバウンドルール完全ガイド

S3パブリックアクセス拒否の原因と解決策:バケットレベルの「Block Public Access」が優先される仕組み