プログレッシブデリバリーとは? 開発チームのための入門ガイド
要約
プログレッシブデリバリーとは、変更を小さな段階に分けて本番に出し、各段階で実際のメトリクスを確認してから次へ進むリリース手法です。デプロイとリリースを分離し、カナリア、ブルーグリーン、フィーチャーフラグを組み合わせ、エラー率やレイテンシが事前に決めた閾値を超えたら自動でロールバックします。
プログレッシブデリバリーとは、変更を小さな段階に分けて本番環境へ出し、各段階で実際のメトリクスを確認してから次の段階に進む、リリースの進め方です。問題が出た場合はリリースが止まるか、自動でロールバックされます。ユーザー全員の前で、1回のデプロイに賭ける必要がなくなります。
こんな状況は、おそらく心当たりがあるはずです。プルリクエストが承認され、CIも緑で、火曜日の午後にデプロイが走る。20分後、Slackで「なぜチェックアウトのレイテンシが倍になったのか」と聞かれる。プログレッシブデリバリーは、この会話を短くするためのものです。そして、その問題を全トラフィックではなく5%のトラフィックだけで起こるようにします。
プログレッシブデリバリーは何を変えるのか
従来の継続的デリバリーが答えるのは「この変更を安全に本番へ出せるか」という一つの問いです。プログレッシブデリバリーは、もう一つ問いを加えます。「誰が最初に見るのか」、そして「何を見たら止めるのか」です。
中心になる考え方は、デプロイとリリースを分けることです。デプロイは、新しいコードがサーバー上で動いている状態を指します。リリースは、そのコードをユーザーに見せる状態を指します。この2つを切り離せば、水曜日の午後2時にデプロイしても、リリースは自分たちのペースで、選んだ対象者に対して、戻る手段を用意したうえで行えます。
読んだ資料の多くは、3つの基本要素を挙げています。段階的なトラフィック移行(カナリア)、並行する環境(ブルーグリーン)、そしてフィーチャーフラグです。これらは競合する手法ではありません。成熟したチームは、異なるレイヤーでこれらを組み合わせて使っています。
カナリアリリース: トラフィックをどれだけ流し、誰が決めるのか
カナリアリリースでは、新しいバージョンに小さな割合のトラフィック(たとえば5%)を流し、残りは古いバージョンに残します。エラー率、レイテンシ、飽和度が閾値の範囲内にとどまっていれば、割合を5%、25%、50%、100%と広げていきます。範囲を外れたら、トラフィックを元に戻します。
難しいのは、細かい割合で分割するには、トラフィックを実際に分けられる仕組みが必要な点です。Argo Rollouts のドキュメントによると、正確なカナリアの割合には、サービスメッシュやIngressコントローラーのようなトラフィックマネージャーが必要です。それがなければ、レプリカ数に基づく粗い制御しかできません。つまり「5%」が実際には「20個のPodのうち1個」を意味することもあります。
段階的なカナリアを Argo Rollouts のマニフェストで書くと、次のようになります。意図的に短くしています。
strategy:
canary:
steps:
- setWeight: 5
- pause: { duration: 10m } # ダッシュボードを見るか、分析を実行する
- setWeight: 25
- pause: { duration: 10m }
- setWeight: 100サービスのトラフィックが少なく、5%が1時間に数件のリクエストしかないなら、カナリアは見送ってください。いつまでもシグナルを待つことになるか、ノイズを安全の証拠と読み違えることになります。トラフィックの少ないサービスでは、社内ユーザーだけを対象にしたフィーチャーフラグの方が、最初の関門として適しています。

ブルーグリーンデプロイ: 本番環境をまるごと2つ持つ価値はあるか
ブルーグリーンでは、完全な本番環境を2つ用意します。ブルーがユーザーにサービスを提供している間、グリーンには新しいバージョンを配置し、待機状態でテストします。十分に確認できたら、トラフィックを片方からもう片方へ切り替えます。
Argo Rollouts のドキュメントによれば、切り替えは一度に行われます。新しいバージョンが検証されるまで古いバージョンがすべての本番トラフィックを保持し、その後、割合が0%から100%へ移ります。これが強みであり、弱みでもあります。ロールバックは切り替えを戻すだけなので素早く済みます。一方で、テストは実ユーザーが来る前に行われ、両方の環境を動かしている間はインフラのコストが2倍になります。
部分的なロールアウトが混乱を招くサービス、たとえば2つのバージョンが同時にリクエストを処理してはいけない決済の経路などでは、ブルーグリーンを使う価値があります。一方で、両方のバージョンで同時に動かせないデータベースのマイグレーションがあるなら、見送ってください。その場合、「即座のロールバック」は実現できない話になります。

フィーチャーフラグはどこに入るのか
カナリアとブルーグリーンはインフラのレベルで動きます。フィーチャーフラグはアプリケーションの内側で動きます。フラグは、コードパスを条件分岐で囲み、再デプロイなしで実行時に切り替えられるようにします。
そのため、フラグは利用できる中で最も細かい制御手段です。まず社員に機能を公開し、次に1%のアカウント、次に特定の顧客セグメントへと広げ、問題があれば数秒で止められます。フラグを多くの手法の一つと見なすチームもあれば、アプローチ全体を可能にするものと見なすチームもあります。実務では後者の見方が成り立ちます。サーバー単位ではなく対象者単位でリリースしたくなった瞬間に、フラグが必要になるからです。
ただし、フラグにはコストもあります。フラグは、テストでカバーすべき分岐であり、誰かが閉じなければならないクリーンアップのタスクでもあります。仕組みと負債の詳しい話は、フィーチャーフラグとはで扱っています。フラグは原則として短命にし、オーナーと削除日を決めておいてください。
LaunchDarkly や Statsig は、管理の層を販売しています。ターゲティングルール、監査ログ、段階的な割合ロールアウト、実験などです。
「遅いデプロイ」ではなく「進行的な」ロールアウトにするには
鍵は自動化です。誰かがダッシュボードを睨みながら10分間待つだけのロールアウトは、単に遅いデプロイです。機械がメトリクスを確認し、判断を下すようになって初めて、プログレッシブデリバリーになります。
どの仕組みでも、流れは同じです。
リリースの前に、シグナルを定義します。エラー率、p95レイテンシ、チェックアウト完了率のようなビジネスメトリクスを1つ、といった具合です。
「止める」基準となる閾値を定義します。誰かの頭の中ではなく、設定ファイルに書いておきます。
コントローラーに、そのシグナルに基づいて昇格、保留、ロールバックを任せます。
Argo Rollouts はメトリクスプロバイダーと連携し、チェックの結果に応じてロールアウトを自動で昇格させたり中止したりできます。今回読んだ資料のひとつは、率直にこう述べています。自動ロールバックのないプログレッシブデリバリーは、ただの遅いデプロイである、と。私たちも同意見です。

どのメトリクスでロールアウトを制御するか
数は絞ってください。すでに信頼しているシグナルを3〜4個選ぶ方が、一度もアラートを設定したことのない20個より効果的です。
出発点として使いやすいのは、次のセットです。カナリアとベースラインの HTTP 5xx 率、カナリアとベースラインの p95 レイテンシ、飽和度(CPU、メモリ、キューの深さ)、そして製品側のメトリクスを1つ。比較は「先週」との比較ではなく、カナリアとベースラインを同じ時間帯で行ってください。トラフィックのパターンは時間とともに変わるからです。
ここで、オブザーバビリティのスタックは「あると良いもの」ではなくなります。メトリクスをバージョンやフラグのバリアントで切り分けられなければ、カナリアとベースラインを見分けられず、この手法全体が成り立ちません。オブザーバビリティとはで、その準備の方法を解説しています。
プログレッシブデリバリーとトランクベース開発の関係
両者は相性が良い組み合わせです。トランクベース開発では、ブランチを短く保ち、小さな変更を頻繁にマージします。リスクは、未完成でテストされていない作業がメインブランチに頻繁に入ることです。プログレッシブデリバリーが、それを安全にします。コードはトランクに入り、フラグの背後で出荷され、段階的にリリースされます。
小さなバッチと段階的な公開は、デバッグのコストも下げます。カナリアが失敗したとき、疑うべき変更は40個ではなく1つです。夜11時に1週間分のマージ済みコミットを二分探索で追いかけた経験がある人なら、その価値がわかるはずです。
10〜30人のチームが最初に取るべき一歩
最初からサービスメッシュを導入しようとしないでください。まずは、止めるボタンを手に入れられる最小の仕組みから始めます。
1週目: リスクの高い機能を1つフラグの背後に置き、まずは自分たちのチームにだけリリースします。
2週目: エラー率とレイテンシをバージョン別に表示するダッシュボードを追加します。ツールがバージョン別に分割できないなら、まずそこを直します。
3週目以降: ステートレスなサービスを1つ、2〜3段階のカナリアコントローラーに移し、エラー率で自動中止する設定にします。
効果は「安心感」ではなく、時間で測ってください。小さな範囲に封じ込められたインシデントの件数と、ロールバックにかかった時間を数えます。この2つの数字が、チームにとって機能しているかどうかを教えてくれます。
プログレッシブデリバリーはどこで壊れやすいのか
壊れやすい場所は3つあり、どれもコントローラーではありません。
データベースのマイグレーション。 カナリアとは、同じデータベースに2つのバージョンのコードが同時にアクセスする状態です。バージョンN+1が、バージョンNがまだ読んでいるカラムを削除したりリネームしたりすると、カナリアがベースラインを道連れに落とします。地味ですが確実な対策は、expand and contract です。まず新しいカラムを追加し、両方に書き込むコードをリリースし、既存データを埋めてから読み取りを切り替え、古いカラムの削除は最後に行います。
スティッキーセッションとキャッシュ。 ユーザーがリクエストごとに古いバージョンと新しいバージョンを行き来すると、誰にも再現できないバグが生まれます。ロールアウトの期間中は、ユーザーを1つのバリアントに固定してください。Cookie、アカウントID、フラグの評価結果などで固定できます。
遅れて届くメトリクス。 1時間ごとにしか更新されないコンバージョン指標では、10分間のカナリアの段階を制御できません。ロールアウト中は素早いシグナル(エラーやレイテンシ)で判断し、50%から100%へ進む前に、遅いビジネス指標を確認してください。
リポジトリ内で何が稼働しているかをどう把握するか
プログレッシブデリバリーでは、1つのリリースが設定ファイル、フラグの定義、ロールアウトのマニフェスト、ダッシュボードに分散します。数か月たつと、「新しい請求経路を制御しているフラグはどれで、誰がオーナーなのか」という問いが、いつもの作業になります。grep し、blame し、最後に誰かに聞く、という流れです。
これはツールの問題ではなく、コードを読む問題です。フラグのキーでリポジトリを検索し、参照のひとつずつを呼び出し元まで追うのが、使われていないフラグや途中で止まったロールアウトを見つける最速の方法です。「このフラグはどこで評価され、オフのときに何が起きるのか」を実際のコードから答えてくれるツールは、別のダッシュボードよりもこの場面で多くの時間を節約します。
最初からやらないこと
インフラの費用がすでに議論の的になっているなら、全面的なブルーグリーンはやめてください。トラフィックがほとんどないサービスでは、カナリアもやめてください。チームの誰も午前3時にデバッグできないロールアウトツールも避けてください。
本当の問題は、選んだ戦略ではありません。コードを出荷することと、それが本番で何をするのかを知ることの間にあるギャップです。プログレッシブデリバリーは、そのギャップをトラフィックの小さな一片ずつ縮めます。そして最初の一片こそが肝心です。小さく保ち、観測可能にし、すぐ止められる状態にしておいてください。