そこに仁義はあるのか(仮)

略してそこ仁!

【翻訳記事】デプロイ戦略の定義

この記事は2017/11の以下のブログ記事の翻訳です。
blog.itaysk.com

まずはじめに、翻訳を快く許可していただいた@itayskさんに感謝いたします。

3年前の記事ですが、デプロイ戦略についてここまで網羅的にまとめられた記事が日本語で見つけられなかったので翻訳してみようと思いました。
初めての翻訳記事であり、かつ翻訳時に多少の意訳を含んでいます。私の翻訳ミスがある可能性も十分にご了承ください。
何か間違いやわかりにくいところがあれば、コメントいただけますと幸いです。



デプロイの話をしましょう。このトピックは、以前は面白くない細かい実装だと考えられていましたが、現在はモダンなシステムの基本要素になりつつあります。全ての人がデプロイの重要性を理解して、それを中心にソリューションを構築しようとしているように感じますが、私たちはデプロイ戦略の構造と定義をしていません。人々は同じ意味なのに違う言葉を使ったり、違う意味なのに同じ言葉を使ったりしています。これは、人々が問題を解決しようとして車輪の再発明をすることにつながります。私たちはより良いツールを構築し、より良い決定を下し、お互いのコミュニケーションをシンプルにするために、このトピックについての共通の理解が必要です。
この記事は、私が以下のように呼んでいる一般的なデプロイメント戦略について一覧化し、定義しています。

  • 無謀なデプロイ (Reckless Deployment)
  • ローリングアップグレード (Rolling Upgrade)
  • ブルーグリーンデプロイ (Blue/Green Deployment)
  • カナリアデプロイ (Canary Deployment)
  • バージョンデプロイ (Versioned Deployment)

これらのリストにはおそらく他の名前や用語があるかもしれません。ここに無い用語は、これらの主要なデプロイ戦略の変形とみなせると主張します。

記事を読む前の注意点:この記事は定義・方法論・アプローチについて書かれたものであり、どのような技術スタックで実装するかについては書かれていません。技術的なチュートリアルについては別のポストで書く予定です。お楽しみに!

無謀なデプロイ (Reckless Deployment)

別名:Highlander*1 , Simple

要約: 古いものを壊して、新しいものを構築する。結果は気にしない。

これは最も簡単な戦略です。全てを破棄し、新しいバージョンを再構築します。通常は、開発/テストのシナリオか影響度がとても小さいアプリケーションに適しています。これ以上の説明はありません…

f:id:syobochim:20200317190111p:plain

ローリングアップグレード (Rolling Upgrade)

別名: Gradual Deployment

要約:既存の環境に新しいバージョンのコードを導入し、古いコードを廃止しながら徐々に新しい環境を増やしていきます。

これは新しいコードを既存の環境に追加していく際の基本の戦略です。既存の環境は古いバージョンと新しいバージョンの混在プールになり、最終的にはゆっくりと古いインスタンスが新しいインスタンスに置き換わります。「インスタンス」と「プール」という用語は採用技術(VM、コンテナ、プロセスなど)によって違う意味になります。

f:id:syobochim:20200317190831p:plain

ヘルスチェックと監視

この戦略の重要な側面は、ヘルスチェックと監視です。新しいコードを徐々に導入していくことへの重要なポイントは、新しいコードで予期しない問題が発生した場合に、障害を制御できることです。そのためには、新しいバージョンがどう動作しているかを知らなければなりません。そのため、ヘルスチェックと監視が不可欠です。

ロールバック

デプロイがうまくいっていないと判断したら、リリースを止めてデプロイをキャンセルし、元に戻すこともできます。(別名:ロールバック)

後方互換性

新しいコードと古いコードが共存しているので、ユーザーはどちらのバージョンにもルーティングされる可能性があり、この戦略を使っている場合は後方互換性が主な懸念点になります。

ちなみに

あなたは、一部のユーザーが一貫して特定のバージョンを取得する、または、一部のユーザーのみに新しいバージョンを公開するために、ユーザーをスマートにルーティングすることを検討しているかもしれません。それは正しいですが、私はそれをローリングアップグレードとは呼びません。私が何を言おうとしてるのかはこのまま読み続ければわかります。

ブルーグリーンデプロイ (Blue/Green Deployment)

別名:Red/Black, Staged deployment, Swapping Slots

要約:現在の環境に影響を与えず、分割された新しい環境に新しいバージョンをデプロイします。

これは最も安全な戦略で、多くの本番環境で利用されています。安全性を確保するために、現在実行中の環境には一切手を加えず、アプリケーション全体のコピーやアップグレードするモジュールを別の環境に用意します。デプロイの範囲を決める(または分離の範囲)を決めるのはあなた次第です。
例えば
・システム全体を再構築するのか、更新があるモジュールだけをアップデートするのか。
・新しいバージョン用にロードバランサーを新規構築するのか、既存のロードバランサーに新しいルールを追加するのか。
・バージョン間で設定値を共有するのか。
これらは考えられる質問の一部に過ぎず、どう決めるかはあなたかあなたのツール次第です。
1つ確かなことは、新しいバージョンは現在のバージョンのデプロイから完全に分離されるべきということです。これは、アップグレードの間に新旧のコードが環境に混在するローリングアップグレードとは対照的です。その結果、後方互換性は必須ではありません。
新しいバージョンが公開されたら、それをテストすべきです。現行のバージョンはまだ稼働中なので、デプロイ完了を急ぐ必要はありません。この時点では、ユーザーはまだアップデートに気づいていません。
バージョンの品質に十分自身が持てたら、ユーザーを古いバージョンではなく新しいバージョンに切り替え始めます。一度に全てのユーザーを切り替える(別名:カットオフまたはカットオーバー)ことも、新しいバージョンに徐々にユーザーを追加することもできます。

f:id:syobochim:20200317212121p:plain

ドレイン

一般的な方法は移行前に古いデプロイを「ドレイン」することです。「ドレイン」とは、現在のアクティブなセッションが自然に終了し、新しいバージョンのみを使用して新しいセッションを開始することを意味しています。

スイッチバック

通常は、完全に移行した後も古いバージョンを保持しておき、簡単に元に戻してスイッチバックできるようにします。

ステージ

この戦略の一般的なバリエーションには、段階的なデプロイとスロット交換があります。デプロイのスコープ(または分離の範囲)はアプリケーション全体です。(つまり、システム全体のコピーがスタンバイ状態になっています。)この方法では、アップグレードが実行中でなくても、私たちは常にアプリケーションとインフラのコピーを2つ持つことになります。一つの環境は本番環境で、もう一つの環境は「ステージ」と呼ばれる本番前の環境です。私たちはQA / UAT / Repros(再現) / CIなどのために、定期的にステージを利用できます。私たちは常に本番環境ではなくステージにデプロイします。よって、ステージは常に本番環境の前にあり、最新の本番環境候補になります。通常のブルーグリーンデプロイのように、本番環境に影響を与えずにステージのテストと検証をすべきです。デプロイに成功したら、2つの環境間でルーティングを切り替えるだけで、ステージが本番環境になり、本番環境がステージになります。これは通常、DNSレコードの更新を利用します。(必ずしもそうではありませんが。)ここでも、何か問題が発生したら、簡単に元に戻せます。

ちなみに

あなたは、ステージ環境(または新しい「グリーン」なデプロイ)を公開して、実際のユーザーが環境を試すことを検討しているかもしれません。それは良いアイデアです。私はそれをカナリアデプロイと読んでいます。次の章で説明します。

カナリアデプロイ (Canary Deployment)

別名: Ringed Deployment, Feature toggling, Dark features, Silent launch, A/B testing, Testing in production.

要約:新しいバージョンを古いバージョンと一緒にデプロイして、新しいバージョンを使用するユーザーを慎重に制御します。検証を監視し、調整しつつ、徐々に人口を増やしていきます。

これはデプロイ方法の聖杯です。また、達成が最も困難です。
これは、前述の戦略を高度に使用したものと考えることができます。システムに新しいコードを導入する場合は、実際のユーザーが新しいバージョンを本番環境で使えるという重要な違いがあり、どの戦略でも使用できます。当然、全てのユーザーが全ての新機能を使える必要はないので、どのユーザーが新バージョンのどの部分を使うかコントロールする必要があります。これは、ロードバランサやプロキシレイヤーで実装することも、アプリケーションの設定を使うことも、ランタイムを使うことも、その他の方法で実装することもできます。カナリアの基本的で一般的な実装では、ブルーグリーンデプロイを利用し、一部のユーザーを新しい「グリーン」バージョンにスマートルーティングします。

f:id:syobochim:20200317221056p:plain

より高度な実装では、拡張されたブルーグリーンデプロイのテクニックを超えて、より詳細なレベルでデプロイします。カナリアはコントロールと監視が全てであり、コンポーネントをより細かくコントロールできるほど、カナリアデプロイはより高度になります。

さらなる監視

前述しましたが、今回はさらに重要な意味を持ってもう一度説明します。これらの高度なパターンは、いずれも適切な監視なしでは機能しません。カナリアでは、基本的な死活監視だけでなく、パフォーマンスやユーザーエクスペリエンスの指標の監視を検討してください。良い可観察性のカナリアによって、動作するバージョンをデプロイすることから、最適なバージョンをデプロイすることへと考えを移行できます。

A/Bテスト

高度な違いは、複数の異なるバージョンを本番環境へデプロイし、各バージョンでの実際のユーザーと彼らのリアクションの実験をしていることです。ここではデプロイメント戦略から成熟した製品計画アプローチに話題が移りますが、デプロイ戦略はこれらの高度なビジネス関連の戦略の重要な基盤であり、2つが密接に関連していることが多いので、ここで言及しています。

ダークフィーチャー

本番環境のカナリアデプロイ / テストの極端なバージョンでは、機能をオフにして本番環境にデプロイし、一部のユーザー(ベータ版やプレビュー版のテスター)に対して選択的に機能をオンにします。このように動作させるには、システムをモジュール化してデザインする必要があります。つまり、デプロイの単位が機能毎になっており、アプリケーションは個別に切り替え可能な機能で動的に構成されます。この場合、どの機能がどのユーザーに対して有効になっているかを管理するための専用リリース管理システムがあることは、悪いアイデアではありません。

バージョンデプロイ (Versioned Deployment)

要約:ユーザーが使用するバージョンを選択できるようにしながら、全てのバージョンを維持します。

これは厳密なデプロイ方法ではなく、アーキテクチャパターンまたはAPIデザインパターンの境界線なので、ここに属しているかはわかりませんでした。それでもデプロイ戦略に影響を与えるかもしれないので、ここでデプロイ戦略として挙げています。
各バージョンを選択する必要がなく、常に全てのバージョンを本番環境で稼働させたらどうでしょう?この魅力的な戦略は、API開発者の間で特に人気があります。この例では、全てのAPIバージョンが常に使用可能(作業バージョンを削除しない)で、ユーザーは使いたいバージョンを選んで使えます。これは、私たち(ユーザーではない)がユーザーが使うバージョンを決める他の戦略とは対照的です。
明らかな問題はレガシーバージョンをホストするための追加の容量と、バージョン間でデータソースを共有することです。しかし、もし後方互換性に十分に注意し、予備の追加容量を確保できるのであれば、こうした問題よりも利点の方が大きくなります。
このデプロイ戦略はとても単純で、新しいバージョンをデプロイするだけです。全てが常に明示的にバージョン管理されているので、新しいバージョンのデプロイを簡単に捨てても影響がありません。優れているところは、新しいバージョン(または任意のバージョン)の使用を明示的に要求する必要があるところです。そのため、デプロイ環境ではバージョン間のユーザーの移行を気にする必要がありません。

f:id:syobochim:20200317224903p:plain

APIデザイン

この記事はAPIの設計に関するものではないので、ここでは具体的な例を取り上げません。しかし、この戦略に興味がある場合は、MicrosoftがAzure Resource Manager(ARM) APIをどのように設計したかを見てみてください。これは、このパターンの素晴らしい例であり、一般的なREST APIの設計にも適しています。

まとめ

以上です!これらは私が不可欠だと考えているデプロイ戦略であり、それらがどう定義され、どう違うと私が考えているかを説明しました。
以下の戦略についてカバーしました。

  • 無謀なデプロイ (Reckless Deployment) - 何も気にしない時
  • ローリングアップグレード (Rolling Upgrade) - ロールバックする時間を確保するために、徐々にデプロイする
  • ブルーグリーンデプロイ (Blue/Green Deployment) - 変更の操作から本番サービスを守り、横の環境で変更を操作することで、安全性を高める
  • カナリアデプロイ (Canary Deployment) - 実際のユーザーに新しいバージョンを公開する
  • バージョンデプロイ (Versioned Deployment) - 複数のバージョンを永久に共存させる特別な目的の設計

*1:翻訳者コメント:Wikipediaを見ると、「外界と隔離にまでは行かないにしても交流が困難で、文明の浸透が遅く、生活環境が快適とは言いがたいハイランド」に住む人とあるので、時代遅れという意図のようです。