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

Microservices Engine:Spring Boot アプリケーションに基づくエンドツーエンドのカナリアリリースを実装する

最終更新日:May 07, 2025

Java エージェントは、Kubernetes サービスディスカバリに基づくエンドツーエンドのカナリアリリースをサポートしています。 Spring Boot アプリケーションはサードパーティのレジストリに接続できません。 このため、Kubernetes クラスターにデプロイされた Spring Boot アプリケーションは、Kubernetes サービスディスカバリに基づいて他のアプリケーションを呼び出します。 このトピックでは、マイクロサービスエンジン(MSE)を使用して、Kubernetes クラスターにデプロイされた Spring Boot アプリケーションのエンドツーエンドのカナリアリリースを実装する方法について説明します。

前提条件

制限事項

重要

この機能はパブリックプレビュー段階であり、次のリージョンでのみ使用できます:中国(北京)、中国(上海)、中国(杭州)、中国(深圳)、中国(張家口)、米国(シリコンバレー)、シンガポール。 その他のリージョンはサポートされていません。

デモの概要

このデモでは、アプリケーションは ACK コンソールにデプロイされます。 次の図は、デモアプリケーションのアーキテクチャを示しています。 アプリケーション呼び出しシナリオには、Nacos インスタンスに基づく Spring Cloud アプリケーションのディスカバリと、Kubernetes サービスに基づく Spring Boot アプリケーションのディスカバリが含まれます。

  • ゲートウェイ:Spring Cloud ゲートウェイとして機能します。 バックエンドトラフィックのイングレスとして使用され、Nacos サービスディスカバリに基づいてアプリケーション A を呼び出します。

  • A:Spring Cloud アプリケーション。 そのノードは、サービスディスカバリのために Nacos インスタンスに登録されます。 アプリケーション A は、Kubernetes サービスディスカバリに基づいてアプリケーション B を呼び出し、Nacos サービスディスカバリに基づいてアプリケーション D を呼び出します。

  • B:Spring Boot アプリケーション。 Kubernetes サービスディスカバリに基づいてアプリケーション D を呼び出します。

  • D:Spring Cloud アプリケーション。 そのノードは、サービスディスカバリのために Nacos インスタンスに登録されます。

手順

手順 1:ベースアプリケーションとカナリアアプリケーションをデプロイする

  1. ACK コンソール にログインします。

  2. 左側のナビゲーションウィンドウで、[クラスター] をクリックします。 次に、管理するクラスターの名前をクリックします。

  3. 左側のナビゲーションウィンドウで、[ワークロード] > [デプロイメント] を選択します。

  4. ページの上部で、クラスターの [名前空間] を選択し、[YAML から作成] をクリックします。

  5. 次のコマンドを実行して、MySQL Flexible Server インスタンスを作成します。

    YAML コードを表示

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nacos-server
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nacos-server
      template:
        metadata:
          labels:
            msePilotAutoEnable: "off"
            app: nacos-server
        spec:
          containers:
            - name: nacos-server
              image: "registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/nacos-server:v2.1.2"
              env:
                - name: MODE
                  value: standalone
                - name: JVM_XMS
                  value: 512M
                - name: JVM_XMX
                  value: 512M
                - name: JVM_XMN
                  value: 256M
              imagePullPolicy: Always
              livenessProbe:
                failureThreshold: 3
                initialDelaySeconds: 15
                periodSeconds: 10
                successThreshold: 1
                tcpSocket:
                  port: 8848
                timeoutSeconds: 3
              readinessProbe:
                failureThreshold: 5
                initialDelaySeconds: 15
                periodSeconds: 15
                successThreshold: 1
                tcpSocket:
                  port: 8848
                timeoutSeconds: 3
              resources:
                requests:
                  cpu: '1'
                  memory: 2Gi
          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
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: spring-cloud-gateway
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: spring-cloud-gateway
      strategy:
        rollingUpdate:
          maxSurge: 100%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
          labels:
            msePilotAutoEnable: "on"
            msePilotCreateAppName: "spring-cloud-gateway"
            mseNamespace: "mse-springboot-demo"
            app: spring-cloud-gateway
            sidecar.istio.io/inject: 'false'
            aliyun.com/agent-version: "4.2.5-proxyless"
        spec:
          containers:
            - image: "registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-gateway:3.1.0-heterogeneous"
              imagePullPolicy: Always
              env:
                - name: nacos.host
                  value: "nacos-server"
                - name: nacos.namespace
                  value: "public"
              name: "spring-cloud-gateway"
              resources:
                requests:
                  cpu: "1"
                  memory: "2Gi"
                limits:
                  cpu: "1"
                  memory: "2Gi"
              ports:
                - name: http-port
                  containerPort: 20000
    ---
    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        service.beta.kubernetes.io/alibaba-cloud-loadbalancer-spec: slb.s1.small
        service.beta.kubernetes.io/alicloud-loadbalancer-address-type: internet
      name: spring-cloud-gateway-slb
    spec:
      ports:
        - port: 80
          protocol: TCP
          targetPort: 20000
      selector:
        app: spring-cloud-gateway
      type: LoadBalancer
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: spring-cloud-a
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: spring-cloud-a
      strategy:
        rollingUpdate:
          maxSurge: 100%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
          labels:
            msePilotAutoEnable: "on"
            msePilotCreateAppName: "spring-cloud-a"
            mseNamespace: "mse-springboot-demo"
            app: "spring-cloud-a"
            sidecar.istio.io/inject: 'false'
            aliyun.com/agent-version: "4.2.5-proxyless"
        spec:
          containers:
            - name: spring-cloud-a
              image: "registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-a:3.1.0-heterogeneous"
              imagePullPolicy: Always
              env:
                - name: nacos.host
                  value: "nacos-server"
                - name: nacos.namespace
                  value: "public"
              resources:
                requests:
                  cpu: "1"
                  memory: "2Gi"
                limits:
                  cpu: "1"
                  memory: "2Gi"
              ports:
                - name: http-port
                  containerPort: 20001
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: spring-cloud-a-gray
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: spring-cloud-a
      strategy:
        rollingUpdate:
          maxSurge: 100%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
          labels:
            msePilotAutoEnable: "on"
            msePilotCreateAppName: "spring-cloud-a"
            mseNamespace: "mse-springboot-demo"
            alicloud.service.tag: gray
            app: "spring-cloud-a"
            sidecar.istio.io/inject: 'false'
            aliyun.com/agent-version: "4.2.5-proxyless"
        spec:
          containers:
            - name: spring-cloud-a
              image: "registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-a:3.1.0-heterogeneous"
              imagePullPolicy: Always
              env:
                - name: nacos.host
                  value: "nacos-server"
                - name: nacos.namespace
                  value: "public"
              resources:
                requests:
                  cpu: "1"
                  memory: "2Gi"
                limits:
                  cpu: "1"
                  memory: "2Gi"
              ports:
                - name: http-port
                  containerPort: 20001
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: spring-cloud-a
    spec:
      ports:
        - port: 20001
          protocol: TCP
          targetPort: 20001
      selector:
        app: spring-cloud-a
      type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: spring-boot-b
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: spring-boot-b
      strategy:
        rollingUpdate:
          maxSurge: 100%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
          labels:
            msePilotAutoEnable: "on"
            msePilotCreateAppName: "spring-boot-b"
            mseNamespace: "mse-springboot-demo"
            app: "spring-boot-b"
            sidecar.istio.io/inject: 'false'
            aliyun.com/agent-version: "4.2.5-proxyless"
        spec:
          containers:
            - name: spring-boot-b
              image: "registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-boot-b:3.1.0-heterogeneous"
              imagePullPolicy: Always
              resources:
                requests:
                  cpu: "1"
                  memory: "2Gi"
                limits:
                  cpu: "1"
                  memory: "2Gi"
              ports:
                - name: http-port
                  containerPort: 20002
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: spring-boot-b-gray
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: spring-boot-b
      strategy:
        rollingUpdate:
          maxSurge: 100%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
          labels:
            msePilotAutoEnable: "on"
            msePilotCreateAppName: "spring-boot-b"
            mseNamespace: "mse-springboot-demo"
            alicloud.service.tag: gray
            app: "spring-boot-b"
            sidecar.istio.io/inject: 'false'
            aliyun.com/agent-version: "4.2.5-proxyless"
        spec:
          containers:
            - name: spring-boot-b
              image: "registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-boot-b:3.1.0-heterogeneous"
              imagePullPolicy: Always
              resources:
                requests:
                  cpu: "1"
                  memory: "2Gi"
                limits:
                  cpu: "1"
                  memory: "2Gi"
              ports:
                - name: http-port
                  containerPort: 20002
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: spring-boot-b
    spec:
      ports:
        - port: 20002
          protocol: TCP
          targetPort: 20002
      selector:
        app: spring-boot-b
      type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: spring-cloud-d
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: spring-cloud-d
      strategy:
        rollingUpdate:
          maxSurge: 100%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
          labels:
            msePilotAutoEnable: "on"
            msePilotCreateAppName: "spring-cloud-d"
            mseNamespace: "mse-springboot-demo"
            app: "spring-cloud-d"
            sidecar.istio.io/inject: 'false'
            aliyun.com/agent-version: "4.2.5-proxyless"
        spec:
          containers:
            - name: spring-cloud-d
              image: "registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-d:3.1.0-heterogeneous"
              imagePullPolicy: Always
              env:
                - name: nacos.host
                  value: "nacos-server"
                - name: nacos.namespace
                  value: "public"
              resources:
                requests:
                  cpu: "1"
                  memory: "2Gi"
                limits:
                  cpu: "1"
                  memory: "2Gi"
              ports:
                - name: http-port
                  containerPort: 20004
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: spring-cloud-d-gray
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: spring-cloud-d
      strategy:
        rollingUpdate:
          maxSurge: 100%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
          labels:
            msePilotAutoEnable: "on"
            msePilotCreateAppName: "spring-cloud-d"
            mseNamespace: "mse-springboot-demo"
            alicloud.service.tag: gray
            app: "spring-cloud-d"
            sidecar.istio.io/inject: 'false'
            aliyun.com/agent-version: "4.2.5-proxyless"
        spec:
          containers:
            - name: spring-cloud-d
              image: "registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-d:3.1.0-heterogeneous"
              imagePullPolicy: Always
              env:
                - name: nacos.host
                  value: "nacos-server"
                - name: nacos.namespace
                  value: "public"
              resources:
                requests:
                  cpu: "1"
                  memory: "2Gi"
                limits:
                  cpu: "1"
                  memory: "2Gi"
              ports:
                - name: http-port
                  containerPort: 20004
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: spring-cloud-d
    spec:
      ports:
        - port: 20004
          protocol: TCP
          targetPort: 20004
      selector:
        app: spring-cloud-d
      type: ClusterIP

ステップ 2: エンドツーエンドカナリアリリース機能を設定する

  1. MSE コンソール にログインし、上部のナビゲーションバーでリージョンを選択します。

  2. 左側のナビゲーションウィンドウで、[マイクロサービスガバナンス] > [フルリンクグレースケール] を選択します。

  3. [フルリンクグレースケール] ページで、マイクロサービス名前空間ドロップダウンリストから mse-springboot-demo を選択します。

  4. 選択したマイクロサービス名前空間にレーン グループが作成されていない場合は、[レーン グループとレーンを作成] をクリックします。選択したマイクロサービス名前空間にレーン グループが既に作成されている場合は、[+ レーン グループを作成] をクリックします。

  5. Create Lane Group パネルでパラメーターを設定し、[OK] をクリックします。

    パラメーター

    レーン グループ名

    mse-springboot-demo など、レーン グループのカスタム名を入力します。

    Ingress タイプ

    [Java マイクロサービス ゲートウェイ] を選択します。

    Lane Group Traffic Entry

    spring-cloud-gateway を選択します。

    Lane Group Application

    spring-cloud-a、spring-boot-b、spring-cloud-d を選択します。

    image

  6. 選択したマイクロサービス名前空間にレーンが作成されていない場合は、Full link grayscale ページの下部にある [最初の分割レーンを作成] をクリックします。選択したマイクロサービス名前空間にレーンが既に作成されている場合は、[レーンを作成] をクリックします。

  7. [レーンを作成] パネルでパラメーターを設定し、[OK] をクリックします。

    パラメーター

    説明

    ノード タグを追加

    カナリア アプリケーション ノードとベース アプリケーション ノードを区別するために、カナリア アプリケーション ノードのタグを追加します。

    レーン情報を入力

    レーン名: 分かりやすいレーン名を入力します。

    レーン タグ: このレーンで一致するトラフィックのタグ名を入力します。この例では、このパラメーターは gray に設定されています。

    一致関係の確認: 指定されたタグを持つアプリケーション ノードの数が想定どおりであることを確認します。

    レーンの状態: スイッチをオンにします。

    カナリアリリース ルールを追加

    レーン内のアプリケーション ノードへのリクエストをルーティングするためのルールを指定します。

    • カナリアリリース モード: [コンテンツによるカナリアリリース] を選択します。

    • カナリアリリース条件: [すべての条件を満たす] を選択します。

      この例の構成の詳細:

      • パラメーター タイプ: Header を選択します。

      • パラメーター: x-springboot-demo を入力します。

      • 条件: == を選択します。

      • Value: 1 を入力します。

    image

ステップ 3: 結果の検証

  1. ACK コンソール にログインします。

  2. 左側のナビゲーションウィンドウで、[クラスター] をクリックします。次に、管理するクラスターの名前をクリックします。

  3. [クラスター情報] ページの左側のナビゲーションウィンドウで、[ネットワーク] > [サービス] を選択します。[サービス] ページで、spring-cloud-gateway-slb外部 IP アドレスをコピーし、次の検証操作を実行します。

    ベース環境での結果の検証

    ルート /A/A/a に基づいて Spring Cloud ゲートウェイにリクエストを送信し、すべてのトラフィックがベースノードにルーティングされていることを確認します。これは、エンドツーエンドカナリアリリース構成が有効であることを示します。

    # テストコマンド
    curl http://xxx.xx.131.81/A/A/a
    
    # テスト結果
    A:192.168.0.17:base -(java)- B:192.168.100.231:base - D:192.168.0.19:base
    カナリア環境での結果の検証

    ルート /A/A/a に基づいて Spring Cloud ゲートウェイにリクエストを送信し、Headerx-springboot-demo=1 を追加します。すべてのトラフィックがカナリアノードにルーティングされていることを確認します。これは、エンドツーエンドカナリアリリース構成が有効であることを示します。

    # テストコマンド
    curl -H "x-springboot-demo:1" http://xxx.xx.131.81/A/A/a
    
    # テスト結果
    A:192.168.100.234:gray -(java)- B:192.168.0.21:gray - D:192.168.0.14:gray

    タブ 2 本文