Blue/Green Deployment:瞬時の切り替えと瞬時のロールバックが必要なときに

こんな場面を想像してみてください。チームがメインのランディングページを大幅にリニューアルした。あるいは、アプリケーションのあらゆる部分に影響を与えるコアライブラリを置き換えた。こうした変更はステージング環境で完璧にテストするのが難しい。なぜなら、ステージングのデータやユーザーの振る舞いは本番と完全には一致しないからだ。ローリングアップデートを試すこともできるが、何か問題が起きた場合、半数のユーザーは壊れたバージョンを目にし、残りの半数は古いバージョンを見続けることになる。そしてロールバック? すべてのインスタンスが1つずつ元に戻るのを待つ必要がある。決して瞬時ではない。

ここで登場するのがBlue/Greenデプロイメントだ。これは特定の問題を解決する。つまり、すべてのユーザーを一度に新バージョンに切り替える方法、そして問題が発生した場合に同じ速さで元に戻す方法だ。

2つの同一環境、一度にアクティブになるのは1つだけ

考え方は単純だ。2つの同一環境を維持する。1つをBlue、もう1つをGreenと呼ぶ。どちらも同じインフラ、同じ設定、同じキャパシティで動作する。唯一の違いは、現在どちらがユーザーにサービスを提供しているかだけだ。

実際の動作を見ていこう。

以下の図は、2つの状態とその間の遷移を示している。

flowchart TD BlueActive["Blue Active (v1)"] -->|Deploy v2 to Green| GreenReady["Green Ready (v2)"] GreenReady -->|Cutover| GreenActive["Green Active (v2)"] GreenActive -->|Rollback| BlueActive BlueActive -.->|Standby for rollback| BlueStandby["Blue Standby (v1)"] GreenActive -.->|Standby for rollback| GreenStandby["Green Standby (v2)"]

今、ユーザーはBlue環境にアクセスしており、そこではアプリケーションのバージョン1が動作しているとする。Green環境も動作しているが、ユーザートラフィックは受け付けていない。チームが内部テストに使っているかもしれないし、単にアイドル状態かもしれない。バージョン2をリリースする時が来たら、新しいバージョンをGreen環境にデプロイする。これでGreenはバージョン2になり、Blueはバージョン1でユーザーにサービスを提供し続ける。

この時点で、本番と同一の環境でバージョン2をテストできる。ヘルスチェックを実行する。機能を検証する。社内の数名に新バージョンを試してもらう。これらすべてが実際のユーザーに影響を与えることなく行われる。

自信がついたら、カットオーバーを実行する。カットオーバーとは、ユーザートラフィックをBlueからGreenに切り替えることだ。ロードバランサーの設定を更新したり、DNSレコードを変更したり、サービスメッシュのルーティングを修正したりする。数秒で、すべてのユーザーがバージョン2にアクセスするようになる。Greenはすでにウォームサーバー、開かれたデータベース接続、完全に初期化されたアプリケーションで動作しているため、ダウンタイムは発生しない。

キラーフィーチャー:瞬時のロールバック

Blue/Greenデプロイメントの最大の利点は、ロールバックの速さだ。バージョン2に問題が見つかり、ユーザーが使い始めた後でも、トラフィックをBlueに戻すだけでよい。ユーザーは瞬時にバージョン1に戻る。再デプロイを待つ必要はない。パイプラインを再実行する必要もない。ロールバックは単なるルーティングの変更だ。

ローリングアップデートと比較してみよう。ローリングアップデートをロールバックするには、インスタンスごとにプロセスを逆戻りさせる必要がある。それぞれ再起動と再接続に時間がかかる。その間、一部のユーザーは壊れたバージョンにアクセスし続ける可能性がある。Blue/Greenでは、古いバージョンはまだ動作しており、いつでもサービスを提供できる。スイッチを切り替えれば完了だ。

コストのトレードオフ

Blue/Greenデプロイメントには明らかな欠点がある。コストだ。2つの完全な環境を同時に実行する必要がある。本番ワークロードに10台のサーバーが必要な場合、Blue/Greenでは移行期間中に20台のサーバーを稼働させることになる。2倍のキャパシティに対して支払うことになる。

一部のチームは、アイドル状態の環境をスケールダウンすることでこのコストを削減している。例えば、Greenはトラフィックを処理していない間は2台のサーバーで稼働し、カットオーバーの直前に10台にスケールアップする。このアプローチにはスケーリングを処理する自動化が必要であり、ローリングアップデートよりも依然としてコストがかかる。しかし、リスクの高い変更の場合、そのコストは安全性に見合うかもしれない。

Blue/Greenを使用すべき時

この戦略は、リスクが高く、ロールバックが瞬時に行われる必要がある変更に適している。以下のようなケースを考えてみよう。

  • ユーザーが製品と対話する方法に影響を与える大規模なUIリニューアル
  • コアとなる依存関係やライブラリの置き換え
  • 元に戻すのが難しいデータベーススキーマの変更
  • クリーンなカットオーバーが必要なコンプライアンスや規制関連のアップデート

しかし、すべての変更に2つの完全な環境が必要なわけではない。徹底的にテストされた小さなバグ修正をデプロイする場合、ローリングアップデートの方が効率的でコストも低い。問題は、どれだけのリスクを受け入れるか、そして問題が発生した場合にどれだけ早く復旧する必要があるか、だ。

実践的なチェックリスト

Blue/Greenデプロイメントを実装する前に、以下の要素が整っていることを確認しよう。

  • 同一の環境。 両方の環境が同じインフラ、設定、キャパシティで動作している必要がある。環境間の差異は目的を損なう。
  • ステートレスまたはセッション対応のアプリケーション。 アプリがセッションデータをローカルに保存している場合、カットオーバー中にユーザーのセッションが失われる。Redisなどの外部セッションストアを使用するか、ステートレスになるように設計する。
  • 自動化されたカットオーバー。 手動のカットオーバーはエラーが発生しやすい。トラフィックの切り替えを自動化し、数秒で完了するようにする。クリック操作に何分もかからないようにする。
  • 新しい環境のヘルスチェック。 デプロイしてすぐに切り替えるのではなく、新しいバージョンがヘルスチェックに合格してからトラフィックをルーティングする。
  • カットオーバー中およびカットオーバー後の監視。 切り替え直後にエラー率、レイテンシ、ビジネスメトリクスを監視する。何か異常が見られたら、すぐにロールバックする。

具体的なポイント

Blue/Greenデプロイメントは、すべてのユーザーを瞬時に新バージョンに切り替え、同じ速さで元に戻す能力を提供する。コストは2つの環境を実行することだが、その見返りはリスクの高い変更に対するセーフティネットだ。チームが大規模なリリースを行っており、復旧時間を懸念しているなら、Blue/Greenは投資する価値がある。小さな変更には、ローリングアップデートを使い続けよう。適切な戦略は、どちらが印象的に聞こえるかではなく、リスクに基づいて選ぶべきだ。