通过阿里云Nginx Ingress提供的全链路灰度能力,可以在不需要修改任何您的业务代码的情况下,实现全链路流量控制。本文介绍通过阿里云Nginx Ingress实现全链路灰度功能。
前提条件
已创建Kubernetes集群。具体操作,请参见创建Kubernetes托管版集群。
使用限制
由于全链路灰度功能整合了标签路由功能,因此不推荐已经加入全链路流量控制的应用同时配置金丝雀发布和标签路由规则功能呢。
使用本功能时,阿里云Nginx Ingress不支持同时使用nginx.ingress.kubernetes.io/configuration-snippet
。
限制项 | 限制值 | 备注 |
Spring Cloud版本 | Spring Cloud Edgware及以上版本。 | 无。 |
Dubbo版本 | 2.5.3~2.7.8 | Dubbo 3.0及以上版本当前处于灰度中,如有场景需求,请加入钉群(钉群号:34754806)联系技术支持。 |
客户端类型 |
| 无。 |
Java应用JDK版本 | 目前支持JDK 1.6、1.7、1.8版本应用接入。 | JDK 1.11版本当前处于灰度中,如有场景需求,请加入钉群(钉群号:34754806)联系技术支持。 |
负载均衡类型 |
| 无。 |
Spring Cloud Gateway版本 | 支持Spring Cloud Gateway 2.1.0.RELEASE及以上版本。 | 无。 |
Spring Cloud Zuul版本 | 1.3.x。 | 无。 |
注册中心类型 |
| 微服务治理能力无关注册中心,可以是MSE托管注册中心,也可以是自建注册中心。 |
背景信息
在微服务场景中,当您部署的Spring Cloud应用或Dubbo应用存在升级版本时,由于应用间的调用是随机的,会导致无法将具有一定特征的流量路由到应用的目标版本。全链路流量控制功能将应用的相关版本隔离成一个独立的运行环境(即泳道),通过设置Ingress路由规则,将满足规则的请求流量路由到应用的目标版本。
本文以电商架构中的下单场景为例,介绍从Ingress网关到微服务的全链路流控功能。假设应用的架构由Nginx Ingress网关以及后端的微服务架构(Spring Cloud)组成,后端调用链路有3个:购物车(A)、交易中心(B)和库存中心(C),可以通过客户端或者是HTML来访问后端服务,这些服务之间通过Nacos注册中心实现服务发现。
客户下单后流量从Ingress网关进来,调用交易中心,交易中心再调用商品中心,商品中心调用下游的库存中心。
交易中心和商品中心各有两个新版本(1和2)在运行,需要对这两个新版本进行灰度验证。此时通过Nginx Ingress网关将满足特定流控规则的请求流量路由到新版本,其余流量全部路由到线上(正式)版本。
名词解释
泳道
为相同版本应用定义的一套隔离环境。只有满足了流控路由规则的请求流量才会路由到对应泳道里的打标应用。一个应用可以属于多个泳道,一个泳道可以包含多个应用,应用和泳道是多对多的关系。
泳道组
泳道的集合。泳道组的作用主要是为了区分不同团队或不同场景。
准备工作
安装Ingress-nginx组件
- 访问ack-ingress-nginx-v1组件的安装详情页,在页面右上方单击一键部署,在基本信息页面,选择目标集群和命名空间,然后单击下一步。说明 命名空间推荐使用kube-system。
- 在参数配置页面,确认组件参数信息,然后单击确定。安装完成后,在命名空间kube-system中出现ack-ingress-nginx-v1-default应用,表示安装成功。
在目标集群下,选择 ,在页面顶部,选择命名空间为kube-system。
在目标配置项nginx-configuration的操作列,单击编辑。在编辑页面底部,单击+ 添加,添加如下两个配置项的名称和值。
配置项名称设置为use-mse,配置项值设置为true。
配置项名称设置为mse-app-name,配置项值设置为您希望接入的MSE应用名称。
说明这种Ingress接入方式会实际上会走AHAS产品计费,每个节点收费标准可以参考计费概述。
开启MSE微服务治理
开通微服务治理专业版。
安装MSE微服务治理组件。
- 登录容器服务控制台。
- 在左侧导航栏,选择 ,在搜索框中输入ack-onepilot,单击该组件。
- 在ack-onepilot页面右上方,单击一键部署,在创建页面,选择集群和命名空间,设置组件发布名称,单击下一步,然后单击确定。说明 建议使用默认的命名空间ack-onepilot。安装完成后,在命名空间ack-onepilot中出现ack-onepilot应用,表示安装成功。
为应用开启微服务治理。
- 登录MSE治理中心控制台。
- 在左侧导航栏,选择 。在目标集群操作列,单击管理。
- 在集群详情页面,在目标命名空间操作列,单击开启微服务治理。然后单击确定。
部署Demo应用程序
- 登录容器服务管理控制台。
- 在左侧导航栏,选择集群,然后单击目标集群名称。
- 在左侧导航栏,选择 。
在无状态页面,选择命名空间,然后单击使用YAML创建资源。
对模板进行相关配置,完成配置后单击创建。
本文示例中部署A、B、C三个应用,每个应用分别部署一个基线版本和一个灰度版本;并部署一个Nacos server应用,用于实现服务发现。
A应用
基线(base)版本YAML:
apiVersion: apps/v1 kind: Deployment metadata: name: spring-cloud-a spec: replicas: 2 selector: matchLabels: app: spring-cloud-a template: metadata: labels: msePilotCreateAppName: spring-cloud-a app: spring-cloud-a spec: containers: - env: - name: JAVA_HOME value: /usr/lib/jvm/java-1.8-openjdk/jre image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-a:0.1-SNAPSHOT imagePullPolicy: Always name: spring-cloud-a ports: - containerPort: 20001 livenessProbe: tcpSocket: port: 20001 initialDelaySeconds: 10 periodSeconds: 30
灰度(gray)版本YAML:
apiVersion: apps/v1 kind: Deployment metadata: name: spring-cloud-a-new spec: replicas: 2 selector: matchLabels: app: spring-cloud-a-new strategy: template: metadata: labels: alicloud.service.tag: gray msePilotCreateAppName: spring-cloud-a app: spring-cloud-a-new spec: containers: - env: - name: JAVA_HOME value: /usr/lib/jvm/java-1.8-openjdk/jre image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-a:0.1-SNAPSHOT imagePullPolicy: Always name: spring-cloud-a-new ports: - containerPort: 20001 livenessProbe: tcpSocket: port: 20001 initialDelaySeconds: 10 periodSeconds: 30
B应用
基线(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: msePilotCreateAppName: spring-cloud-b app: spring-cloud-b spec: containers: - env: - name: JAVA_HOME value: /usr/lib/jvm/java-1.8-openjdk/jre image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-b:0.1-SNAPSHOT imagePullPolicy: Always name: spring-cloud-b ports: - containerPort: 8080 livenessProbe: tcpSocket: port: 20002 initialDelaySeconds: 10 periodSeconds: 30
C应用
基线(base)版本YAML:
apiVersion: apps/v1 kind: Deployment metadata: name: spring-cloud-c spec: replicas: 2 selector: matchLabels: app: spring-cloud-c template: metadata: labels: msePilotCreateAppName: spring-cloud-c app: spring-cloud-c spec: containers: - env: - name: JAVA_HOME value: /usr/lib/jvm/java-1.8-openjdk/jre image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-c:0.1-SNAPSHOT imagePullPolicy: Always name: spring-cloud-c ports: - containerPort: 8080 livenessProbe: tcpSocket: port: 20003 initialDelaySeconds: 10 periodSeconds: 30
灰度(gray)版本YAML:
apiVersion: apps/v1 kind: Deployment metadata: name: spring-cloud-c-new spec: replicas: 2 selector: matchLabels: app: spring-cloud-c-new template: metadata: labels: alicloud.service.tag: gray msePilotCreateAppName: spring-cloud-c app: spring-cloud-c-new spec: containers: - env: - name: JAVA_HOME value: /usr/lib/jvm/java-1.8-openjdk/jre image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-c:0.1-SNAPSHOT imagePullPolicy: IfNotPresent name: spring-cloud-c-new ports: - containerPort: 8080 livenessProbe: tcpSocket: port: 20003 initialDelaySeconds: 10 periodSeconds: 30
Nacos 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: - env: - name: MODE value: standalone image: nacos/nacos-server:v2.2.0 imagePullPolicy: Always name: nacos-server dnsPolicy: ClusterFirst restartPolicy: Always # Nacos Server Service 配置 --- apiVersion: v1 kind: Service metadata: name: nacos-server spec: 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 type: ClusterIP
针对入口应用A,配置K8s Service。
在集群详情页面左侧导航栏,选择 。
在服务页面选择命名空间,然后单击使用YAML创建资源。
对模板进行相关配置,完成配置后单击创建。
apiVersion: v1 kind: Service metadata: name: spring-cloud-a spec: ports: - name: http port: 20001 protocol: TCP targetPort: 20001 selector: app: spring-cloud-a
步骤一:创建泳道组
登录MSE治理中心控制台,并在顶部菜单栏选择地域。
在左侧导航栏,选择 。
在全链路灰度页面,单击创建泳道组及泳道。如果您选择的微服务空间内已经创建过泳道组,则单击+创建泳道组。
在创建泳道组对话框,设置泳道组相关参数,然后单击确定。
配置项
描述
泳道组名称
自定义设置泳道组的名称。
入口类型
选择阿里云Ingress网关。
入口应用
选择您的入口应用或入口网关所涉及的所有相关服务。
开启消息灰度
开启状态,表示打开泳道组所有应用的消息灰度开关。
关闭状态,表示关闭泳道组所有应用的消息灰度开关。
开启数据库灰度
开启状态,表示打开泳道组所有应用的数据库灰度开关。
关闭状态,表示关闭泳道组所有应用的数据库灰度开关。
泳道组创建完成后,在全链路灰度页面的泳道组涉及应用区域出现您所创建的泳道组。请检查入口应用和所涉及的应用是否正确,如需变更泳道组信息,请单击右侧的图标并修改相关信息。
步骤二:创建泳道
在全链路灰度页面顶部,选择和创建泳道组时相同的地域,然后底部单击点击创建第一个分流泳道。
如果您选择的微服务空间内已经创建过泳道,则单击创建泳道。
说明加入全链路流量控制的应用,不推荐同时使用金丝雀发布和标签路由等功能。
在创建泳道对话框,设置流控泳道相关参数,然后单击确定。
配置项
描述
泳道名称
自定义设置流控泳道的名称。
配置应用标签
配置方式:在容器服务控制台去应用YAML的
spec.template.metadata.labels
下增加alicloud.service.tag:{tag}
。添加应用
当STPE 2配置应用标签完成后,单击刷新按钮,下拉框中会出现相应的标签列表,选择对应的标签,就会自动添加相应的应用。
路由规则
设置相应的路由规则条件。
Path:选择需要匹配的路径,可以多选,也可以不填写。如果不填写,会匹配任意路径。
条件模式:路由条件之间的关系。
条件列表:单击下方的+ 添加新的规则条件,新增规则条件。
在全链路灰度页面的流量分配区域,查看泳道信息。
单击图标,查看该泳道的流量比例。
单击图标,可在泳道列表的操作列,设置该泳道应用的状态。
开启泳道:单击开启,创建的泳道将会生效,即流量会按照泳道方式进行流转,满足规则的流量会优先流向标记有当前泳道对应标签的应用版本,如果没有对应标签的应用版本则流向未打标的应用版本。
关闭泳道:单击关闭,关闭创建的泳道,即该应用往后的流量会流向未打标的应用版本。
修改泳道:单击编辑,修改当前泳道的配置信息。
删除泳道:单击删除,删除目标泳道。
配置流量入口的Ingress规则,访问
www.base.com
路由到A应用的base版本。apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: spring-cloud-a-base spec: rules: - host: www.base.com http: paths: - backend: serviceName: spring-cloud-a-base servicePort: 20001 path: /
步骤三:配置基线环境的Ingress规则
使用curl命令访问example.com
路由到基线环境。
curl -H"Host:www.example.com" http://106.14.XX.XX/a
返回结果如下。
A[172.18.XX.XX] -> B[172.18.XX.XX] -> C[172.18.XX.XX]%
步骤四:配置灰度环境的Ingress规则
使用curl命令访问example.com
路由到灰度环境。
curl -H"Host:www.gray.com" http://106.14.XX.XX/a
返回结果如下。灰度流量优先访问了A和C的灰度版本,由于B没有灰度版本,所以访问了B的基线版本。
Agray[172.18.XX.XX] -> B[172.18.XX.XX] -> Cgray[172.18.XX.XX]%