[アップデート] RDS ブルー/グリーンデプロイの RDS Proxy サポートを検証してみた
はじめに
Amazon RDS の ブルー/グリーンデプロイが、アップデートにより RDS Proxy をサポートするようになりました。
どのような挙動になるのか、早速試してみました。
やってみた
検証用に RDS for MySQL を用意しました。
DB エンジンのバージョンは 8.0 系とします。なお、8.0 系の標準サポートは 2026 年の 7 月に終了となります。
この DB を 8.4 系にブルー/グリーンデプロイするというシナリオを想定してみます。
RDS Proxy も作成済みです。

では、ブルー/グリーンデプロイを作成しましょう。
グリーンのエンジンバージョンが 8.4 系であることを確認します。インスタンスやストレージの設定は今回は変更しません。

内容を確認し、問題なければ作成します。

しばらく待っていると、無事に作成されました。

デプロイする前に、以下のような Lambda を用意して、接続断が発生するかどうかを検証してみることにします。
Lambda の実行環境は以下のとおりです。
- Python ランタイム: 3.14
- VPC: RDS Proxy にアクセスできるサブネット・セキュリティグループを設定
- 環境変数:
RDS_PROXY_HOST、DB_USER、DB_PASSWORD、DB_NAMEを設定
import json
import os
import time
from datetime import datetime, timezone
import pymysql
_SSL_CA = "/etc/pki/tls/certs/ca-bundle.crt"
conn: pymysql.Connection | None = None
def _get_connection() -> pymysql.Connection:
"""
グローバルコネクションを返す。
初回呼び出し時にコネクションを確立し、以降は再利用する。
切断されている場合は _probe() 側で conn を None にリセットしてから呼ぶこと。
"""
global conn
if conn is None:
conn = pymysql.connect(
host=os.environ["RDS_PROXY_HOST"],
port=int(os.environ.get("DB_PORT", "3306")),
user=os.environ["DB_USER"],
password=os.environ["DB_PASSWORD"],
database=os.environ["DB_NAME"],
connect_timeout=5,
read_timeout=5,
write_timeout=5,
ssl={"ca": _SSL_CA},
)
return conn
def _probe() -> dict:
"""
DB に SELECT NOW() を 1 回実行し、結果と所要時間を返す。
エラー時は例外を握りつぶし ok=False のレコードを返す。
"""
ts = datetime.now(timezone.utc).isoformat()
t0 = time.perf_counter()
try:
global conn
if conn is not None:
try:
conn.ping(reconnect=False)
except Exception:
conn = None
c = _get_connection()
with c.cursor() as cur:
cur.execute("SELECT NOW()")
db_now = str(cur.fetchone()[0])
elapsed_ms = round((time.perf_counter() - t0) * 1000)
return {"ts": ts, "ok": True, "db_now": db_now, "elapsed_ms": elapsed_ms}
except Exception as e:
elapsed_ms = round((time.perf_counter() - t0) * 1000)
conn = None
return {"ts": ts, "ok": False, "error": str(e), "elapsed_ms": elapsed_ms}
def _run_downtime_check(duration_seconds: int, interval_seconds: float) -> dict:
"""
duration_seconds 秒間、interval_seconds 秒ごとに DB への接続を試みる。
各接続テスト結果を CloudWatch Logs に出力し、最後にサマリーを返す。
"""
records: list[dict] = []
end_at = time.monotonic() + duration_seconds
print(json.dumps({
"event": "start",
"duration_seconds": duration_seconds,
"interval_seconds": interval_seconds,
}))
while time.monotonic() < end_at:
result = _probe()
print(json.dumps(result))
records.append(result)
time.sleep(interval_seconds)
errors = [r for r in records if not r["ok"]]
first_error = errors[0] if errors else None
last_error = errors[-1] if errors else None
downtime_ms: int | None = None
if first_error and last_error and first_error is not last_error:
t_first = datetime.fromisoformat(first_error["ts"])
t_last = datetime.fromisoformat(last_error["ts"])
downtime_ms = round((t_last - t_first).total_seconds() * 1000) + last_error["elapsed_ms"]
elif first_error:
downtime_ms = first_error["elapsed_ms"]
summary = {
"total_probes": len(records),
"success": len(records) - len(errors),
"errors": len(errors),
"estimated_downtime_ms": downtime_ms,
"first_error": first_error,
"last_error": last_error,
}
print(json.dumps({"event": "summary", **summary}))
return summary
def lambda_handler(event: dict, context: object) -> dict:
"""
duration_seconds 秒間、interval_seconds 秒ごとに DB への接続を試みる。
Lambda のタイムアウトを duration_seconds + 30 秒以上に設定すること。
"""
duration = int(event.get("duration_seconds", 120))
interval = float(event.get("interval_seconds", 1))
summary = _run_downtime_check(duration, interval)
return {"statusCode": 200, "body": json.dumps(summary, ensure_ascii=False)}
5 分間 1 秒間隔で接続を試みるようにして Lambda 関数を実行し、RDS 側もブルー環境からグリーン環境に切り替えます。

切り替え自体は 2 分くらいで完了しました。

Lambda 関数のログを見てみると、295 回の接続テストのうちエラーは 1 回のみでした。
RDS Proxy がバックエンドの接続先を切り替えるタイミングで Lost connection to MySQL server during query が発生しましたが、推定ダウンタイムは約 1.1 秒で、次の接続テストではすぐに回復しています。

おわりに
RDS Proxy がサポートされたことで、RDS のブルー/グリーンデプロイがさらに使いやすくなりました。
まずは検証環境などでお試しいただき、その後、本番環境で実施することをおすすめいたします。
なお、本番環境での Lambda から RDS Proxy への接続には、今回のようなパスワード認証ではなく IAM 認証の利用をおすすめします。
IAM 認証を利用することでパスワード管理が不要になり、よりセキュアな構成を実現できます。







