6.5. ルートベースのデプロイメントストラテジーの使用
デプロイメントストラテジーは、アプリケーションを進化させる手段として使用します。一部のストラテジーは Deployment
オブジェクトを使用して、アプリケーションに解決されるすべてのルートのユーザーが確認できる変更を実行します。このセクションで説明される他の高度なストラテジーでは、ルーターを Deployment
オブジェクトと併用して特定のルートに影響を与えます。
最も一般的なルートベースのストラテジーとして blue-green デプロイメント を使用します。新規バージョン (green バージョン) を、テストと評価用に起動しつつ、安定版 (blue バージョン) をユーザーが継続して使用します。準備が整ったら、green バージョンに切り替えられます。問題が発生した場合には、blue バージョンに戻すことができます。
あるいは、両方のバージョンが同時にアクティブになる A/B バージョン ストラテジーを使用することもできます。このストラテジーでは、一部のユーザーは バージョン A を使用し、他のユーザーは バージョン B を使用できます。このストラテジーを使用すると、ユーザーインターフェイスの変更やその他の機能を試して、ユーザーからのフィードバックを得ることができます。また、ユーザーに対する問題の影響が限られている場合に、実稼働のコンテキストで操作が正しく行われていることを検証するのに使用することもできます。
カナリアデプロイメントでは、新規バージョンをテストしますが、問題が検出されると、すぐに以前のバージョンにフォールバックされます。これは、上記のストラテジーどちらでも実行できます。
ルートベースのデプロイメントストラテジーでは、サービス内の Pod 数はスケーリングされません。希望とするパフォーマンスの特徴を維持するには、デプロイメント設定をスケーリングする必要がある場合があります。
6.5.1. プロキシーシャードおよびトラフィック分割
実稼働環境で、特定のシャードに到達するトラフィックの分散を正確に制御できます。多くのインスタンスを扱う場合は、各シャードに相対的なスケールを使用して、割合ベースのトラフィックを実装できます。これは、他の場所で実行中の別のサービスやアプリケーションに転送または分割する プロキシーシャード とも適切に統合されます。
最も単純な設定では、プロキシーは要求を変更せずに転送します。より複雑な設定では、受信要求を複製して、別のクラスターだけでなく、アプリケーションのローカルインスタンスにも送信して、結果を比較することができます。他のパターンとしては、DR のインストールのキャッシュを保持したり、分析目的で受信トラフィックをサンプリングすることができます。
TCP (または UDP) のプロキシーは必要なシャードで実行できます。oc scale
コマンドを使用して、プロキシーシャードで要求に対応するインスタンスの相対数を変更してください。より複雑なトラフィックを管理する場合には、Red Hat OpenShift Service on AWS ルーターを比例分散機能でカスタマイズすることを検討してください。
6.5.2. N-1 互換性
新規コードと以前のコードが同時に実行されるアプリケーションの場合は、新規コードで記述されたデータが、以前のバージョンのコードで読み込みや処理 (または正常に無視) できるように注意する必要があります。これは、スキーマの進化と呼ばれる複雑な問題です。
これは、ディスクに保存したデータ、データベース、一時的なキャッシュ、ユーザーのブラウザーセッションの一部など、多数の形式を取ることができます。多くの Web アプリケーションはローリングデプロイメントをサポートできますが、アプリケーションをテストし、設計してこれに対応させることが重要です。
アプリケーションによっては、新旧のコードが並行的に実行されている期間が短いため、バグやユーザーのトランザクションに失敗しても許容範囲である場合があります。別のアプリケーションでは失敗したパターンが原因で、アプリケーション全体が機能しなくなる場合もあります。
N-1 互換性を検証する 1 つの方法として、A/B デプロイメントを使用できます。 制御されたテスト環境で、以前のコードと新しいコードを同時に実行して、新規デプロイメントに流れるトラフィックが以前のデプロイメントで問題を発生させないかを確認します。
6.5.3. 正常な終了
Red Hat OpenShift Service on AWS および Kubernetes は、負荷分散のローテーションから削除する前にアプリケーションインスタンスがシャットダウンする時間を設定します。ただし、アプリケーションでは、終了前にユーザー接続も正常に終了されていることを確認する必要があります。
シャットダウン時に、Red Hat OpenShift Service on AWS はコンテナーのプロセスに TERM
シグナルを送信します。SIGTERM
を受信すると、アプリケーションコードは、新規接続の受け入れを停止します。これにより、ロードバランサーによって他のアクティブなインスタンスにトラフィックがルーティングされるようになります。アプリケーションコードは、開放されている接続がすべて終了するか、次の機会に個別接続が正常に終了されるまで待機してから終了します。
正常に終了する期間が終わると、終了されていないプロセスに KILL
シグナルが送信され、プロセスが即座に終了されます。Pod の terminationGracePeriodSeconds
属性または Pod テンプレートは正常に終了する期間 (デフォルトの 30 秒) を制御し、必要に応じてこれらをアプリケーションごとにカスタマイズすることができます。
6.5.4. Blue-Green デプロイメント
Blue-green デプロイメントでは、同時にアプリケーションの 2 つのバージョンを実行し、実稼働版 (blue バージョン) からより新しいバージョン (green バージョン) にトラフィックを移動します。ルートでは、ローリングストラテジーまたは切り替えサービスを使用できます。
多くのアプリケーションは永続データに依存するので、N-1 互換性 をサポートするアプリケーションが必要です。つまり、データを共有して、データ層を 2 つ作成し、データベース、ストアまたはディスク間のライブマイグレーションを実装します。
新規バージョンのテストに使用するデータについて考えてみてください。実稼働データの場合には、新規バージョンのバグにより、実稼働版を破損してしまう可能性があります。
6.5.4.1. Blue-Green デプロイメントの設定
Blue-green デプロイメントでは 2 つの Deployment
を使用します。どちらも実行され、実稼働のデプロイメントはルートが指定するサービスによって変わります。この際、各 Deployment
オブジェクトは異なるサービスに公開されます。
ルートは、Web (HTTP および HTTPS) トラフィックを対象としているので、この手法は Web アプリケーションに最適です。
新規バージョンに新規ルートを作成し、これをテストすることができます。準備ができたら、実稼働ルートのサービスが新規サービスを参照するように変更します。 新規 (green) バージョンは有効になります。
必要に応じて以前のバージョンにサービスを切り替えて、以前の (blue) バージョンにロールバックすることができます。
手順
2 つの独立したアプリケーションコンポーネントを作成します。
v1
イメージをexample-blue
サービスで実行するサンプルアプリケーションのコピーを作成します。$ oc new-app openshift/deployment-example:v1 --name=example-blue
example-green
サービスでv2
イメージを使用する 2 つ目のコピーを作成します。$ oc new-app openshift/deployment-example:v2 --name=example-green
以前のサービスを参照するルートを作成します。
$ oc expose svc/example-blue --name=bluegreen-example
-
bluegreen-example-<project>.<router_domain>
でアプリケーションを参照し、v1
イメージが表示されることを確認します。 ルートを編集して、サービス名を
example-green
に変更します。$ oc patch route/bluegreen-example -p '{"spec":{"to":{"name":"example-green"}}}'
-
ルートが変更されたことを確認するには、
v2
イメージが表示されるまで、ブラウザーを更新します。
6.5.5. A/B デプロイメント
A/B デプロイメントストラテジーでは、新しいバージョンのアプリケーションを実稼働環境での制限された方法で試すことができます。実稼働バージョンは、ユーザーの要求の大半に対応し、要求の一部が新しいバージョンに移動されるように指定できます。
各バージョンへの要求の割合を制御できるので、テストが進むにつれ、新しいバージョンへの要求を増やし、最終的に以前のバージョンの使用を停止することができます。各バージョン要求負荷を調整する際に、期待どおりのパフォーマンスを出せるように、各サービスの Pod 数もスケーリングする必要が生じる場合があります。
ソフトウェアのアップグレードに加え、この機能を使用してユーザーインターフェイスのバージョンを検証することができます。以前のバージョンを使用するユーザーと、新しいバージョンを使用するユーザーが出てくるので、異なるバージョンに対するユーザーの反応を評価して、設計上の意思決定を知らせることができます。
このデプロイメントを有効にするには、以前のバージョンと新しいバージョンは同時に実行できるほど類似している必要があります。これは、バグ修正リリースや新機能が以前の機能と干渉しないようにする場合の一般的なポイントになります。これらのバージョンが正しく連携するには N-1 互換性が必要です。
Red Hat OpenShift Service on AWS は、Web コンソールと CLI で N-1 互換性をサポートします。
6.5.5.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 の数を減らします。
手順
A/B 環境を設定するには、以下を実行します。
2 つのアプリケーションを作成して、異なる名前を指定します。それぞれが
Deployment
オブジェクトを作成します。これらのアプリケーションは同じプログラムのバージョンであり、通常 1 つは現在の実稼働バージョンで、もう 1 つは提案される新規バージョンとなります。最初のアプリケーションを作成します。以下の例では、
ab-example-a
という名前のアプリケーションを作成します。$ oc new-app openshift/deployment-example --name=ab-example-a
2 番目のアプリケーションを作成します。
$ oc new-app openshift/deployment-example:v2 --name=ab-example-b
どちらのアプリケーションもデプロイされ、サービスが作成されます。
ルート経由でアプリケーションを外部から利用できるようにします。この時点でサービスを公開できます。現在の実稼働バージョンを公開してから、後でルートを編集して新規バージョンを追加すると便利です。
$ oc expose svc/ab-example-a
ab-example-a.<project>.<router_domain>
でアプリケーションを参照して、予想されるバージョンが表示されていることを確認します。ルートをデプロイする場合には、ルーターはサービスに指定した
weights
に従ってトラフィックを分散します。この時点では、デフォルトのweight=1
と指定されたサービスが 1 つ存在するので、すべての要求がこのサービスに送られます。他のサービスをalternateBackends
として追加し、weights
を調整すると、A/B 設定が機能するようになります。これは、oc set route-backends
コマンドを実行するか、ルートを編集して実行できます。注記また、
alternateBackends
を使用する場合は、roundrobin
ロードバランシング戦略を使用して、重みに基づいてリクエストが想定どおりにサービスに分散されるようにします。roundrobin
は、ルートアノテーション を使用してルートに設定できます。oc set route-backend
を0
に設定することは、サービスがロードバランシングに参加しないが、既存の持続する接続を提供し続けることを意味します。注記ルートに変更を加えると、さまざまなサービスへのトラフィックの部分だけが変更されます。デプロイメントをスケーリングして、必要な負荷を処理できるように Pod 数を調整する必要がある場合があります。
ルートを編集するには、以下を実行します。
$ oc edit route <route_name>
出力例
apiVersion: route.openshift.io/v1 kind: Route 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 # ...
6.5.5.1.1. Web コンソールを使用した既存ルートの重みの管理
手順
-
Networking
Routes ページに移動します。 - 編集するルートの横にある Actions メニューをクリックし、Edit Route を選択します。
-
YAML ファイルを編集します。
weight
を0
から256
の間の整数になるように更新します。これは、他のターゲット参照オブジェクトに対するターゲットの相対的な重みを指定します。値0
はこのバックエンドへの要求を抑制します。デフォルトは100
です。オプションの詳細は、oc explain routes.spec.alternateBackends
を実行します。 - Save をクリックします。
6.5.5.1.2. Web コンソールを使用した新規ルートの重みの管理
-
Networking
Routes ページに移動します。 - Create Route をクリックします。
- ルートの Name を入力します。
- Service を選択します。
- Add Alternate Service をクリックします。
-
Weight および Alternate Service Weight の値を入力します。他のターゲットとの相対的な重みを示す
0
から255
の間の数字を入力します。デフォルトは100
です。 - Target Port を選択します。
- Create をクリックします。
6.5.5.1.3. CLI を使用した重みの管理
手順
サービスおよび対応する重みのルートによる負荷分散を管理するには、
oc set route-backends
コマンドを使用します。$ 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 ab-example ab-example-a=198 ab-example-b=2
つまり、99% のトラフィックはサービス
ab-example-a
に、1% はサービスab-example-b
に送信されます。このコマンドでは、デプロイメントはスケーリングされません。要求の負荷を処理するのに十分な Pod がある状態でこれを実行する必要があります。
フラグなしのコマンドを実行して、現在の設定を確認します。
$ oc set route-backends ab-example
出力例
NAME KIND TO WEIGHT routes/ab-example Service ab-example-a 198 (99%) routes/ab-example Service ab-example-b 2 (1%)
負荷分散アルゴリズムのデフォルト値を上書きするには、アルゴリズムを
roundrobin
に設定してルートのアノテーションを調整します。Red Hat OpenShift Service on AWS のルートの場合、デフォルトの負荷分散アルゴリズムはrandom
値またはsource
値に設定されます。アルゴリズムを
roundrobin
に設定するには、次のコマンドを実行します。$ oc annotate routes/<route-name> haproxy.router.openshift.io/balance=roundrobin
Transport Layer Security (TLS) パススルールートの場合、デフォルト値は
source
です。他のすべてのルートの場合、デフォルトはrandom
です。--adjust
フラグを使用すると、個別のサービスの重みを、それ自体に対して、または主要なサービスに対して相対的に変更できます。割合を指定すると、主要サービスまたは 1 番目の代用サービス (主要サービスを設定している場合) に対して相対的にサービスを調整できます。他にバックエンドがある場合には、重みは変更に比例した状態になります。以下の例では、
ab-example-a
およびab-example-b
サービスの重みを変更します。$ oc set route-backends ab-example --adjust ab-example-a=200 ab-example-b=10
または、パーセンテージを指定してサービスの重みを変更します。
$ oc set route-backends ab-example --adjust ab-example-b=5%
パーセンテージ宣言の前に
+
を指定すると、現在の設定に対して重み付けを調整できます。以下に例を示します。$ oc set route-backends ab-example --adjust ab-example-b=+15%
--equal
フラグでは、全サービスのweight
が100
になるように設定します。$ oc set route-backends ab-example --equal
--zero
フラグは、全サービスのweight
を0
に設定します。すべての要求に対して 503 エラーが返されます。注記ルートによっては、複数のバックエンドまたは重みが設定されたバックエンドをサポートしないものがあります。
6.5.5.1.4. 1 サービス、複数の Deployment
オブジェクト
手順
すべてのシャードに共通の
ab-example=true
ラベルを追加して新規アプリケーションを作成します。$ oc new-app openshift/deployment-example --name=ab-example-a --as-deployment-config=true --labels=ab-example=true --env=SUBTITLE\=shardA
$ oc delete svc/ab-example-a
アプリケーションがデプロイされ、サービスが作成されます。これは最初のシャードです。
ルートを使用してアプリケーションを利用できるようにしてください (または、サービス IP を直接使用してください)。
$ oc expose deployment ab-example-a --name=ab-example --selector=ab-example\=true
$ oc expose service ab-example
-
ab-example-<project_name>.<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" --as-deployment-config=true
$ oc delete svc/ab-example-b
この時点で、いずれの Pod のセットもルートで提供されます。しかし、両ブラウザー (接続を開放) とルーター (デフォルトでは cookie を使用) で、バックエンドサーバーへの接続を維持しようとするので、シャードが両方返されない可能性があります。
1 つのまたは他のシャードに対してブラウザーを強制的に実行するには、以下を実行します。
oc scale
コマンドを使用して、ab-example-a
のレプリカを0
に減らします。$ oc scale dc/ab-example-a --replicas=0
ブラウザーを更新して、
v2
およびshard B
(赤) を表示させます。ab-example-a
を1
レプリカに、ab-example-b
を0
にスケーリングします。$ oc scale dc/ab-example-a --replicas=1; oc scale dc/ab-example-b --replicas=0
ブラウザーを更新して、
v1
およびshard A
(青) を表示します。
いずれかのシャードでデプロイメントをトリガーする場合、そのシャードの Pod のみが影響を受けます。どちらかの
Deployment
オブジェクトでSUBTITLE
環境変数を変更してデプロイメントをトリガーできます。$ oc edit dc/ab-example-a
または
$ oc edit dc/ab-example-b