すべてのプロダクト
Search
ドキュメントセンター

Alibaba Cloud Service Mesh:ハッシュタグ付けプラグインを用いた、独立比率による複数アプリケーションのカナリアリリース

最終更新日:Mar 12, 2026

トラフィックレーン(例:ロースモードおよびストリクトモードのトラフィックレーン)を用いてカナリアリリースを実行する場合、呼び出しチェーン上のすべてのアプリケーションは同一のリリーススケジュールを共有します。しかし実際には、異なるアプリケーションがそれぞれ独立したカナリア比率を必要とするケースが多く見られます。たとえば、2 つのアプリケーションが新機能をリリースする際に 10 % のユーザーを対象とする一方で、3 つ目のアプリケーションがバグ修正をリリースするにあたり 50 % のユーザーに到達する必要がある — このような状況が、同一の呼び出しチェーン上で同時に発生することがあります。

Alibaba Cloud Service Mesh (ASM) では、この課題をハッシュタグ付けプラグインによって解決します。このプラグインは、ゲートウェイにおいて各リクエストに複数のタグを割り当てます。さらに、タグ伝搬のための ASMHeaderPropagation CRD およびタグに基づくマッチングを行う Istio ルーティングルールと組み合わせることで、呼び出しチェーン上の各アプリケーションが、それぞれ独自のカナリア比率に基づいて独立してトラフィックをルーティングできます。

Kubernetes ネイティブのカナリアリリースがレプリカ比率に依存するのとは異なり、ASM ではトラフィックルーティングと Pod のスケーリングが分離されています。カナリア比率はルーティングルールによって制御され、各バージョンが実行するレプリカ数とは無関係です。このため、10 % のユーザーをカナリアバージョンにルーティングする場合でも、正確に「10 分の 1」の数だけ Pod をプロビジョニングする必要はありません。

仕組み

標準的なトラフィックレーン構成では、単一のタグによって呼び出しチェーン上のすべてのアプリケーションがどのバージョンを提供するかが決定されます。独立したカナリア比率を実現するため、ハッシュタグ付けプラグインは各アプリケーションごとに個別のタグヘッダーを追加します(例: appver-aappver-bappver-c)。各タグには、カナリアバージョンへルーティングされるユーザーの割合を制御するための独自のハッシュ範囲が設定されます。

エンドツーエンドの処理フローは以下のとおりです:

  1. クライアントがユーザー識別子(例: x-user-id ヘッダー)を含むリクエストを送信します。

  2. ASM ゲートウェイ上のハッシュタグ付けプラグインが、その識別子をハッシュ化し、モジュロ(例: 100)で除算した余剰値を計算し、各タグの設定済み範囲内に該当するかを判定します。

  3. 範囲に一致した各タグについて、プラグインはリクエストにタグヘッダーを追加します(例: appver-a: v2)。

  4. ASMHeaderPropagation CRD が、呼び出しチェーン全体を通じて appver で始まるすべてのヘッダーを伝搬します。

  5. 各アプリケーションの VirtualService が対応するタグヘッダーをマッチさせ、リクエストを適切なバージョンへルーティングします。

ハッシュは決定論的であるため、同一のユーザーは常に同一のバージョンセットに到達し、リクエスト間で一貫した体験を提供します。

Traffic flow with multi-tag routing

シナリオ概要

本チュートリアルでは、呼び出しチェーン app-a → app-b → app-c を構成する 3 つのアプリケーションからなる分散システムを使用します。

アプリケーション安定版カナリア版カナリア比率理由
app-av1v210 %新機能の展開
app-bv1v210 %新機能の展開
app-cv2v350 %バグ修正(リスクが低く、迅速なリリースが必要)

本チュートリアルでは、まず安定版のベースラインをデプロイし、次に app-a v2 および app-b v2 を 10 % のユーザーに展開、さらに app-c v3 を 50 % のユーザーに追加展開した後、最終的に app-c v3 を 100 % に昇格させる手順を説明します。

以下の図は、複数バージョンを備えた分散システムのトラフィックレーンアーキテクチャを示しています。

Traffic lane architecture

以下の図は、各アプリケーションに対して独立したカナリア比率を適用した目標状態を示しています。

Application architecture with version distribution

前提条件

開始する前に、以下の条件を満たしていることを確認してください。

ステップ 1:ベースラインアプリケーションのデプロイ

app-a v1、app-b v1、app-c v2 およびそれらの Istio ルーティングリソースをデプロイします。このステップ完了後、すべてのトラフィックは呼び出しチェーン app-a(v1) → app-b(v1) → app-c(v2) に従います。

Baseline call chain

アプリケーションワークロードのデプロイ

  1. 以下の内容で app-init.yaml ファイルを作成します。

app-init.yaml

apiVersion: v1
kind: Service
metadata:
  name: app-a
  labels:
    app: app-a
    service: app-a
spec:
  ports:
  - port: 8000
    name: http
  selector:
    app: app-a
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-a-v1
  labels:
    app: app-a
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app-a
      version: v1
      ASM_TRAFFIC_TAG: v1
  template:
    metadata:
      labels:
        app: app-a
        version: v1
        ASM_TRAFFIC_TAG: v1
      annotations:
        instrumentation.opentelemetry.io/inject-java: "true"
        instrumentation.opentelemetry.io/container-names: "default"
    spec:
      containers:
      - name: default
        image: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-java
        imagePullPolicy: IfNotPresent
        env:
        - name: version
          value: v1
        - name: app
          value: app-a
        - name: upstream_url
          value: "http://app-b:8000/"
        ports:
        - containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
  name: app-b
  labels:
    app: app-b
    service: app-b
spec:
  ports:
  - port: 8000
    name: http
  selector:
    app: app-b
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-b-v1
  labels:
    app: app-b
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app-b
      version: v1
      ASM_TRAFFIC_TAG: v1
  template:
    metadata:
      labels:
        app: app-b
        version: v1
        ASM_TRAFFIC_TAG: v1
      annotations:
        instrumentation.opentelemetry.io/inject-java: "true"
        instrumentation.opentelemetry.io/container-names: "default"
    spec:
      containers:
      - name: default
        image: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-java
        imagePullPolicy: IfNotPresent
        env:
        - name: version
          value: v1
        - name: app
          value: app-b
        - name: upstream_url
          value: "http://app-c:8000/"
        ports:
        - containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
  name: app-c
  labels:
    app: app-c
    service: app-c
spec:
  ports:
  - port: 8000
    name: http
  selector:
    app: app-c
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-c-v2
  labels:
    app: app-c
    version: v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app-c
      version: v2
      ASM_TRAFFIC_TAG: v2
  template:
    metadata:
      labels:
        app: app-c
        version: v2
        ASM_TRAFFIC_TAG: v2
      annotations:
        instrumentation.opentelemetry.io/inject-java: "true"
        instrumentation.opentelemetry.io/container-names: "default"
    spec:
      containers:
      - name: default
        image: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-java
        imagePullPolicy: IfNotPresent
        env:
        - name: version
          value: v2
        - name: app
          value: app-c
        ports:
        - containerPort: 8000
  1. データプレーンクラスターの kubeconfig を使用してファイルを適用します。本例では default 名前空間を使用します。自動サイドカープロキシ注入が有効化された任意の名前空間でも動作します。

kubectl apply -f app-init.yaml -n default

Istio ルーティングリソースの構成

  1. 以下の内容で app-init-mesh.yaml ファイルを作成します。このファイルでは、VirtualService、DestinationRule、および Gateway を定義し、すべてのトラフィックを安定版へルーティングします。

app-init-mesh.yaml

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: app-b
  namespace: default
spec:
  hosts:
  - app-b.default.svc.cluster.local
  http:
  - name: default
    route:
    - destination:
        host: app-b.default.svc.cluster.local
        port:
          number: 8000
        subset: v1
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: app-c
  namespace: default
spec:
  hosts:
  - app-c.default.svc.cluster.local
  http:
  - name: default
    route:
    - destination:
        host: app-c.default.svc.cluster.local
        port:
          number: 8000
        subset: v2
---
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: ingressgateway
  namespace: default
spec:
  selector:
    istio: ingressgateway
  servers:
    - hosts:
        - '*'
      port:
        name: http
        number: 80
        protocol: HTTP
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: ingressgateway
  namespace: istio-system
spec:
  gateways:
  - default/ingressgateway
  hosts:
  - '*'
  http:
  - name: default
    route:
    - destination:
        host: app-a.default.svc.cluster.local
        port:
          number: 8000
        subset: v1
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: app-a
  namespace: default
spec:
  host: app-a.default.svc.cluster.local
  subsets:
    - labels:
        version: v1
      name: v1
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: app-b
  namespace: default
spec:
  host: app-b.default.svc.cluster.local
  subsets:
    - labels:
        version: v1
      name: v1
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: app-c
  namespace: default
spec:
  host: app-c.default.svc.cluster.local
  subsets:
    - labels:
        version: v2
      name: v2
  1. ASM インスタンス(コントロールプレーン)の kubeconfig を使用してファイルを適用します。

kubectl apply -f app-init-mesh.yaml

ベースラインの検証

  1. テストリクエストを送信します。<ingress-gateway-ip> をご利用のイングレスゲートウェイの IP アドレスに置き換えてください。このアドレスを取得する方法については、「イングレスゲートウェイの IP アドレスの取得」をご参照ください。

curl -H 'x-user-id: 0001' <ingress-gateway-ip>

期待される出力:

-> app-a(バージョン: v1, IP: 10.0.250.27)-> app-b(バージョン: v1, IP: 10.0.250.6)-> app-c(バージョン: v2, IP: 10.0.250.11)
-> app-a(バージョン: v1, IP: 10.0.250.27)-> app-b(バージョン: v1, IP: 10.0.250.6)-> app-c(バージョン: v2, IP: 10.0.250.11)
-> app-a(バージョン: v1, IP: 10.0.250.27)-> app-b(バージョン: v1, IP: 10.0.250.6)-> app-c(バージョン: v2, IP: 10.0.250.11)
-> app-a(バージョン: v1, IP: 10.0.250.27)-> app-b(バージョン: v1, IP: 10.0.250.6)-> app-c(バージョン: v2, IP: 10.0.250.11)
-> app-a(バージョン: v2, IP: 10.0.250.14)-> app-b(バージョン: v2, IP: 10.0.250.8)-> app-c(バージョン: v2, IP: 10.0.250.11)

すべてのリクエストは呼び出しチェーン app-a(v1) → app-b(v1) → app-c(v2) に従います。

ステップ 2:app-a および app-b のカナリアリリースの開始

このステップでは、app-a v2 および app-b v2 をデプロイし、ハッシュタグ付けプラグインを構成して、10 % のユーザーを新バージョンへルーティングします。以下の 4 つの変更を実施します。

  1. app-a v2 および app-b v2 のワークロードをデプロイします。

  2. DestinationRule および VirtualService を更新し、v2 サブセットおよびタグベースのルーティングルールを追加します。

  3. ASMHeaderPropagation CRD を構成し、呼び出しチェーン全体で appver で始まるヘッダーを伝搬します。

  4. app-a および app-b のタグ付けルールを備えたハッシュタグ付けプラグイン(WasmPlugin)をデプロイします。

説明

注: ここに記載した順序は理解しやすさを重視したものであり、実際の運用ではアプリケーション間の依存関係に応じて順序を調整してください。

Canary architecture for app-a and app-b

カナリアワークロードのデプロイ

  1. 以下の内容で app-ab-v2.yaml ファイルを作成します。

app-ab-v2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-a-v2
  labels:
    app: app-a
    version: v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app-a
      version: v2
      ASM_TRAFFIC_TAG: v2
  template:
    metadata:
      labels:
        app: app-a
        version: v2
        ASM_TRAFFIC_TAG: v2
      annotations:
        instrumentation.opentelemetry.io/inject-java: "true"
        instrumentation.opentelemetry.io/container-names: "default"
    spec:
      containers:
      - name: default
        image: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-java
        imagePullPolicy: IfNotPresent
        env:
        - name: version
          value: v2
        - name: app
          value: app-a
        - name: upstream_url
          value: "http://app-b:8000/"
        ports:
        - containerPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-b-v2
  labels:
    app: app-b
    version: v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app-b
      version: v2
      ASM_TRAFFIC_TAG: v2
  template:
    metadata:
      labels:
        app: app-b
        version: v2
        ASM_TRAFFIC_TAG: v2
      annotations:
        instrumentation.opentelemetry.io/inject-java: "true"
        instrumentation.opentelemetry.io/container-names: "default"
    spec:
      containers:
      - name: default
        image: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-java
        imagePullPolicy: IfNotPresent
        env:
        - name: version
          value: v2
        - name: app
          value: app-b
        - name: upstream_url
          value: "http://app-c:8000/"
        ports:
        - containerPort: 8000
  1. データプレーンクラスターの kubeconfig を使用してファイルを適用します。

kubectl apply -f app-ab-v2.yaml

ルーティングルールの更新

  1. 以下の内容で app-ab-v2-mesh.yaml ファイルを作成します。このファイルでは、DestinationRule に v2 サブセットを追加し、app-a および app-b の VirtualService にタグマッチングルートを追加します。リクエストに appver-a: v2 ヘッダーが含まれる場合、app-a v2 へルーティングされます。同様に、appver-b: v2 ヘッダーが含まれる場合は app-b v2 へルーティングされます。これらのヘッダーが含まれないリクエストは v1(デフォルト)へルーティングされます。

app-ab-v2-mesh.yaml

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: app-b
  namespace: default
spec:
  hosts:
  - app-b.default.svc.cluster.local
  http:
  - name: v2
    match:
    - headers:
        appver-b:
          exact: v2
    route:
    - destination:
        host: app-b.default.svc.cluster.local
        port:
          number: 8000
        subset: v2
  - name: default
    route:
    - destination:
        host: app-b.default.svc.cluster.local
        port:
          number: 8000
        subset: v1
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: app-c
  namespace: default
spec:
  hosts:
  - app-c.default.svc.cluster.local
  http:
  - name: default
    route:
    - destination:
        host: app-c.default.svc.cluster.local
        port:
          number: 8000
        subset: v2
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: ingressgateway
  namespace: default
spec:
  gateways:
  - default/ingressgateway
  hosts:
  - '*'
  http:
  - name: v2
    match:
    - headers:
        appver-a:
          exact: v2
    route:
    - destination:
        host: app-a.default.svc.cluster.local
        port:
          number: 8000
        subset: v2
  - name: default
    route:
    - destination:
        host: app-a.default.svc.cluster.local
        port:
          number: 8000
        subset: v1
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: app-a
spec:
  host: app-a.default.svc.cluster.local
  subsets:
    - labels:
        version: v1
      name: v1
    - labels:
        version: v2
      name: v2
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: app-b
spec:
  host: app-b.default.svc.cluster.local
  subsets:
    - labels:
        version: v1
      name: v1
    - labels:
        version: v2
      name: v2
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: app-c
spec:
  host: app-c.default.svc.cluster.local
  subsets:
    - labels:
        version: v2
      name: v2
  1. ASM インスタンス(コントロールプレーン)の kubeconfig を使用してファイルを適用します。

kubectl apply -f app-ab-v2-mesh.yaml

ヘッダー伝搬の有効化

  1. 以下の内容で header-propagation.yaml ファイルを作成します。ASMHeaderPropagation CRD は、サイドカープロキシに対し、appver で始まるすべてのヘッダーを呼び出しチェーン全体で転送するよう指示します。この設定がない場合、ゲートウェイで追加されたタグは下流のアプリケーションに到達しません。

apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMHeaderPropagation
metadata:
  name: tag-propagation
spec:
  headerPrefixes:
    - appver
  1. データプレーンクラスターの kubeconfig を使用してファイルを適用します。

kubectl apply -f header-propagation.yaml -n default

ハッシュタグ付けプラグインの構成

  1. 以下の内容で hash-tagging-plugin.yaml ファイルを作成します。

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: hash-tagging
  namespace: istio-system
spec:
  imagePullPolicy: IfNotPresent
  selector:
    matchLabels:
      istio: ingressgateway
  url: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-wasm-hash-tagging:v1.22.6.2-g72656ba-aliyun
  phase: AUTHN
  pluginConfig:
    rules:
      - header: x-user-id
        modulo: 100
        tagHeader: appver-a
        policies:
          - range: 10
            tagValue: v2
      - header: x-user-id
        modulo: 100
        tagHeader: appver-b
        policies:
          - range: 10
            tagValue: v2
      - header: x-user-id
        modulo: 100
        tagHeader: appver-c
        policies:
          - range: 50           # app-c のカナリア比率は 50%
            tagValue: v3

以下の表は、この構成におけるタグ付けルールを説明しています。

ルールタグヘッダー範囲効果
app-aappver-a10x-user-id 値をモジュロ 100 でハッシュ化し、余剰値が 10 以下の場合に appver-a: v2 ヘッダーを追加します。これにより、約 10 % のユーザーが app-a v2 へルーティングされます。
app-bappver-b100同様のハッシュ計算ですが、範囲を 100 に設定しているため、すべてのユーザーに appver-b: v2 ヘッダーが付与され、app-b v2 へルーティングされます。ターゲットとなるカナリア比率に応じて range 値を調整してください。
  1. WasmPlugin 構成を適用します。

kubectl apply -f hash-tagging-plugin.yaml

カナリアリリースの検証

  1. 異なるユーザー ID を使用してテストリクエストを送信します。

curl -H 'x-user-id: 0001' <ingress-gateway-ip>
curl -H 'x-user-id: 0002' <ingress-gateway-ip>
curl -H 'x-user-id: 0003' <ingress-gateway-ip>
curl -H 'x-user-id: 0004' <ingress-gateway-ip>
curl -H 'x-user-id: 0005' <ingress-gateway-ip>

期待される出力:

-> app-a(version: v1, ip: 10.0.250.27)-> app-b(version: v1, ip: 10.0.250.6)-> app-c(version: v2, ip: 10.0.250.11)
-> app-a(version: v1, ip: 10.0.250.27)-> app-b(version: v1, ip: 10.0.250.6)-> app-c(version: v2, ip: 10.0.250.11)
-> app-a(version: v1, ip: 10.0.250.27)-> app-b(version: v1, ip: 10.0.250.6)-> app-c(version: v2, ip: 10.0.250.11)
-> app-a(version: v1, ip: 10.0.250.27)-> app-b(version: v1, ip: 10.0.250.6)-> app-c(version: v2, ip: 10.0.250.11)
-> app-a(version: v2, ip: 10.0.250.14)-> app-b(version: v2, ip: 10.0.250.8)-> app-c(version: v2, ip: 10.0.250.11)

ユーザー 0005 のハッシュ余剰値が設定済み範囲内に該当したため、ハッシュタグ付けプラグインがリクエストにタグを付与し、app-a v2 および app-b v2 へルーティングされました。ユーザー 0001 ~ 0004 は引き続き v1 へルーティングされます。

ステップ 3:app-c のカナリアリリースの開始

app-a v2 および app-b v2 のカナリアリリースが継続中の状態で、チームが app-c v2 にバグを発見し、app-c v3 を 50 % のユーザーに展開することを決定しました。

app-c v3 のデプロイ

  1. 以下の内容で app-c-v3.yaml ファイルを作成します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-c-v3
  labels:
    app: app-c
    version: v3
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app-c
      version: v3
      ASM_TRAFFIC_TAG: v3
  template:
    metadata:
      labels:
        app: app-c
        version: v3
        ASM_TRAFFIC_TAG: v3
      annotations:
        instrumentation.opentelemetry.io/inject-java: "true"
        instrumentation.opentelemetry.io/container-names: "default"
    spec:
      containers:
      - name: default
        image: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-java
        imagePullPolicy: IfNotPresent
        env:
        - name: version
          value: v3
        - name: app
          value: app-c
        ports:
        - containerPort: 8000
  1. データプレーンクラスターの kubeconfig を使用してファイルを適用します。

kubectl apply -f app-c-v3.yaml

app-c v3 のルーティング構成

  1. 以下の内容で app-c-v3-mesh.yaml ファイルを作成します。このファイルでは、DestinationRule に v3 サブセットを追加し、app-c の VirtualService にタグマッチングルートを追加します。リクエストに appver-c: v3 ヘッダーが含まれる場合、app-c v3 へルーティングされます。それ以外のリクエストは app-c v2(デフォルト)へルーティングされます。

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: app-c
  namespace: default
spec:
  hosts:
  - app-c.default.svc.cluster.local
  http:
  - name: default
    route:
    - destination:
        host: app-c.default.svc.cluster.local
        port:
          number: 8000
        subset: v3
  1. ASM インスタンス(コントロールプレーン)の kubeconfig を使用してファイルを適用します。

kubectl apply -f app-c-v3-mesh.yaml

ハッシュタグ付けプラグインの更新

  1. 以下の内容で wasm-plugin-ab-v2-c-v3.yaml ファイルを作成します。このファイルでは、app-c 用の第 3 のタグ付けルールを追加し、範囲を 50 に設定することで、50 % のユーザーを app-c v3 へルーティングします。

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: hash-tagging
  namespace: istio-system
spec:
  imagePullPolicy: IfNotPresent
  selector:
    matchLabels:
      istio: ingressgateway
  url: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-wasm-hash-tagging:v1.22.6.2-g72656ba-aliyun
  phase: AUTHN
  pluginConfig:
    rules:
      - header: x-user-id
        modulo: 100
        tagHeader: appver-a
        policies:
          - range: 10
            tagValue: v2
      - header: x-user-id
        modulo: 100
        tagHeader: appver-b
        policies:
          - range: 10
            tagValue: v2
      - header: x-user-id
        modulo: 100
        tagHeader: appver-c
        policies:
          - range: 50           # app-c のカナリア比率:50 %
            tagValue: v3
  1. 更新されたプラグイン構成を適用します。

kubectl apply -f wasm-plugin-ab-v2-c-v3.yaml

結果の検証

  1. 異なるユーザー ID を使用してテストリクエストを送信します。

curl -H 'x-user-id: 0001' <ingress-gateway-ip>
curl -H 'x-user-id: 0002' <ingress-gateway-ip>
curl -H 'x-user-id: 0003' <ingress-gateway-ip>
curl -H 'x-user-id: 0004' <ingress-gateway-ip>
curl -H 'x-user-id: 0005' <ingress-gateway-ip>

期待される出力:

-> app-a(version: v1, ip: 10.0.250.27)-> app-b(version: v1, ip: 10.0.250.6)-> app-c(version: v2, ip: 10.0.250.11)
-> app-a(version: v1, ip: 10.0.250.27)-> app-b(version: v1, ip: 10.0.250.6)-> app-c(version: v2, ip: 10.0.250.11)
-> app-a(version: v1, ip: 10.0.250.27)-> app-b(version: v1, ip: 10.0.250.6)-> app-c(version: v3, ip: 10.0.250.23)
-> app-a(version: v1, ip: 10.0.250.27)-> app-b(version: v1, ip: 10.0.250.6)-> app-c(version: v3, ip: 10.0.250.23)
-> app-a(version: v2, ip: 10.0.250.14)-> app-b(version: v2, ip: 10.0.250.8)-> app-c(version: v3, ip: 10.0.250.23)

結果より、以下の 3 つの異なるルーティングパスが独立して決定されていることがわかります。

ユーザー IDapp-aapp-bapp-c説明
0001、0002v1v1v2タグが一致しなかったため、すべて安定版が使用されます
0003、0004v1v1v3appver-c のみが一致(50 % 範囲)
0005v2v2v3すべてのタグが一致:appver-a および appver-b(10 % 範囲)に加え、appver-c(50 % 範囲)

ステップ 4:app-c v3 の全トラフィックへの昇格

app-c v3 がカナリア環境で正常に動作することを確認した後、すべてのトラフィックを v3 へルーティングすることで昇格を行います。この操作には、以下の 2 つの変更が必要です:VirtualService を更新してタグマッチングルートを削除し、デフォルトルートを v3 へ向けること、およびプラグインから app-c のタグ付けルールを削除して不要なヘッダーの伝搬を停止することです。

VirtualService の更新

  1. 以下の YAML を ASM インスタンス(コントロールプレーン)の kubeconfig を使用して適用します。これにより、デフォルトルートを更新して app-c のすべてのトラフィックを v3 へルーティングします。

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: app-c
  namespace: default
spec:
  hosts:
  - app-c.default.svc.cluster.local
  http:
  - name: default
    route:
    - destination:
        host: app-c.default.svc.cluster.local
        port:
          number: 8000
        subset: v3

app-c のタグ付けルールの削除

  1. 以下の YAML を適用してハッシュタグ付けプラグインを更新します。appver-c ルールを削除し、app-a および app-b のルールのみを残します。

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: hash-tagging
  namespace: istio-system
spec:
  imagePullPolicy: IfNotPresent
  selector:
    matchLabels:
      istio: ingressgateway
  url: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-wasm-hash-tagging:v1.22.6.2-g72656ba-aliyun
  phase: AUTHN
  pluginConfig:
    rules:
      - header: x-user-id
        modulo: 100
        tagHeader: appver-a
        policies:
          - range: 10
            tagValue: v2
      - header: x-user-id
        modulo: 100
        tagHeader: appver-b
        policies:
          - range: 10
            tagValue: v2

プロモーションを確認する

  1. 異なるユーザー ID を使用してテストリクエストを送信します。

curl -H 'x-user-id: 0001' <ingress-gateway-ip>
curl -H 'x-user-id: 0002' <ingress-gateway-ip>
curl -H 'x-user-id: 0003' <ingress-gateway-ip>
curl -H 'x-user-id: 0004' <ingress-gateway-ip>
curl -H 'x-user-id: 0005' <ingress-gateway-ip>

期待される出力:

-> app-a(version: v1, ip: 10.0.250.27)-> app-b(version: v1, ip: 10.0.250.6)-> app-c(version: v3, ip: 10.0.250.23)
-> app-a(version: v1, ip: 10.0.250.27)-> app-b(version: v1, ip: 10.0.250.6)-> app-c(version: v3, ip: 10.0.250.23)
-> app-a(version: v1, ip: 10.0.250.27)-> app-b(version: v1, ip: 10.0.250.6)-> app-c(version: v3, ip: 10.0.250.23)
-> app-a(version: v1, ip: 10.0.250.27)-> app-b(version: v1, ip: 10.0.250.6)-> app-c(version: v3, ip: 10.0.250.23)
-> app-a(version: v2, ip: 10.0.250.14)-> app-b(version: v2, ip: 10.0.250.8)-> app-c(version: v3, ip: 10.0.250.23)

すべてのユーザーが app-c v3 に到達しており、昇格が完了したことが確認できます。

説明

注: すべてのトラフィックが app-c v3 に切り替わった後は、運用要件に応じて app-c v2 のデプロイメントを 0 レプリカにスケールダウンするか、削除してください。