DBAtlas · データベース運用アトラス

GitOps と blue-green / 無停止デプロイ

症状

目標: スキーマとアプリケーションの変更をダウンタイムなしでデプロイする。expand-contract マイグレーション、blue-green 環境、フィーチャーフラグ、自動ロールバックで無停止に近づける。

1. GitOps: Git を唯一の信頼できる情報源にする

インフラ、スキーママイグレーション、アプリケーションのバージョンを Git で定義する。デプロイはリポジトリへのマージによってトリガーされる (GitOps)。リコンサイラー (Argo CD/Flux または CI/CD) が望ましい状態を実環境に適用する。これによりすべての変更が監査可能かつ再現可能になり、必要に応じて以前のコミットに戻せる。

PostgreSQL

# repo/
#   migrations/  (Vxxx__*.sql)
#   k8s/         (Deployment, Service)
#   flags/       (feature flag config)

2. スキーマを後方互換に変更する (expand-contract)

無停止のためには、スキーマを破壊的な 1 ステップで変更せず、2 つのフェーズに分ける。EXPAND: 旧コードと新コードが同時に動作できるよう新しい構造 (新しい列/テーブル) を追加する (NULL 許容列、デフォルト付き、二重書き込み)。アプリケーションが新しい構造に移行した後に CONTRACT: 使われなくなった古い列/テーブルを別のマイグレーションで削除する。これによりデプロイ中も旧バージョンと新バージョンのアプリケーションが問題なく並行稼働する。

PostgreSQL

-- EXPAND (V5): backward-compatible addition
ALTER TABLE customer ADD COLUMN email text;

-- for a while the code writes/reads both columns

-- CONTRACT (V9): drop the old column
ALTER TABLE customer DROP COLUMN mail_old;

3. リスクのある動作をフィーチャーフラグの背後に置く

新しいコードパス (新しい列の読み取りなど) をフィーチャーフラグの背後で条件付きで実行する。スキーマの準備ができたらフラグをオンにし、問題があればデプロイに触れずにオフにする。フラグはコードのデプロイ (deploy) と機能の有効化 (release) を分離する。expand フェーズは出荷されるが、動作の変更は制御された形で有効化され、迅速に元に戻せる。

PostgreSQL

-- application layer (pseudocode)
-- if flag('new_email_field'):
--     SELECT email FROM customer ...
-- else:
--     SELECT mail_old FROM customer ...

4. blue-green 環境を構築する

2 つの同一の環境を保持する: 'blue' (本番稼働中) と 'green' (新バージョン)。新しいアプリケーションバージョンを green にデプロイし、実トラフィックを受ける前に検証する。準備ができたらルーター/トラフィックを green に切り替える。重要な点: データベースは通常共有されているため、スキーマは両方のバージョンと互換でなければならない (expand-contract がこれを保証する)。切り替え時に接続先が変わっても、スキーマの互換性によりダウンタイムは発生しない。

PostgreSQL

# traffic is switched to green (new version)
# shared DB: schema must be compatible with both blue and green

5. 監視でデプロイを検証する (カナリア/観察)

すべてのトラフィックを切り替える前に、エラー率、レイテンシ、データベースのエラー/ロック数、レプリケーションラグなどのメトリクスを監視する。必要に応じてトラフィックのごく一部 (カナリア) を green に送って観察する。ヘルス指標が良好ならトラフィックを段階的に増やし、悪ければ先に進まない。監視は自動ロールバックの判断材料となる。

PostgreSQL

-- live health queries
SELECT count(*) FROM pg_stat_activity WHERE wait_event_type='Lock';
SELECT * FROM pg_stat_replication;

6. 自動ロールバックを準備する

メトリクスがしきい値を超えたら、デプロイは自動的にロールバックされなければならない: blue-green では、トラフィックを素早く blue (旧バージョン) に戻す。blue はまだ稼働しているため、アプリケーションのロールバックは即時である。スキーマ側のロールバックは通常不要である: expand-contract により新しいスキーマは旧コードとも互換であるため、アプリケーションをロールバックすれば十分である。そのため、スキーマの変更はアプリケーションのデプロイから独立させ、常に後方互換に保つべきである。

PostgreSQL

# traffic instantly returns to blue (application rollback)
# schema is not rolled back: expand-contract is compatible with old code
# if truly needed: write a new corrective migration
DBAtlas で開く →