PG16 アップグレード preflight・リファレンス:dr-work-record(★Global Database・本番)
📌 本書 = このサービスの
preflight.md(=調査/リファレンス doc)。命名規約上preflight.mdは「各サービスの調査結果・固有値・consumer・設計判断・ゲート根拠・preflight を集約したリファレンス」を指す(手順本体はproduction.md/staging.md/clone-rehearsal.md)。手順本体は Cloneリハーサル版 / 本番実施版 を参照。本書は dr-work-record 固有値+Global Database 特有の考慮+本番実施順序(§6-A)+consumer(§6-D)+ゲート(§6-E)+preflight(§7)。
📚 dr-work-record 手順書セット(テストは本番とは別ファイル):
- 🏭 本番当日の実行手順(コピペ可・自己完結):
production.md— ①〜⑦ 通し+ゲート/ロールバック内蔵- 📖 本書(
preflight.md)= リファレンス:調査結果・consumer 棚卸し(§6-D)・設計判断・§6-E ゲート根拠・§7 preflight(=なぜ)- 🧪 clone テスト:
clone-rehearsal.md— 本番 Clone で「Global 削除経路」を素振り- 🧪 staging テスト:
staging.md— 非-Global staging で「PG16 アプリ互換」を検証(#12841) 【採用方針(2026-07-29)】Global Database を削除して standalone 化 → 標準(非-Global)Blue/Green で実施する。詳細は §6。 ℹ️ 前提: Aurora Global Database 自体は BG 対応(AWS 公式「Aurora Global Database limitations for blue/green deployments」)で「Global のまま直接 BG」も技術的に可能。だが本サービスは**単一リージョン(セカンダリ無し)**のため、global を外して標準 BG にする方が単純で、Global-DB BG 固有の制約(topology 凍結・BG中 global switchover 不可・secondary 同名PG)を回避できる。よって本方針を採用。
対象サービス: dr-work-record / 担当: <name> / 最終更新: 2026-07-29 関連: 実施イシュー #16266 / 汎用 stub #12729 / preflight ツール terraform_for_aws#2361 / 難易度マトリクス #13044
1. 環境・接続
| 項目 | production |
|---|---|
AWS プロファイル(P) | production-admin(⚠️ 書き込み権限・read-only 不可) |
リージョン(R) | us-east-1(※ dr-* 系の active は us-east-1。東京の同名クラスタは空の旧残骸で対象外) |
| Secrets Manager Secret ID | dr-work-record(-dd は Datadog・無関係) |
DB 名(psql dbname) | work_record_production |
| 踏み台(bastion) | i-09384db1d690bcfd0(fd-platform-bastion・us-east-1) ← dr-work-record SG が fd-platform SG を許可 |
| 接続方式 | Prisma DATABASE_URL 単一 Secret(cluster endpoint) |
| アプリ | NestJS 10 + Prisma 5.1.1(Node 20)=PG16 対応(Prisma 5.0+ で PostgreSQL 16 正式サポート)。source: fastdoctor-jp/microservice-nestjs の work-record(医師系マイクロサービス monorepo) |
staging クラスタは存在(実機確認 2026-08-04):
dr-work-record(acct 301608970378 / ap-northeast-1・Aurora PG 13.20・1インスタンス・非-Global)。本番(us-east-1・Global・Writer+Reader)とはリージョン/Global 有無/台数が異なる。→ staging は 非-Global なので「Global 削除」を素振りできない。そのため Global 削除→標準 BG の検証は §6-B の Clone リハーサル(本番 Clone を Global 化→detach)で担保する。driver/アプリ互換(PG16)の素振りには staging クラスタも活用可(#12841)。
2. クラスタ構成(アップグレード対象)
★本 Global DB はセカンダリ無しの「単一リージョン構成」(プライマリ us-east-1 のみ・
GlobalClusterMembersは writer 1件・readers:[])。クロスリージョン冗長性は現状なし。移行は us-east-1 のみが対象で、Global-DB BG の「セカンダリに同名 PG が必要」要件は N/A。 ※ 東京(ap-northeast-1)にある同名 standalone クラスタ(13.14・0インスタンス・global=null)は Global 外の空残骸で対象外。dr-work-record-0はセカンダリではなくプライマリ us-east-1 内の Reader。
| 項目 | 値 |
|---|---|
クラスタ識別子(SOURCE_CL) | dr-work-record |
| Global Cluster | dr-work-record(メンバー=us-east-1 primary のみ・★セカンダリ無し=単一リージョン) |
| インスタンス構成 | Writer dr-work-record-1 1台 / Reader dr-work-record-0 1台(MultiAZ) |
| インスタンスクラス | db.r6g.large |
| DB Subnet Group | dr-work-record-subnet |
| VPC Security Group | sg-074e71eb70c8bc948 |
| KMS | arn:aws:kms:us-east-1:967691968827:key/d29c6ace-407c-42e2-94d5-93e1d1238f15 |
| ストレージ規模 | 約 92MB(VolumeBytesUsed・極小) |
| 現行エンジン | aurora-postgresql 13.23(★2026-08-26 実機で訂正。13.20 は 2026-07-28 preflight 時点の値で、その後 minor が上がった。ValidUpgradeTarget の範囲が 13.20 と 13.23 で異なるため要注意) |
| target エンジン | 16.14(ValidUpgradeTarget に 16.11/16.13/16.14 available・2026-08-25 本番実機で確認。staging が 16.14 で移行済のため揃える。CPG は family aurora-postgresql16 で共通=変更不要) |
| writer endpoint | dr-work-record.cluster-cxmwyphil4em.us-east-1.rds.amazonaws.com |
⚠️ Reader が1台あるため、CPG 付替後の再起動は Reader→Writer の順で1台ずつ(AWS推奨・安全側・generic 手順 2-3。Writer-first でも動くが、万一の計画外 failover 時に未適用 Reader 昇格の恐れがあるため Reader を先に)。
3. パラメータグループ(★未作成・要作成)
現状(実機 2026-08-04)+★pgaudit ドリフト(2026-08-06 判明):
- 実 cluster PG=
default.aurora-postgresql13(user param 0・logical=off・pgaudit 無し)。 - ⚠️ ただし TF(
fastdoctor-template/dr-work-record/production/variable.tf)は custom cluster PGdr-work-recordにshared_preload_libraries=pgaudit,pg_stat_statements+pgaudit.log=allを意図(cluster_parameter_group_custom_enable=true)。=本番は TF からドリフトして pgaudit 未適用(staging・他サービス〔online-karte/online-ops/dr-worker-information〕は本番でも pgaudit 有効)。 - 【方針】PG16 移行で本番にも pgaudit を適用し、staging・TF・他サービスと揃える(ドリフト是正)。
BG には ①blue(PG13) 側の logical 有効化+pgaudit と ②green(PG16) 側の target PG(pgaudit 込み) が要る。両方 Terraform(共通モジュール aurora-bluegreen-param-groups・cluster_parameters を override)で作成する(作成のみ・付替は §6-A/§6-C のとおり CLI)。
| 役割 | cluster PG 名 | family | 主 param |
|---|---|---|---|
| ② target(green・PG16) | dr-work-record-pg16(cluster + instance) | aurora-postgresql16 | rds.logical_replication=1 / wal_sender_timeout=0 / shared_preload_libraries=pgaudit,pg_stat_statements / pgaudit.log=all |
| ① source(blue・PG13) | dr-work-record-pg13-bg(cluster PG) | aurora-postgresql13 | 同上(shared_preload_libraries に pgaudit を含め、付替+reboot で blue にも pgaudit を適用=ドリフト是正) |
3-1. Terraform(fastdoctor-template/dr-work-record/production/pg16_param_groups.tf・凍結前に apply)
locals {
# 本番も pgaudit を含める(TF/staging/他サービスと揃える・ドリフト是正)
dwr_cluster_params = {
"rds.logical_replication" = { value = "1", apply_method = "pending-reboot" }
"wal_sender_timeout" = { value = "0", apply_method = "pending-reboot" }
"shared_preload_libraries" = { value = "pgaudit,pg_stat_statements", apply_method = "pending-reboot" }
"pgaudit.log" = { value = "all", apply_method = "immediate" }
}
}
# ② target(PG16): cluster PG + instance PG。cluster_parameters に pgaudit を含める
module "pg16_blue_green_param_groups" {
source = "../../template_modules/options/aurora-bluegreen-param-groups"
name = var.project # = dr-work-record
target_family = "aurora-postgresql16"
cluster_parameters = local.dwr_cluster_params # ★pgaudit 込み(既定を override)
# instance_parameters は空(現行 instance PG も user param 0)
}
# ① source(PG13) 用 cluster PG(logical+pgaudit)
module "pg13_source_param_group" {
source = "../../template_modules/options/aurora-bluegreen-param-groups"
name = var.project
name_suffix = "pg13-bg" # → dr-work-record-pg13-bg
target_family = "aurora-postgresql13"
cluster_parameters = local.dwr_cluster_params # ★pgaudit 込み
}⚠️ この apply は「PG 作成のみ」。既存 cluster には付けない(付替は §6-A ②で CLI・
db_cluster_parameter_group_nameはignore_changes=ドリフトしない/§6-C)。★source CPG(
dr-work-record-pg13-bg)を blue に付替+reboot(§6-A ②)した時点で、本番 blue に pgaudit が有効化される(現状 default PG=pgaudit 無しからの是正)。green(PG16) も target CPG で pgaudit 有効。instance PG:現行
dr-work-record(user param 0)=実質デフォルト → target instance PG(dr-work-record-pg16)もモジュール既定(空)で等価。BG の--target-db-parameter-group-nameに指定。★本番でも pgaudit を有効化する(
pgaudit.log=all。他サービスは既に有効で整合的・ドリフト是正)。監査ログ量が増える点は関係者へ周知しておく。[ ]
dr-work-record-pg16(cluster/instance)とdr-work-record-pg13-bg(cluster)が TF apply で作成され、logical_replication=1/wal_sender_timeout=0を持つ
4. 使用拡張・後処理(preflight 実測 → #16266)
| 項目 | 該当 | 備考 |
|---|---|---|
インストール拡張(\dx) | plpgsql のみ | 要対応拡張(postgis/pg_repack/pgrouting)なし=互換ブロッカーなし |
| pg_stat_statements | preload 済み・拡張は未作成(実機 \dx=plpgsql のみ/pg_available_extensions installed_version 空) | ⚠️BG 作成前に blue で CREATE EXTENSION pg_stat_statements(汎用 procedure-clone-rehearsal §3-4。Green は同期中 read-only で後から作れない)→ Switchover 後に ALTER EXTENSION pg_stat_statements UPDATE。※監視用で移行必須ではないが未作成のままだと事後 UPDATE が空振りになるため BG 前作成が正。staging 実機で作成済み(2026-08-11・1.8) |
| pg_cron / pg_partman / pg_repack | 未使用 | |
| PKなしテーブル | 0 | BG 採用でも REPLICA IDENTITY 対応不要 |
| 外部論理レプリ(publication) | 0 | Datastream/Trocco/BI 等の下流なし |
| Reader / AutoScaling | Reader あり | Switchover 後に構成確認 |
| logical_replication | off(要有効化・§3 の CPG) | |
| pgaudit | ⚠️本番は未適用(default PG)=TF ドリフト | TF は pgaudit を意図(staging・他サービスは有効)。移行で本番にも pgaudit 追加=ドリフト是正(§3・§6-E)。監査ログは CW /aws/rds/cluster/dr-work-record/postgresql(consumer バッチは無し・保全目的) |
5. Blue/Green 名・Clone 名
| 項目 | 値 |
|---|---|
Blue/Green 名(本番 BG_NAME) | dr-work-record-bg |
| Blue/Green 名(リハーサル) | dr-work-record-bgtest |
Clone 名(リハーサル CL) | dr-work-record-bgtest-blue |
| リハ用 使い捨て Global Cluster | g-dr-work-record-bgtest |
6. ★Global Database の Blue/Green(方針: Global 削除 → 標準 BG)
【採用方針】Global Database を削除して standalone 化 → 標準(非-Global)Blue/Green で実施する。
ℹ️ Aurora Global Database は BG 対応(AWS 公式)だが、**本サービスは単一リージョン(セカンダリ無し)**のため、global を外してから標準 BG にする方が単純。Global-DB BG 固有の制約(topology 凍結・BG中の global switchover 不可・secondary 同名PG)を回避できる。セカンダリが無いので global 削除のコストは低い。
6-A. 本番での順序(Global 削除 → 標準 BG・当日は数秒狙い)
(事前枠) ① Global 削除で standalone 化:
remove-from-global-cluster(primary を切り離し・メタ操作/無停止想定)→ delete-global-cluster(空 global 削除)
② source PG13 CPG `dr-work-record-pg13-bg`(logical=1 / wal_sender_timeout=0) を blue に付替 → Reader→Writer 再起動(★瞬断 30〜60秒)
(枠前) ③ 標準 BG 作成(非-Global・target=16.14 / cluster・instance PG=`dr-work-record-pg16`)→ AVAILABLE → Green 検証
(切替枠) ④ Switchover(★書込断 数秒・endpoint 据え置き)
(事後) ⑤ ALTER EXTENSION pg_stat_statements UPDATE / 監視 / 旧 blue(-old1) 削除
⑥ tfvars の rds_engine_version を 16.x に更新(§6-C)
⑦ (任意) Global 復元: create-global-cluster … 単一リージョンでは通常不要。将来クロスリージョン DR が要るなら別途。export AWS_PROFILE=production-admin ; R=us-east-1
# ① Global 削除(standalone 化)
CL_ARN=arn:aws:rds:us-east-1:967691968827:cluster:dr-work-record
aws rds remove-from-global-cluster --region $R --global-cluster-identifier dr-work-record --db-cluster-identifier "$CL_ARN"
aws rds wait db-cluster-available --region $R --db-cluster-identifier dr-work-record # 稼働継続を確認
# ★削除保護の解除が必要(★2026-08-26 実機で判明。この環境の Global Cluster は全て DeletionProtection=true)
# 解除しないと: InvalidParameterCombination: Cannot delete protected Global Cluster dr-work-record,
# please disable deletion protection and try again.
aws rds describe-global-clusters --region $R --global-cluster-identifier dr-work-record \
--query 'GlobalClusters[0].{protection:DeletionProtection,members:length(GlobalClusterMembers)}' --output json # members=0 をガード確認
aws rds modify-global-cluster --region $R --global-cluster-identifier dr-work-record --no-deletion-protection
aws rds delete-global-cluster --region $R --global-cluster-identifier dr-work-record
aws rds describe-global-clusters --region $R --global-cluster-identifier dr-work-record # → GlobalClusterNotFoundFault が正
# ② source PG13 CPG(logical=1) を blue に付替 → Reader→Writer 再起動(★瞬断 30〜60秒・事前枠)
# ★Reader を先に reboot(AWS推奨・安全側・generic 2-3)。計画 reboot は failover しないため
# Writer-first でも動くが、万一の計画外 failover 時に未適用 Reader 昇格で logical=on にならない恐れ。
aws rds modify-db-cluster --region $R --db-cluster-identifier dr-work-record \
--db-cluster-parameter-group-name dr-work-record-pg13-bg --apply-immediately
aws rds wait db-cluster-available --region $R --db-cluster-identifier dr-work-record
aws rds reboot-db-instance --region $R --db-instance-identifier dr-work-record-0 # Reader を先に
aws rds wait db-instance-available --region $R --db-instance-identifier dr-work-record-0
aws rds reboot-db-instance --region $R --db-instance-identifier dr-work-record-1 # Writer(★これが瞬断)
aws rds wait db-instance-available --region $R --db-instance-identifier dr-work-record-1
# 踏み台 psql で SHOW rds.logical_replication;=on / SHOW wal_sender_timeout;=0 を確認
# ③ 標準 BG 作成(非-Global・target=16.14・cluster/instance PG=dr-work-record-pg16)
aws rds create-blue-green-deployment --region $R \
--blue-green-deployment-name dr-work-record-bg \
--source "$CL_ARN" \
--target-engine-version 16.14 \
--target-db-cluster-parameter-group-name dr-work-record-pg16 \
--target-db-parameter-group-name dr-work-record-pg16
# → 以降 ④ Switchover / ⑤ 事後 は generic 手順 7-8停止は ①(無停止想定)+②の瞬断(事前枠)+④の数秒(切替枠)。①②は事前枠に置き、当日枠は Switchover の数秒のみ。
6-B. リハーサル(Clone で Global 削除経路を素振り)→ 別手順書
別手順書に分離: Clone(copy-on-write)で「Global 化 → Global 削除 → 標準 BG」を素振りするテスト手順は →
clone-rehearsal.md。本体 dr-work-record は無操作。Global 削除経路の検証を担当。
6-C. Terraform 整合(重要・本番/staging 共通)
BG・CPG 付替はすべて AWS CLI で行う。Terraform では実施しない。かつ TF ドリフトは起きない——fastdoctor-template/modules/rds_aurora の aws_rds_cluster.default が下記のとおり設計されているため(global_cluster_identifier も ignore なので、万一 Global 操作をしても TF は無視する):
lifecycle {
ignore_changes = [
db_cluster_parameter_group_name, # CPG 付替を無視
global_cluster_identifier, # Global 所属を無視
replication_source_identifier,
]
}aws_rds_global_clusterリソースは TF に存在しない(Global Cluster は TF 管理外=CLI 運用)。- cluster の
global_cluster_identifier/db_cluster_parameter_group_nameはignore_changes→ CLI でremove-from-global-cluster/ CPG 付替 /create-global-cluster(復元)してもドリフトしない。 - 同一モジュールを使う staging も同じ。
⚠️ ただし engine_version は ignore_changes に入っていない。BG/Switchover で実体は 16.x に上がるため、アップグレード後に tfvars の rds_engine_version を 16.x へ更新しないと、次の terraform apply で「16→13 に戻す」ドリフトが出る(必須の TF 整合作業)。
- [ ] Switchover 後、
rds_engine_versionを 16.14 に更新する PR を用意(apply で no-change になることを確認)
| 操作 | 方法 | TF ドリフト |
|---|---|---|
| Global 切り離し / 削除 / 復元 | CLI | なし(ignore_changes・global リソース無し) |
| CPG 付替・BG・Switchover | CLI | なし(cluster PG は ignore) |
| engine_version(13→16) | 実体は CLI/BG で変化 | あり → tfvars を 16.x に更新して解消 |
6-D. エンドポイント影響・consumer 棚卸し
結論: 「Global 削除」でも「BG Switchover」でも、cluster/reader エンドポイントは据え置き(DNS 完全一致で維持)。cluster/reader エンドポイントで接続している consumer は再設定不要。 ただし instance 直指定・IP 直指定の consumer だけは要修正 → 事前棚卸し必須。
現行エンドポイント(実 API 確認・2026-07-29)
- writer:
dr-work-record.cluster-cxmwyphil4em.us-east-1.rds.amazonaws.com - reader:
dr-work-record.cluster-ro-cxmwyphil4em.us-east-1.rds.amazonaws.com global 専用エンドポイントは存在しない(→ ★訂正(実機 2026-08-26):CustomEndpoints=null/ Aurora Global に managed global DNS 無し)CustomEndpoints=nullは正しいが、Global Cluster 自体には専用エンドポイントが存在した:dr-work-record.global-ggkskzd9ar7x.global.rds.amazonaws.com(describe-global-clustersのEndpoint)。 Global 削除でこのエンドポイントは消滅するため、これを使う consumer が居ないことを削除前に確認すること。 今回は consumer が cluster/reader ep のみ(DB SG は source SG 3つ・CIDR 無し)で影響なし、削除後の api-probe 200 で裏取り済み。 なお detach(remove-from-global-cluster)した時点でメンバー0になり、global エンドポイントは実質機能しなくなる(削除を待たずに影響が出る)点に注意。
据え置きの根拠
- ① detach(
remove-from-global-cluster): cluster 識別子は不変 → エンドポイント不変。 - ② BG Switchover: green が
dr-work-recordへリネーム、ハッシュcxmwyphil4em(account+region 共通・cluster/instance で同一を実確認)を継承 → cluster/reader エンドポイントは byte 一致で維持。
要修正になる例外(← ここを棚卸し)
| 接続方式 | 影響 | 対処 |
|---|---|---|
| cluster / reader エンドポイント | ✅ 不変 | 再設定不要 |
instance 直指定(dr-work-record-1/-0...) | ❌ BG でインスタンス名が変わる(green→本名 / 旧→-old1) | 事前に cluster/reader エンドポイントへ移行 |
| IP 直指定 | ❌ Aurora は DNS 前提 | DNS 名へ変更 |
sslmode=verify-full(ホスト名 pin) | ✅ ホスト名不変 | 対処不要 |
| PG16 ドライバ互換(Prisma 等) | — 別論点 | staging 検証(#12841) |
★実測結果(2026-08-04・本番 us-east-1・SG allowlist + ECS env) DB SG sg-074e71eb70c8bc948 の 5432 inbound = source SG 3つのみ(CIDR 無し=外部 SaaS 直結なし):
| # | 許可 SG | 実体 | 接続方式(実測) | 判定 |
|---|---|---|---|---|
| 1 | sg-09132d83ca9d08143(dr-work-record-sg) | dr-work-record-service(ECS 本体・dr-work-record-cluster) | DB_HOST=dr-work-record.cluster-cxmwyphil4em.us-east-1…=cluster endpoint | ✅ 据え置き・再設定不要 |
| 2 | sg-09a3dec4eb92eebf0(fd-platform) | 踏み台 i-09384db1d690bcfd0(10.0.2.105)のみ(管理) | psql/管理 | ✅ consumer ではない |
| 3 | sg-024766cf722c3329a(fd-platform-retool) | Retool self-hosted(fd-platform-retool-bastion・i-03f5590f3dd6f7ed7・10.0.0.104・running) | ⚠️未確認(cluster ep か instance 直か) | ⚠️ Retool 管理画面で接続 Host を直接確認(instance 直なら BG 前に cluster/reader ep へ移行) |
★SG 実アタッチ先を完全列挙(2026-08-04)=隠れ consumer なし(確定):3 source SG はそれぞれ1つにしかアタッチされていない → ① dr-work-record-sg=ECS 1本(10.0.2.208=dr-work-record-service)/② fd-platform(広域SG)は us-east-1 では踏み台 1台のみ(10.0.2.105)=別サービスがぶら下がる取りこぼし無し/③ fd-platform-retool=Retool 1台。consumer は {アプリ・踏み台・Retool} の3つで確定。
✅ 再確認(2026-08-12):DB SG
sg-074e71eb70c8bc948の 5432 inbound は依然 source SG 3つのみ・CIDR/IP 直開放なし、各 SG のアタッチ先も ① dr-work-record-sg=ECS 1本 / ② fd-platform=踏み台 1台 / ③ fd-platform-retool=Retool 1台 で不変。DMS/Datastream 用の source SG は存在せず=常設 CDC 消費者は無い見込み(実体確認は §6-E(b) のpg_replication_slots)。Global にセカンダリ無しも不変のため、Global 削除はクロスリージョン読み取り/DR に無影響。 ★Aurora Auto Scaling / Serverless=無し(2026-08-04):describe-scalable-targets空・EngineMode=provisioned・serverless 設定なし → Reader は固定2台(アップグレード中に Reader が自動増減して手順が崩れる心配なし)。
- 本体アプリは cluster endpoint 接続= Global 削除・BG Switchover とも無影響(§6-D 結論どおり)。
- 外部 SaaS(Trocco 等)の公開IP 許可は無し(SG に CIDR ゼロ)= fastdoctor-manager と違い外部直結なし。
- ⚠️ 唯一の要確認は Retool。fastdoctor-manager の教訓(BI の接続先は SG/Flow Logs では cluster-ep/instance-直を判別不可)に従い、Retool の resource 設定 Host を直接確認する。
残チェック(Retool のみ実施すればクローズ)
- [ ] Retool(
fd-platform-retool・10.0.0.104)の dr-work-record 向け resource の Host が cluster endpoint か instance 直指定かを管理画面で確認 → instance 直なら BG 前に cluster/reader endpoint へ移行 - [ ] (最終確認)
pg_stat_activityで実接続元 IP を突合(app=cluster ep / Retool=10.0.0.104 / 踏み台 以外が居ないか) - [ ] Switchover 後、全 consumer が再接続できるか(driver 再接続・#12841)
6-E. BG 前チェック / Switchover 前 GO-NO-GO(dr-work-record 固有の追加ゲート)
汎用の可否ゲート(procedure-production.md A-2 / C-1 / D-0 / D-1)を基本とし、Global DB 由来の前後チェックと本 DB 固有の consumer/Reader 項目を上乗せする。
★注意(順序): 汎用 A-2 の「Global 非所属(何も出ないこと)」チェックは、dr-work-record では §6-A ① の Global 削除後に初めて満たす(初期は Global 所属)。A-2/C-1 を回す前に §6-A ① を完了しておくこと。
(a) Global 削除の前後チェック(§6-A ① 前後)
- [ ] 削除前:
GlobalClusterMembersが writer 1件のみ・secondary リージョン/reader 無し(単一リージョン)を実行直前に再確認(構成変化が無いこと)bashaws rds describe-global-clusters --region $R --global-cluster-identifier dr-work-record \ --query "GlobalClusters[0].GlobalClusterMembers[].{arn:DBClusterArn,writer:IsWriter,readers:Readers}" --output json - [ ] 削除前: 直近バックアップ/スナップショットが存在(万一に備え・
remove-from-global-clusterはメタ操作だが保険) - [ ] 削除後: クラスタが standalone(
GlobalClusterIdentifier=null) かつStatus=available(稼働継続)を確認 → その後 ②CPG/③BG へbashaws rds describe-db-clusters --region $R --db-cluster-identifier dr-work-record \ --query "DBClusters[0].{global:GlobalClusterIdentifier,status:Status}" --output json # global=null 期待
(b) BG 作成前チェック(汎用 C-1 + 固有)
- [ ] 汎用 C-1 実施(Status=available / Backup>0 / Global=None / custom CPG
dr-work-record-pg13-bgが Writer/Reader とも in-sync / PG16 CPGdr-work-record-pg16(cluster/instance) 存在 / 長時間tx 0 / logical 制限・default_transaction_read_only監査) - [ ] Writer で logical 有効:
dr-work-record-1(Writer) がSHOW rds.logical_replication;=on /SHOW wal_level;=logical - [ ] ★Reader(
dr-work-record-0)はlogical=off/wal_level=replicaが正常(★2026-08-26 実機で訂正。以前は「双方 on」と書いていたが Aurora 仕様上達成不可能)- RDS が Reader に対して自動調整する:
The parameter rds.logical_replication was set to a value incompatible with replication. It has been adjusted from 1 to 0. pg_settingsもsource=configuration file/pending_restart=f/reset_val=off= 再 reboot しても on にならない。reboot 順序とも無関係(CPG 付替時と Reader reboot 時の 2 回同イベントが記録される)- 移行への影響なし: wal sender / replication slot は Writer 側に作られ、BG も Writer から slot を作る
- Reader 側の適用確認は
shared_preload_librariesに pgaudit が入ったこととwal_sender_timeout=0で行う
- RDS が Reader に対して自動調整する:
- [ ] 参考: reboot 時に
max_wal_senders ... adjusted from 10 to 20が両機で出るが、これも Aurora による正常な自動調整(CPG では未指定=「明示しない」方針と整合) - [ ] (任意・A-3)pg_stat_statements ベースラインを実トラフィックのある本番 blue で取得(Switchover 後の性能比較用。92MB と極小のため優先度低だが取得推奨)
- [ ] ★常設の論理レプリケーション消費者が無いこと(pg_replication_slots / pg_publication 最終確認):§6-D の「外部論理レプリ=0(Datastream/Trocco/BI 下流なし)」を実行直前に本番 blue で実測確認。SG 上も DMS/Datastream 用 source SG は無い(consumer は {アプリ・踏み台・Retool} の3つのみ・2026-08-04/再確認 2026-08-12)が、DB 実体でも裏取りする。もし consumer 所有の logical slot / publication が存在したら、Global 削除・custom CPG 付替・BG が下流 CDC を壊し得るため着手前に停止/調整する。BG 作成で AWS が自前 slot を作るため、BG 前は 0 件が期待値。bash
# 踏み台 psql(sanctioned): SELECT slot_name, plugin, slot_type, active, database FROM pg_replication_slots; -- consumer所有slotが無い(0行)こと SELECT pubname FROM pg_publication; -- publication が無い(0行)こと
(c) Switchover 前 GO-NO-GO(汎用 D-1 の12項目 + dr-work-record 固有)
- [ ] 汎用 D-1 の12項目を全てクリア(BG AVAILABLE / StatusDetails=null / SwitchoverDetails 全 AVAILABLE /
AuroraReplicaLag・OldestReplicationSlotLag≒0 / 長時間tx 0 / DDL・migration 凍結 / D-0 PG13 スナップショット available / 監視 mute / DNS TTL≤5s /default_transaction_read_only非上書き / ロールバック担当待機 / TF PG16 整合 PR 準備済) - [ ] ★Green 実接続検証(describe だけで済ませない): green cluster endpoint へ踏み台 psql →
SHOW server_version=16.14 /work_records件数が blue と一致 / green member CPGin-sync/default_transaction_read_only=on(同期中は正常) - [ ] ★Retool(§6-D)が cluster/reader endpoint 接続と確認済み(
fd-platform-retool-bastionの resource Host がdr-work-record.cluster-…/…cluster-ro-…)。instance 直指定なら Switchover でインスタンス名が変わり切断 → BG 前に cluster/reader endpoint へ移行済みであること - [ ] ★Reader(
dr-work-record-0)経由の consumer も Switchover 後に再接続(reader endpoint 据え置き。driver 再接続・#12841) - [ ] dr-work-record-service(cluster endpoint 接続・✅据え置き)が Switchover 後に自動再接続することを確認できる体制
(d) Switchover 後の E2E 確認(アプリ側・4層) 消費者アプリ=FastDoctor Doctor App(fastdoctor_doctor_app・dr-app://・jp.fastdoctor.doctorapp)。BFF=dr-app-bff(internet-facing・医師系MS集約)。dr-work-record は「勤務実績(診察数・報酬)」担当・テーブル work_records/patient_feedbacks。 E2E 経路:Doctor App → dr-app-bff(WORK_RECORD_MICROSERVICE_URL=http://dr-work-record-ms.fstdr.jp)→ dr-work-record-ms(内部ALB /healthCheck:3000)→ Prisma 5.1.1 → Aurora PG(cluster endpoint)。上流は dr-app-bff の1つのみ。API: GET /work-records?doctorId=&offset=&limit=(read)/POST /work-records/bulk(write)。
- [ ] ①インフラ:ECS
dr-work-record-serviceRunningCount=Desired / ALB target groupdr-work-record-bluetarget=healthy - [ ] ②API/ヘルス:内部ALB
http://dr-work-record-ms.fstdr.jp/healthCheck=200(浅い)+ 勤務記録 取得/登録 API が 200+データ=Prisma→PG16 read/write 疎通 - [ ] ③APM/ログ:Datadog
service:dr-work-record-msの Errors で Prisma/PG 接続エラー(Can't reach database等)無し・レイテンシ正常(Switchover 前後比較) - [ ] ④ユーザー E2E:医師アプリ(dr-app)で「勤務記録」を 表示(read)→ 登録/更新(write) が成功(=dr-app-bff→dr-work-record-ms→PG16 の全経路 OK)。上流 dr-app-bff の APM でも work-record 呼び出しが 2xx。実施材料は下記「④ 実施メモ」
- [ ] (残留で不調時)
aws ecs update-service --cluster dr-work-record-cluster --service dr-work-record-service --force-new-deploymentで強制再接続
④ 実施メモ(Notion/Slack 調査 2026-08-06)
- テスト医師アカウント:
dr-app-test@fastdoctor.jp(PW は DM 運用・出典 Notion「医師ポータルのメンテナンスフロー」)。ログイン基盤 = Cognitodr-pool(属性custom:doctor_id)。ログイン不可時の再作成手順は Notion「💉 医師 DA Squad 保守運用マニュアル」。 - ✅ 本番の実機確認はストア版「ファストドクターDr」アプリ+在宅事業部の協力で行う(切替タイミングに合わせ日程調整・書込断は数秒想定)。医師アプリ管理=在宅事業部(旧 医師DA Squad)・連絡先 湯尾大祐さん/
#squad-drda-dev。 - ⚠️ staging では医師アプリ実機は不可(確定・2026-08-06〜07):staging ビルドは配信されておらず TestFlight も規制でデプロイ不可・貸与/シェア端末にも動作する医師アプリ無し。staging は API 直プローブ+DB 直 psql で代替(staging §G-1)。
- → 実機ビルドが手配できない場合は ④ を代替(DB read の担保):
- DB 直 psql(推奨・実行可):踏み台
fd-platformから SSM port-forward → psql(踏み台 SG は DB 5432 を許可)。SELECT doctor_id,count(*),max(updated_at) FROM work_records GROUP BY 1;を Switchover 前後で一致確認。手順は staging §G-1 のコマンド参照。 - ⚠️ API 直プローブ(
GET /work-records)は本番では不可:内部ALB(dr-work-record-ms) は SG が BFF系のみ許可で踏み台からは叩けず、ECS Exec も task role にssmmessages権限が無く未接続(要 IaC で権限追加+再デプロイ)。使うなら BFF/タスク側 SG 内から、または ssmmessages 権限付与後の ECS Exec。 ※staging のみterraform_for_aws#2574(Issue: mental-online-karte#17017)で踏み台→ALB 許可を追加し API プローブ可能にしている(本番には入れない)。
- DB 直 psql(推奨・実行可):踏み台
- ⚠️ 混同注意:
online-doctor-appの/doctor/me/monthly-doctor-evaluations(報酬テーブル・評価制度)は 別 web アプリ+online-doctor-service=dr-work-record とは無関係。 - 移行後の監視: Slack
#fdt-dr-work-record-error-prod(勤務情報本番エラー)/#fdt-dr-app-bff-error-prod(BFF)。 - [ ] ★pgaudit(ドリフト是正の確認):Switchover 後の新 primary(PG16) で
SHOW shared_preload_libraries;に pgaudit が含まれる・SHOW pgaudit.log;=all・PG ログ(CloudWatch/aws/rds/cluster/dr-work-record/postgresql)に監査ログが出ること。※§B の CPG 付替時点で blue にも pgaudit が有効化される(現状 default PG=未適用からの是正)
★ staging テスト(
staging.md§5)で同 E2E を本番前に先行検証しておく(#12841)。
(e) 接続残留時の復旧手順(②CPG付替reboot / ④Switchover 共通) アプリ・Retool とも cluster/reader endpoint 接続(Global 削除・BG Switchover とも DNS 据え置き)→ 基本は自動再接続で自己回復。復旧作業が要るのは、コネクションプールが切れた接続を掴んだままエラーを出し続ける残留ケースのみ(Multi-AZ/切替後に起きうる)。
- 検知:直後の一時的な接続エラーは数分で消えれば正常。残るかを監視。
- Datadog
service:dr-work-record-msError rate/Errors(Can't reach database server/server closed the connection/PG::ConnectionBad/terminating connection due to administrator command) /healthCheck=200 / ダッシュボードdr-work-record-aurora-pg16-bluegreenのDatabaseConnections回復
- Datadog
- アプリ復旧(残留時・ローリング=無停止):bash
aws ecs update-service --region us-east-1 \ --cluster dr-work-record-cluster --service dr-work-record-service --force-new-deployment - Retool 復旧(§6-D で cluster/reader ep 接続を確認済み前提):クエリ再実行で自動再接続 → 残留なら self-hosted Retool(
fd-platform-retool-bastion)のコンテナ再起動。 - 確認:API 直プローブ(本番は §6-D の許可経路)/踏み台 psql で疎通、Datadog Errors 解消、
DatabaseConnections平常化。
⚠️ instance 直指定の consumer(もし残っていれば)は Switchover でインスタンス名が変わり再接続では戻らない(cluster/reader ep への事前移行が前提・§6-D)。
6-F. staging テスト実施手順(アプリ互換)→ 別手順書
別手順書に分離: staging クラスタ(Aurora PG 13.23・非-Global・Writer 1台)での PG16 アプリ互換テスト(dr-work-record-service / Prisma / Retool・#12841)は →
staging.md。Global 無しなので Global 削除はスキップ・reboot は Writer 1台のみ。
7. preflight 結果サマリ(2026-07-28・#16266/★2026-08-04 本番実機で再確認)
SUMMARY: PASS=23 WARN=4 FAIL=0 / blocker:none / risk:medium(medium 要因は Global DB+Reader+logical=off の手順面のみ)- クリーン: PKなし0 / 拡張=plpgsql のみ / publication 0 / 長時間tx 0 / シーケンス2 / reg*型0 / matview0 / physical slot0 / FDW0 / event trigger0
- next: reader-plan / custom-cpg / app-grep(driver 再接続確認 #12841)
★2026-08-04 本番実機(pg16-preflight-aurora.sh 読み取り専用)で再確認した追加事実
- 接続方式=writer cluster endpoint(
dr-work-record.cluster-cxmwyphil4em…)→ §6-D「本体アプリは cluster ep=Switchover 据え置き」を DB 側からも裏付け。 - 現行
wal_level=replica/wal_sender_timeout=1min/ logical=off(→ §3 の CPG で logical=1・wal_sender_timeout=0 へ)。password_encryption=md5。 - cluster PG=
default.aurora-postgresql13(logical off)/ DB数=3 /max_replication_slots=20max_wal_senders=20。 - INFO:
publicスキーマに roleBY0mRFqijXMwIh67の UC 権限あり(移行ブロッカーでない・非標準ロール名・記録のみ)。 - 2026-06-18 は staging 実機(#13044 コメント)、2026-07-28・2026-08-04 は production 実機で PASS=23/WARN=4/FAIL=0 が一致。
7-1. 移行前後の検証スクリプト(read + write/シーケンス継続性)
preflight(pg16-preflight-aurora.sh・読み取り専用)とは別に、Switchover の前後で DB 直の read/write を機械的に確認するスクリプトを用意(実装 PR: terraform_for_aws#2575 / Issue: mental-online-karte#17062)。
- 場所:
docs/sre/scripts/pg16-verify-dr-work-record.sh(GitHub) - 検証: ①
server_version(13→16 確認)②read プローブ(work_records件数・医師数・最新 updated_at)③write/シーケンス継続性(BEGIN; INSERT(id=DEFAULT); ROLLBACK)。- ★write は ROLLBACK で本番に test 行をコミットしない。
nextvalは INSERT 時に評価されるため、BG/Switchover 最頻事故=シーケンスずれ(論理レプリケーションはシーケンス値を複製しない)を検出できる(read では検出不可)。
- ★write は ROLLBACK で本番に test 行をコミットしない。
- 使い方(切替の前後で実行し比較):bashenv で profile/region/踏み台を自動切替(staging=ap-northeast-1/
bash pg16-verify-dr-work-record.sh --env staging --label pre # 切替前 bash pg16-verify-dr-work-record.sh --env staging --label post # 切替後 → server_version=16.x / sequence_ok=t bash pg16-verify-dr-work-record.sh --env production --label pre|posti-0ddd2353e102d9006・production=us-east-1/i-09384db1d690bcfd0)。secret はどちらもdr-work-record。 - 合格基準: 切替後に
server_versionが 16 系・read が切替前と同件数・sequence_ok=t(新 id > max・PK 衝突なし)・test 行コミット 0。 - staging 検証済(2026-08-07):
13.23 / total=21 doctors=6 / sequence_ok=t / 未コミット。
8. 実施記録
- (リハーサル実施時にコマンド・結果・所要時間を追記)