通过MSE Ingress网关提供的全链路灰度能力,您可以在不需要修改任何业务代码的情况下,实现全链路流量控制。本文介绍如何通过MSE Ingress网关实现全链路灰度功能。
使用限制
由于全链路灰度功能整合了标签路由功能,因此不推荐已经加入全链路流量控制的应用配置金丝雀发布和标签路由规则。
全链路灰度能力支持的Java版本及框架详见微服务治理支持的Java框架。
背景信息
在微服务场景中,当您部署的Spring Cloud应用或Dubbo应用存在升级版本时,由于应用之间的调用是随机的,会导致无法将具有一定特征的流量路由到应用的目标版本。全链路流量控制功能将应用的相关版本隔离成一个独立的运行环境(即泳道),通过设置Ingress路由规则,将满足规则的请求流量路由到目标版本应用。
全链路灰度场景
本文以电商架构中的下单场景为例,介绍从MSE Ingress网关到微服务的全链路流控功能。假设应用的架构由MSE Ingress网关以及后端的微服务架构(Spring Cloud)组成,后端调用链路有3个:交易中心(A)、商品中心(B)和库存中心(C),可以通过客户端或者是HTML来访问后端服务,这些服务之间通过Nacos注册中心实现服务发现。
客户下单后流量从MSE Ingress网关进入,先调用交易中心(A),然后交易中心(A)再调用商品中心(B),最后商品中心(B)再调用下游的库存中心(C)。调用链路从左到右依次为:客户->MSE Ingress->A->B->C。
随着业务不断迭代,功能也不断更新。在新版本正式上线之前,需要同时对应用A和应用C进行灰度验证,确认无误后方可正式上线。新功能上线过程中,涉及到应用A和应用C同时发布新版本。通过MSE Ingress网关和MSE微服务治理提供的全链路灰度能力,您可以端到端的构建从网关到多个后端服务的全链路灰度,控制具有一定特征的灰度流量始终路由到应用对应的灰度环境,满足您同时灰度验证多个服务的诉求。此外,在应用无目标灰度版本时,自动容灾到正式环境中。
名词解释
泳道
为相同版本应用定义的一套隔离环境。只有满足了流控路由规则的请求流量才会路由到对应泳道里的打标应用。一个应用可以属于多个泳道,一个泳道可以包含多个应用,应用和泳道是多对多的关系。
泳道组
泳道的集合。泳道组的作用主要是为了区分不同团队或不同场景。
MSE Ingress网关
MSE Ingress网关是在MSE云原生网关基础上提供的Ingress流量管理方式,兼容Nginx Ingress以及超50种Nginx Ingress注解,支持多服务版本同时灰度发布。同时,灵活的服务治理能力以及全方位的安全防护保障,可以满足大规模云原生分布式应用的流量治理诉求。
准备工作
开启MSE微服务治理
开通微服务治理专业版。
为应用开启微服务治理。
- 登录MSE治理中心控制台。
- 在左侧导航栏,选择。在目标集群操作列,单击管理。
- 在集群详情页面,在目标命名空间操作列,单击开启微服务治理。然后单击确定。
部署Demo应用程序
登录容器服务管理控制台。
在控制台左侧导航栏,单击集群。
在集群列表页面,单击目标集群名称或者目标集群右侧操作列下的详情。
在集群管理页左侧导航栏,选择。
在无状态页面,选择命名空间,然后单击使用YAML创建资源。
对模板进行相关配置,完成配置后单击创建。
本文示例中部署一个Nacos Server应用,用于实现服务发现,部署A、B、C三个应用。其中A和C应用分别部署一个基线版本和一个灰度版本,B应用部署一个基线版本。
部署Nacos Server应用。
展开查看YAML文件
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
# Nacos Server Service配置
---
apiVersion: v1
kind: Service
metadata:
name: nacos-server
spec:
ports:
- port: 8848
protocol: TCP
targetPort: 8848
selector:
app: nacos-server
type: ClusterIP
部署A应用
基线(base)版本的YAML如下。
展开查看基线(base)版本的YAML文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-a
spec:
replicas: 2
selector:
matchLabels:
app: spring-cloud-a
template:
metadata:
labels:
app: spring-cloud-a
msePilotAutoEnable: 'on'
msePilotCreateAppName: 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-governance-demo/spring-cloud-a:3.0.1
imagePullPolicy: Always
name: spring-cloud-a
ports:
- containerPort: 20001
livenessProbe:
tcpSocket:
port: 20001
initialDelaySeconds: 10
periodSeconds: 30
灰度(gray)版本的YAML如下。
展开查看灰度(gray)版本的YAML文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-a-gray
spec:
replicas: 2
selector:
matchLabels:
app: spring-cloud-a-gray
strategy:
template:
metadata:
labels:
app: spring-cloud-a-gray
msePilotAutoEnable: 'on'
alicloud.service.tag: gray
msePilotCreateAppName: 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-governance-demo/spring-cloud-a:3.0.1
imagePullPolicy: Always
name: spring-cloud-a-gray
ports:
- containerPort: 20001
livenessProbe:
tcpSocket:
port: 20001
initialDelaySeconds: 10
periodSeconds: 30
部署B应用
基线(base)版本的YAML如下。
展开查看基线(base)版本的YAML文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-b
spec:
replicas: 2
selector:
matchLabels:
app: spring-cloud-b
strategy:
template:
metadata:
labels:
app: spring-cloud-b
msePilotAutoEnable: 'on'
msePilotCreateAppName: 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-governance-demo/spring-cloud-b:3.0.1
imagePullPolicy: Always
name: spring-cloud-b
ports:
- containerPort: 8080
livenessProbe:
tcpSocket:
port: 20002
initialDelaySeconds: 10
periodSeconds: 30
部署C应用
基线(base)版本的YAML如下。
展开查看基线(base)版本的YAML文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-c
spec:
replicas: 2
selector:
matchLabels:
app: spring-cloud-c
template:
metadata:
labels:
app: spring-cloud-c
msePilotAutoEnable: 'on'
msePilotCreateAppName: 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-governance-demo/spring-cloud-c:3.0.1
imagePullPolicy: Always
name: spring-cloud-c
ports:
- containerPort: 8080
livenessProbe:
tcpSocket:
port: 20003
initialDelaySeconds: 10
periodSeconds: 30
灰度(gray)版本的YAML如下。
展开查看灰度(gray)版本的YAML文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-c-gray
spec:
replicas: 2
selector:
matchLabels:
app: spring-cloud-c-gray
template:
metadata:
labels:
app: spring-cloud-c-gray
msePilotAutoEnable: 'on'
alicloud.service.tag: gray
msePilotCreateAppName: 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-governance-demo/spring-cloud-c:3.0.1
imagePullPolicy: IfNotPresent
name: spring-cloud-c-gray
ports:
- containerPort: 8080
livenessProbe:
tcpSocket:
port: 20003
initialDelaySeconds: 10
periodSeconds: 30
针对入口应用A,配置两个K8s Service。
- 登录容器服务控制台。
在集群管理页左侧导航栏,选择。
在服务页面,选择命名空间,然后单击使用YAML创建资源,对模板进行相关配置,完成配置后单击创建。
步骤一:创建泳道组
登录MSE治理中心控制台,并在顶部菜单栏选择地域。
在左侧导航栏,选择治理中心 > 全链路灰度。
在全链路灰度页面,单击创建泳道组及泳道。如果您选择的微服务空间内已经创建过泳道组,则单击+创建泳道组。
在创建泳道组面板,设置泳道组相关参数,然后单击确定。
配置项 | 说明 |
泳道组名称 | 自定义设置泳道组的名称。 |
入口类型 | 选择Ingress/自建网关。 |
泳道组涉及应用 | 选择您的入口应用或入口网关所涉及的所有相关服务。 |
泳道组创建完成后,请检查入口应用和所涉及的应用是否正确。您可以在全链路灰度页面的泳道组及涉及的应用区域,查看您已创建的泳道组。如需变更泳道组信息,请单击右侧的图标并修改相关信息。
步骤二:创建泳道
在全链路灰度页面顶部,选择和泳道组相同的地域,然后在页面底部单击点击创建第一个分流泳道。
如果您选择的微服务空间内已经创建过泳道,则单击创建泳道。
重要 加入全链路流量控制的应用,不推荐使用金丝雀发布和标签路由功能。
在创建泳道面板,设置流控泳道相关参数,然后单击确定。
重要 如果您的网关应用是Ingress网关,需要在容器服务管理控制台配置Ingress路由规则。
配置项 | 说明 |
配置节点标签 | |
泳道名称 | 自定义设置流控泳道的名称。 |
泳道标签 | 完成配置节点标签后,下拉框中会出现相应的标签列表,选择对应的标签,则会自动添加相应的应用。 |
完成泳道创建后,在全链路灰度的流量分配区域,可以查看或配置泳道信息。
步骤三:配置基线环境的Ingress规则
如果业务域名为example.com
,访问example.com
的请求流量只通过基线环境(线上环境),可以通过如下代码配置基线环境的Ingress规则。
展开查看YAML文件
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: spring-cloud-a
namespace: default
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: spring-cloud-a-base
port:
number: 20001
path: /
pathType: Prefix
使用curl命令访问example.com
路由到基线环境。
curl -H "host: example.com" http://47.98.xxx.xx/a
返回结果如下:
A[192.168.0.98][config=base] -> B[192.168.0.157] -> C[192.168.0.161]
步骤四:配置灰度环境的Ingress规则
如果基于Header策略来区分线上正式流量和灰度流量,希望带有HTTP Header为x-user-id: 100
的请求流量访问example.com
路由到灰度环境中,流量会优先访问链路中各个应用对应的灰度版本,若无灰度版本,则会容灾到基线版本。通过如下代码配置灰度环境的Ingress规则。
展开查看YAML文件
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: 'true'
nginx.ingress.kubernetes.io/canary-by-header: x-user-id
nginx.ingress.kubernetes.io/canary-by-header-value: '100'
mse.ingress.kubernetes.io/request-header-control-update: x-mse-tag gray
name: spring-cloud-a-gray
namespace: default
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: spring-cloud-a-gray
port:
number: 20001
path: /
pathType: Prefix
上述代码使用注解实现路由灰度发布、Header配置以及Header控制能力。关于注解的更多用法,请参见MSE Ingress高级用法。
使用curl命令访问example.com
路由到灰度环境,其中带有HTTP Header为x-user-id: 100
的请求流量。
curl -H "host: example.com" -H "x-user-id: 100" http://47.98.xxx.xx/a
返回结果如下。灰度流量优先访问了A和C的灰度版本,由于B没有灰度版本,所以访问了B的基线版本。
Agray[192.168.0.128][config=base] -> B[192.168.0.152] -> Cgray[192.168.0.151]
控制台查看应用的流量监控图
查看单个应用的监控图
在全链路灰度页面,单击目标泳道组页签。
在泳道组及涉及的应用区域,单击目标应用名称,在右侧会出现对应的QPS数据
查看泳道组内所有应用的监控图。
在全链路灰度页面,单击目标泳道组页签。
在应用 QPS 监控右侧,单击查看流量详情,可以查看该泳道所有应用的流量监控图。