@shinyaz

Aurora Blue/Green 実践検証 — メンテナンス時に実際どれだけ止まるのかを実測する

目次

はじめに

Aurora PostgreSQL を本番運用していると、メンテナンス時のダウンタイムは避けて通れない課題だ。マイナーバージョンアップ、メジャーバージョンアップグレード、パラメータ変更 — いずれも「どれくらい止まるのか」が事前にわからないと、メンテナンスウィンドウの設計ができない。

AWS は 2023年に Aurora で Blue/Green デプロイメントをサポートし、さらに 2026年2月には AWS JDBC Driver の Blue/Green プラグインを発表した。公式ブログでは「ほぼゼロダウンタイム」を謳っているが、実際のところどうなのか。

本記事では、Aurora PostgreSQL 16.9 のクラスターを使って以下を実測する。

  1. 通常のフェイルオーバーでどれだけ止まるか
  2. Blue/Green Switchover(PG 16.9 → 17.6 メジャーアップグレード)でどれだけ止まるか
  3. DNS の挙動がダウンタイムにどう影響するか

これはシリーズ「Aurora Blue/Green 実践検証」の第1回だ。第2回では AWS JDBC Driver の Blue/Green プラグインを使った場合の改善効果を検証する。

検証環境

項目
リージョンap-northeast-1(東京)
エンジンAurora PostgreSQL 16.9(Blue)→ 17.6(Green)
インスタンスクラスdb.r6g.large
構成Writer × 1 + Reader × 1
VPCデフォルト VPC(3 AZ)
接続テスト間隔1秒(psql で SELECT inet_server_addr() を実行)

前提条件:

  • AWS CLI セットアップ済み(rds:*ec2:* の操作権限)
  • psql(PostgreSQL クライアント)
  • dig(DNS 問い合わせ用)

セットアップから Switchover まで全工程を再現可能な形で記載する。結果だけ知りたい場合は まとめ にスキップできる。

Step 1: Aurora クラスターの構築

サブネットグループとクラスターの作成

クラスター構築コマンド(サブネットグループ → クラスター → インスタンス)
Terminal
# サブネットグループ作成(デフォルト VPC の 3 AZ)
aws rds create-db-subnet-group \
  --db-subnet-group-name bg-test-subnet-group \
  --db-subnet-group-description "Subnet group for Blue/Green deployment test" \
  --subnet-ids '["subnet-xxxxx","subnet-yyyyy","subnet-zzzzz"]' \
  --region ap-northeast-1
 
# Aurora PostgreSQL 16.9 クラスター作成
aws rds create-db-cluster \
  --db-cluster-identifier bg-test-apg \
  --engine aurora-postgresql \
  --engine-version 16.9 \
  --master-username postgres \
  --master-user-password '<your-password>' \
  --db-subnet-group-name bg-test-subnet-group \
  --storage-encrypted \
  --no-deletion-protection \
  --region ap-northeast-1
 
# Writer インスタンス
aws rds create-db-instance \
  --db-instance-identifier bg-test-apg-writer \
  --db-cluster-identifier bg-test-apg \
  --db-instance-class db.r6g.large \
  --engine aurora-postgresql \
  --no-auto-minor-version-upgrade \
  --region ap-northeast-1
 
# Reader インスタンス
aws rds create-db-instance \
  --db-instance-identifier bg-test-apg-reader \
  --db-cluster-identifier bg-test-apg \
  --db-instance-class db.r6g.large \
  --engine aurora-postgresql \
  --no-auto-minor-version-upgrade \
  --region ap-northeast-1

クラスターとインスタンスの作成には約10〜15分かかった。以下のコマンドで両方のインスタンスが available になるまで待つ。

Terminal(状態確認)
aws rds describe-db-instances \
  --filters Name=db-cluster-id,Values=bg-test-apg \
  --query 'DBInstances[].{Id:DBInstanceIdentifier,Status:DBInstanceStatus}' \
  --region ap-northeast-1

available になったら、ローカルから接続するためにセキュリティグループとパブリックアクセスを設定する。

ローカル接続用の設定(SG インバウンドルール + パブリックアクセス)
Terminal
# クラスターが使用しているセキュリティグループ ID を確認
SG_ID=$(aws rds describe-db-clusters \
  --db-cluster-identifier bg-test-apg \
  --query 'DBClusters[0].VpcSecurityGroups[0].VpcSecurityGroupId' \
  --output text --region ap-northeast-1)
 
# 自分のパブリック IP を取得
MY_IP=$(curl -s https://checkip.amazonaws.com)
 
# PostgreSQL ポートを自分の IP からのみ許可
aws ec2 authorize-security-group-ingress \
  --group-id "${SG_ID}" \
  --protocol tcp --port 5432 \
  --cidr "${MY_IP}/32" \
  --region ap-northeast-1
 
# 両インスタンスをパブリックアクセス可能にする
aws rds modify-db-instance \
  --db-instance-identifier bg-test-apg-writer \
  --publicly-accessible --apply-immediately \
  --region ap-northeast-1
 
aws rds modify-db-instance \
  --db-instance-identifier bg-test-apg-reader \
  --publicly-accessible --apply-immediately \
  --region ap-northeast-1

パブリックアクセスの反映には1〜2分かかる。反映後、DNS が パブリック IP を返すようになる。

接続を確認する。

Terminal
psql -h bg-test-apg.cluster-xxxxx.ap-northeast-1.rds.amazonaws.com \
  -U postgres -d postgres -c "SELECT version();"
Output
PostgreSQL 16.9 on aarch64-unknown-linux-gnu, compiled by aarch64-unknown-linux-gnu-gcc (GCC) 10.5.0, 64-bit

DNS の初期状態を確認する

Aurora のクラスターエンドポイントは CNAME レコードで、Writer インスタンスのエンドポイントを指している。

Terminal
dig +noall +answer bg-test-apg.cluster-xxxxx.ap-northeast-1.rds.amazonaws.com A
Output
bg-test-apg.cluster-xxxxx...rds.amazonaws.com. 60 IN CNAME bg-test-apg-writer.xxxxx...rds.amazonaws.com.
bg-test-apg-writer.xxxxx...rds.amazonaws.com.  60 IN A     172.31.37.206

ここで注目すべきは TTL が 60秒 という点だ。フェイルオーバーや Switchover で DNS が切り替わっても、クライアント側のキャッシュが最大60秒間古い IP を返し続ける可能性がある。これがダウンタイムの主要因になる。

Step 2: フェイルオーバーのダウンタイム計測

接続テストスクリプト

1秒間隔でクラスターエンドポイントに接続し、成功/失敗・レイテンシ・接続先 IP を記録するスクリプトを用意した。

connectivity-test.sh(接続テストスクリプト全体)
connectivity-test.sh
#!/usr/bin/env bash
set -euo pipefail
 
ENDPOINT="${1:?Usage: $0 <cluster-endpoint> <password> [interval_ms]}"
PASSWORD="${2:?Password required}"
INTERVAL_MS="${3:-500}"
INTERVAL_SEC=$(echo "scale=3; ${INTERVAL_MS}/1000" | bc)
 
TOTAL=0; SUCCESS=0; FAIL=0
FIRST_FAIL_TS=""; LAST_FAIL_TS=""
OUTFILE="/tmp/bg-test/connectivity-$(date '+%Y%m%d-%H%M%S').csv"
 
echo "timestamp,query_num,status,latency_ms,server_ip,error" | tee "${OUTFILE}"
 
cleanup() {
  echo ""
  echo "=== Summary ==="
  echo "Total: ${TOTAL} | Success: ${SUCCESS} | Failed: ${FAIL}"
  if [ -n "${FIRST_FAIL_TS}" ]; then
    echo "First failure: ${FIRST_FAIL_TS}"
    echo "Last failure: ${LAST_FAIL_TS}"
  fi
}
trap cleanup EXIT
 
export PGCONNECT_TIMEOUT=3
 
while true; do
  TOTAL=$((TOTAL + 1))
  TS=$(date '+%Y-%m-%dT%H:%M:%S.%3N')
  START_NS=$(date '+%s%N')
 
  RESULT=$(PGPASSWORD="${PASSWORD}" psql -h "${ENDPOINT}" -p 5432 -U postgres -d postgres \
    -t -A -c "SELECT inet_server_addr()::text" 2>&1) && STATUS="OK" || STATUS="FAIL"
 
  END_NS=$(date '+%s%N')
  LATENCY_MS=$(( (END_NS - START_NS) / 1000000 ))
 
  if [ "${STATUS}" = "OK" ]; then
    SUCCESS=$((SUCCESS + 1))
    echo "${TS},${TOTAL},OK,${LATENCY_MS},${RESULT}," | tee -a "${OUTFILE}"
  else
    FAIL=$((FAIL + 1))
    ERROR=$(echo "${RESULT}" | tr '\n' ' ' | cut -c1-100)
    [ -z "${FIRST_FAIL_TS}" ] && FIRST_FAIL_TS="${TS}"
    LAST_FAIL_TS="${TS}"
    echo "${TS},${TOTAL},FAIL,${LATENCY_MS},,${ERROR}" | tee -a "${OUTFILE}"
  fi
 
  sleep "${INTERVAL_SEC}"
done

フェイルオーバーの実行と結果

バックグラウンドで接続テストを走らせた状態で、Reader をターゲットにフェイルオーバーを実行した。

Terminal
# 接続テスト開始(バックグラウンド)
./connectivity-test.sh bg-test-apg.cluster-xxxxx.rds.amazonaws.com '<password>' 1000 &
 
# フェイルオーバー実行
aws rds failover-db-cluster \
  --db-cluster-identifier bg-test-apg \
  --target-db-instance-identifier bg-test-apg-reader \
  --region ap-northeast-1

結果は以下の通りだ。

Output(フェイルオーバー中の接続テスト結果)
10:01:29.278  #18  OK    124ms  172.31.37.206  ← Blue Writer
10:01:30.406  #19  FAIL  634ms                 ← 接続失敗開始
10:01:32.050  #20  FAIL   54ms
10:01:33.113  #21  FAIL   55ms
10:01:34.177  #22  FAIL   52ms
10:01:35.238  #23  FAIL   58ms
10:01:36.304  #24  FAIL   53ms
10:01:37.364  #25  FAIL   54ms
10:01:38.427  #26  FAIL  742ms
10:01:40.178  #27  OK    141ms  172.31.37.206  ← 復旧(同じ IP)
  ... 約36秒間正常 ...
10:02:16.658  #59  FAIL 3113ms                 ← 2回目の障害(タイムアウト)
10:02:20.780  #60  FAIL 3052ms
10:02:24.841  #61  FAIL 3099ms
10:02:28.949  #62  FAIL 3043ms                 ← テスト停止(復旧未確認)

フェイルオーバーの分析

指標
接続失敗回数12回
第1障害期間約10秒(10:01:30〜10:01:40、8回の接続拒否)
第2障害期間約12秒以上(10:02:16〜10:02:28、4回のタイムアウト)
障害パターン2つの障害期間に分離

注目すべき点が2つある。

  1. 2つの障害期間が発生した — 最初の約10秒間は接続拒否(即座に失敗)で、フェイルオーバー処理中にインスタンスが接続を受け付けなくなったことが原因だ。その後正常に戻ったが、約36秒後に再び3秒のタイムアウトが連続で発生した。第1障害期間の復旧後は旧 Writer の IP(172.31.37.206)に接続成功し続けていたことから、DNS キャッシュが切れて再解決が走ったタイミングで、エンドポイントの切り替え途中の不安定な状態に当たったと考えられる。
  2. 復旧後も同じ IP に接続している — フェイルオーバー後、クラスターエンドポイントの CNAME は新しい Writer(旧 Reader)を指すように更新されるが、DNS キャッシュが残っている間は古い IP に接続し続ける。今回は旧 Writer がまだ起動中だったため読み取りクエリは成功したが、書き込みを行うワークロードであれば read-only エラーになっていた可能性がある。これは DNS ベースのフェイルオーバーの根本的な限界だ。

フェイルオーバーでは、DNS キャッシュの影響で障害が2回に分離し、復旧後も誤ったインスタンスに接続し続けるリスクがある。では、Blue/Green デプロイメントではどうなるか。

Step 3: Blue/Green デプロイメントの構築と Switchover

論理レプリケーションの有効化

Blue/Green デプロイメントには論理レプリケーションが必要だ。カスタムパラメータグループを作成してクラスターに適用し、全インスタンスを再起動する。

論理レプリケーション有効化の手順(パラメータグループ作成 → 適用 → 再起動)
Terminal
# Blue 環境用カスタムパラメータグループ作成
aws rds create-db-cluster-parameter-group \
  --db-cluster-parameter-group-name bg-test-apg16-params \
  --db-parameter-group-family aurora-postgresql16 \
  --description "Custom params for Blue/Green deployment test"
 
# 論理レプリケーション有効化
aws rds modify-db-cluster-parameter-group \
  --db-cluster-parameter-group-name bg-test-apg16-params \
  --parameters "ParameterName=rds.logical_replication,ParameterValue=1,ApplyMethod=pending-reboot"
 
# クラスターに適用
aws rds modify-db-cluster \
  --db-cluster-identifier bg-test-apg \
  --db-cluster-parameter-group-name bg-test-apg16-params \
  --apply-immediately
 
# 全インスタンスを再起動(pending-reboot → in-sync にするため)
aws rds reboot-db-instance --db-instance-identifier bg-test-apg-writer
aws rds reboot-db-instance --db-instance-identifier bg-test-apg-reader

再起動後、パラメータグループのステータスが in-sync になるまで待つ。

Terminal(ステータス確認)
aws rds describe-db-clusters \
  --db-cluster-identifier bg-test-apg \
  --query 'DBClusters[0].DBClusterMembers[].{Id:DBInstanceIdentifier,ParamStatus:DBClusterParameterGroupStatus}' \
  --region ap-northeast-1

in-sync になったら、論理レプリケーションが有効になっていることを確認する。

Terminal
psql -h <cluster-endpoint> -U postgres -c "SHOW rds.logical_replication;"
Output
 rds.logical_replication
-------------------------
 on

ここで1つ注意点がある。カスタムパラメータグループを使っている場合、Green 環境用のパラメータグループも事前に作成しておく必要がある。今回は PG 16 → 17 のメジャーアップグレードなので、aurora-postgresql17 ファミリーのパラメータグループが必要だ。

Green 環境用パラメータグループの作成
Terminal
aws rds create-db-cluster-parameter-group \
  --db-cluster-parameter-group-name bg-test-apg17-params \
  --db-parameter-group-family aurora-postgresql17 \
  --description "Custom params for PG17 green environment"
 
aws rds modify-db-cluster-parameter-group \
  --db-cluster-parameter-group-name bg-test-apg17-params \
  --parameters "ParameterName=rds.logical_replication,ParameterValue=1,ApplyMethod=pending-reboot"

Blue/Green デプロイメントの作成

Terminal
aws rds create-blue-green-deployment \
  --blue-green-deployment-name bg-test-upgrade \
  --source arn:aws:rds:ap-northeast-1:<account-id>:cluster:bg-test-apg \
  --target-engine-version 17.6 \
  --target-db-cluster-parameter-group-name bg-test-apg17-params \
  --region ap-northeast-1

Green 環境のプロビジョニングは3つのフェーズで進行する。進捗は以下のコマンドで確認できる。

Terminal(進捗確認)
aws rds describe-blue-green-deployments \
  --blue-green-deployment-identifier bgd-xxxxx \
  --query 'BlueGreenDeployments[0].{Status:Status,Tasks:Tasks[].{Name:Name,Status:Status}}' \
  --region ap-northeast-1
フェーズ内容所要時間(実測)
CREATING_READ_REPLICA_OF_SOURCEBlue クラスターのレプリカを作成約18分
DB_ENGINE_VERSION_UPGRADEPG 16.9 → 17.6 へアップグレード約8分
CREATE_DB_INSTANCES_FOR_CLUSTERGreen インスタンスを作成約4分
合計約30分

この30分間、Blue 環境は完全に稼働し続ける。アプリケーションへの影響はゼロだ。

Switchover の実行と結果

Green 環境が AVAILABLE になったら、接続テストを走らせた状態で Switchover を実行する。

Terminal
aws rds switchover-blue-green-deployment \
  --blue-green-deployment-identifier bgd-xxxxx \
  --switchover-timeout 300 \
  --region ap-northeast-1

結果は以下の通りだ。

Output(Switchover 中の接続テスト結果)
10:55:55.518  #24  OK    134ms  172.31.26.53   ← Blue Writer (PG 16.9)
10:55:56.658  #25  FAIL 3046ms                 ← 接続タイムアウト開始
10:56:00.713  #26  FAIL 3055ms
10:56:04.777  #27  FAIL 3050ms
10:56:08.837  #28  FAIL 3049ms
10:56:12.895  #29  FAIL 3045ms
10:56:16.953  #30  FAIL 3045ms
10:56:21.008  #31  OK    249ms  172.31.26.53   ← 一瞬 Blue に接続
10:56:22.263  #32  OK    204ms  172.31.21.178  ← Green Writer (PG 17.6)

Switchover の分析

指標
接続失敗回数6回
ダウンタイム約26秒(10:55:56〜10:56:22)
失敗パターンすべてタイムアウト(各約3秒)
IP 遷移172.31.26.53 → 172.31.21.178

フェイルオーバーとの違いが明確だ。

  1. 失敗はすべてタイムアウト — フェイルオーバーでは即座に接続拒否されるケースがあったが、Switchover では全て3秒のタイムアウト。接続拒否ではなくタイムアウトになるのは、Switchover 中に Blue 環境のインスタンスが停止し、TCP レベルで応答しなくなるためだ。
  2. IP が明確に切り替わる — フェイルオーバーでは同じ IP に接続し続けたが、Switchover では Green 環境の新しい IP に切り替わった。なお、#31 で一瞬 Blue の IP(172.31.26.53)に接続成功しているのは、DNS がまだ更新途中で旧 IP を返し、そのタイミングで Blue インスタンスが一時的に接続を受け付けたためと考えられる。
  3. バージョンが上がっている — Switchover 後の接続で PG 17.6 が返ってきた。メジャーバージョンアップグレードが完了している。
Terminal(Switchover 後の確認)
psql -h bg-test-apg.cluster-xxxxx.rds.amazonaws.com -U postgres \
  -c "SELECT version();"
Output
PostgreSQL 17.6 on aarch64-unknown-linux-gnu

まとめ

検証結果の比較

指標フェイルオーバーBlue/Green Switchover
ダウンタイム約10秒 + 約12秒(2回に分離)約26秒(連続)
接続失敗回数12回6回
失敗パターン接続拒否 + タイムアウト混在タイムアウトのみ
バージョン変更なしPG 16.9 → 17.6
事前準備不要約30分(Green 環境構築)
アプリ変更不要不要

得られた知見

  • DNS TTL 60秒が最大のボトルネック — フェイルオーバーでも Switchover でも、DNS キャッシュが古い IP を返し続けることがダウンタイムの主要因だ。アプリケーション側で DNS キャッシュの TTL を短くするか、IP ベースのルーティングに切り替えることで改善できる可能性がある。
  • Blue/Green Switchover のダウンタイムは「長いが予測可能」 — フェイルオーバーでは接続拒否とタイムアウトが混在し2回に分離したのに対し、Switchover は26秒の連続したタイムアウトで予測しやすい。リトライロジックの設計がしやすい。
  • Green 環境の構築に30分かかる — メジャーバージョンアップグレードを含む場合、Green 環境の準備に約30分必要だ。この間 Blue 環境は完全に稼働するが、メンテナンスウィンドウの計画には含める必要がある。
  • 論理レプリケーションの有効化は事前準備が必要 — Blue/Green デプロイメントには rds.logical_replication = 1 が必須で、これにはカスタムパラメータグループの作成と全インスタンスの再起動が必要だ。本番環境では事前に有効化しておくべきだ。

次回予告

今回の検証では、psql による単純な接続テストで26秒のダウンタイムを観測した。AWS の公式ブログでは、AWS JDBC Driver の Blue/Green プラグインを使うことで「ほぼゼロダウンタイム」を実現できるとしている。

第2回では、このプラグインを実際に使い、HikariCP のリトライのみの場合と比較して、どの程度ダウンタイムが改善されるかを検証する。

クリーンアップ

リソース削除コマンド
Terminal
# Blue/Green デプロイメントの削除
aws rds delete-blue-green-deployment \
  --blue-green-deployment-identifier bgd-xxxxx \
  --delete-target \
  --region ap-northeast-1
 
# 旧 Blue 環境(-old1 サフィックス)のインスタンス削除
aws rds delete-db-instance \
  --db-instance-identifier bg-test-apg-reader-old1 \
  --skip-final-snapshot \
  --region ap-northeast-1
aws rds delete-db-instance \
  --db-instance-identifier bg-test-apg-writer-old1 \
  --skip-final-snapshot \
  --region ap-northeast-1
 
# 旧 Blue クラスター削除
aws rds delete-db-cluster \
  --db-cluster-identifier bg-test-apg-old1 \
  --skip-final-snapshot \
  --region ap-northeast-1
 
# 新クラスター(Green が昇格したもの)のインスタンス削除
aws rds delete-db-instance \
  --db-instance-identifier bg-test-apg-reader \
  --skip-final-snapshot \
  --region ap-northeast-1
aws rds delete-db-instance \
  --db-instance-identifier bg-test-apg-writer \
  --skip-final-snapshot \
  --region ap-northeast-1
 
# 新クラスター削除
aws rds delete-db-cluster \
  --db-cluster-identifier bg-test-apg \
  --skip-final-snapshot \
  --region ap-northeast-1
 
# パラメータグループ削除(クラスター削除後)
aws rds delete-db-cluster-parameter-group \
  --db-cluster-parameter-group-name bg-test-apg16-params
aws rds delete-db-cluster-parameter-group \
  --db-cluster-parameter-group-name bg-test-apg17-params
 
# サブネットグループ削除
aws rds delete-db-subnet-group \
  --db-subnet-group-name bg-test-subnet-group
 
# セキュリティグループのインバウンドルール削除
aws ec2 revoke-security-group-ingress \
  --group-id sg-xxxxx \
  --protocol tcp --port 5432 \
  --cidr <your-ip>/32

共有する

田原 慎也

田原 慎也

ソリューションアーキテクト @ AWS

AWS ソリューションアーキテクトとして金融業界のお客様を中心に技術支援を行っています。クラウドアーキテクチャや AI/ML に関する学びをこのサイトで発信しています。このサイトの内容は個人の見解であり、所属企業の公式な意見や見解を代表するものではありません。

関連記事