随着Go、Rust、Php等语言逐渐普及、生态日趋丰富,许多服务架构不再由单一语言开发构成,而是由多语言混合构建,例如Java和Go、Java和Php等。本文将介绍如何使用MSE和ASM产品(Java应用使用MSE Java 探针,其他语言应用使用ASM Proxy),在无需修改任何业务代码的情况下,实现多语言场景下的全链路灰度。
前提条件
创建Kubernetes集群。具体操作,请参见创建ACK托管集群和创建ACK Serverless集群。
安装MSE微服务治理组件ack-onepilot(建议版本在3.3.x及以上)。
说明如果您的ack-onepilot版本在4.x及以上,由于存在延迟,请开启高阶服务治理等待约10分钟后或重启ack-onepilot后再部署应用,关于延迟问题我们正在优化中。
为Kubernetes集群启用高阶治理能力。
使用限制
由于多语言全链路灰度能力目前正在公测,仅以下地区开放支持:北京、上海、杭州、深圳、张家口、硅谷、新加坡,其他地区暂不支持。
流量入口目前只支持云原生网关和云原生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应用,由于MSE和Arms共用同一个Java探针,如果您希望使用MSE全链路灰度能力的同时具有可观测能力需求,可以直接复用MSE Java探针接入ARMS即可。
若您的系统在此之前已经完成了可观测能力接入并且具备了Trace能力,可以直接忽略并跳过此步骤。
步骤二:应用接入服务治理
Java应用接入
在确保已经安装ack-onepilot并且开启高阶服务治理的前提下,参见为ACK和ACS命名空间中的应用开启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格式)如下所示。
添加MSE的Label声明接入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的应用,分别为其配置一份流量标签、目标规则、虚拟服务。
登录ASM控制台,在左侧导航栏,选择 。
在网格管理页面,单击目标网格实例名称。
流量标签配置
在左侧导航栏选择流量管理中心 > 流量标签,参考如下模板为泳道组内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 service的FQDN 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 service的FQDN http: - name: default route: - destination: host: gin-c.default.svc.cluster.local #k8s service的FQDN subset: $asm-label fallback: target: host: gin-c.default.svc.cluster.local #k8s service的FQDN 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。
操作步骤
将上述Demo部署到容器集群的default命名空间中,同时为A、D挂载MSE Java 探针,为C挂载ASM网格代理,并且基于Arms Golang探针为C接入Trace能力。然后通过操作MSE和ASM控制台,为Demo配置全链路灰度能力,并验证最终效果。
在开始以下步骤之前,请确保前提条件和已开通ARMS服务都已经满足。
步骤一:配置ASM网格代理自动注入
在确保已经将Kubernetes集群添加到ASM实例的前提下,为default命名空间开启Sidecar网格代理自动注入。
登录ASM控制台,在左侧导航栏,选择 。
在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择 。
在全局命名空间页面,单击从Kubernetes集群同步自动注入,选择待部署应用的Kubernetes集群,单击确定。
在全局命名空间页面的自动注入列,单击default命名空间对应的启用 Sidecar 网格代理自动注入,然后在确认对话框,单击确定。
步骤二:部署应用
登录容器服务控制台。
在左侧导航栏,单击集群列表,然后单击目标集群名称。
在左侧导航栏,选择 。
在页面上方,选择集群的命名空间,然后单击右上角的使用YAML创建资源。
使用如下YAML部署应用。
完成上述步骤后,会在容器集群中部署应用A、C、D的基线版本和灰度版本,同时A、D会挂载MSE Java探针、C会挂载Arms Golang探针和ASM Sidecar。
步骤三:添加云原生网关作为流量入口
步骤四:MSE配置全链路灰度
由于没有配置全链路灰度,可以观察到通过网关路由发起调用时,流量会随机路由到基线和gray节点,需要分别在MSE和ASM进行必要的配置,才能实现流量的灰度路由。
登录MSE治理中心控制台,并在顶部菜单栏选择地域。
在左侧导航栏,选择 。
在全链路灰度页面的微服务命名空间处选择
mse-heterogeneous-demo
。如果您选择的微服务命名空间内没有创建过泳道组,则单击创建泳道组及泳道。如果您选择的微服务命名空间内已经创建过泳道组,则单击+创建泳道组。
在创建泳道组面板,设置如下相关配置,然后单击确定。
配置项
示例
泳道组名称
自定义泳道组的名称,例如mse-asm-demo。
入口类型
选择MSE 云原生网关。
入口网关
选择创建的MSE云原生网关。
泳道组涉及应用
选择spring-cloud-a、gin-c和spring-cloud-d。
在全链路灰度页面底部,如果您选择的微服务命名空间内没有创建过泳道,则单击点击创建第一个分流泳道。如果您选择的微服务命名空间内已经创建过泳道,则单击+创建泳道。
在创建泳道面板,设置流控泳道相关配置,然后单击确定。
配置项
说明
配置节点标签
需要您给灰度应用节点打上标签,以便与正常节点做区分。
填写泳道信息
泳道名称:输入便于理解和识别的泳道名称。
泳道标签:该泳道内的匹配的流量去往的目标标签,本示例为gray。
确认匹配关系:检查您配置了该标签的应用节点数是否符合预期。
泳道状态:选择开启。
配置灰度规则
设置流量进入该泳道的规则。
灰度模式:选择按内容灰度。
灰度条件:选择以下条件同时满足。
本示例灰度条件配置如下:
参数类型:
Header
。参数:
x-mse-asm-demo
。条件:
==
。值:
1
。
在云原生网关的路由页签,单击目标路由操作列下的调试,通过网关向路由
/A/a?call_type=golang
发起调用,可以观察到网关 —> 应用、Java应用 —> Go应用的普通流量均路由到基线节点,说明MSE与Java 探针侧的全链路灰度配置已经生效。
步骤五:ASM配置全链路灰度
完成上述步骤后,我们发现在进行路由调试时,Go应用 —> Java应用的路由依然是随机的,需要在ASM控制台对ASM Sidecar配置规则,使得流量按照灰度规则路由。
登录ASM控制台,在左侧导航栏,选择 。
在网格管理页面,单击目标网格实例名称。
流量标签配置
在左侧导航栏,选择流量管理中心 > 流量标签。单击使用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
在云原生网关的路由页签调试路由,单击目标路由操作列下的调试,通过网关向路由
/A/a?call_type=golang
发起调用,可以观察除了网关 —> 应用、Java应用 —> Go应用,Go应用 —> Java应用的普通流量也均路由到基线节点,说明ASM侧的全链路灰度配置已经生效。
步骤六:结果验证
登录MSE网关管理控制台,并在顶部菜单栏选择地域。
在左侧导航栏,选择云原生网关 > 网关列表,单击目标网关名称。
在左侧导航栏,单击路由管理,然后选择路由页签。
单击目标路由
mse-asm-demo
操作列下的调试,分别进行如下验证。灰度验证
通过网关向路由
/A/a?call_type=golang
和/A/d
发起调用,并且在Header
中添加x-mse-asm-demo=1
,观察到所有流量都路由到灰度节点,说明全链路灰度配置生效。灰度回滚验证
登录MSE治理中心控制台,并在顶部菜单栏选择地域。
在左侧导航栏,选择 。
在对应泳道的操作列下单击关闭。
通过网关向路由
/A/a?call_type=golang
和/A/d
发起调用,并且在Header
中添加x-mse-asm-demo=1
,观察到所有流量都路由到基线节点,说明全链路灰度配置已经关闭成功,流量默认路由到基线节点。
Tab 2 正文