9.4. 高度なデプロイメントストラテジー
9.4.1. 高度なデプロイメントストラテジー
デプロイメントストラテジーは、アプリケーションを進化させる手段として使用します。一部のストラテジーは デプロイメント設定 を使用して変更を加えます。これらの変更は、アプリケーションを解決する全ルートのユーザーに表示されます。これらの変更は、アプリケーションを解決する全ルートのユーザーに表示されます。 ここで説明している他のストラテジーは、ルート機能を使用して固有のルートに影響を与えます。
9.4.2. Blue-Green デプロイメント
Blue-green デプロイメントでは、同時に 2 つのバージョンを実行し、実稼働版 (green バージョン) からより新しいバージョン (blue バージョン) にトラフィックを移動します。ルートでは、ローリングストラテジーまたは切り替えサービスを使用できます。
多くのアプリケーションは永続データに依存するので、N-1 互換性 をサポートするアプリケーションが必要です。 つまり、データを共有して、データ層を 2 つ作成し、データベース、ストアまたはディスク間のライブマイグレーションを実装します。
新規バージョンのテストに使用するデータについて考えてみてください。実稼働データの場合には、新規バージョンのバグにより、実稼働版を破損してしまう可能性があります。
9.4.2.1. Blue-Green デプロイメントの使用
Blue-Green デプロイメントは 2 つのデプロイメント設定を使用します。いずれも実行され、実稼働のデプロイメントはルートが指定するルートによって変わります。この際、各デプロイメント設定は異なるサービスに公開されます。新しいバージョンに新規ルートを作成して、これをテストすることができます。 準備が整うと、実稼働ルートのサービスを新規サービスを参照するように変更し、新しい blue バージョンがライブになります。
必要に応じて以前のバージョンにサービスを切り替えて、以前の green バージョンにロールバックすることができます。
ルートと 2 つのサービスの使用
以下の例は、2 つのデプロイメント設定を行います。 1 つは、安定版 (green バージョン) で、もう 1 つは新規バージョン (blue バージョン) です。
ルートは、サービスを参照し、いつでも別のサービスを参照するように変更できます。開発者は、実稼働トラフィックが新規サービスにルーティングされる前に、新規サービスに接続して、コードの新規バージョンをテストできます。
ルートは、Web (HTTP および HTTPS) トラフィックを対象としているので、この手法は Web アプリケーションに最適です。
アプリケーションサンプルを 2 つ作成します。
$ oc new-app openshift/deployment-example:v1 --name=example-green $ oc new-app openshift/deployment-example:v2 --name=example-blue
上記のコマンドにより、独立したアプリケーションコンポーネントが 2 つ作成されます。 1 つは、
example-green
サービスで v1 イメージを実行するコンポーネントと、もう 1 つはexample-blue
サービスで v2 イメージを使用するコンポーネントです。以前のサービスを参照するルートを作成します。
$ oc expose svc/example-green --name=bluegreen-example
-
bluegreen-example.<project>.<router_domain>
でアプリケーションを参照し、v1 イメージが表示されることを確認します。 ルートを編集して、サービス名を
example-blue
に変更します。$ oc patch route/bluegreen-example -p '{"spec":{"to":{"name":"example-blue"}}}'
- ルートが変更されたことを確認するには、v2 イメージが表示されるまで、ブラウザーを更新します。
9.4.3. A/B デプロイメント
A/B デプロイメントストラテジーでは、新しいバージョンのアプリケーションを実稼働環境での制限された方法で試すことができます。実稼働バージョンは、ユーザーの要求の大半に対応し、要求の一部が新しいバージョンに移動されるように指定できます。各バージョンへの要求の部分を制御できるので、テストが進むにつれ、新しいバージョンへの要求を増やし、最終的に以前のバージョンの使用を停止することができます。各バージョン要求負荷を調整するにつれ、期待どおりのパフォーマンスを出せるように、各サービスの Pod 数もスケーリングする必要があります。
ソフトウェアのアップグレードに加え、この機能を使用してユーザーインターフェースのバージョンを検証することができます。以前のバージョンを使用するユーザーと、新しいバージョンを使用するユーザーが出てくるので、異なるバージョンに対するユーザーの反応を評価して、設計上の意思決定を知らせることができます。
このデプロイメントの効果を発揮するには、以前のバージョンと新しいバージョンは同時に実行できるほど類似している必要があります。これは、バグ修正リリースや新機能が以前の機能と干渉しないようにする場合の一般的なポイントになります。これらのバージョンが正しく連携するには N-1 互換性 が必要です。
OpenShift Online は、Web コンソールとコマンドラインインターフェースで N-1 互換性をサポートします。
9.4.3.1. A/B テスト用の負荷分散
ユーザーは複数のサービスのルートを設定します。各サービスは、アプリケーションの 1 つのバージョンを処理します。
各サービスには weight
が割り当てられ、各サービスへの要求の部分については service_weight
を sum_of_weights
で除算します。エンドポイントの weights
の合計がサービスの weight
になるように、サービスごとの weight
がサービスのエンドポイントに分散されます。
ルートにはサービスを最大で 4 つ含めることができます。サービスの weight
は、0
から 256
の間で指定してください。weight
が 0
の場合、新しい要求はサービスには送信されませんが、既存の接続はアクティブのままになります。サービスの weight
が 0
でない場合は、エンドポイントの最小 weight
は 1
となります。これにより、エンドポイントが多数含まれるサービスは、最終的に weight
は必要な値よりも大きくなる可能性があります。このような場合は、負荷分散の weight
を必要なレベルに下げるために Pod の数を減らします。詳細は、Alternate Backends and Weights のセクションを参照してください。
Web コンソールでは、重みを設定したり、各サービス間の重みの分散を表示したりできます。
A/B 環境を設定するには以下を行います。
2 つのアプリケーションを作成して、異なる名前を指定します。それぞがデプロイメント設定を作成します。これらのアプリケーションは同じアプリケーションのバージョンであり、通常 1 つは現在の実稼働バージョンで、もう 1 つは提案される新規バージョンとなります。
$ oc new-app openshift/deployment-example1 --name=ab-example-a $ oc new-app openshift/deployment-example2 --name=ab-example-b
デプロイメント設定を公開してサービスを作成します。
$ oc expose dc/ab-example-a --name=ab-example-A $ oc expose dc/ab-example-b --name=ab-example-B
この時点で、いずれのアプリケーションもデプロイ、実行され、サービスが追加されています。
ルート経由でアプリケーションを外部から利用できるようにします。この時点でサービスを公開できます。 現在の実稼働バージョンを公開してから、後でルートを編集して新規バージョンを追加すると便利です。
$ oc expose svc/ab-example-A
ab-example.<project>.<router_domain>
でアプリケーションを参照して、希望とするバージョンが表示されていることを確認します。ルートをデプロイする場合には、ルーターはサービスに指定した weight に従って
トラフィックを分散します
。この時点では、デフォルトのweight=1
と指定されたサービスが 1 つ存在するので、すべての要求がこのサービスに送られます。他のサービスをalternateBackends
として追加し、weights
を調整すると、A/B 設定が機能するようになります。これは、oc set route-backends
コマンドを実行するか、ルートを編集して実行できます。注記ルートに変更を加えると、さまざまなサービスへのトラフィックの部分だけが変更されます。デプロイメント設定をスケーリングして、必要な負荷を処理できるように Pod 数を調整する必要がある場合があります。
ルートを編集するには、以下を実行します。
$ oc edit route <route-name> ... metadata: name: route-alternate-service annotations: haproxy.router.openshift.io/balance: roundrobin spec: host: ab-example.my-project.my-domain to: kind: Service name: ab-example-A weight: 10 alternateBackends: - kind: Service name: ab-example-B weight: 15 ...
9.4.3.1.1. Web コンソールを使用した重みの管理
- Route の詳細ページ (アプリケーション/ルート) に移動します。
- Actions メニューから Edit を選択します。
- Split traffic across multiple services にチェックを入れます。
Service Weights スライダーで、各サービスに送信するトラフィックの割合を設定します。
2 つ以上のサービスにトラフィックを分割する場合には、各サービスに 0 から 256 の整数を使用して、相対的な重みを指定します。
トラフィックの重みは、トラフィックを分割したアプリケーションの行を展開すると Overview に表示されます。
9.4.3.1.2. CLI を使用した重みの管理
このコマンドは、ルートでサービスと対応する重みの 負荷分散を管理します。
$ oc set route-backends ROUTENAME [--zero|--equal] [--adjust] SERVICE=WEIGHT[%] [...] [options]
たとえば、以下のコマンドは ab-example-A
に weight=198
を指定して主要なサービスとし、ab-example-B
に weight=2
を指定して 1 番目の代用サービスとして設定します。
$ oc set route-backends web ab-example-A=198 ab-example-B=2
つまり、99% のトラフィックはサービス ab-example-A
に、1% はサービス ab-example-B
に送信されます。
このコマンドでは、デプロイメント設定はスケーリングされません。要求の負荷を処理するのに十分な Pod がある状態でこれを実行する必要があります。
フラグなしのコマンドでは、現在の設定が表示されます。
$ oc set route-backends web NAME KIND TO WEIGHT routes/web Service ab-example-A 198 (99%) routes/web Service ab-example-B 2 (1%)
--adjust
フラグを使用すると、個別のサービスの重みを、それ自体に対して、または主要なサービスに対して相対的に変更できます。割合を指定すると、主要サービスまたは 1 番目の代用サービス (主要サービスを設定している場合) に対して相対的にサービスを調整できます。他にバックエンドがある場合には、重みは変更に比例した状態になります。
$ oc set route-backends web --adjust ab-example-A=200 ab-example-B=10 $ oc set route-backends web --adjust ab-example-B=5% $ oc set route-backends web --adjust ab-example-B=+15%
--equal
フラグでは、全サービスの weight
が 100 になるように設定します。
$ oc set route-backends web --equal
--zero
フラグは、全サービスの weight
を 0 に設定します。すべての要求に対して 503 エラーが返されます。
ルートによっては、複数のバックエンドたは重みが設定されたバックエンドをサポートしないものがあります。
9.4.3.1.3. 1 サービス、複数のデプロイメント設定
ルーターをインストールしている場合は、ルートを使用してアプリケーションを利用できるようにしてください (または、サービス IP を直接使用してください)。
$ oc expose svc/ab-example
ab-example.<project>.<router_domain>
でアプリケーションを参照し、v1 イメージが表示されることを確認します。
1 つ目のシャードと同じだが別のバージョンがタグ付けされたソースイメージを基に 2 つ目のシャードを作成して、一意の値を設定します。
$ oc new-app openshift/deployment-example:v2 --name=ab-example-b --labels=ab-example=true SUBTITLE="shard B" COLOR="red"
新たに作成したシャードを編集して、全シャードに共通の
ab-example=true
ラベルを設定します。$ oc edit dc/ab-example-b
エディターで、
spec.selector
およびspec.template.metadata.labels
の下に、既存のdeploymentconfig=ab-example-b
ラベルと一緒にab-example: "true"
の行を追加します。保存してからエディターを終了します。2 番目のシャードの再デプロイメントをトリガーして、新規ラベルを取得します。
$ oc rollout latest dc/ab-example-b
この時点で、いずれの Pod もルートでサービスが提供されます。しかし、両ブラウザー (接続を開放) とルーター (デフォルトでは cookie を使用) で、バックエンドサーバーへの接続を維持しようとするので、シャードが両方返されない可能性があります。1 つまたは他のシャードに対してブラウザーを強制的に実行するには、scale コマンドを使用します。
$ oc scale dc/ab-example-a --replicas=0
ブラウザーを更新すると、 v2 および shard B (赤字) が表示されているはずです。
$ oc scale dc/ab-example-a --replicas=1; oc scale dc/ab-example-b --replicas=0
ブラウザーを更新すると、v1 と shard A (青字) が表示されているはずです。
いずれかのシャードでデプロイメントをトリガーした場合には、そのシャード内の Pod のみが影響を受けます。いずれかのデプロイメント設定で
SUBTITLE
環境変数を変更して (oc edit dc/ab-example-a
またはoc edit dc/ab-example-b
)、デプロイメントを簡単にトリガーできます。ステップ 5-7 を繰り返すと、別のシャードを追加できます。注記これらの手順は、今後の OpenShift Online バージョンでは簡素化される予定です。
9.4.4. プロキシーシャード/トラフィックスプリッター
実稼働環境で、特定のシャードに到達するトラフィックの分散を正確に制御できます。多くのインスタンスを扱う場合は、各シャードに相対的なスケールを使用して、割合ベースのトラフィックを実装できます。これは、他の場所で実行中の別のサービスやアプリケーションに転送または分割する プロキシーシャード とも適切に統合されます。
最も単純な設定では、プロキシーは要求を変更せずに転送します。より複雑な設定では、受信要求を複製して、別のクラスターだけでなく、アプリケーションのローカルインスタンスにも送信して、結果を比較することができます。他のパターンとしては、DR のインストールのキャッシュを保持したり、分析目的で受信トラフィックをサンプリングすることができます。
実装がこの例のスコープ外の場合でも、TCP (または UDP) のプロキシーは必要なシャードで実行できます。oc scale
コマンドを使用して、プロキシーシャードで要求に対応するインスタンスの相対数を変更してください。より複雑なトラフィックを管理する場合には、OpenShift Online ルーターを比例分散機能でカスタマイズすることを検討してください。
9.4.5. N-1 互換性
新規コードと以前のコードが同時に実行されるアプリケーションの場合は、新規コードで記述されたデータが、以前のコードで読み込みや処理 (または正常に無視) できるように注意する必要があります。これは、スキーマの進化 と呼ばれ、複雑な問題です。
これは、ディスクに保存したデータ、データベース、一時的なキャッシュ、ユーザーのブラウザーセッションの一部など、多数の形式を取ることができます。多くの Web アプリケーションはローリングデプロイメントをサポートできますが、アプリケーションをテストし、設計してこれに対応させることが重要です。
アプリケーションによっては、新旧のコードが並行的に実行されている期間が短いため、バグやユーザーのトランザクションに失敗しても許容範囲である場合があります。別のアプリケーションでは失敗したパターンが原因で、アプリケーション全体が機能しなくなる場合もあります。
N-1 互換性を検証する 1 つの方法として、A/B デプロイメントがあります。制御されたテスト環境で、以前のコードと新しいコードを同時に実行して、新規デプロイメントに流れるトラフィックが以前のデプロイメントで問題を発生させないかを確認します。
9.4.6. 正常な終了
OpenShift Online および Kubernetes は、負荷分散のローテーションから削除する前にアプリケーションインスタンスがシャットダウンする時間を設定します。ただし、アプリケーションでは、終了前にユーザー接続が正常に中断されていることを確認する必要があります。
シャットダウン時に、OpenShift Online はコンテナーのプロセスに TERM シグナルを送信します。SIGTERM を受信すると、アプリケーションコードは、新規接続の受け入れを停止する必要があります。こうすることで、ロードバランサーにより、他のアクティブなインスタンスにトラフィックをルーティングされるようになります。アプリケーションコードは、開放されている接続がすべて終了する (または、次の機会に個別接続が正常に終了される) まで待機してから終了します。
正常に終了する期間が終わると、終了されていないプロセスに KILL シグナルが送信され、プロセスが即座に終了されます。Pod の terminationGracePeriodSeconds
属性または Pod テンプレートが正常に終了する期間 (デフォルト 30 秒) を制御し、必要に応じてアプリケーションごとにカスタマイズすることができます。