在微服务架构中,当需求开发涉及到多个微服务的改动时,每个微服务通常会有灰度环境或分组来接受灰度流量。如果希望上游应用灰度环境中的流量也能进入到下游应用的灰度环境中,请确保一个请求始终在灰度环境中传递。即使调用链路上存在一些没有灰度环境的微服务应用,它们在请求下游应用时,也能够回到下游应用的灰度环境中。借助阿里云ALB负载均衡的灵活路由功能和MSE的全链路灰度能力,您可以轻松实现全链路灰度,而无需修改业务代码。
全链路灰度实现流程
注意事项
如果您使用的是Flannel网络插件,则ALB Ingress后端Service服务仅支持NodePort和LoadBalancer类型。
ALB的交换机所在的VPC需要与ACK集群的VPC一致。关于ALB支持的地域,请参见支持的地域与可用区。
场景示例:按照域名路由,实现全链路灰度
若应用的架构由ALB负载均衡以及后端的微服务架构(Spring Cloud)组成,后端调用链路有3个:交易中心(A)、商品中心(B)和库存中心(C),可以通过客户端或者是HTML来访问后端服务,这些服务之间通过Nacos注册中心实现服务发现。
您可以通过不同的域名来区分线上基线环境和灰度环境,灰度环境可单独配置域名,例如,通过访问www.example.com
请求灰度环境,通过访问www.aliyundoc.com
请求基线环境。
如图所示,调用链路为Ingress-ALB > A > B > C,其中A可以是一个Spring Boot的应用。
准备工作
创建Kubernetes集群
通过Kubectl工具连接ACK集群
通过Kubectl工具连接ACK集群。具体操作,请参见获取集群KubeConfig并通过kubectl工具连接集群。
安装ALB Ingress Controller组件
为ACK集群安装ALB Ingress Controller组件。以下两种方式选择一种即可。
在ACK创建集群时,通过在组件配置向导页面的Ingress字段右侧,选择ALB Ingress,为集群安装ALB Ingress Controller组件。
若已创建ACK集群,在组件管理页面,可安装ALB Ingress Controller组件。具体操作,请参见管理组件。
开启MSE微服务治理
在MSE微服务治理开通页面,开通微服务治理专业版。
关于微服务治理的计费详情,请参见计费概述。
将ACK微服务应用接入MSE治理中心,您可以选择您需要的方式实现应用接入。更多信息,请参见ACK微服务应用接入MSE治理中心。
为ACK命名空间中的应用开启MSE微服务治理
登录MSE治理中心控制台,并在顶部菜单栏选择地域。
在左侧导航栏,选择治理中心 > 应用治理。
在应用列表页面,单击ACK应用接入。
在ACK应用接入对话框中,进行配置,配置完成后,单击确定。
配置项
说明
集群类型
选择ACK集群或者ACK Serverless集群。
说明如果您尚未授权容器服务调用微服务引擎,则需要单击请授权进行授权。
集群名称/ID
选择接入MSE微服务治理的集群名称/ID,可通过关键词搜索。
ack-onepilot
显示ack-onepilot接入状态。
如果您未安装ack-onepilot,单击ack-onepilot右侧的点击安装,安装完成后状态会显示为已安装。
如果您使用子账号接入,提示没有权限使用时,您可以登录容器服务管理控制台进入目标集群,然后单击运维管理>组件管理,然后找到ack-onepilot,点击安装。
说明该步骤接入的组件为ack-onepilot,您可以登录容器服务管理控制台进入目标集群,然后单击运维管理>组件管理查看详情。
ack-onepilot安装后会自动注入探针,可能会导致应用启动耗时增加(10s内)。
接入类型
选择命名空间接入。
容器集群命名空间
选择容器集群命名空间。
治理命名空间
选择治理命名空间。在对应命名空间下重新部署现有应用或新创建的应用,均会接入到MSE微服务治理中。关于命名空间的相关信息,请参见微服务命名空间管理。
为单个应用开启MSE微服务治理
登录MSE治理中心控制台,并在顶部菜单栏选择地域。
在左侧导航栏,选择治理中心 > 应用治理。
在应用列表页面,单击ACK应用接入。
在ACK应用接入对话框中,进行配置,配置完成后,单击确定。
配置项
说明
集群类型
选择ACK集群或者ACK Serverless集群。
说明如果您尚未授权容器服务调用微服务引擎,则需要单击请授权进行授权。
集群名称/ID
选择接入MSE微服务治理的集群名称/ID,可通过关键词搜索。
ack-onepilot
显示ack-onepilot接入状态。
如果您未安装ack-onepilot,单击ack-onepilot右侧的点击安装,安装完成后状态会显示为已安装。
如果您使用子账号接入,提示没有权限使用时,您可以登录容器服务管理控制台进入目标集群,然后单击运维管理>组件管理,然后找到ack-onepilot,点击安装。
说明该步骤接入的组件为ack-onepilot,您可以登录容器服务管理控制台进入目标集群,然后单击运维管理>组件管理查看详情。
ack-onepilot安装后会自动注入探针,可能会导致应用启动耗时增加(10s内)。
接入类型
选择单个应用接入。
接入步骤
按照接入步骤进行操作。
Step 1:进入集群工作负载-无状态应用页面,切换到应用的命名空间下。
Step 2:找到所接入的应用,点击「查看Yaml」。
Step 3:按以下格式编辑Labels,完成后点击「更新」。
spec: template: metadata: labels: # 填写“on”表示开启接入,需加上双引号 msePilotAutoEnable: "on" # 填写接入到的治理命名空间,值不存在可自动新建 mseNamespace: 202401 # 填写接入MSE的实际应用名称,需加上双引号 msePilotCreateAppName: "your-deployment-name"
部署Demo应用程序
登录容器服务管理控制台,在左侧导航栏选择集群。
在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择 。
在无状态页面,选择命名空间,然后单击使用YAML创建资源,对模板进行相关配置,完成配置后单击创建。
本文示例中部署A、B、C三个应用,每个应用分别部署一个基线版本和一个灰度版本,并部署一个Nacos Server应用,用于实现服务发现。
# A应用base版本 --- 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-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 # A应用gray版本 --- 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 - name: profiler.micro.service.tag.trace.enable value: "true" image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-a:3.0.1 imagePullPolicy: Always name: spring-cloud-a-new ports: - containerPort: 20001 livenessProbe: tcpSocket: port: 20001 initialDelaySeconds: 10 periodSeconds: 30 # B应用base版本 --- 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-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 # B应用gray版本 --- apiVersion: apps/v1 kind: Deployment metadata: name: spring-cloud-b-new spec: replicas: 2 selector: matchLabels: app: spring-cloud-b-new template: metadata: labels: alicloud.service.tag: gray msePilotCreateAppName: spring-cloud-b app: spring-cloud-b-new 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-new ports: - containerPort: 8080 livenessProbe: tcpSocket: port: 20002 initialDelaySeconds: 10 periodSeconds: 30 # C应用base版本 --- 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-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 # C应用gray版本 --- 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-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-c:3.0.1 imagePullPolicy: IfNotPresent name: spring-cloud-c-new ports: - containerPort: 8080 livenessProbe: tcpSocket: port: 20003 initialDelaySeconds: 10 periodSeconds: 30 # Nacos Server --- 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配置两个K8s Service,spring-cloud-a-base对应A的base版本,spring-cloud-a-gray对应A的gray版本。
apiVersion: v1
kind: Service
metadata:
name: spring-cloud-a-base
spec:
ports:
- name: http
nodePort: 32605
port: 20001
protocol: TCP
targetPort: 20001
selector:
app: spring-cloud-a
sessionAffinity: None
type: NodePort
---
apiVersion: v1
kind: Service
metadata:
name: spring-cloud-a-gray
spec:
ports:
- name: http
nodePort: 31622
port: 20001
protocol: TCP
targetPort: 20001
selector:
app: spring-cloud-a-new
sessionAffinity: None
type: NodePort
步骤一:配置ALB路由
创建ALB Config。具体操作,请参见创建AlbConfig。
重要ALB交换机所在的VPC需与集群所在的VPC一致,否则会影响业务使用。
配置Ingress。
拷贝以下内容到gray-ingress.yaml文件中。
1.19版本以下集群。
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: demo namespace: default spec: ingressClassName: alb rules: - host: www.aliyundoc.com http: paths: - path: /a backend: serviceName: spring-clud-a-base servicePort: 20001 - host: www.example.com http: paths: - backend: serviceName: spring-cloud-a-gray servicePort: 20001 path: /a pathType: ImplementationSpecific
1.19及以上版本集群。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: cafe-ingress spec: ingressClassName: alb rules: - host: www.aliyundoc.com http: paths: # 配置Context Path - path: /a pathType: ImplementationSpecific backend: service: name: spring-clud-a-base port: number: 20001 - host: www.example.com http: paths: # 配置Context Path - path: /a pathType: ImplementationSpecific backend: service: name: spring-clud-a-base-gray port: number: 20001
执行如下命令。
kubectl apply -f gray-ingress.yaml
若没有出现对应的ADDRESS(端点),可前往以下页面查看事件,并对照本文的前提条件排查错误。
步骤二:配置MSE全链路灰度
登录MSE治理中心控制台,并在顶部菜单栏选择地域。
在左侧导航栏,选择治理中心 > 全链路灰度。
- 单击创建泳道组及泳道。如果您选择的微服务空间内已经创建过泳道组,则单击+创建泳道组。
在创建泳道组面板,配置泳道组相关参数,然后单击确定。
添加spring-cloud-a、spring-cloud-b和spring-cloud-c应用到泳道组。
在全链路灰度页面底部,单击点击创建第一个分流泳道。在创建泳道面板,设置流控泳道相关参数,选择标签gray,然后单击确定。
步骤三:验证结果
访问
www.aliyundoc.com
路由到基线环境。# 测试命令 curl -H"Host:aliyundoc.base.com" http://alb-828vagckg5omzfy49n.cn-beijing.alb.aliyuncs.com/a # 测试结果 A[172.18.XX.XX] -> B[172.18.XX.XX] -> C[172.18.XX.XX]%
访问
www.example.com
路由到灰度环境。# 测试命令 curl -H"Host:www.example.com" http://alb-828vagckg5omzfy49n.cn-beijing.alb.aliyuncs.com/a # 测试结果 Agray[172.18.XX.XX] -> Bgray[172.18.XX.XX] -> Cgray[172.18.XX.XX]%
其中alb-828vagckg5omzfy49n.cn-beijing.alb.aliyuncs.com
为ALB的地址。