アプリケーションのデプロイとテストの戦略

Last reviewed 2023-07-20 UTC

このドキュメントでは、一般的に使用されるアプリケーションのデプロイとテストのパターンの概要について説明します。各パターンがどのように機能するか、各パターンの利点、各パターンを実装する際の考慮事項について解説しています。

実行中のアプリケーションを新しいバージョンにアップグレードするとします。シームレスなロールアウトを実現するために、通常は以下の項目を検討します。

  • (ダウンタイムがある場合)アプリケーションのダウンタイムを最小限に抑える方法。
  • ユーザーへの影響を最小限に抑えながらインシデントを管理、解決する方法。
  • 失敗したデプロイを確実かつ効果的に処理する方法。
  • ヒューマン エラーや処理エラーを最小限に抑えて、予測可能かつ繰り返し可能なデプロイを実現する方法。

どのデプロイ パターンを選択するかは、ビジネス目標に大きく依存します。たとえば、ダウンタイムなしで変更をロールアウトする必要がある場合もあれば、機能を一般提供する前に何かしらの環境や一部のユーザーに変更をロールアウトする必要がある場合もあります。このドキュメントで説明する各方法では、デプロイを成功したとみなすために達成する必要がある特定の目標について説明します。

このドキュメントは、さまざまなアプリケーション、システム、フレームワークのリリースおよびデプロイ戦略の定義と実装に取り組むシステム管理者と DevOps エンジニアを対象としています。

デプロイ戦略

サービスをデプロイしても、直ちにユーザーに公開されるとは限りません。また、サービスがリリースされた後でないと、ユーザーがアプリケーションの変更点を確認できないこともあります。ですが、サービスがインプレースでリリースされる場合、デプロイとリリースは同時に行われます。この場合、新しいバージョンをデプロイすると、そのバージョンは本番環境トラフィックの受け入れを開始します。また、複数のサービス バージョンを同時にプロビジョニングするデプロイ戦略もあります。このデプロイ パターンを使用すると、受信リクエストを受信するバージョンの制御と管理が可能になります。デプロイ、リリース、および関連するコンセプトの詳細については、Kubernetes と継続的ソフトウェア デリバリーの課題をご覧ください。

このセクションで説明するデプロイ パターンを使用すれば、新しいソフトウェアのリリースを柔軟に自動化できます。どの方法が最適かは、何を目的とするかによって異なります。

デプロイの再作成パターン

デプロイの再作成では、新しいアプリケーション バージョンをスケールアップする前に、既存のアプリケーション バージョンを完全にスケールダウンします。

次の図は、アプリケーションに対するデプロイの再作成アプローチがどのように機能するかを示しています。

デプロイの再作成のフロー。

バージョン 1 は現在のアプリケーション バージョンを表し、バージョン 2 は新しいアプリケーション バージョンを表します。現在のアプリケーション バージョンを更新する際、最初に既存のバージョン 1 のレプリカをゼロにスケールダウンしてから、新しいバージョンのレプリカを同時にデプロイします。

主な利点

再作成アプローチの利点は、そのシンプルさです。複数のアプリケーション バージョンを同時に管理する必要がないため、データとアプリケーションの下位互換性の問題を回避できます。

考慮事項

再作成アプローチでは、更新プロセス中にダウンタイムが発生します。メンテナンスの時間枠や停止に対応できるアプリケーションであれば、ダウンタイムは問題になりません。ですが、サービスレベル契約(SLA)と可用性の要件が厳しいミッション クリティカルなアプリケーションの場合は、別のデプロイ戦略も検討してください。

ローリング アップデートによるデプロイ パターン

ローリング アップデートによるデプロイでは、次の図に示すように、すべてのアプリケーション インスタンスを同時に更新するのではなく、実行中のアプリケーション インスタンスのサブセットを更新します。

ローリング アップデートによるデプロイのフロー。

このデプロイ方法では、同時に更新するインスタンスの数をウィンドウ サイズと呼びます。上の図のローリング アップデートでは、ウィンドウ サイズは 1 です。一度につき 1 つのアプリケーション インスタンスが更新されます。クラスタが大きい場合は、ウィンドウ サイズを大きくします。

ローリング アップデートでは、アプリケーションを柔軟に更新できます。

  • 古いバージョンをスケールダウンする前に、新しいバージョンのアプリケーション インスタンスをスケールアップできます(サージ アップグレードと呼ばれるプロセス)。
  • 新しいインスタンスを同時にスケールアップする際に使用不可となるアプリケーション インスタンスの最大数を指定できます。

主な利点

  • ダウンタイムなし。ウィンドウ サイズに基づいて、デプロイ ターゲットを段階的に(1 つずつ、2 つずつなど)更新します。アプリケーションの新しいバージョンがトラフィックを受け入れる準備ができてから、更新されたデプロイ ターゲットにトラフィックを転送します。
  • デプロイリスクの軽減。アップデートを徐々にロールアウトするため、新しいバージョンに含まれる不安定さはごく一部のユーザーのみにしか影響しません。

考慮事項

  • ロールバックが遅い。新しいリリースが不安定な場合、新しいレプリカを終了して古いバージョンを再デプロイできます。ただし、ロールアウトと同様に、ロールバックは徐々に行われます。
  • 下位互換性。新しいコードと古いコードが並べて表示されるため、ユーザーがランダムにどちらかのバージョンへとルーティングされる可能性があります。そのため、新しいデプロイに下位互換性があることを確認してください。つまり、新しいアプリケーション バージョンで、古いバージョンに保存されているデータの読み取りや処理ができることを確認してください。このデータには、ディスク、データベース、またはユーザーのブラウザ セッションの一部として保存されたデータが含まれます。
  • スティッキー セッション。アプリケーションでセッションの永続性が必要な場合は、ロードバランサで固定コネクション ドレインをサポートすることをおすすめします。また、可能な場合はセッション共有を呼び出して(セッション レプリケーションやデータストアを使用したセッション管理を通じて)、セッションを基盤となるリソースから分離できるようにすることをおすすめします。

Blue/Green デプロイ パターン

Blue/Green デプロイ(Red/Black デプロイとも呼ばれます)では、次の図に示すように、2 つの同一のアプリケーションのデプロイを行います。

Blue/Green デプロイのフロー。

この図では、青色が現在のアプリケーションのバージョンを表し、緑色が新しいアプリケーションのバージョンを表します。一度に公開できるバージョンは 1 つのみです。トラフィックは青色のデプロイにルーティングされます。その間に、緑色のデプロイが作成されてテストされます。テストが完了したら、トラフィックを新しいバージョンに転送します。

デプロイが成功したら、青色のデプロイをロールバック先として保持するか、または終了させます。また、これらのインスタンスに新しいバージョンのアプリケーションをデプロイすることもできます。この場合、現在の(青色の)環境が次のリリースのステージング領域として機能します。

主な利点

  • ダウンタイムなし。Blue/Green デプロイでは、ダウンタイムなしで迅速にカットオーバーできます。
  • 即時ロールバック。ロードバランサを調整してトラフィックを青色の環境にルーティングし直すことで、デプロイ プロセス中にいつでもロールバックできます。ダウンタイムの影響は、問題を検出してからトラフィックを青色の環境に切り替える際にかかる時間に限定されます。
  • 環境の分離。Blue/Green デプロイでは、緑色の環境を同時に起動しても、青色の環境をサポートするリソースが影響を受けないことが保証されています。この分離により、デプロイリスクが軽減されます。

考慮事項

  • コストと運用上のオーバーヘッド。Blue/Green デプロイ パターンを使用する場合、重複する環境を同じインフラストラクチャ上で維持する必要があります。そのため、運用上のオーバーヘッドとコストが増加する可能性があります。
  • 下位互換性。青色のデプロイと緑色のデプロイで、データポイントとデータストアを共有できます。アプリケーションの両方のバージョンで、データストアのスキーマとレコードの形式を使用できることを確認することをおすすめします。この下位互換性は、ロールバックが必要となった際に 2 つのバージョンをシームレスに切り替えるときに必要となります。
  • カットオーバー。現在のバージョンを廃止する場合は、既存のトランザクションとセッションで適当なコネクション ドレインを有効にすることを推奨します。この手順により、現在のデプロイで処理されたリクエストを正常に完了、または終了できます。

テスト戦略

このセクションで説明するテストパターンは通常、同時実行と負荷の現実的なレベルでの妥当な期間におけるサービスの信頼性と安定性を検証するために使用されます。

カナリアテスト パターン

カナリアテストでは、次の図に示すように、変更の一部をロールアウトして、そのパフォーマンスをベースライン デプロイと比較することで評価します。

カナリアテストの構成。

このテストパターンでは、新しいバージョンのアプリケーションを本番環境バージョンと一緒にデプロイします。次に、トラフィックの一部を分割して本番環境バージョンからカナリア バージョンに転送し、カナリアのパフォーマンスを評価します。

カナリアの構成時、評価用の主要な指標を選択します。実際の本番環境ではなく、それに相当するベースラインとカナリアを比較することを推奨します。

分析に影響する可能性のある因子(キャッシュ、長時間接続、ハッシュ オブジェクトなど)を減らすために、アプリケーションのベースライン バージョンで次の手順を行うことをおすすめします。

  • アプリケーションのベースライン バージョンと本番環境バージョンが同じであることを確認します。
  • カナリアのデプロイと同時に、ベースライン バージョンをデプロイします。
  • ベースライン デプロイ(アプリケーション インスタンスの数や自動スケーリング ポリシーなど)がカナリア デプロイと一致していることを確認します。
  • ベースライン バージョンを使用して、カナリアと同じトラフィックを配信します。

カナリアテストでは、さまざまなパーティショニング戦略で部分的なロールアウトを行うことができます。たとえば、アプリケーションのユーザーが地理的に分散している場合に、新しいバージョンの特定のリージョンや特定のロケーションへのロールアウトから始めることができます。詳細については、Spinnaker を使用した GKE のカナリア分析の自動化をご覧ください。

主なメリット

  • 本番環境トラフィックでテスト可能。ステージング環境でシミュレートされたトラフィックを使用してアプリケーションをテストするのではなく、本番環境トラフィックでカナリアテストを実行できます。カナリア ロールアウトでは、新しいアプリケーションをリリースする際の増分と、リリースの次のステップをトリガーするタイミングを決定する必要があります。カナリアテストでは、モニタリング機能が問題を明確に検出できるようにする必要があるため、十分な量のトラフィックが必要になります。
  • 高速ロールバック。ユーザー トラフィックを古いバージョンのアプリケーションにリダイレクトすることで、すぐにロールバックできます。
  • ダウンタイムなし。カナリア リリースでは、本番環境トラフィックをダウンタイムなしでさまざまなバージョンのアプリケーションに転送できます。

考慮事項

  • ロールアウトが遅い。リリースの各段階で、適当な期間のモニタリングが必要となります。そのため、全体としてのリリースが遅れる場合があります。カナリアテストに数時間かかる場合もあります。
  • オブザーバビリティ。カナリアテストを実装するためには、インフラストラクチャとアプリケーション スタックを効果的に観察、モニタリングする機能が必要です。堅牢なモニタリング機能を実装する場合、かなりの労力が必要となることがあります。
  • 下位互換性とスティッキー セッション。ローリング アップデートと同様に、カナリアがデプロイされている間に複数のアプリケーション バージョンが環境内で実行されるため、カナリアテストは下位非互換性とセッションの永続性にリスクをもたらす可能性があります。

A/B テストパターン

A/B テストでは、バリアント実装を使用して仮説をテストします。A/B テストは、データから得られた結果に基づいて(予測だけでなく)ビジネス上の意思決定を行う際に使用されます。

A/B テストを実行すると、次の図に示すように、ルーティング ルールに基づいてユーザーのサブセットが新しい機能に転送されます。

A/B テストの構成。

多くの場合、ルーティング ルールにはブラウザのバージョン、ユーザー エージェント、位置情報、オペレーティング システムなどといった因子が含まれます。2 つのバージョンを測定して比較した後、より良い結果が得られたバージョンで本番環境を更新します。

主な利点

A/B テストは、アプリケーション機能の効果を測定するのに最適です。前述したデプロイ パターンのユースケースでは、新しいソフトウェアを安全にリリースし、予測可能な形でロールバックすることに重点を置いています。A/B テストでは、新機能のターゲット ユーザーを管理して、ユーザーの行動における統計的に有意な差異をモニタリングします。

考慮事項

  • 複雑な設定。A/B テストでは、あるバージョンが他のバージョンよりも優れているということの裏付けとなる、代表的なサンプルが求められます。たとえば、A/B テスト サンプルサイズ計算ツールなどを使用して、サンプルサイズを事前計算し、95% 以上の統計的有意性に達するように適当な回数のテストを実行する必要があります。
  • 結果の妥当性。偽陽性、サンプリング バイアス、その他の外部因子(季節性、マーケティング プロモーションなど)といった要因がテスト結果を歪める可能性があります。
  • オブザーバビリティ。重複するトラフィックに対して複数の A/B テストを実行すると、モニタリングとトラブルシューティングのプロセスが難しくなることがあります。たとえば、商品ページ A と商品ページ B を、あるいは購入ページ C と購入ページ D を比較してテストする場合に、バージョン間のトラフィック分割などの指標を決定するための分散トレースが重要になります。

シャドーテスト パターン

カナリアテストのような順次的なテスト手法では、テストの初期段階でお客様に下位のアプリケーション バージョンを公開してしまう可能性があります。このリスクは、シミュレーションなどのオフライン手法を使用して管理できます。ですが、新しいバージョンとユーザーとのやり取りが発生しないため、オフライン手法ではアプリケーションの改善点が検証できません。

シャドーテストでは、次の図に示すように、新しいバージョンを現在のバージョンと一緒にデプロイして実行しますが、新しいバージョンはユーザーには表示されません。

シャドーテストの構成。

受信したリクエストはミラーリングされ、テスト環境で再現されます。このプロセスは、事前にキャプチャされた本番環境トラフィックのコピーが新しくデプロイされたサービスで再現された後、リアルタイムで、あるいは非同期で発生します。

シャドーテストが、既存の本番環境やユーザー状態を変更しかねない副作用を引き起こさないことを確認する必要があります。

主な利点

  • 本番環境への影響がゼロ。トラフィックが複製されているため、シャドーデータを処理しているサービスで発生するバグは本番環境には影響しません。
  • 本番環境の負荷を使用して新しいバックエンド機能をテスト可能。トラフィックのシャドーイングを Diffy などのツールと組み合わせて使用すれば、本番環境のトラフィックに対するサービスの動作を測定できます。この機能を使用することで、エラー、例外、パフォーマンス、アプリケーション バージョン間の結果の等価性をテストできます。
  • デプロイリスクの軽減。トラフィックのシャドーイングは通常、カナリアテストなどの他の手法と組み合わせて使用します。トラフィックのシャドーイングを使用して新しい機能をテストした後、より多くのユーザーに機能をリリースしていって、ユーザー エクスペリエンスをテストします。アプリケーションが安定性とパフォーマンスの要件を満たすまで、完全なロールアウトはなされません。

考慮事項

  • 副作用。トラフィックのシャドーイングでは、状態を変更するサービスやサードパーティのサービスとやり取りするサービスを処理する際に注意する必要があります。たとえば、ショッピング カート プラットフォームの支払いサービスをシャドーテストすると、お客様は注文に対して 2 回の支払いを行うことになる可能性があります。望ましくない変更など、リスクが発生しかねない相互作用を引き起こす可能性のあるシャドーテストを回避するには、サードパーティのシステムやデータストアではなく、スタブや Hoverfly などの仮想化ツールを使用することをおすすめします。
  • コストと運用上のオーバーヘッド。シャドーテストの設定はかなり複雑です。また、Blue/Green デプロイと同様に、シャドー デプロイでは、2 つの環境を同時に実行して管理する必要があるため、コストや運用に影響します。

適切な戦略の選択

アプリケーションをデプロイしてリリースするための方法はいくつかあり、それぞれにメリットとデメリットがあります。最適な選択は、ビジネスのニーズや制約によって異なります。次の点を考慮してください。

  • 最も重要な考慮事項は何か。たとえば、ダウンタイムが発生しても問題ないか。コストによる制約を受けるか。自身のチームに、複雑なロールアウト、ロールバックの設定を行うための適切なスキルを持った人材がいるか。
  • 厳格なテスト管理を実施するか。また、リリースの安定性を確保して悪影響を制限するために、本番環境トラフィックに対して新しいリリースをテストするか。
  • ユーザーのプール間で機能をテストして、特定のビジネス仮説を相互検証するか。ターゲット ユーザーが更新を承認するかどうかを管理できるか。たとえば、モバイル デバイスでの更新にはユーザー操作が必要なため、追加の権限が必要になることがあります。
  • 環境内のマイクロサービスは完全に独立しているか。または、従来の変更が困難なアプリケーションと連携して動作するマイクロサービススタイルのアプリケーションのハイブリッドがあるか。詳細については、ハイブリッド環境とマルチクラウド環境でのデプロイ パターンを参照してください。
  • 新しいリリースでスキーマの変更が伴うか。(「はい」の場合)スキーマの変更が複雑でコードの変更から分離できないか。

以下のテーブルでは、このドキュメントの前半で説明したデプロイ パターンとテストパターンの主な特徴をまとめています。さまざまなデプロイ方法、テスト方法の長所、短所を比較検討する際は、ビジネスニーズと技術リソースを検討し、最もメリットのあるオプションを選択します。

デプロイ パターン
またはテストパターン
ゼロ ダウンタイム 本番環境トラフィックでのテスト 条件に基づいたユーザーへの公開 ロールバック時間 ハードウェアとクラウドのコストへの影響
再作成
バージョン 1 が終了し、バージョン 2 がロールアウトされます。
x x x 高速だがダウンタイムが発生するため破壊的 追加の設定は不要
ローリング アップデート
バージョン 2 が、バージョン 1 に置き換わる形で段階的にロールアウトされます。
x x 低速 サージ アップグレードの追加設定が必要な場合あり
Blue/Green
バージョン 2 はバージョン 1 と一緒にリリースされます。トラフィックはバージョン 2 のテスト後にバージョン 2 にルーティングされます。
x x 即時 青色の環境と緑色の環境を同時に維持する必要がある
カナリア
バージョン 2 が一部のユーザーに公開され、その後完全に公開されます。
x 高速 追加の設定は不要
A/B
バージョン 2 が、特定の条件下でユーザーの一部に公開されます。
高速 追加の設定は不要
シャドー
バージョン 2 が、ユーザーのリクエストに影響を与えずに実世界のトラフィックを受信します。
x 適用されません ユーザーのリクエストを取得して再現するための並列環境を維持する必要がある

ベスト プラクティス

以下に示すいくつかのベスト プラクティスに沿って進めることで、アプリケーション チームはデプロイとテストのリスクを最小限に抑えることができます。

  • 下位互換性。複数のアプリケーション バージョンを同時に実行する場合は、データベースがすべてのアクティブなバージョンと互換性があることを確認します。たとえば、新しいリリースではデータベース スキーマを変更する必要があります(新しい列など)。このような場合は、データベース スキーマが古いバージョンと下位互換性を持つように変更する必要があります。完全なロールアウトが完了してから、古いスキーマのサポートを削除して、最新バージョンのサポートのみを残せるようになります。下位互換性を実現する 1 つの方法は、コードの変更とスキーマの変更を切り離すことです。詳細については、同時変更データベース リファクタリングのパターンをご覧ください。
  • 継続的インテグレーション / 継続的デプロイ(CI / CD)。CI は、機能ブランチにチェックインされたコードが、依存関係チェック、ユニットテスト、統合テスト、ビルドプロセスに合格した後にのみ、メインブランチとマージすることを保証します。そのため、アプリケーションへの変更はすべて、デプロイ前にテストされます。CD では、CI 組み込みのコード アーティファクトがパッケージ化され、1 つ以上の環境でデプロイされます。詳細については、Google Cloud を使用した CI / CD パイプラインの構築をご覧ください。
  • 自動化。アプリケーション更新を継続的にユーザーに配布するのであれば、ソフトウェアを確実にビルド、テスト、デプロイする自動プロセスを構築することを推奨します。また、コードの変更が、アーティファクトの作成、単体テスト、機能テスト、本番環境のロールアウトを含む CI / CD パイプラインを介して自動的に実行されるようにすることをおすすめします。Cloud BuildCloud DeploySpinnakerJenkins などの自動化ツールを使用することで、デプロイ プロセスを自動化し、より効率的で信頼性が高く、予測可能なプロセスにすることができます。
  • IaC と GitOps。複雑なデプロイとテストの戦略を管理する必要がある場合は、Infrastructure as Code(IaC)と GitOps ツールの使用を検討してください。TerraformConfig Connector で IaC を使用すると、宣言型言語を使用してインフラストラクチャと戦略を定義できます。Config SyncArgo CD で GitOps を使用すると、git でコードを管理できます。
  • ロールバック戦略。問題が発生することもあります。不測の事態が発生したときに備えてロールバック戦略を作成しておくことをおすすめします。信頼性の高いロールバック戦略により、管理者と DevOps エンジニアはリスクを管理できます。ロールバック戦略を作成する場合は、App EngineCloud Run など、組み込み機能としてロールバックをサポートするプラットフォームを使用します。ロールバックの要件に応じて、Cloud DeploySpinnakerArgo RollOuts などのリリース自動化ツールを使用することもできます。
  • デプロイ後のモニタリング。重要な指標をモニタリングし、デプロイやテストが失敗したときに担当者に通知が届くようにするには、Google Cloud Observability を使用してモニタリング システムを構築します。ヘルスチェックに失敗したデプロイに対して自動ロールバックを有効にすることもできます。Error ReportingCloud TraceCloud Profiler を使用すると、デプロイ後の単純な問題や複雑な問題の原因を特定できます。

次のステップ