Deployment topology comparison

Blue-Green Deployment構成と旧・単一runtime構成の比較

Blue-Green Deployment構成と単一runtime構成の違い、Worker数、AI処理中の切替を説明します。

この資料は、リポジトリに併存する2つのproduction実行方式を比較したものです。Blue-Green Deployment構成はproduction用local blue/green設定、旧構成はsingle production runtime / Compose実装を表します。実ホストには接続していないため、どちらが過去または現在採用されているかは未確認です。

先に結論#

  • Blue-Green Deployment構成は、Cloudflare Tunnelの接続先を固定HAProxyに保ち、空slotを準備してから新規要求の行き先を切り替えます。
  • AI Worker containerは平常時1つ、更新中だけ新旧2つです。各container内では3種類の論理processorが動きます。
  • 切替後も旧Webは接続数が0になるまで、旧Workerは旧releaseのAI処理が全て完了するまで残します。
  • 旧・単一runtime構成は、Web/APIとAI Workerが1つのcombined processで動きます。更新時は旧containerを停止・削除した後に新containerを起動するため、blue/greenの同時稼働やdrainはありません。
  • 停止時間を生じさせない切替の対象は、同じmigrationVersionで行う通常リリースです。可用性SLAや実環境での実績を示すものではありません。

1. Blue-Green Deployment構成#

Cloudflare Tunnel、固定HAProxy、blueとgreenのWeb・AI Worker、共有PostgreSQL、OpenAIからなるBlue-Green Deployment構成。平常時はactive slotのAI Workerが1 container、更新中だけ新旧2 containersが並行稼働し、旧Workerは旧releaseのAI処理完了後に停止する。

AI Workerはいくつか#

  • 平常時は1 containerです。active slotにWeb 1 containerとAI Worker 1 containerが動き、もう一方のslotは空です。
  • 更新中だけ2 containersです。candidate slotのAI Workerを先に起動するため、旧releaseと新releaseのWorkerが一時的に並行稼働します。
  • 1つのAI Worker process内では、durable feedback worker、durable AI generation worker、production command materializerの3 processorを起動します。したがって、1 containerで同時に1 jobしか処理できないという意味ではありません。

通常の更新は次の順序です。

  1. 現在使われていないslotで、新releaseのAI Worker containerを起動し、続いてWeb containerを起動する。
  2. WebとWorkerの認証済みreadiness成功を連続3回確認する。
  3. HAProxyのweightを変更し、新規要求をcandidate slotへ一括で切り替える。
  4. 旧Webへの新規流入を止め、既存接続が0になるまでdrainする。
  5. 旧Workerは旧release向けのAI処理が0になるまで残し、その後に旧slotを回収する。

PostgreSQLは新旧slotが共有する正本です。業務データ、session、永続queueをcontainer外に置き、WorkerはreleaseVersionに対応するjobをclaimします。旧slotを保持している間は、HAProxyを戻すrollback経路もあります。

AI処理中に更新した場合#

  1. 切替前に開始されたAI処理は、旧Workerが旧releaseの契約のまま継続します。新WorkerはreleaseVersionが一致する新release側のjobを担当し、旧jobを横取りしません。
  2. 通常のreaperは、旧releaseについてbackground job、実行中attempt、command execution、OpenAI provider leaseの4項目を確認します。
  3. 4項目が全て0になるまで旧Worker containerを残し、drained=trueになってから停止します。
  4. Worker containerにはshutdown mode drainが設定されます。generation/feedback処理は停止signal時も実行中controllerをabortせず、command materializerも実行中promiseの完了を待ちます。

したがって、通常のBlue-Green Deploymentでは、OpenAIへ要求中という理由だけで旧Workerを直ちに終了しません。ただし、強制kill、host停止、電源断、drain timeout、外部provider障害まで処理完了を保証するものではありません。

適用範囲#

  • 通常deployでは現在とcandidateのmigrationVersionが同一である必要があります。異なる場合はdeployが拒否されます。
  • 非互換なDB変更は通常切替に含めず、計画停止を伴うmigrationとして扱います。
  • 単一runtimeからblue/greenへ初めて移行する際は、1回限りの計画停止が必要です。
  • 切替中は新旧slotを同時に動かすため、アプリ部分はおおむね2倍のresourceを必要とします。
  • drain timeoutや外部依存障害まで無停止を保証する図ではありません。実稼働の可用性はhost、HAProxy state、container、監視記録で別途確認が必要です。

2. 旧・単一runtime構成#

Cloudflare Tunnelが単一のcombined SaaS containerへ接続し、そのcontainerがPostgreSQLとOpenAIを利用する旧構成。host-runtimeが旧containerを停止・削除して新containerを起動し、readiness後にTunnelを開始する。

deploy/production/host-runtime.mjs は、単一のSaaS containerをloopback :3000 で管理します。runtime roleを指定しない場合はcombinedとなり、Next.js Web/APIとdurable AI Workerが同じprocessで起動します。

更新または再起動の流れは、既存のcloudflaredとcontainerを停止し、既存containerを削除してから、新containerを作成・起動し、readiness成功後にcloudflaredを開始する順序です。したがって、更新中に新旧アプリを並行稼働させるslotや、旧processを段階的にdrainする仕組みはありません。

AI jobの正本がPostgreSQLにあることは、process停止とデータ消失が同義ではないことを意味します。一方でcombined process自体は停止するため、その間のWeb受付とWorker実行は連続しません。この図は停止時間やデータ損失の実績を示すものではありません。

比較表#

観点Blue-Green Deployment構成旧・単一runtime構成
公開入口Tunnel → 固定HAProxy :3001Tunnel → 単一container :3000
アプリ実行単位active slotにWeb ×1 + AI Worker ×1Web/APIとWorkerを含む1 combined container
AI Worker container数平常時1、更新中のみ新旧2平常時1。更新時は旧を停止後に新を起動
Worker内processorfeedback、generation、command materializerの3系統同じ3系統がcombined process内で動作
更新前の準備空slotを起動しreadinessを確認旧containerを先に停止・削除
トラフィック切替HAProxy weightで新規要求を一括切替新container readiness後にTunnel開始
旧Web新規流入を止め、接続0までdraincontainer停止時に終了
AI処理中の更新旧Workerが旧release処理を完了。drained確認後に停止combined process停止時に終了。既定のshutdown drainはOFF
rollback旧slot保持中にHAProxyを戻せる新旧の同時保持を前提とした切替はない
DB新旧slotで共有するPostgreSQLcontainer外のPostgreSQL
通常更新の制約同一migrationVersion。非互換DB変更は計画停止blue/greenのmigration gateなし
実稼働確認未確認採用履歴・実稼働とも未確認

根拠#

  • Blue-Green Deploymentの全体手順と制約:docs/operations/bluegreen/local-bluegreen-deployment.md:3-38,40-47(R041)
  • production slot・port・drain設定:config/local-bluegreen.production.example.json:1-52(R042)
  • Web/Worker container分離とworker drain mode:deploy/local-bluegreen/local-bluegreen.mjs:26,232-294(R043)
  • candidate起動、readiness、HAProxy切替、旧slot回収、rollback:deploy/local-bluegreen/local-bluegreen.mjs:583-688,985-1050,1177-1236(R044)
  • 単一containerのcombined role、停止・再作成、readiness、Tunnel起動:deploy/production/host-runtime.mjs:29-45,65-72,98-140(R045)
  • role未指定時のcombinedとshutdown drain既定値:okr-cai-saas/src/lib/runtime-role.ts:1-33(R046)
  • Worker process内の3 processor起動:okr-cai-saas/src/instrumentation.ts:9-44(R047)
  • 単一SaaS serviceとPostgreSQL:compose.yaml:1-121(R048)
  • 旧releaseのdrained判定:okr-cai-saas/src/lib/db/postgres/runtime-control.ts:170-240(R049)
  • generation workerのrelease fenceとshutdown drain:okr-cai-saas/src/lib/ai/generation-job.ts:540-555,1979-2011(R050)
  • feedback workerのrelease別claimとshutdown drain:okr-cai-saas/src/lib/ai/feedback-job.ts:235-332,950-971(R051)
  • command materializerのrelease別claimと完了待ち:okr-cai-saas/src/lib/ai/production-command-job.ts:557-593,869-900(R052)

ノード・接続・根拠参照は 共通モデル、調査上の不整合と未確認事項は 調査・検証記録 にまとめています。