トラフィックの5%がステージング環境よりも多くのことを教えてくれる理由
数週間前、とあるチームが新しい認証フローをデプロイしました。ステージング環境ではテストはすべてグリーン、応答時間も許容範囲内、エラーもゼロでした。そのまま本番環境に昇格させ、数分以内に全ユーザーを新しいバージョンにルーティングしました。30分後、サポートチケットが山積みになり始めました。特定の地域のユーザーがログインできなくなっていたのです。ステージング環境では決して捕捉できませんでした。なぜなら、本番環境のような現実的なトラフィックパターン、地域ごとのレイテンシ、多様なデバイス構成がなかったからです。
チームはロールバックしましたが、被害はすでに発生していました。ユーザーの信頼は失われ、チームは本番環境の実際の条件下でしか発生しない問題のデバッグに2日間を費やしました。
このギャップを埋めようとするのが、プログレッシブデリバリー戦略です。全員に一度にスイッチを切り替えるのではなく、まずは少数のユーザーまたはトラフィックだけを新しいバージョンにさらします。その結果を観察し、それから続行するか、一時停止するか、ロールバックするかを判断します。
このための2つの一般的な戦略が、カナリアリリースと段階的ロールアウトです。似ているように聞こえますが、解決する問題は異なります。その違いを理解することで、変更をリリースするたびに適切なアプローチを選択できるようになります。
カナリアリリース:トラフィックに判断を委ねる
カナリアリリースは、新しいバージョンに少量のトラフィックをルーティングすることから始まります。アプリケーションが1秒間に100リクエストを受信しているとします。ロードバランサーまたはサービスメッシュを設定して、そのうちの5リクエストを新しいバージョンを実行しているサーバーに送信します。残りの95リクエストは引き続き旧バージョンに送られます。
そして、エラー率、レイテンシ、CPU使用率、データベースクエリのパフォーマンスといった主要なシグナルを監視します。新しいバージョンが数分経っても健全に見える場合は、トラフィックの割合を10%、20%、50%と増やし、最終的に100%にします。
ここでの重要な考え方は、分割が確率的であるということです。どのユーザーも、100リクエスト中の5番目に該当すれば、新しいバージョンに当たる可能性があります。ユーザーは自分がどのバージョンに当たったかを知ることはなく、アプリケーションが正常に動作している限り、気にする必要もありません。
カナリアリリースは、実際の本番負荷の下で変更が安定していることを検証したい場合に役立ちます。ステージング環境はロジックエラーの検出には優れていますが、本番環境のカオスを再現することはできません。不均一なトラフィックスパイク、特定の地域からの遅いデータベース接続、負荷がかかったときだけ現れるサードパーティAPIのレート制限などです。
この戦略は、リスクの高い変更に特に有効です。主要なビジネスロジックの書き換え、データベーススキーマのマイグレーション、ネットワーキングや並行処理に影響を与えるライブラリのアップグレード、キャッシュ動作の変更などは、すべてカナリアリリースの良い候補です。何か問題が発生しても、影響を受けるユーザーはごく一部であり、新しいバージョンからのトラフィックを迅速にドレインできます。
段階的ロールアウト:誰が最初に受け取るかを選択する
段階的ロールアウトは異なるアプローチを取ります。トラフィックをランダムに分割する代わりに、どのユーザーグループが最初に新しいバージョンを受け取るかを決定します。これらのグループはしばしばリングと呼ばれます。
リング1には、社内チームと少数のベータテスターが含まれるかもしれません。リング2は、特定の地域または特定のデバイスタイプのユーザーの一部です。リング3は全フリーティアユーザーかもしれません。リング4は、厳格なSLAを持つエンタープライズ顧客です。
ロールアウトは、前のリングで重大な問題が報告されない場合にのみ、これらのリングを進行します。リング1で問題が報告された場合は、拡大する前に一時停止します。リング2でエラー率の上昇が見られた場合は、リング3に到達する前にロールバックします。
カナリアリリースとの主な違いは、意図性です。どれだけのトラフィックかだけでなく、誰が新しいバージョンを受け取るかを選択します。これは、ユーザーグループごとに期待値、使用パターン、契約上の義務が異なる場合に重要です。
例えば、アプリケーションが個人ユーザーとSLAを結んだ大規模なエンタープライズクライアントの両方にサービスを提供している場合、エンタープライズのリクエストを誤ってバグのある新しいバージョンにルーティングしたくはないでしょう。段階的ロールアウトを使用すれば、重要度の低いユーザーで最初に変更をテストし、確信が持てた後にのみ高価値の顧客に拡大できます。
段階的ロールアウトは、モバイルアプリのリリースにも適しています。モバイルアプリの場合、ネットワークレベルでトラフィックを簡単に制御できません。代わりに、アプリストアの段階的ロールアウト機能を使用して、ユーザーのごく一部にアップデートをリリースし、クラッシュレポートと評価を監視してから、より多くのユーザーに拡大します。
両方の戦略を組み合わせる
実際には、カナリアリリースと段階的ロールアウトは相互排他的ではありません。多くのチームはこれらを組み合わせて、単一のプログレッシブデリバリーパイプラインにしています。
以下の図は、2つの戦略を並べて示し、それらをどのように連鎖させることができるかを示しています。
パイプラインは、技術的な安定性を検証するために、まず5%のトラフィックでカナリアリリースから始めるかもしれません。カナリアが合格したら、パイプラインは段階的ロールアウトに移行します。最初に社内ユーザー、次にベータユーザー、次に本番ユーザーの一部、そして最後に全員へと展開します。
この組み合わせアプローチにより、両方の安全レイヤーが得られます。カナリアはメモリリークや遅いデータベースクエリのようなインフラストラクチャレベルの問題を捕捉します。段階的ロールアウトは、特定のアカウントタイプや地域でのワークフロー破損のようなユーザー向けの問題を捕捉します。
適切に設計されたプログレッシブデリバリーパイプラインは、これらの判断を自動化できます。定義されたメトリクスを監視し、しきい値と比較し、次のステップに進むか、手動レビューのためにロールアウトを保留するか、自動ロールバックをトリガーします。
始める前に必要なもの
プログレッシブデリバリー戦略は、判断に使用するデータと同じくらい有用です。優れた可観測性がなければ、カナリアリリースは本番環境を壊すための単なる遅い方法に過ぎません。
必要なもの:
- バージョン別に分類されたリアルタイムのエラー率監視
- 新しいバージョンと旧バージョンのレイテンシパーセンタイル比較
- コンバージョン率やサインアップ完了率など、製品にとって重要なビジネスメトリクス
- ユーザーレポートを、そのユーザーが実行しているバージョンと関連付ける方法
また、迅速にロールバックできることも必要です。カナリアで問題が発生した場合、新しいバージョンからのトラフィックを数時間ではなく数秒でドレインできる必要があります。これには、ロードバランサー、サービスメッシュ、またはフィーチャーフラグシステムなど、トラフィックシフトをサポートするインフラストラクチャが必要です。
実践的なクイックチェックリスト
初めてプログレッシブデリバリーを設定する場合の、実装を導くための短いリストです。
- 1つの戦略から始める。 本番負荷下での技術的な安定性を重視するならカナリアリリースを選びます。どのユーザーが最初に変更を目にするかを制御する必要があるなら段階的ロールアウトを選びます。
- 開始前に明確なgo/no-go基準を定義する。 許容できるエラー率は?どの程度のレイテンシ増加なら多すぎる?これらのしきい値を文書化し、パイプラインに設定します。
- 監視が技術メトリクスとビジネスメトリクスの両方をカバーしていることを確認する。 カナリアでエラーがゼロでも、ユーザーが購入を完了できなければチェックアウトフローが壊れている可能性があります。
- ロールバックを練習する。 何かが壊れてから、トラフィックシフトに10分かかることが判明するのを避けましょう。
- 各戦略に個別に慣れてから組み合わせる。 組み合わせたパイプラインは複雑さを増すため、積み重ねる前に各レイヤーを理解しておく必要があります。
具体的な要点
カナリアリリースと段階的ロールアウトは、単に慎重になるためのものではありません。コードが全員に届く前に、本番環境が実際にコードに何を行うかを学ぶためのものです。ステージング環境はテストへの信頼を与えます。カナリアまたは段階的ロールアウトは、現実への信頼を与えます。
1つの戦略から始め、メトリクスを計装し、データが次に進むタイミングを教えてくれるようにしましょう。目標はリスクを完全に排除することではありません。目標はリスクを少数のユーザーグループに封じ込め、そこから学び、確信が持てたときにのみ拡大することです。