基于MSE和ASM实现多语言全链路灰度

随着Go、Rust、Php等语言逐渐普及、生态日趋丰富,许多服务架构不再由单一语言开发构成,而是由多语言混合构建,例如JavaGo、JavaPhp等。本文将介绍如何使用MSEASM产品(Java应用使用MSE Java 探针,其他语言应用使用ASM Proxy),在无需修改任何业务代码的情况下,实现多语言场景下的全链路灰度。

前提条件

使用限制

重要

由于多语言全链路灰度能力目前正在公测,仅以下地区开放支持:北京、上海、杭州、深圳、张家口、硅谷、新加坡,其他地区暂不支持。

  • 流量入口目前只支持云原生网关云原生API网关,暂不支持Java网关和ASM网关。

  • Java应用调用其他语言只支持HTTP方式调用,具体支持的HTTP框架及版本限制,请参见微服务治理支持的框架

  • 由于该能力目前正在公测,Java探针需要指定特殊版本为4.2.5-proxyless。指定探针版本具体操作请参见指定MSE探针版本

配置概览

请确保按照前提条件完成容器集群、MSE以及ASM的前置准备之后,按照以下方式操作。

步骤一:应用接入Trace能力

由于流量标签在Java探针中基于Trace能力透传,保证了流量标签能够在Java应用间的调用透传。为了确保流量标签也能够顺利在非Java语言应用中传递,需要您的非Java应用也具备Trace能力。

  • 对于非Java应用,推荐通过OpenTelemetry/阿里云ARMS自动插桩进行无感接入。

  • 对于Java应用,由于MSEArms共用同一个Java探针,如果您希望使用MSE全链路灰度能力的同时具有可观测能力需求,可以直接复用MSE Java探针接入ARMS即可。

说明

若您的系统在此之前已经完成了可观测能力接入并且具备了Trace能力,可以直接忽略并跳过此步骤。

步骤二:应用接入服务治理

Java应用接入

在确保已经安装ack-onepilot并且开启高阶服务治理的前提下,参见ACKACS命名空间中的应用开启MSE微服务治理将应用接入到MSE服务治理。

对于应用级别的接入,可参考的Label字段(Yaml格式)如下所示。

spec:
  template:
    metadata:
      labels:
        # 填写“on”表示开启接入,需加上双引号
        msePilotAutoEnable: "on"
        # 填写接入到的治理命名空间,值不存在可自动新建
        mseNamespace: "your-mse-namespace"
        # 填写接入MSE的实际应用名称,需加上双引号
        msePilotCreateAppName: "your-deployment-name"
        # 指定特殊公测Java Agent版本
        aliyun.com/agent-version: "4.2.5-proxyless"
        # 节点标签,不添加则默认为基线节点
        alicloud.service.tag: gray

如果您应用所在的容器集群本地域名不是cluster.local,还需要为应用配置以下环境变量。

env:
  # 应用所在集群的本地域名
  - name: KUBERNETES_CLUSTER_DOMAIN
    value: "your-cluster-domain"
Java应用接入

在确保已经创建ASM实例并将Kubernetes集群添加到ASM实例的前提下,添加下述MSE Label的同时,为应用挂载ASM Proxy,具体的配置方式详见配置Sidecar注入策略

对于应用级别的接入,可参考的Label字段(Yaml格式)如下所示。

说明

添加MSELabel声明接入MSE,只是便于ack-onepilot处理节点标签,实际上不会挂载探针。

spec:
  template:
    metadata:
      labels:
        # 填写“on”表示开启接入,需加上双引号
        msePilotAutoEnable: "on"
        # 填写接入到的治理命名空间,值不存在可自动新建
        mseNamespace: "your-mse-namespace"
        # 填写接入MSE的实际应用名称,需加上双引号
        msePilotCreateAppName: "your-deployment-name"
        # 声明挂载ASM Proxy
        sidecar.istio.io/inject: 'true'
        # 节点标签,不添加则默认为基线节点
        alicloud.service.tag: gray

步骤三:MSE配置全链路灰度

详情可参见配置泳道组泳道

步骤四:ASM配置全链路灰度

ASM控制台为应用配置流量规则,对于泳道组内存在k8s service的应用,分别为其配置一份流量标签目标规则虚拟服务

  1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

  2. 网格管理页面,单击目标网格实例名称。

    流量标签配置

    在左侧导航栏选择流量管理中心 > 流量标签,参考如下模板为泳道组内k8s service配置流量标签规则。关于TraffciLabel的介绍和说明请详见流量标签TrafficLabel说明

    单应用级别
    apiVersion: istio.alibabacloud.com/v1
    kind: TrafficLabel
    metadata:
      name: "your-resource-name" # 资源名称,确保名称不重复
      namespace: "service-namespace" # k8s service所在的namespace
    spec:
      rules:
        - labels:
            - name: asm-label
              valueFrom:
                - '$getExternalInboundRequestHeader(x-mse-tag, Eagleeye-Traceid)' # 左侧固定, 右侧为traceid对应的header名称
      workloadSelector:
        labels:
          app: "your-service-name"
    集群命名空间级别
    apiVersion: istio.alibabacloud.com/v1
    kind: TrafficLabel
    metadata:
      name: "your-resource-name" # 资源名称,确保名称不重复
      namespace: "service-namespace" # k8s service所在的namespace
    spec:
      rules:
        - labels:
            - name: asm-label
              valueFrom:
                - '$getExternalInboundRequestHeader(x-mse-tag, Eagleeye-Traceid)' # 左侧固定, 右侧为traceid对应的header名称
    目标规则配置

    在左侧导航栏选择流量管理中心 > 目标规则,参考如下模板为泳道组内k8s service配置目标规则。关于DestinationRule的介绍和说明请详见目标规则(Destination Rule)CRD说明

    apiVersion: networking.istio.io/v1
    kind: DestinationRule
    metadata:
      name: "your-resource-name" # 资源名称,确保名称不重复
      namespace: istio-system
    spec:
      host: gin-c.default.svc.cluster.local # k8s serviceFQDN
      subsets:
        - labels: #此项必填
            opensergo.io/canary: ''
          name: base
        - labels: #和MSE泳道标签配置保持一致
            opensergo.io/canary-gray: gray
          name: gray
        - labels: #和MSE泳道标签配置保持一致
            opensergo.io/canary-traffictag: traffictag 
          name: traffictag
    虚拟服务配置

    在左侧导航栏选择流量管理中心 > 虚拟服务,参考如下模板为泳道组内k8s service配置虚拟服务规则。关于VirtualService的介绍和说明请详见虚拟服务(Virtual Service)CRD说明

    apiVersion: networking.istio.io/v1
    kind: VirtualService
    metadata:
      name: "your-resource-name" # 资源名称,确保名称不重复
      namespace: istio-system
    spec:
      hosts:
        - gin-c.default.svc.cluster.local #k8s serviceFQDN
      http:
        - name: default
          route:
            - destination:
                host: gin-c.default.svc.cluster.local #k8s serviceFQDN
                subset: $asm-label
              fallback:
                target:
                  host: gin-c.default.svc.cluster.local #k8s serviceFQDN
                  subset: base

Demo演示示例

Demo概述

本文以容器服务控制台部署应用为例进行说明,模拟一个真实的调用链路。Demo应用的结构图如下所示。应用之间的调用既包含了Java —> Java的调用,也包含了Java —> Golang、Golang —> Java的调用。各个应用的详细说明如下:

  • Gateway:云原生API网关作为流量入口。通过路由/A/a发起A —> C —> D的调用,通过路由/A/d发起A —> D的调用。

  • A:Java语言应用,基于Spring Cloud框架开发,应用节点会注册到Nacos进行服务发现;基于K8s Service发现方式调用C、基于Nacos发现方式调用D。

  • C:Golang语言应用,基于Gin框架开发,为C应用创建K8s Service;基于K8s Service发现方式调用D;通过接入ARMS Golang探针实现Trace能力。

  • D:Java语言应用,基于Spring Cloud框架开发,应用节点会注册到Nacos进行服务发现,为D应用创建K8s Service。

image

操作步骤

将上述Demo部署到容器集群的default命名空间中,同时为A、D挂载MSE Java 探针,为C挂载ASM网格代理,并且基于Arms Golang探针为C接入Trace能力。然后通过操作MSEASM控制台,为Demo配置全链路灰度能力,并验证最终效果。

在开始以下步骤之前,请确保前提条件已开通ARMS服务都已经满足。

步骤一:配置ASM网格代理自动注入

在确保已经将Kubernetes集群添加到ASM实例的前提下,为default命名空间开启Sidecar网格代理自动注入。

  1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

  2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择网格实例 > 全局命名空间

  3. 全局命名空间页面,单击Kubernetes集群同步自动注入,选择待部署应用的Kubernetes集群,单击确定

  4. 全局命名空间页面的自动注入列,单击default命名空间对应的启用 Sidecar 网格代理自动注入,然后在确认对话框,单击确定

步骤二:部署应用

  1. 登录容器服务控制台

  2. 在左侧导航栏,单击集群列表,然后单击目标集群名称。

  3. 在左侧导航栏,选择工作负载 > 无状态

  4. 在页面上方,选择集群的命名空间,然后单击右上角的使用YAML创建资源

  5. 使用如下YAML部署应用。

    展开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-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-heterogeneous-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-heterogeneous-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: gin-c
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: gin-c
      strategy:
        rollingUpdate:
          maxSurge: 100%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
          labels:
            msePilotAutoEnable: "on"
            msePilotCreateAppName: "gin-c"
            mseNamespace: "mse-heterogeneous-demo"
            armsPilotAutoEnable: "on"
            armsPilotCreateAppName: "gin-c"
            aliyun.com/app-language: golang
            app: "gin-c"
            sidecar.istio.io/inject: 'true'
        spec:
          containers:
            - name: gin-c
              image: "registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/gin-c: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: 20003
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: gin-c-gray
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: gin-c
      strategy:
        rollingUpdate:
          maxSurge: 100%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
          labels:
            msePilotAutoEnable: "on"
            msePilotCreateAppName: "gin-c"
            mseNamespace: "mse-heterogeneous-demo"
            armsPilotAutoEnable: "on"
            armsPilotCreateAppName: "gin-c"
            aliyun.com/app-language: golang
            alicloud.service.tag: gray
            app: "gin-c"
            sidecar.istio.io/inject: 'true'
        spec:
          containers:
            - name: gin-c
              image: "registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/gin-c: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: 20003
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: gin-c
    spec:
      ports:
        - port: 20003
          protocol: TCP
          targetPort: 20003
      selector:
        app: gin-c
      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-heterogeneous-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-heterogeneous-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

完成上述步骤后,会在容器集群中部署应用A、C、D的基线版本和灰度版本,同时A、D会挂载MSE Java探针、C会挂载Arms Golang探针和ASM Sidecar。

步骤三:添加云原生网关作为流量入口

  1. 创建MSE云原生网关

  2. 创建网关服务来源于容器服务ACK

  3. 创建服务并选择default命名空间中的spring-cloud-a服务。

  4. 创建路由,配置参数如下图所示,路由的服务名称spring-cloud-a

    image

  5. 在云原生网关的路由页签,单击目标路由操作列下的调试向路由/A/a?call_type=golang发起调用,返回下图结果说明路由配置成功。

    image

步骤四:MSE配置全链路灰度

由于没有配置全链路灰度,可以观察到通过网关路由发起调用时,流量会随机路由到基线和gray节点,需要分别在MSEASM进行必要的配置,才能实现流量的灰度路由。

  1. 登录MSE治理中心控制台,并在顶部菜单栏选择地域。

  2. 在左侧导航栏,选择治理中心 > 全链路灰度

  3. 全链路灰度页面的微服务命名空间处选择mse-heterogeneous-demo

  4. 如果您选择的微服务命名空间内没有创建过泳道组,则单击创建泳道组及泳道。如果您选择的微服务命名空间内已经创建过泳道组,则单击+创建泳道组

  5. 创建泳道组面板,设置如下相关配置,然后单击确定

    配置项

    示例

    泳道组名称

    自定义泳道组的名称,例如mse-asm-demo。

    入口类型

    选择MSE 云原生网关

    入口网关

    选择创建的MSE云原生网关

    泳道组涉及应用

    选择spring-cloud-a、gin-cspring-cloud-d。

    image

  6. 全链路灰度页面底部,如果您选择的微服务命名空间内没有创建过泳道,则单击点击创建第一个分流泳道。如果您选择的微服务命名空间内已经创建过泳道,则单击+创建泳道

  7. 创建泳道面板,设置流控泳道相关配置,然后单击确定

    配置项

    说明

    配置节点标签

    需要您给灰度应用节点打上标签,以便与正常节点做区分。

    填写泳道信息

    泳道名称:输入便于理解和识别的泳道名称。

    泳道标签:该泳道内的匹配的流量去往的目标标签,本示例为gray。

    确认匹配关系:检查您配置了该标签的应用节点数是否符合预期。

    泳道状态:选择开启。

    配置灰度规则

    设置流量进入该泳道的规则。

    • 灰度模式:选择按内容灰度

    • 灰度条件:选择以下条件同时满足

      本示例灰度条件配置如下:

      • 参数类型Header

      • 参数x-mse-asm-demo

      • 条件==

      • 1

    image

  8. 在云原生网关的路由页签,单击目标路由操作列下的调试通过网关向路由/A/a?call_type=golang发起调用,可以观察到网关 —> 应用、Java应用 —> Go应用的普通流量均路由到基线节点,说明MSEJava 探针侧的全链路灰度配置已经生效。

步骤五:ASM配置全链路灰度

完成上述步骤后,我们发现在进行路由调试时,Go应用 —> Java应用的路由依然是随机的,需要在ASM控制台对ASM Sidecar配置规则,使得流量按照灰度规则路由。

  1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

  2. 网格管理页面,单击目标网格实例名称。

    流量标签配置

    在左侧导航栏,选择流量管理中心 > 流量标签。单击使用YAML创建命名空间选择default,场景模板选择Namespace 级别配置,使用如下YAML部署资源。

    apiVersion: istio.alibabacloud.com/v1
    kind: TrafficLabel
    metadata:
      name: trafficlabel-mse-asm-demo
      namespace: default
    spec:
      rules:
        - labels:
            - name: asm-label
              valueFrom:
                - '$getExternalInboundRequestHeader(x-mse-tag, Eagleeye-Traceid)'
    目标规则配置

    在左侧导航栏,选择流量管理中心 > 目标规则,然后单击使用YAML创建,在命名空间选择istio-system,分别使用如下YAML部署资源。

    spring-cloud-a
    apiVersion: networking.istio.io/v1
    kind: DestinationRule
    metadata:
      name: destinationrule-mse-asm-demo-spring-cloud-a
      namespace: istio-system
    spec:
      host: spring-cloud-a.default.svc.cluster.local
      subsets:
        - labels:
            opensergo.io/canary: ''
          name: base
        - labels:
            opensergo.io/canary-gray: gray
          name: gray
    gin-c
    apiVersion: networking.istio.io/v1
    kind: DestinationRule
    metadata:
      name: destinationrule-mse-asm-demo-gin-c
      namespace: istio-system
    spec:
      host: gin-c.default.svc.cluster.local
      subsets:
        - labels:
            opensergo.io/canary: ''
          name: base
        - labels:
            opensergo.io/canary-gray: gray
          name: gray
    spring-cloud-d
    apiVersion: networking.istio.io/v1
    kind: DestinationRule
    metadata:
      name: destinationrule-mse-asm-demo-spring-cloud-d
      namespace: istio-system
    spec:
      host: spring-cloud-d.default.svc.cluster.local
      subsets:
        - labels:
            opensergo.io/canary: ''
          name: base
        - labels:
            opensergo.io/canary-gray: gray
          name: gray
    虚拟服务配置

    在左侧导航栏,选择流量管理中心 > 虚拟服务,然后单击使用YAML创建。命名空间选择istio-system,分别使用如下YAML部署资源。

    spring-cloud-a
    apiVersion: networking.istio.io/v1
    kind: VirtualService
    metadata:
      name: virtualservice-mse-asm-demo-spring-cloud-a
      namespace: istio-system
    spec:
      hosts:
        - spring-cloud-a.default.svc.cluster.local
      http:
        - name: default
          route:
            - destination:
                host: spring-cloud-a.default.svc.cluster.local
                subset: $asm-label
              fallback:
                target:
                  host: spring-cloud-a.default.svc.cluster.local
                  subset: base
    gin-c
    apiVersion: networking.istio.io/v1
    kind: VirtualService
    metadata:
      name: virtualservice-mse-asm-demo-gin-c
      namespace: istio-system
    spec:
      hosts:
        - gin-c.default.svc.cluster.local
      http:
        - name: default
          route:
            - destination:
                host: gin-c.default.svc.cluster.local
                subset: $asm-label
              fallback:
                target:
                  host: gin-c.default.svc.cluster.local
                  subset: base
    spring-cloud-d
    apiVersion: networking.istio.io/v1
    kind: VirtualService
    metadata:
      name: virtualservice-mse-asm-demo-spring-cloud-d
      namespace: istio-system
    spec:
      hosts:
        - spring-cloud-d.default.svc.cluster.local
      http:
        - name: default
          route:
            - destination:
                host: spring-cloud-d.default.svc.cluster.local
                subset: $asm-label
              fallback:
                target:
                  host: spring-cloud-d.default.svc.cluster.local
                  subset: base
  3. 在云原生网关的路由页签调试路由,单击目标路由操作列下的调试通过网关向路由/A/a?call_type=golang发起调用,可以观察除了网关 —> 应用、Java应用 —> Go应用,Go应用 —> Java应用的普通流量也均路由到基线节点,说明ASM侧的全链路灰度配置已经生效。

    image

步骤六:结果验证

  1. 登录MSE网关管理控制台,并在顶部菜单栏选择地域。

  2. 在左侧导航栏,选择云原生网关 > 网关列表,单击目标网关名称。

  3. 在左侧导航栏,单击路由管理,然后选择路由页签。

  4. 单击目标路由mse-asm-demo操作列下的调试,分别进行如下验证。

    灰度验证

    通过网关向路由/A/a?call_type=golang/A/d发起调用,并且在Header中添加x-mse-asm-demo=1,观察到所有流量都路由到灰度节点,说明全链路灰度配置生效。

    image

    image

    灰度回滚验证
    1. 登录MSE治理中心控制台,并在顶部菜单栏选择地域。

    2. 在左侧导航栏,选择治理中心 > 全链路灰度

    3. 在对应泳道的操作列下单击关闭

    4. 通过网关向路由/A/a?call_type=golang/A/d发起调用,并且在Header中添加x-mse-asm-demo=1,观察到所有流量都路由到基线节点,说明全链路灰度配置已经关闭成功,流量默认路由到基线节点。

      image

      image

    Tab 2 正文