在进行应用的自动化构建和部署时,通常希望能够快速将部署后的应用发布到灰度环境,并且能够方便地对灰度环境的应用进行全链路测试,将运维效率提升到极致。本文介绍如何通过云效整合MSE全链路灰度来实现。
前提条件
应用使用云效进行构建和部署。
整体架构
整体上应用的调用链路是,客户端入口流量首先达到网关应用,而后按顺序经过A、B、C三个应用:
在一次上线窗口中,A和C进行了迭代,进行了灰度发布。在测试流程中,需要对A和C的灰度版本进行全链路灰度的测试,调用链路如下:
通过云效,在流水线上增加一个灰度流程。每个应用走到线上环境部署阶段前,都会先发布到灰度环境。等到开发/测试人员对灰度环境的应用测试没有问题时,再手工放行流水线走到真正的线上发布部署阶段:
准备工作
本文将以A、B、C三个SpringCloud应用为例,介绍如何通过阿里云云效整合MSE全链路灰度的功能,实现将应用一键部署到灰度环境,并进行全链路灰度的测试。假设已有A、B、C三个应用的基线版本正在运行。
步骤一:开启MSE微服务治理
将ACK微服务应用接入MSE治理中心。具体操作,请参见ACK微服务应用接入MSE治理中心。
步骤二:准备基线版本(若已有则可忽略)
您可以按如下步骤,部署基线环境:
创建MSE Nacos,并复制其内网域名。具体操作,请参见创建Nacos引擎。
创建MSE云原生网关,并关联第一步创建的Nacos。具体操作,请参见创建MSE云原生网关和新建服务来源。
登录容器服务管理控制台,在左侧导航栏选择集群。
在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择 。
在无状态页面,单击使用YAML创建资源。模板内容使用如下YAML示例部署A、B、C三个应用,然后单击创建。
说明代码中的{nacos server address}需要替换成您的Nacos内网域名,同时需要去掉大括号{}。
# 应用 A 的基线版本 apiVersion: apps/v1 kind: Deployment metadata: name: spring-cloud-a namespace: default spec: selector: matchLabels: app: spring-cloud-a template: metadata: labels: app: spring-cloud-a msePilotCreateAppName: spring-cloud-a msePilotAutoEnable: 'on' spec: containers: - name: spring-cloud-a image: "registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-a:3.0.1" imagePullPolicy: Always ports: - containerPort: 20001 livenessProbe: tcpSocket: port: 20001 initialDelaySeconds: 30 periodSeconds: 60 env: - name: spring.cloud.nacos.discovery.server-addr value: {nacos server address} - name: dubbo.registry.address value: 'nacos://{nacos server address}:8848' --- # 应用 B 的基线版本 apiVersion: apps/v1 kind: Deployment metadata: name: spring-cloud-b namespace: default spec: selector: matchLabels: app: spring-cloud-b template: metadata: labels: app: spring-cloud-b msePilotCreateAppName: spring-cloud-b msePilotAutoEnable: 'on' spec: containers: - name: spring-cloud-b image: "registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-b:3.0.1" imagePullPolicy: Always ports: - containerPort: 20002 livenessProbe: tcpSocket: port: 20002 initialDelaySeconds: 30 periodSeconds: 60 env: - name: spring.cloud.nacos.discovery.server-addr value: {nacos server address} - name: dubbo.registry.address value: 'nacos://{nacos server address}:8848' --- # 应用 C 的基线版本 apiVersion: apps/v1 kind: Deployment metadata: name: spring-cloud-c namespace: default spec: selector: matchLabels: app: spring-cloud-c template: metadata: labels: app: spring-cloud-c msePilotCreateAppName: spring-cloud-c msePilotAutoEnable: 'on' spec: containers: - name: spring-cloud-c image: "registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/spring-cloud-c:3.0.1" imagePullPolicy: Always ports: - containerPort: 20003 livenessProbe: tcpSocket: port: 20003 initialDelaySeconds: 30 periodSeconds: 60 env: - name: spring.cloud.nacos.discovery.server-addr value: {nacos server address} - name: dubbo.registry.address value: 'nacos://{nacos server address}:8848'
登录MSE治理中心控制台。选择 治理中心 > 应用治理,在顶部选择您的命名空间。单击进入目标应用,在 QPS 数据中可以看到流量的情况,确认流量都打到未打标的节点,并没有灰度节点的流量。
步骤三:创建MSE全链路灰度泳道
登录MSE治理中心控制台,并在顶部菜单栏选择地域。
在左侧导航栏,选择治理中心 > 全链路灰度。
在全链路灰度页面,单击+ 创建泳道组及泳道。
如果您已经创建过泳道组,则单击+ 创建泳道组。
在创建泳道组面板,设置如下相关配置,然后单击确定。
配置项
说明
泳道组名称
自定义泳道组的名称。
入口类型
选择MSE 云原生网关。
泳道组流量入口
选择目标云原生网关。
泳道组涉及应用
选择spring-cloud-a、spring-cloud-b和spring-cloud-c。
泳道组创建完成后,在全链路灰度页面的泳道组区域,可以查看您创建的泳道组。如需变更泳道组信息,单击图标,可在页面修改相关信息。
在全链路灰度页面底部,单击点击创建第一个分流泳道。
如果您已经创建过泳道,则单击创建泳道。
在创建泳道对话框中设置相关配置,然后单击确定。
在云效上整合MSE全链路灰度
您可以根据以下两种方式集成MSE全链路灰度。
方式一:通过Flow方式构建CI/CD流水线
在本例中,使用其他 > 空模板创建云效流水线,创建后,需要进行四部分配置:
步骤一:配置云效流水线源
配置流水线的代码源。配置完成后,添加到流水线中。
代码仓库:https://gitee.com/mse-group/alibabacloud-microservice-demo.git。
为了避免网络延迟,所以采用gitee仓库。
默认分支:master。
选择凭证类型:选择服务连接。
由于本示例中代码仓库为公开代码仓库,所以只需要按照默认值创建即可。
步骤二:构建阶段配置
此阶段配置云效如何构建Docker镜像。删除原有的阶段和空任务,手动添加新任务。
配置项 | 说明 |
构建集群 | 就近选择。本示例选择北京构建集群。 |
服务连接 | 按照提示添加ACR的服务连接。通过RAM授权的方式,让云效可以推送镜像到ACR中。 |
仓库 | 选择您需要推送、部署的镜像仓库。 |
标签 | 默认 |
Dockerfile路径 | 输入Dockerfile路径。本示例为 |
步骤三:部署Gray阶段配置
本步骤介绍如何部署Gray节点。云效可以直接替换Kubernetes中的Workload镜像,可以直接使用此机制来发布。
配置项 | 说明 |
集群连接 | 授权云效修改ACK集群中Workload配置。按照授权添加对应ACK集群连接。 |
Kubectl版本 | 选择相近版本。 |
命名空间 | 输入命名空间。 |
Workloads类型 | 选择Workloads类型。本示例为Deployment。 |
Workloads名称 | 输入Workloads名称。本示例为 |
容器名称 | 输入容器名称。本示例为spring-cloud-a-gray。 |
镜像 | 选择上一步构建的镜像。可以选择镜像公网地址。 |
步骤四:部署线上阶段配置
类似步骤三的配置:
Workloads名称:此处为基线环境的Workloads,值为spring-cloud-a。
容器名称:spring-cloud-a。
最后,将部署Gray阶段和部署线上阶段的发模式改为手动触发。
完整配置好后的效果如下图所示:
步骤五:运行流水线
配置好流水线后,您可以按照发布流程逐步运行流水线:
打包构建。手动运行刚刚的创建好的流水线,观察构建状态。
运行成功效果如下:
您也可以查看日志来确定运行状态、排查问题等:
部署Gray并验证。单击部署Gray阶段的手动触发按钮,开始部署。
方式二:通过AppStack方式构建CI/CD流水
步骤一:在云效上创建应用并做好灰度配置
登录云效控制台,设置创建应用。进入应用首页,单击右上角新建应用(若已有则可忽略)。
单击新创建的应用。进入应用概览,选择部署编排 > 前往配置 > 选择 Kubernetes 部署 > 从模板开始 > 空模板,然后单击确定(若已有则可忽略)。
在Kubernetes部署中,创建应用发布流程(以A应用为例)。单击添加组件 > 输入名称(如spirng-cloud-a-deploy)> 空模板(若已有则可忽略)。
输入应用的YAML配置。
一些关键的地方使用占位符取代。您可以参考以下代码部署A的Deployment(其中{{}}需要定义相应的变量,AppStack开头的表示云效预置占位符,Values开头的表示自定义占位符,可以在上方点击提取占位符后,在右边编辑占位符的值。值可以定义成常量,也可以从变量组中引用):
apiVersion: apps/v1 kind: Deployment metadata: name: {{ .AppStack.appName }}-{{ .AppStack.envName }} labels: run: {{ .AppStack.appName }}-{{ .AppStack.envName }} namespace: {{ .Values.namespace }} spec: selector: matchLabels: app: {{ .AppStack.appName }}-{{ .AppStack.envName }} template: metadata: labels: app: {{ .AppStack.appName }}-{{ .AppStack.envName }} spec: containers: - name: {{ .AppStack.appName }} image: {{ .AppStack.image.backend }} imagePullPolicy: Always ports: - containerPort: 20001 livenessProbe: tcpSocket: port: 20001 initialDelaySeconds: 30 periodSeconds: 60 env: - name: spring.cloud.nacos.discovery.server-addr value: 'nacos-server' - name: dubbo.registry.address value: 'nacos://nacos-server:8848'
在应用配置的
spec.template.metadata.labels
下加入MSE基本配置及灰度相关。msePilotCreateAppName: {{ .AppStack.appName }} msePilotAutoEnable: 'on' {{if eq .Values.mseGrayTag "gray" }} alicloud.service.tag: gray {{end}}
说明msePilotCreateAppName
为MSE服务治理接入的应用名;msePilotAutoEnable
为是否接入MSE服务治理的开关on
表示开启,off
表示关闭;alicloud.service.tag
则是MSE用于灰度发布的节点标签。您可以在MSE服务治理控制台,节点详情页面看到节点的标签情况。更多信息,请参见ACK微服务应用接入MSE服务治理和节点详情。其中
{{if eq .Values.mseGrayTag "gray" }}
是基于GO template的方式识别当前云效发布的应用。环境变量中如果有mseGrayTag=gray
的变量,则认定该应用属于灰度应用。更多信息,请参见Kubernetes 部署编排。
在页面右上方,单击提取占位符。您可按需设置配置中的占位符。
namespace设置成常量;值填写default;mseGrayTag设置成变量,值使用mseGrayTag。
单击保存。
保存时需要勾选可用的环境,建议全选。
说明如果您使用本文中的示例A、B、C应用,则您都需要创建对应的应用,并做好相应的配置。
步骤二:在云效中加入灰度环境和灰度变量组
登录云效控制台,进入需要做灰度发布的应用(比如A和C,都需要做如下操作)。
在控制台左侧选择变量组,然后单击新建变量组,创建一个灰度环境变量组。保存后单击编辑变量,输入
mseGrayTag=gray
,然后保存并提交。在控制台左侧选择环境,然后单击新建灰度环境。输入灰度环境的信息,在关联变量组一栏,单击添加关联,选中上一步创建的灰度环境变量组。
当应用通过云效发布到灰度环境时,会自动加入mseGrayTag=gray
,并在我们的应用YAML中添加alicloud.service.tag: gray标签,这样就完成了灰度环境发布的应用,能够携带灰度标签alicloud.service.tag: gray。
如果您使用本文中的示例A、B、C应用,建议您除灰度环境和灰度变量组外,再创建其他环境和对应的变量组,以方便您的测试。但是需要明确的是,其他环境的变量组不应该添加变量mseGrayTag=gray
。
步骤三:使用云效AppStack研发流程进行应用灰度发布
如果您的云效菜单中没有研发流程和变更按钮,您可以在创建应用后按以下步骤开启变更流程的功能:
开启后,您可以按照以下子步骤创建灰度环境发布流程并进行应用发布。
子步骤 1:新增灰度研发流程和变更信息
如果您尚未配置任何研发流程,请单击研发流程 > 前往配置,输入研发流程名称,选择Java k8s 应用标准研发流程模板,完成后进入第二步。如果您已存在一些研发配置,单击研发流程 > 研发流程设置 > 新建研发流程,输入研发流程名称,选择Java k8s 应用标准研发流程模板,单击创建。
说明如果您使用本文中的示例A、B、C应用,您还需要在应用概览页面代码源设置中配置代码源。A、B、C应用源码可以从github上获取。更多内容,请参见mse-simple-demo。
在上一步配置的研发流程中,选择生产阶段 > 编辑流水线。在合适的节点处(一般为生产环境部署之前),单击加号图标或者添加任务按钮添加灰度任务。
在当前流程下方的变更集成方式中,选择运行固定分支,选择master分支(可按需设置)。
流水线配置完毕后,保存当前的流水线。
子步骤2:进行灰度发布
单击研发流程,选择上一步创建的灰度发布流程,然后单击运行。
当流程执行完毕后,查看您的集群是否已经启动了灰度应用。
应用名称为步骤一:在云效上创建应用并做好灰度配置中配置的名称,格式为:应用名-环境名。
子步骤3:发布生产环境
灰度验证通过后,即可继续发布生产环境。点击手动触发生产环境发布,查看生产发布批次,观测新老版本号,部署完成后观测生产监控日志。
子步骤4:销毁灰度环境
生产发布成功后,销毁灰度环境资源,所有流量都进入生产环境。
至此即完成了应用基线环境的准备、灰度流程配置、灰度发布验证、生产发布、灰度销毁完整流程。
其他参考
针对AppStack方式灰度发布,支持扩缩容和应用回滚。更多信息,请参见2.3 回滚。如果是Flow方式,则需要登录容器服务管理控制台进行相关操作。
验证全链路灰度是否生效
如果您启动的是您自己的灰度应用,则您可以考虑按照您的方式去做验证。如果您使用本文中示例的A、B、C应用程序,您可以按照一定的访问条件(比如携带特定的灰度header或query参数)直接访问MSE云原生网关,查看结果是否包含gray字样,包含则表明全链路灰度生效。如本文示例中配置的全链路灰度路由规则:请求参数中携带group=gray的去往灰度泳道。
发起符合条件的请求,则结果如下(A和C进行了灰度发布,B没有进行灰度发布,所以请求去往了B的基线环境)所示:
> curl -X GET http://47.96.XX.XXX/A/a?group=gray
Agray[192.168.110.161][config=base] -> B[192.168.110.14] -> Cgray[192.168.110.160]
如果请求条件不符合条件,则去往A、B、C的基线环境:
> curl -X GET http://47.96.XX.XXX/A/a?group=xxx
A[192.168.110.162][config=base] -> B[192.168.110.57] -> C[192.168.110.62]
您还可以在MSE控制台上看到刚刚发起的灰度请求:
相关文档
通过云效AppStack和MSE微服务引擎实现灰度发布的具体内容,请参见MSE+云效AppStack实现应用服务全链路灰度。