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

Microservices Engine:Kruise Rollouts を使用した MSEベースのエンドツーエンドカナリアリリースの実装

最終更新日:Mar 11, 2026

標準的なカナリアリリースでは、デプロイするサービスのみを検証します。アップストリームおよびダウンストリームの依存関係とサービスがどのように相互作用するかは検証しません。サービス A がサービス B を呼び出し、サービス B がサービス C を呼び出す場合、A のカナリアバージョンを単独でリリースしても、完全なリクエストパスはテストされません。

エンドツーエンドカナリアリリースは、トラフィックレーンを作成することでこの問題を解決します。トラフィックレーンは、Ingress でリクエストにタグを付け、そのタグを呼び出しチェーン内のすべてのサービスに伝播します。各サービスはタグをチェックし、カナリアバージョンが存在する場合はリクエストをそのカナリアバージョンにルーティングします。サービスにカナリアバージョンがデプロイされていない場合、リクエストはベースバージョンに転送されますが、タグは保持されるため、次のダウンストリームサービスは引き続き正しくルーティングされます。結果として、カナリアトラフィックは Ingress から最終的なダウンストリームサービスまで分離され、複数のサービス変更を本番環境にプロモートする前にまとめて検証できます。

このウォークスルーでは、Container Service for Kubernetes (ACK) クラスター内で、Kruise Rollouts を Microservices Engine (MSE) マイクロサービスガバナンスと統合します。これらの手順を完了すると、タグ付きリクエストは複数のサービスのカナリアバージョンを通過しますが、本番トラフィックには影響しません。

End-to-end canary release architecture

Kruise Rollouts の仕組み

Kruise Rollouts は、OpenKruise のプログレッシブデリバリー用コンポーネントです。Kruise Rollouts を使用すると、カナリアリリース、ブルーグリーンデプロイメント、および A/B テストを実行できます。ワークロードタイプを置き換える必要がある他のツールとは異なり、Kruise Rollouts は バイパスコンポーネント として動作します。既存の Deployment、StatefulSet、または CloneSet は変更されず、Kruise Rollouts がそれらと並行してカナリアプロセスを調整します。リリースプロセスは、Managed Service for Prometheus のメトリックに基づいてバッチ単位で自動化および一時停止できます。アプリケーションのリリースおよび更新を自動化するには、ACK クラスター内に Rollouts リソースを作成するだけで済みます。Kruise Rollouts は、コストを抑えながら Helm や PaaS プラットフォームとのシームレスな統合をサポートしています。

カナリアリリースのライフサイクル

Deployment イメージが変更されると、Kruise Rollouts は次のシーケンスに従います。

  1. Deployment のネイティブローリングアップデートを一時停止します。

  2. 新しいイメージバージョンのカナリア Pod を作成します。

  3. 一致するリクエストがカナリア Pod に到達するようにトラフィックルーティングを設定します。

  4. 手動承認 (または自動メトリックチェック) を待ちます。

  5. 承認されると、ローリングアップデートを使用してカナリアバージョンをすべての Pod にプロモートします。

  6. カナリア Pod を削除し、ネイティブトラフィックルーティングを復元します。

Kruise Rollouts canary release architecture

前提条件

開始する前に、次のことを確認してください。

ステップ 1: 必要なコンポーネントのインストール

ack-kruise のインストール

  1. ACK コンソールにログインし、左側のナビゲーションウィンドウで[クラスター]をクリックします。

  2. [クラスター] ページで、目的のクラスターを見つけ、その名前をクリックします。左側のナビゲーションウィンドウで、[運用] > [アドオン] を選択します。

  3. コンポーネントの管理」ページで、「アプリケーションの管理」タブをクリックします。

  4. [ack-kruise] カードを見つけ、[インストール] をクリックします。

  5. 確認ダイアログで、[OK] をクリックします。

MSE Ingress Controller のインストール

クラスターの MSEベースのIngress を有効にするには、MseIngressConfig と IngressClass リソースを作成します。詳細な手順については、「ACK クラスターで MSE Ingress を使用してアプリケーションにアクセスする」をご参照ください。

Microservices Governance の有効化

ターゲットアプリケーションの Microservices Governance を有効にします。詳細な手順については、「ACK クラスターでマイクロサービスアプリケーションの Microservices Governance を有効にする」をご参照ください。

ステップ 2: デモアプリケーションのデプロイ

このデモでは、A、B、C の 3 つの Spring Cloud アプリケーションを使用します。これらは、A が B を呼び出し、B が C を呼び出すという呼び出しチェーンを形成します。Nacos サーバーがサービス検出を処理し、MySQL インスタンスがデータストレージを提供します。

アプリケーションリソースの作成

  1. 次の内容で mse-demo.yaml という名前のファイルを作成します。

    mse-demo.yaml ファイルの表示

        # Service for application A
        apiVersion: v1
        kind: Service
        metadata:
          name: spring-cloud-a
        spec:
          ports:
            - name: http
              port: 20001
              protocol: TCP
              targetPort: 20001
          selector:
            app: spring-cloud-a
        ---
        # Deployment for application A (base version)
        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: spring-cloud-a
        spec:
          replicas: 2
          selector:
            matchLabels:
              app: spring-cloud-a
          template:
            metadata:
              annotations:
                msePilotCreateAppName: spring-cloud-a
              labels:
                app: spring-cloud-a
            spec:
              containers:
                - env:
                    - name: JAVA_HOME
                      value: /usr/lib/jvm/java-1.8-openjdk/jre
                  image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/spring-cloud-a:mse-2.0.0
                  imagePullPolicy: Always
                  name: spring-cloud-a
                  ports:
                    - containerPort: 20001
        ---
        # Deployment for application B (base version)
        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: spring-cloud-b
        spec:
          replicas: 2
          selector:
            matchLabels:
              app: spring-cloud-b
          template:
            metadata:
              annotations:
                msePilotCreateAppName: spring-cloud-b
              labels:
                app: spring-cloud-b
            spec:
              containers:
                - env:
                    - name: JAVA_HOME
                      value: /usr/lib/jvm/java-1.8-openjdk/jre
                  image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/spring-cloud-b:mse-2.0.0
                  imagePullPolicy: Always
                  name: spring-cloud-b
        ---
        # Deployment for application C (base version)
        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: spring-cloud-c
        spec:
          replicas: 2
          selector:
            matchLabels:
              app: spring-cloud-c
          template:
            metadata:
              annotations:
                msePilotCreateAppName: spring-cloud-c
              labels:
                app: spring-cloud-c
            spec:
              containers:
                - env:
                    - name: JAVA_HOME
                      value: /usr/lib/jvm/java-1.8-openjdk/jre
                  image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/spring-cloud-c:mse-2.0.0
                  imagePullPolicy: Always
                  name: spring-cloud-c
        ---
        # Nacos service discovery server
        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: nacos-server
        spec:
          replicas: 1
          selector:
            matchLabels:
              app: nacos-server
          template:
            metadata:
              labels:
                app: nacos-server
            spec:
              containers:
              - env:
                - name: MODE
                  value: standalone
                image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/nacos-server:v2.1.2
                imagePullPolicy: Always
                name: nacos-server
              dnsPolicy: ClusterFirst
              restartPolicy: Always
        ---
        apiVersion: v1
        kind: Service
        metadata:
          name: nacos-server
        spec:
          type: ClusterIP
          ports:
            - name: nacos-server-8848-8848
              port: 8848
              protocol: TCP
              targetPort: 8848
            - name: nacos-server-9848-9848
              port: 9848
              protocol: TCP
              targetPort: 9848
          selector:
            app: nacos-server
        ---
        # MySQL database
        apiVersion: v1
        kind: Service
        metadata:
          labels:
            app: demo-mysql
          name: demo-mysql
        spec:
          ports:
            - port: 3306
              targetPort: 3306
          selector:
            app: demo-mysql
        ---
        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: demo-mysql
        spec:
          selector:
            matchLabels:
              app: demo-mysql
          replicas: 1
          strategy:
            type: Recreate
          template:
            metadata:
              labels:
                app: demo-mysql
            spec:
              containers:
                - args:
                    - --character-set-server=utf8mb4
                    - --collation-server=utf8mb4_unicode_ci
                  env:
                    - name: MYSQL_ROOT_PASSWORD
                      value: root
                  image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/demo-mysql:3.0.1
                  name: demo-mysql
                  ports:
                    - containerPort: 3306
  2. アプリケーションをデプロイします。

        kubectl apply -f mse-demo.yaml

Ingress リソースの作成

  1. 次の内容で mse-ingress.yaml という名前のファイルを作成します。

    mse-ingress.yaml ファイルの表示

        apiVersion: networking.k8s.io/v1
        kind: Ingress
        metadata:
          annotations:
            mse.ingress.kubernetes.io/service-subset: ""
          name: spring-cloud-a
        spec:
          ingressClassName: mse
          rules:
            - http:
                paths:
                  - backend:
                      service:
                        name: spring-cloud-a
                        port:
                          number: 20001
                    path: /
                    pathType: Prefix
  2. Ingress 設定を適用します。

        kubectl apply -f mse-ingress.yaml

デプロイの確認

  1. Ingress の外部 IP アドレスを取得します。期待される出力:

        kubectl get ingress
        NAME              CLASS    HOSTS   ADDRESS        PORTS   AGE
        spring-cloud-a    <none>   *       EXTERNAL_IP    80      12m
  2. テストリクエストを送信します。<EXTERNAL_IP> を前の出力の IP アドレスに置き換えます。期待される出力: この出力は、呼び出しチェーン A -> B -> C が機能しており、3 つのサービスすべてがベースバージョンを実行していることを確認します。

        curl http://<EXTERNAL_IP>/a -H "User-Agent: xiaoming"
        A[192.168.42.115][config=base] -> B[192.168.42.118] -> C[192.168.42.101]

ステップ 3: エンドツーエンドカナリアリリースの設定

Rollout および TrafficRouting リソースの定義

このデモでは、カナリアリリースは 3 つのバッチで実行されます。

  1. A/B テストが実行されます。header[User-Agent]=xiaoming を含むリクエストはカナリアバージョンに転送されます。その他のリクエストはベースバージョンに転送されます。

  2. Pod の半分がカナリアバージョンを実行し、リクエストの半分がカナリアバージョンに転送されます。

  3. すべての Pod がカナリアバージョンを実行し、すべてのリクエストがカナリアバージョンに転送されます。

次のように Rollout リソースを作成して適用します。

  1. 次の内容で rollout.yaml という名前のファイルを作成します。

    rollout.yaml ファイルの表示

        # Rollout configuration for application A
        apiVersion: rollouts.kruise.io/v1alpha1
        kind: Rollout
        metadata:
          name: rollout-a
          annotations:
            rollouts.kruise.io/trafficrouting: mse-traffic
        spec:
          objectRef:
            workloadRef:
              apiVersion: apps/v1
              kind: Deployment
              name: spring-cloud-a
          strategy:
            canary:
              steps:
              - pause: {}
                replicas: 1
              patchPodTemplateMetadata:
                labels:
                  alicloud.service.tag: gray
                  opensergo.io/canary-gray: gray
        ---
        # Rollout configuration for application B
        apiVersion: rollouts.kruise.io/v1alpha1
        kind: Rollout
        metadata:
          name: rollout-b
          annotations:
            rollouts.kruise.io/trafficrouting: mse-traffic
        spec:
          objectRef:
            workloadRef:
              apiVersion: apps/v1
              kind: Deployment
              name: spring-cloud-b
          strategy:
            canary:
              steps:
                - pause: {}
                  replicas: 1
              patchPodTemplateMetadata:
                labels:
                  alicloud.service.tag: gray
                  opensergo.io/canary-gray: gray
        ---
        # Rollout configuration for application C
        apiVersion: rollouts.kruise.io/v1alpha1
        kind: Rollout
        metadata:
          name: rollout-c
          annotations:
            rollouts.kruise.io/trafficrouting: mse-traffic
        spec:
          objectRef:
            workloadRef:
              apiVersion: apps/v1
              kind: Deployment
              name: spring-cloud-c
          strategy:
            canary:
              steps:
                - pause: {}
                  replicas: 1
              patchPodTemplateMetadata:
                labels:
                  alicloud.service.tag: gray
                  opensergo.io/canary-gray: gray
        ---
        # TrafficRouting: defines how canary traffic is identified and routed
        apiVersion: rollouts.kruise.io/v1alpha1
        kind: TrafficRouting
        metadata:
          name: mse-traffic
        spec:
          objectRef:
          - service: spring-cloud-a
            ingress:
              classType: mse
              name: spring-cloud-a
          strategy:
            matches:
            # Route requests with User-Agent: xiaoming to the canary version
            - headers:
              - type: Exact
                name: User-Agent
                value: xiaoming
            requestHeaderModifier:
              set:
              - name: x-mse-tag
                value: gray

    この設定を適用するとどうなるか:

    Rollout リソースは Deployment を監視します。Deployment イメージが変更されると、Kruise Rollouts は次の処理を行います。

    1. ネイティブローリングアップデートを一時停止します。

    2. 新しいイメージバージョンのカナリア Pod (replicas: 1) を 1 つ作成します。

    3. カナリア Pod に patchPodTemplateMetadata ラベルを適用します。

      • alicloud.service.tag: gray -- この Pod がカナリア (gray) グループの一部であることを MSE Microservices Governance に認識させます。

      • opensergo.io/canary-gray: gray -- 呼び出しチェーン全体で OpenSergo準拠のトラフィックレーンルーティングを有効にします。

    4. プロモートする前に一時停止し、手動承認を待ちます。

    TrafficRouting リソースは、トラフィック分割ルールを定義します。

    • User-Agent: xiaoming ヘッダーを持つリクエストはカナリアルールに一致します。

    • requestHeaderModifier は、一致するリクエストに x-mse-tag: gray ヘッダーを挿入します。MSE はこのヘッダーを呼び出しチェーン全体に伝播し、エンドツーエンドカナリアルーティングを可能にします。チェーン内のすべてのサービスは、このヘッダーをチェックし、カナリア Pod が存在する場合はそこにルーティングします。

  2. Rollout リソースをデプロイします。

        kubectl apply -f rollout.yaml
  3. Rollout ステータスを確認します。出力に STATUS=Healthy と表示されている場合、Rollout リソースは準備完了です。

        kubectl get rollouts rollout-a -n default
        kubectl get rollouts rollout-c -n default

カナリアリリースのトリガー

Kruise Rollouts は一度限りの設定です。Rollout リソースがデプロイされた後、Deployment イメージを更新することでカナリアリリースをトリガーします。追加の Rollout 設定は必要ありません。kubectl に加えて、Helm または Vela を使用して Deployment をクラスターにデプロイできます。

  1. mse-demo.yaml で、spring-cloud-a と spring-cloud-c のイメージバージョンを mse-2.0.0 から mse-2.0.1 に更新します。アプリケーション B は mse-2.0.0 のままです。B にはカナリアバージョンがないため、カナリアレーンにルーティングされたリクエストは B のベースバージョンを通過しますが、C のカナリアバージョンに続行されます。これはエンドツーエンドのトラフィックレーンを示しています。チェーンの中央にあるサービスにカナリアデプロイメントがない場合でも、カナリアタグは保持され、ダウンストリームサービスは引き続き正しくルーティングされます。

        # In the spring-cloud-a Deployment
        image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/spring-cloud-a:mse-2.0.1
    
        # In the spring-cloud-c Deployment
        image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/spring-cloud-c:mse-2.0.1
  2. 更新された Deployment を適用します。

        kubectl apply -f mse-demo.yaml
  3. Rollout の進行状況を確認します。期待される出力:

    フィールド意味
    STATUSProgressingカナリアリリースが進行中です
    CANARY_STATEStepPausedカナリアバッチがデプロイされ、Rollout は手動承認を待機しています
        kubectl get rollouts rollout-a -n default
        kubectl get rollouts rollout-c -n default
        NAME         STATUS        CANARY_STEP   CANARY_STATE   MESSAGE                                                                        AGE
        rollout-a    Progressing   1             StepPaused     Rollout is in step(1/1), and you need manually confirm to enter the next step   41m
        rollout-c    Progressing   1             StepPaused     Rollout is in step(1/1), and you need manually confirm to enter the next step   41m

カナリアバージョンの確認とプロモート

  1. User-Agent: xiaoming ヘッダーを含めてカナリアテストリクエストを送信します。カナリアトラフィックは A と C のカナリアバージョンを通過し、B はそのベースバージョンを使用します。アプリケーションログと監視メトリックを通じて動作を確認します。

        curl http://<EXTERNAL_IP>/a -H "User-Agent: xiaoming"
  2. カナリアバージョンが期待どおりに機能することを確認したら、Rollout を承認して本番環境にプロモートします。カナリアバージョンがデプロイされている各 Rollout (このデモでは rollout-arollout-c) に対して次のコマンドを実行します。<rollouts-demo> を Rollout リソースの名前に置き換えます。

        rollout.rollouts.kruise.io/<rollouts-demo> approved

カナリアリリースのロールバック

カナリアバージョンが期待を満たさない場合は、mse-demo.yaml のイメージバージョンを元の値に戻して再適用します。

kubectl apply -f mse-demo.yaml

Rollout リソースに変更は必要ありません。Kruise Rollouts は Deployment の変更を検出し、ロールバックを自動的に処理します。

Microservices Governance のエンドツーエンドカナリアリリース機能は、レーンを提供し、テストおよびリリース中の検証を大幅に容易にします。Microservices Governance を Kruise Rollouts と組み合わせて使用することで、DevOps プロセスにおけるオンラインアプリケーションの安定性を大幅に向上させることができます。