このドキュメントでは、一般的に使用されるアプリケーションのデプロイとテストのパターンの概要について説明します。各パターンがどのように機能するか、各パターンの利点、各パターンを実装する際の考慮事項について解説しています。
実行中のアプリケーションを新しいバージョンにアップグレードするとします。シームレスなロールアウトを実現するために、通常は以下の項目を検討します。
- (ダウンタイムがある場合)アプリケーションのダウンタイムを最小限に抑える方法。
- ユーザーへの影響を最小限に抑えながらインシデントを管理、解決する方法。
- 失敗したデプロイを確実かつ効果的に処理する方法。
- ヒューマン エラーや処理エラーを最小限に抑えて、予測可能かつ繰り返し可能なデプロイを実現する方法。
どのデプロイ パターンを選択するかは、ビジネス目標に大きく依存します。たとえば、ダウンタイムなしで変更をロールアウトする必要がある場合もあれば、機能を一般提供する前に何かしらの環境や一部のユーザーに変更をロールアウトする必要がある場合もあります。このドキュメントで説明する各方法では、デプロイを成功したとみなすために達成する必要がある特定の目標について説明します。
このドキュメントは、さまざまなアプリケーション、システム、フレームワークのリリースおよびデプロイ戦略の定義と実装に取り組むシステム管理者と DevOps エンジニアを対象としています。付属のチュートリアルでは、Google Kubernetes Engine(GKE)に基づく例を使用して、このドキュメントで説明するデプロイとテストの手法を実装する方法を説明しています。
デプロイ戦略
サービスをデプロイしても、直ちにユーザーに公開されるとは限りません。また、サービスがリリースされた後でないと、ユーザーがアプリケーションの変更点を確認できないこともあります。ですが、サービスがインプレースでリリースされる場合、デプロイとリリースは同時に行われます。この場合、新しいバージョンをデプロイすると、そのバージョンは本番環境トラフィックの受け入れを開始します。また、複数のサービス バージョンを同時にプロビジョニングするデプロイ戦略もあります。このデプロイ パターンを使用すると、受信リクエストを受信するバージョンの制御と管理が可能になります。デプロイ、リリース、および関連するコンセプトの詳細については、Kubernetes と継続的ソフトウェア デリバリーの課題をご覧ください。
このセクションで説明するデプロイ パターンを使用すれば、新しいソフトウェアのリリースを柔軟に自動化できます。どの方法が最適かは、何を目的とするかによって異なります。
デプロイの再作成パターン
デプロイの再作成では、新しいアプリケーション バージョンをスケールアップする前に、既存のアプリケーション バージョンを完全にスケールダウンします。
次の図は、アプリケーションに対するデプロイの再作成アプローチがどのように機能するかを示しています。
バージョン 1 は現在のアプリケーション バージョンを表し、バージョン 2 は新しいアプリケーション バージョンを表します。現在のアプリケーション バージョンを更新する際、最初に既存のバージョン 1 のレプリカをゼロにスケールダウンしてから、新しいバージョンのレプリカを同時にデプロイします。
主な利点
再作成アプローチの利点は、そのシンプルさです。複数のアプリケーション バージョンを同時に管理する必要がないため、データとアプリケーションの下位互換性の問題を回避できます。
考慮事項
再作成アプローチでは、更新プロセス中にダウンタイムが発生します。メンテナンスの時間枠や停止に対応できるアプリケーションであれば、ダウンタイムは問題になりません。ですが、サービスレベル契約(SLA)と可用性の要件が厳しいミッション クリティカルなアプリケーションの場合は、別のデプロイ戦略も検討してください。
ローリング アップデートによるデプロイ パターン
ローリング アップデートによるデプロイでは、次の図に示すように、すべてのアプリケーション インスタンスを同時に更新するのではなく、実行中のアプリケーション インスタンスのサブセットを更新します。
このデプロイ方法では、同時に更新するインスタンスの数をウィンドウ サイズと呼びます。上の図のローリング アップデートでは、ウィンドウ サイズは 1 です。一度につき 1 つのアプリケーション インスタンスが更新されます。クラスタが大きい場合は、ウィンドウ サイズを大きくします。
ローリング アップデートでは、アプリケーションを柔軟に更新できます。
- 古いバージョンをスケールダウンする前に、新しいバージョンのアプリケーション インスタンスをスケールアップできます(サージ アップグレードと呼ばれるプロセス)。
- 新しいインスタンスを同時にスケールアップする際に使用不可となるアプリケーション インスタンスの最大数を指定できます。
主な利点
- ダウンタイムなし。ウィンドウ サイズに基づいて、デプロイ ターゲットを段階的に(1 つずつ、2 つずつなど)更新します。アプリケーションの新しいバージョンがトラフィックを受け入れる準備ができてから、更新されたデプロイ ターゲットにトラフィックを転送します。
- デプロイリスクの軽減。アップデートを徐々にロールアウトするため、新しいバージョンに含まれる不安定さはごく一部のユーザーのみにしか影響しません。
考慮事項
- ロールバックが遅い。新しいリリースが不安定な場合、新しいレプリカを終了して古いバージョンを再デプロイできます。ただし、ロールアウトと同様に、ロールバックは徐々に行われます。
- 下位互換性。新しいコードと古いコードが並べて表示されるため、ユーザーがランダムにどちらかのバージョンへとルーティングされる可能性があります。そのため、新しいデプロイに下位互換性があることを確認してください。つまり、新しいアプリケーション バージョンで、古いバージョンに保存されているデータの読み取りや処理ができることを確認してください。このデータには、ディスク、データベース、またはユーザーのブラウザ セッションの一部として保存されたデータが含まれます。
- スティッキー セッション。アプリケーションでセッションの永続性が必要な場合は、ロードバランサで固定とコネクション ドレインをサポートすることをおすすめします。また、可能な場合はセッション共有を呼び出して(セッション レプリケーションやデータストアを使用したセッション管理を通じて)、セッションを基盤となるリソースから分離できるようにすることをおすすめします。
Blue/Green デプロイ パターン
Blue/Green デプロイ(Red/Black デプロイとも呼ばれます)では、次の図に示すように、2 つの同一のアプリケーションのデプロイを行います。
この図では、青色が現在のアプリケーションのバージョンを表し、緑色が新しいアプリケーションのバージョンを表します。一度に公開できるバージョンは 1 つのみです。トラフィックは青色のデプロイにルーティングされます。その間に、緑色のデプロイが作成されてテストされます。テストが完了したら、トラフィックを新しいバージョンに転送します。
デプロイが成功したら、青色のデプロイをロールバック先として保持するか、または終了させます。また、これらのインスタンスに新しいバージョンのアプリケーションをデプロイすることもできます。この場合、現在の(青色の)環境が次のリリースのステージング領域として機能します。
主な利点
- ダウンタイムなし。Blue/Green デプロイでは、ダウンタイムなしで迅速にカットオーバーできます。
- 即時ロールバック。ロードバランサを調整してトラフィックを青色の環境にルーティングし直すことで、デプロイ プロセス中にいつでもロールバックできます。ダウンタイムの影響は、問題を検出してからトラフィックを青色の環境に切り替える際にかかる時間に限定されます。
- 環境の分離。Blue/Green デプロイでは、緑色の環境を同時に起動しても、青色の環境をサポートするリソースが影響を受けないことが保証されています。この分離により、デプロイリスクが軽減されます。
考慮事項
- コストと運用上のオーバーヘッド。Blue/Green デプロイ パターンを使用する場合、重複する環境を同じインフラストラクチャ上で維持する必要があります。そのため、運用上のオーバーヘッドとコストが増加する可能性があります。
- 下位互換性。青色のデプロイと緑色のデプロイで、データポイントとデータストアを共有できます。アプリケーションの両方のバージョンで、データストアのスキーマとレコードの形式を使用できることを確認することをおすすめします。この下位互換性は、ロールバックが必要となった際に 2 つのバージョンをシームレスに切り替えるときに必要となります。
- カットオーバー。現在のバージョンを廃止する場合は、既存のトランザクションとセッションで適当なコネクション ドレインを有効にすることを推奨します。この手順により、現在のデプロイで処理されたリクエストを正常に完了、または終了できます。
テスト戦略
このセクションで説明するテストパターンは通常、同時実行と負荷の現実的なレベルでの妥当な期間におけるサービスの信頼性と安定性を検証するために使用されます。
カナリアテスト パターン
カナリアテストでは、次の図に示すように、変更の一部をロールアウトして、そのパフォーマンスをベースライン デプロイと比較することで評価します。
このテストパターンでは、新しいバージョンのアプリケーションを本番環境バージョンと一緒にデプロイします。次に、トラフィックの一部を分割して本番環境バージョンからカナリア バージョンに転送し、カナリアのパフォーマンスを評価します。
カナリアの構成時、評価用の主要な指標を選択します。実際の本番環境ではなく、それに相当するベースラインとカナリアを比較することを推奨します。
分析に影響する可能性のある因子(キャッシュ、長時間接続、ハッシュ オブジェクトなど)を減らすために、アプリケーションのベースライン バージョンで次の手順を行うことをおすすめします。
- アプリケーションのベースライン バージョンと本番環境バージョンが同じであることを確認します。
- カナリアのデプロイと同時に、ベースライン バージョンをデプロイします。
- ベースライン デプロイ(アプリケーション インスタンスの数や自動スケーリング ポリシーなど)がカナリア デプロイと一致していることを確認します。
- ベースライン バージョンを使用して、カナリアと同じトラフィックを配信します。
カナリアテストでは、さまざまなパーティショニング戦略で部分的なロールアウトを行うことができます。たとえば、アプリケーションのユーザーが地理的に分散している場合に、新しいバージョンの特定のリージョンや特定のロケーションへのロールアウトから始めることができます。詳細については、Spinnaker を使用した GKE でのカナリア分析の自動化をご覧ください。
主な利点
- 本番環境トラフィックでテスト可能。ステージング環境でシミュレートされたトラフィックを使用してアプリケーションをテストするのではなく、本番環境トラフィックでカナリアテストを実行できます。カナリア ロールアウトでは、新しいアプリケーションをリリースする際の増分と、リリースの次のステップをトリガーするタイミングを決定する必要があります。カナリアテストでは、モニタリング機能が問題を明確に検出できるようにする必要があるため、十分な量のトラフィックが必要になります。
- 高速ロールバック。ユーザー トラフィックを古いバージョンのアプリケーションにリダイレクトすることで、すぐにロールバックできます。
- ダウンタイムなし。カナリア リリースでは、本番環境トラフィックをダウンタイムなしでさまざまなバージョンのアプリケーションに転送できます。
考慮事項
- ロールアウトが遅い。リリースの各段階で、適当な期間のモニタリングが必要となります。そのため、全体としてのリリースが遅れる場合があります。カナリアテストに数時間かかる場合もあります。
- オブザーバビリティ。カナリアテストを実装するためには、インフラストラクチャとアプリケーション スタックを効果的に観察、モニタリングする機能が必要です。堅牢なモニタリング機能を実装する場合、かなりの労力が必要となることがあります。
- 下位互換性とスティッキー セッション。ローリング アップデートと同様に、カナリアがデプロイされている間に複数のアプリケーション バージョンが環境内で実行されるため、カナリアテストは下位互換性とセッションの永続性にリスクをもたらす可能性があります。
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 パイプラインを介して自動的に実行されるようにすることをおすすめします。Spinnaker、Jenkins、TravisCI、Cloud Build などの自動化ツールを使用すると、デプロイ プロセスを自動化して、効率性、信頼性、予測可能性を改善できます。
- 運用環境と構成管理。Vagrant や Packer などのツールを使用すれば、ローカル開発環境、ステージング環境、本番環境の一貫した維持が可能です。また、Puppet、Chef、Ansible などの構成管理ツールを使用して、ターゲット サーバーに OS 設定やパッチを自動的に適用することもできます。
- ロールバック戦略。ロールバック戦略を作成し、何か問題が発生した場合にその戦略に従います。Spinnaker や Harness などのリリース自動化ツールをロールバックで活用できます。また、新しいバージョンが正しく動作することがわかるまで、最後のアプリケーション バージョンのバックアップを保持できます。
- デプロイ後のモニタリング。アプリケーション パフォーマンス管理ツールは、重要なパフォーマンス指標をモニタリングする際に役立ちます。ビルドやデプロイが失敗した場合に担当チームに通知するプロセスを作成します。可用性やエラー率の問題が原因でヘルスチェックに失敗したデプロイの自動ロールバックを有効にします。
次のステップ
- Kubernetes と継続的ソフトウェア デリバリーの課題でこのドキュメントのコンセプトについて読む。
- 他の Google Cloud の DevOps ソリューションについて学ぶ。
- コンテナ実行のおすすめの方法について学ぶ。
- GKE での継続的インテグレーションと配信について学ぶ。
- 信頼できるリリースとロールバックのための CRE ライフレッスンについて学ぶ。
- クラウド移行に役立つ DevOps ツールの詳細を確認する。
- Google Cloud に関するリファレンス アーキテクチャ、図、ベスト プラクティスを確認する。Cloud Architecture Center をご覧ください。