複数のサービスに対してエンドツーエンドのカナリアリリースを実装する必要がある場合は、トラフィックラベルを設定してトラフィック特性を識別し、ゲートウェイのイングレストラフィックを通常のトラフィックとカナリアトラフィックに分割できます。 カナリアトラフィックの特性は、ユーザーリクエストの処理に使用されるサービス間で渡されます。 この方法で、エンドツーエンドのカナリアリリースが実装されます。 このトピックでは、トラフィックラベルを使用してマイクロサービスのエンドツーエンドのカナリアリリースを実装する方法について説明します。
前提条件
Enterprise EditionまたはUltimate EditionのService Mesh(ASM)インスタンスが作成されています。 ASMインスタンスのバージョンは 1.17.2.22 以降です。 詳細については、ASM インスタンスの作成またはASM インスタンスの更新をご参照ください。
クラスターがASMインスタンスに追加されています。 詳細については、ASM インスタンスへのクラスターの追加をご参照ください。
イングレスゲートウェイが作成されています。 詳細については、イングレスゲートウェイの作成をご参照ください。
機能の説明
カナリアリリースはさまざまな方法で実装できます。 たとえば、ASM を使用して、ブルーグリーンリリースモードと段階的リリースモードでアプリケーションをデプロイできます。 サンプルモードは、単一サービスのリリースに適用できます。 このモードでは、オープンソース Istio の VirtualService を使用して、サービスの各バージョンのトラフィックの重みを指定します。 このモードは、複数のサービスのカナリアリリースタイミングの要件を満たすことができません。
ASM は、トラフィックのラベル付けとラベルベースのルーティング機能に基づいて、エンドツーエンドのカナリアリリース機能を提供します。 これにより、複数のサービスのカナリアリリースを同時に実装できます。 ビジネスのカナリアテスト中に、システムはイングレストラフィックを通常のトラフィックとカナリアトラフィックに分割し、トラフィックの特性を識別します。 リクエストのトラフィックがカナリアトラフィックとして識別されると、リクエストはカナリアリリースサービスにルーティングされます。 このようにして、システムは単に特定のトラフィック比率で異なるバージョンのバックエンドサービスにトラフィックを分散するのではなく、カナリアトラフィックの特性がユーザーリクエストの処理に使用されるすべてのサービス間で渡されます。 詳細については、トラフィックのラベル付けをご参照ください。
構成の説明
ここをクリックして、サンプル構成ファイルをダウンロードできます。 次の図は、例に示すサービスの呼び出しチェーンを示しています。
この例では、サービス A がサービス B を呼び出すとき、サービス A には HTTP ヘッダー my-trace-id を渡すためのコード実装ロジックが含まれています。 詳細については、src/mock-abc/go/main.go パスの main.go 構成ファイルをご参照ください。
他のアプリケーションを使用する場合は、アプリケーションに HTTP ヘッダーを渡すロジックが含まれていることを確認してください。 後続の関数は HTTP ヘッダーに依存します。
手順 1: ACK クラスターにサンプルサービスをデプロイする
目的のネームスペース(この例ではデフォルトのネームスペース)に対して、サイドカープロキシの自動インジェクションを有効にします。 詳細については、サイドカープロキシの自動インジェクションの有効化をご参照ください。
kubeconfig ファイルの情報に基づいて kubectl を使用して ACK クラスターに接続し、次のコマンドを実行してサンプルサービスをデプロイします。
YAML ファイルの詳細については、構成の説明をご参照ください。
kubectl apply -n default -f application-base.yaml kubectl apply -n default -f application-canary.yaml
手順 2: 初期ルーティングルールを設定する
routing.yaml という名前のファイルを作成し、次の内容をファイルにコピーします。
kubeconfig ファイルの情報に基づいて kubectl を使用して ASM インスタンスに接続し、次のコマンドを実行してルーティングルールを設定します。
kubectl apply -n default -f routing.yaml
異なるバージョンのサービスにアクセスできるかどうかを確認します。
ASM コンソールでイングレスゲートウェイのパブリック IP アドレスを取得します。 詳細については、手順 2: ASM イングレスゲートウェイの IP アドレスを取得するをご参照ください。
次のコマンドを実行して環境変数を設定します。
xxxx
は、サブステップ a で取得した IP アドレスです。export ASM_GATEWAY_IP=xxxx
次のコマンドを実行して、異なるバージョンのサービスにアクセスできるかどうかを確認します。
for i in {1..200}; do curl -H'my-asm-prefer-tag: version-base' -H'my-trace-id: x000'$i http://${ASM_GATEWAY_IP}/; echo; sleep 1; done;
期待される出力:
-> mocka(version: canary, ip: 172.17.0.129)-> mockb(version: base, ip: 172.17.0.70) -> mocka(version: base, ip: 172.17.0.132)-> mockb(version: base, ip: 172.17.0.70) -> mocka(version: base, ip: 172.17.0.132)-> mockb(version: canary, ip: 172.17.0.54) -> mocka(version: canary, ip: 172.17.0.129)-> mockb(version: canary, ip: 172.17.0.54) -> mocka(version: canary, ip: 172.17.0.129)-> mockb(version: base, ip: 172.17.0.70) -> mocka(version: base, ip: 172.17.0.132)-> mockb(version: base, ip: 172.17.0.70) -> mocka(version: canary, ip: 172.17.0.129)-> mockb(version: canary, ip: 172.17.0.54)
出力は、イングレスゲートウェイからサービス A へ、およびサービス A からサービス B へのトラフィックフローにランダムロードバランシングのルーティングポリシーが採用されていることを示しています。
my-asm-prefer-tag
ヘッダーまたはcurl
コマンドを使用して指定された他のリクエストヘッダーは、ランダムルーティングポリシーを変更しません。
手順 3: サンプルサービスのトラフィックラベルを設定する
ASM では、TrafficLabel CustomResourceDefinition(CRD)を使用してトラフィックラベルを設定し、トラフィックラベルに基づいてトラフィックを異なるワークロードにルーティングできます。 詳細については、トラフィックのラベル付けをご参照ください。
trafficlabel.yaml という名前のファイルを作成し、次の内容をファイルにコピーします。
構成の説明:
trafficlabel-ns
トラフィックラベルは、この例でデプロイされた mocka サービスや mockb サービスなど、デフォルトのネームスペースのすべてのサービスに有効です。ingressgateway
トラフィックラベルは、ingressgateway ゲートウェイのみに有効です。この例では、
my-asm-prefer-tag
リクエストヘッダーを使用してバージョンを区別します。 したがって、getExternalInboundRequestHeader
の最初のパラメーターをmy-asm-prefer-tag
に設定します。 ビジネス要件に基づいて構成を変更してください。この例では、
my-trace-id
は渡す必要がある HTTP ヘッダーです。 したがって、getExternalInboundRequestHeader
の 2 番目のパラメーターをmy-trace-id
に設定します。 ビジネス要件に基づいて構成を変更してください。
kubeconfig ファイルの情報に基づいて kubectl を使用して ASM インスタンスに接続し、次のコマンドを実行してトラフィックラベルを設定します。
kubectl apply -f trafficlabel.yaml
手順 4: ラベルベースのルーティングルールを設定する
ラベルベースのルーティングルールを設定して、トラフィックフローを制御できます。
1. サービスプロバイダー側でカナリアリリースを確認する
サービス A からサービス B へのトラフィックルーティングが期待どおりであるかどうかを確認します。 具体的には、サービス A に流れ込むカナリアトラフィックがサービス B のカナリアリリースバージョンに転送されるかどうか、およびサービス A に流れ込むベーストラフィックがサービス B のベースバージョンに転送されるかどうかを確認します。
次の図は、サービス B にトラフィックラベルベースのルーティングルールを設定した後のトラフィックフローを示しています:
vs-tf-mockb.yaml という名前のファイルを作成し、次の内容をファイルにコピーします。
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: vs-mockb spec: hosts: - mockb http: - route: - destination: host: mockb subset: $asm-labels-sample
次のコマンドを実行して、サービス A にルーティングルールを有効にします。
kubectl apply -n default -f vs-tf-mockb.yaml
次のコマンドを実行して、サービス A に流れ込むカナリアトラフィックがサービス B のカナリアリリースバージョンに転送されるかどうかを確認します。
for i in {1..200}; do curl -H'my-asm-prefer-tag: version-canary' -H'my-trace-id: x000'$i http://${ASM_GATEWAY_IP}/; echo; sleep 1; done;
期待される出力:
-> mocka(version: canary, ip: 172.17.0.129)-> mockb(version: canary, ip: 172.17.0.54) -> mocka(version: base, ip: 172.17.0.132)-> mockb(version: canary, ip: 172.17.0.54) -> mocka(version: base, ip: 172.17.0.132)-> mockb(version: canary, ip: 172.17.0.54) -> mocka(version: canary, ip: 172.17.0.129)-> mockb(version: canary, ip: 172.17.0.54) -> mocka(version: canary, ip: 172.17.0.129)-> mockb(version: canary, ip: 172.17.0.54) -> mocka(version: base, ip: 172.17.0.132)-> mockb(version: canary, ip: 172.17.0.54)
次のコマンドを実行して、サービス A に流れ込むベーストラフィックがサービス B のベースバージョンに転送されるかどうかを確認します。
for i in {1..200}; do curl -H'my-asm-prefer-tag: version-base' -H'my-trace-id: x000'$i http://${ASM_GATEWAY_IP}/; echo; sleep 1; done;
期待される出力:
-> mocka(version: canary, ip: 172.17.0.129)-> mockb(version: base, ip: 172.17.0.70) -> mocka(version: base, ip: 172.17.0.132)-> mockb(version: base, ip: 172.17.0.70) -> mocka(version: base, ip: 172.17.0.132)-> mockb(version: base, ip: 172.17.0.70) -> mocka(version: canary, ip: 172.17.0.129)-> mockb(version: base, ip: 172.17.0.70) -> mocka(version: base, ip: 172.17.0.132)-> mockb(version: base, ip: 172.17.0.70) -> mocka(version: canary, ip: 172.17.0.129)-> mockb(version: base, ip: 172.17.0.70) -> mocka(version: canary, ip: 172.17.0.129)-> mockb(version: base, ip: 172.17.0.70) -> mocka(version: base, ip: 172.17.0.132)-> mockb(version: base, ip: 172.17.0.70)
結果は、サービス A に流れ込むイングレスカナリアトラフィックとイングレスベーストラフィックが、サービス B の予期されるバージョンにルーティングされていないことを示しています。 サービス A のトラフィックラベルベースのルーティングルールを設定する必要があります。 詳細については、次の手順に進みます。
2. エンドツーエンドのカナリアリリース機能を確認する
サービス A の a-vs-tf.yaml という名前のトラフィックラベルベースのルーティングルールファイルを設定し、イングレスゲートウェイに対してファイルを有効にします。 期待される結果は、イングレスリクエストのカナリアトラフィックが最初にサービス A のカナリアリリースバージョンに転送され、次にサービス B のカナリアリリースバージョンに転送され、ベーストラフィックが最初にサービス A のベースバージョンに転送され、次にサービス B のベースバージョンに転送されることです。
次の図は、サービス A にトラフィックラベルベースのルーティングルールを設定した後のトラフィックフローを示しています:
vs-tf-mocka.yaml という名前のファイルを作成し、次の内容をファイルにコピーします。
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: vs-gateway-mocka spec: gateways: - simple-gateway hosts: - "*" http: - route: - destination: host: mocka subset: $asm-labels-sample
次のコマンドを実行して、イングレスゲートウェイにルーティングルールを有効にします。
kubectl apply -n default -f vs-tf-mocka.yaml
次のコマンドを実行して、イングレスリクエストのカナリアトラフィックが最初にサービス A のカナリアリリースバージョンに転送され、次にサービス B のカナリアリリースバージョンに転送されるかどうかを確認します。
for i in {1..200}; do curl -H'my-asm-prefer-tag: version-canary' -H'my-trace-id: x000'$i http://${ASM_GATEWAY_IP}/; echo; sleep 1; done;
期待される出力:
-> mocka(version: canary, ip: 172.17.0.69)-> mockb(version: canary, ip: 172.17.0.130) -> mocka(version: canary, ip: 172.17.0.69)-> mockb(version: canary, ip: 172.17.0.130) -> mocka(version: canary, ip: 172.17.0.69)-> mockb(version: canary, ip: 172.17.0.130) -> mocka(version: canary, ip: 172.17.0.69)-> mockb(version: canary, ip: 172.17.0.130) -> mocka(version: canary, ip: 172.17.0.69)-> mockb(version: canary, ip: 172.17.0.130) -> mocka(version: canary, ip: 172.17.0.69)-> mockb(version: canary, ip: 172.17.0.130) -> mocka(version: canary, ip: 172.17.0.69)-> mockb(version: canary, ip: 172.17.0.130)
次のコマンドを実行して、イングレスリクエストのベーストラフィックが最初にサービス A のベースバージョンに転送され、次にサービス B のベースバージョンに転送されるかどうかを確認します。
for i in {1..200}; do curl -H'my-asm-prefer-tag: version-base' -H'my-trace-id: x000'$i http://${ASM_GATEWAY_IP}/; echo; sleep 1; done;
期待される出力:
-> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93)
3. トラフィックラベルベースのルーティングに対応する重みベースのトラフィック分散が要件を満たしているかどうかを確認する
次の図は、サービス A に重みベースおよびトラフィックラベルベースのルーティングルールを設定した後のトラフィックフローを示しています:
vs-tf-mocka-90-10.yaml という名前のファイルを作成し、次の内容をファイルにコピーします。
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: vs-gateway-mocka spec: gateways: - simple-gateway hosts: - "*" http: - route: - destination: host: mocka subset: version-base weight: 90 - destination: host: mocka subset: $asm-labels-sample weight: 10
次のコマンドを実行して、イングレスゲートウェイにルーティングルールを有効にします。
kubectl apply -n default -f vs-tf-mocka-90-10.yaml
次のコマンドを実行して、イングレスリクエストのカナリアトラフィックがサービス A のカナリアリリースバージョンとベースバージョンに転送されるかどうかを確認します。
for i in {1..200}; do curl -H'my-asm-prefer-tag: version-canary' -H'my-trace-id: x000'$i http://${ASM_GATEWAY_IP}/; echo; sleep 1; done;
期待される出力:
-> mocka(version: base, ip: 172.17.0.90)-> mockb(version: canary, ip: 172.17.0.130) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: canary, ip: 172.17.0.130) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: canary, ip: 172.17.0.130) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: canary, ip: 172.17.0.130) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: canary, ip: 172.17.0.130) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: canary, ip: 172.17.0.130) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: canary, ip: 172.17.0.130) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: canary, ip: 172.17.0.130) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: canary, ip: 172.17.0.130) -> mocka(version: canary, ip: 172.17.0.69)-> mockb(version: canary, ip: 172.17.0.130)
結果は、イングレスリクエストのカナリアトラフィックの約 90% がサービス A のベースバージョンに転送され、約 10% がサービス A のカナリアリリースバージョンに転送されることを示しています。上記のルーティングルールに従って、リクエストトラフィックの約 90% がサービス A のベースバージョンに転送され、残りの 10% は
my-asm-prefer-tag
ヘッダーの値に基づいて転送されます。 リクエストコマンドは、my-asm-prefer-tag
の値をversion-canary
に設定します。 したがって、リクエストトラフィックの 10% がサービス A のカナリアリリースバージョンに転送されます。次のコマンドを実行して、イングレスリクエストのすべてのベーストラフィックがサービス A のベースバージョンに転送されるかどうかを確認します。
for i in {1..200}; do curl -H'my-asm-prefer-tag: version-base' -H'my-trace-id: x000'$i http://${ASM_GATEWAY_IP}/; echo; sleep 1; done;
期待される出力:
-> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93) -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93)
上記のルーティングルールに従って、リクエストトラフィックの約 90% がサービス A のベースバージョンに転送され、残りの 10% は
my-asm-prefer-tag
ヘッダーの値に基づいて転送されます。 リクエストコマンドはmy-asm-prefer-tag
の値をversion-base
に設定します。 したがって、リクエストトラフィックの 10% がサービス A のベースバージョンに転送されます。