「ECSのタスク数を増やすたびにデータベースが応答しなくなる」
この問題の根本原因は、コネクションプールを持たない実行環境がRDSへ直接接続するアーキテクチャにあります。Lambdaは呼び出しのたびに新しいTCPコネクションをRDSへ張ります。同時実行数が100になれば100本のコネクションが走り、db.t3.microの上限(約85本)を軽く超えます。
この問題を根本から解消するのがAmazon RDS Proxyです。コネクションプーリングをAWS側で引き受け、Lambda・ECSからの接続を集約してRDSへの接続数を最小化します。この記事では、RDS Proxyの仕組みとマルチAZ配置のVPC設計、Secrets Manager連携、Lambda・ECSからの接続設定、フェイルオーバー動作の確認まで実践的に解説します。
動作確認環境: Amazon Linux 2023 / RDS MySQL 8.0.35 / RDS Proxy(MySQL対応)
この記事のポイント
・RDS ProxyはLambdaの同時起動による接続数爆発をコネクションプールで解消する
・プライベートサブネットにマルチAZ配置し、RDSフェイルオーバー時の切断を10秒以内に短縮できる
・Secrets ManagerでDB認証情報を管理し、IAMロールでProxyに参照権限を付与する
・LambdaはProxyエンドポイントへの接続文字列変更だけで利用でき、コード改修は不要
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜLambdaからRDSへ直接接続すると問題が起きるのか
RDSのmax_connectionsはインスタンスクラスのメモリ量から自動計算されます。MySQL(RDS)の場合はDBInstanceClassMemory / 12582880が基準になり、代表的なクラスでは次の程度です。| インスタンスクラス | メモリ | max_connections(目安) |
|---|---|---|
| db.t3.micro | 1 GB | 約 85 |
| db.t3.small | 2 GB | 約 170 |
| db.m5.large | 8 GB | 約 683 |
| db.m5.xlarge | 16 GB | 約 1365 |
ECSタスクも同様です。AutoScalingでタスクがスケールアウトするたびに接続数が増え、ピーク時に上限に達します。「夜間は安定しているが朝のスパイク時だけダウンする」という症状のほとんどはこのパターンです。
RDS Proxyの仕組みとマルチAZ設計の全体像
RDS ProxyはVPC内に配置されるフルマネージドのデータベースプロキシです。クライアント(Lambda・ECSタスク)はRDSへ直接接続せず、ProxyのDNSエンドポイントに接続します。Proxyは内部でRDSへの接続を少数だけ維持し、多数のクライアント接続をその少数のRDS接続に多重化します。実際に100本のLambda接続を10本前後のRDS接続に集約できるため、max_connectionsの上限問題をほぼ解消できます。クライアントからは「通常のMySQLエンドポイント」として見えるので、既存コードの変更は接続文字列のホスト名だけです。
マルチAZ設計のポイント:
・Proxyは複数のAZにまたがるプライベートサブネットへ配置する(最低2 AZ推奨)
・Proxyのエンドポイントは1つのDNS名で提供され、クライアントは同じ接続文字列を使い続ける
・RDSのプライマリがフェイルオーバーしてもProxyがDNS名を変えずに新しいプライマリへ接続を自動切替する
・直接接続の30~120秒の切断時間がProxy経由で10秒以内に短縮される
VPCとセキュリティグループの設計
RDS Proxyを配置する際のVPC設計の基本は、Proxyをプライベートサブネットに置き、直接接続の経路をセキュリティグループで物理的に塞ぐことです。セキュリティグループの構成:
・sg-lambda(Lambda実行環境用): アウトバウンドで sg-proxy のポート 3306 を許可
・sg-proxy(RDS Proxy用): インバウンドで sg-lambda からのポート 3306 を許可。アウトバウンドで sg-rds のポート 3306 を許可
・sg-rds(RDS用): インバウンドで sg-proxy からのポート 3306 のみ許可(Lambdaからの直接接続は拒否)
このSG設計のポイントは、RDSのインバウンドにLambdaのSGを入れないことです。Proxyを経由しない接続を塞ぐことで接続数の制御が確実になります。
サブネット設計:
・Proxyには最低2つのAZにまたがるプライベートサブネットを指定する
・Proxyのサブネットにインターネットゲートウェイへのルートは不要(Proxyはプライベートで動作する)
・RDSのサブネットとProxyのサブネットは同じVPC内であれば別サブネットでも構わない
Secrets ManagerとIAMロールの準備
RDS ProxyはDB認証情報をSecrets Managerから取得します。CLIでシークレットを作成する場合は次のコマンドです。# Secrets ManagerにDB認証情報のシークレットを作成 aws secretsmanager create-secret \ --name rds/myapp-db \ --description "RDS myapp-db credentials" \ --secret-string '{"username":"myapp","password":"P@ssw0rd!2026"}' \ --region ap-northeast-1
# 信頼ポリシーを作成(rds.amazonaws.comがAssumeRoleできる) cat <<'EOF' > trust-policy.json { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": { "Service": "rds.amazonaws.com" }, "Action": "sts:AssumeRole" }] } EOF # IAMロール作成 aws iam create-role \ --role-name myapp-rds-proxy-role \ --assume-role-policy-document file://trust-policy.json # シークレット参照権限のポリシーをアタッチ aws iam attach-role-policy \ --role-name myapp-rds-proxy-role \ --policy-arn arn:aws:iam::aws:policy/AmazonRDSProxyAccess
RDS Proxyの作成とターゲット登録
1. RDS Proxyを作成する
VPCのプライベートサブネット、セキュリティグループ、シークレットARN、IAMロールARNが揃ったらProxyを作成します。# RDS Proxyの作成(複数AZのサブネットを指定してマルチAZ配置) aws rds create-db-proxy \ --db-proxy-name myapp-proxy \ --engine-family MYSQL \ --auth "AuthScheme=SECRETS,SecretArn=arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:rds/myapp-db-AbCdEf,IAMAuth=DISABLED" \ --role-arn arn:aws:iam::123456789012:role/myapp-rds-proxy-role \ --vpc-subnet-ids subnet-0a1b2c3d4e5f67890 subnet-0e1f2a3b4c5d67890 \ --vpc-security-group-ids sg-0123456789abcdef0 \ --region ap-northeast-1
# verify the proxy status (wait until "available") aws rds describe-db-proxies \ --db-proxy-name myapp-proxy \ --query 'DBProxies[0].{Status:Status,Endpoint:Endpoint}' \ --output table \ --region ap-northeast-1
---------------------------------------------------------------------------------------------------------- | DescribeDBProxies | +----------+---------------------------------------------------------------------------------------------+ | Status | Endpoint | +----------+---------------------------------------------------------------------------------------------+ | available| myapp-proxy.proxy-c0q8l6t4xf3r.ap-northeast-1.rds.amazonaws.com | +----------+---------------------------------------------------------------------------------------------+
2. RDSインスタンスをターゲットとして登録する
ProxyはデフォルトでどのRDSにも接続しません。ターゲットグループを通じてRDSを紐づける必要があります。# ターゲットグループにRDSインスタンスを登録 aws rds register-db-proxy-targets \ --db-proxy-name myapp-proxy \ --db-instance-identifiers myapp-db \ --region ap-northeast-1 # ターゲットの状態確認 aws rds describe-db-proxy-targets \ --db-proxy-name myapp-proxy \ --region ap-northeast-1 \ --query 'Targets[].{Endpoint:Endpoint,Port:Port,TargetHealth:TargetHealth}' \ --output table
---------------------------------------------------------------------------------------------------- | DescribeDBProxyTargets | +-----------------------------------------------------+------+----------------------------------+ | Endpoint | Port | TargetHealth | +-----------------------------------------------------+------+----------------------------------+ | myapp-db.c0q8l6t4xf3r.ap-northeast-1.rds.amazonaws.com | 3306 | {'State': 'AVAILABLE', 'Description': 'DBProxy Target available'} | +-----------------------------------------------------+------+----------------------------------+
LambdaとECSからRDS Proxyを使う設定
1. LambdaのVPC設定とセキュリティグループ
LambdaがProxyにアクセスするには、LambdaをProxyと同じVPCのプライベートサブネットに配置する必要があります。CLIから既存Lambdaに対してVPC設定を追加する場合は次のとおりです。# LambdaのVPC設定を更新(既存のLambdaに対して) aws lambda update-function-configuration \ --function-name myapp-function \ --vpc-config SubnetIds=subnet-0a1b2c3d4e5f67890,subnet-0e1f2a3b4c5d67890,SecurityGroupIds=sg-0lambda0sg \ --region ap-northeast-1
2. 接続文字列をProxyエンドポイントに変更する
コードの変更は接続先のホスト名をProxyエンドポイントに変えるだけです。ポート・データベース名・ユーザー名・パスワードは変更不要です。# Lambda環境変数の例(変更前) DB_HOST=myapp-db.c0q8l6t4xf3r.ap-northeast-1.rds.amazonaws.com # Lambda環境変数の例(変更後 → Proxyエンドポイントに変更するだけ) DB_HOST=myapp-proxy.proxy-c0q8l6t4xf3r.ap-northeast-1.rds.amazonaws.com
3. ECSタスク定義でProxyエンドポイントを渡す
ECSタスク定義のコンテナ定義で環境変数またはSecrets Managerの動的参照を使い、Proxyエンドポイントをコンテナに渡します。# ECSタスク定義(JSON抜粋) { "environment": [ { "name": "DB_HOST", "value": "myapp-proxy.proxy-c0q8l6t4xf3r.ap-northeast-1.rds.amazonaws.com" } ], "secrets": [ { "name": "DB_PASSWORD", "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:rds/myapp-db-AbCdEf:password::" } ] }
フェイルオーバーの動作確認と監視の設計
1. RDSのフェイルオーバーをテストする
RDSの手動フェイルオーバーを実行して、Proxy経由の接続切断時間を確認します。【注意】force-failoverオプションはRDSのスタンバイへの即時切替を強制します。本番DBに対して実行すると一時的な接続切断が発生するため、必ずステージング環境で確認してください。
# RDSマルチAZのフェイルオーバーをテスト(ステージング環境で実施) aws rds reboot-db-instance \ --db-instance-identifier myapp-db \ --force-failover \ --region ap-northeast-1 # フェイルオーバー後のターゲット状態確認(Proxyが新しいプライマリを認識しているか) aws rds describe-db-proxy-targets \ --db-proxy-name myapp-proxy \ --region ap-northeast-1 \ --query 'Targets[].{Endpoint:Endpoint,TargetHealth:TargetHealth}'
マルチAZ冗長設計をシステム全体のアーキテクチャとして体系的に学びたい方は、AWSマスターセミナー上級編でVPC設計からフェイルオーバー設計まで実機ハンズオンで習得できます。
2. CloudWatchで接続数を監視する
RDS Proxyにはプロキシ専用のCloudWatchメトリクスがあります。・ClientConnections: LambdaなどクライアントからProxyへの接続数
・DatabaseConnections: ProxyからRDSへの実際の接続数(コネクションプールの効果を数値で確認できる)
・QueryDuration: クエリ所要時間(パフォーマンス監視)
・ConnectionBorrowTimeout: 接続プールが満杯でクライアントが待機した回数(これが増えたらmax_connectionsPercent調整の合図)
ClientConnectionsとDatabaseConnectionsの比率が10:1以上になっていれば、コネクションプーリングが効いている証拠です。
# CloudWatchでClientConnectionsを確認(過去1時間の最大値) aws cloudwatch get-metric-statistics \ --namespace AWS/RDS \ --metric-name ClientConnections \ --dimensions Name=ProxyName,Value=myapp-proxy \ --start-time 2026-09-23T09:00:00Z \ --end-time 2026-09-23T10:00:00Z \ --period 300 \ --statistics Maximum \ --region ap-northeast-1 \ --query 'sort_by(Datapoints,&Timestamp)[*].{Time:Timestamp,Max:Maximum}' \ --output table
よくあるエラーと対処法
1. 「Access denied for user」がProxy経由で出る
ProxyのAuth設定とSecrets Manager内のDBユーザー名・パスワードが正しいか確認します。ProxyのStatusがavailableでも、シークレット内のパスワードが更新(ローテーション)されている場合は再認証に失敗します。# Proxyが参照しているシークレットARNを確認 aws rds describe-db-proxies \ --db-proxy-name myapp-proxy \ --query 'DBProxies[0].Auth' \ --region ap-northeast-1
2. 「Connection timed out」が出てProxyに繋がらない
次の3点を順番に確認します。・LambdaがProxyと同じVPC内のプライベートサブネットに配置されているか
・LambdaのSGからProxyのSGへポート3306のアウトバウンドが許可されているか
・ProxyのSGのインバウンドにLambdaのSGが含まれているか
VPC外のLambdaからプライベートSubnetのProxyへは到達できません。LambdaのVPC設定が未設定の場合は「LambdaとECSからRDS Proxyを使う設定」の手順を再確認してください。
3. Proxy経由でも「Too many connections」が出る
ProxyのターゲットグループにMaxConnectionsPercent(デフォルト100%)が設定されています。RDSのmax_connections全量をProxyが使い切っている状態です。インスタンスクラスのアップグレード、またはProxyを複数作成してターゲットグループを分割する設計を検討してください。本記事のまとめ
Lambda・ECSとRDSの接続数問題はアーキテクチャの問題です。RDS ProxyをプライベートサブネットにマルチAZ配置することで、コネクションプーリングと自動フェイルオーバーの両方を解決できます。| やりたいこと | 設計ポイント |
|---|---|
| Lambda同時起動による接続数爆発を解消する | RDS ProxyでLambdaとRDSの間にコネクションプールを配置する |
| ProxyをマルチAZ配置する | create-db-proxyの--vpc-subnet-idsに複数AZのサブネットを指定する |
| RDSへの直接接続を防ぐ | sg-rdsのインバウンドをsg-proxyからのみ許可しLambdaからの直接接続を塞ぐ |
| DB認証情報を安全に管理する | Secrets ManagerにシークレットをIAMロール経由でProxyに参照させる |
| フェイルオーバー切断時間を短くする | Proxy経由で直接接続の30~120秒から10秒以内に短縮できる |
| プーリング効果を数値で確認する | CloudWatchのClientConnections / DatabaseConnections比率を監視する |
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、Amazon LinuxとAWSを実務レベルで学べる無料マニュアルをご用意しています。AWSの設計を現場で自在に扱えるエンジニアになるために、まずは無料マニュアルをお受け取りください。
>> 無料マニュアルを受け取る3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:ALBの加重ルーティングでカナリアリリースを設計する方法|ターゲットグループ重み付けでAWS本番環境のトラフィックを段階移行する実践パターン
- この記事の属するカテゴリ:AWS(Amazon Linux)へ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます