⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 阿里巴巴中间件 「卜比」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

本文介绍通过 Jenkins 构建流水线的方式实现全链路灰度功能。

在发布过程中,为了整体稳定性,我们总是希望能够用小部分特定流量来验证下新发布应用是否正常。

即使新版本有问题,也能及时发现,控制影响面,保障了整体的稳定性。

01 整体架构

Aliware

我们以如下 Demo 为例:

为了保证稳定,我们约定如下上线流程:

其中,在灰度验证中,有几种不同的策略:

  • 直接使用线上小部分流量来测试(按照百分比放量)
  • 从线上按照特定规则选择流量(比如特定的 header、特定的 cookie 等)
  • 在客户端或浏览器上标识出流量是否灰度(比如通过 header 传递)

02 部署应用&创建泳道

Aliware

按照参考文档部署应用后,我们首先要区分线上流量和灰度流量。

创建泳道组,将整个链路涉及到的应用全选:

然后创建泳道组,将符合规则的应用划入 gray 泳道:

注:没有匹配的流量,会走到基线环境,也就是没有打标的应用节点上。

配置完成后,访问网关,如果不符合灰度规则,走基线环境:

如何符合灰度规则,走灰度环境:

03 Jenkins 流水线

Aliware

本文实践需要将源码打包后执行镜像推送,请确保 Jenkins 有权限推送到镜像仓库中。具体操作,请参见使用 kaniko 构建和推送容器镜像。

在 Jenkins 命名空间下使用生成的 config.json 文件创建名为 jenkins-docker-cfg 的 Secret。

kubectl create secret generic jenkins-docker-cfg -n jenkins --from-file=/root/.docker/config.json

1 在 Jenkins 中创建全链路灰度发布流水线

基于 Jenkins 实现自动化发布的流水线,通过该流水线可以使应用发布具备可灰度、可观测、可回滚的安全生产三板斧能力。

  1. 在 Jenkins 控制台左侧导航栏单击新建任务

  2. 输入任务名称,选择流水线,然后单击确定

  3. 在顶部菜单栏单击流水线页签,在流水线区域配置相关参数选择,输入脚本路径,然后单击保存

  • 定义:选择 Pipeline script from SCM。
  • SCM:选择 Git。
  • Repository URL:输入 Git 仓库的 URL。
  • 脚本路径:输入 Jenkinsfile。

您可以参考以下的文件填写好指定的参数,当然您也可以根据需求编写 Jenkinsfile ,并上传至 Git 的指定路径下(流水线中指定的脚本路径)。

#!groovy
pipeline {
// 定义本次构建使用哪个标签的构建环境,本示例中为 “slave-pipeline”
agent{
node{
label 'slave-pipeline'
}
}
//常量参数,初始确定后一般不需更改
environment{
IMAGE = sh(returnStdout: true,script: 'echo registry.$image_region.aliyuncs.com/$image_namespace/$image_reponame:$image_tag').trim()
BRANCH = sh(returnStdout: true,script: 'echo $branch').trim()
}
options {
//保持构建的最大个数
buildDiscarder(logRotator(numToKeepStr: '10'))
}
parameters {
string(name: 'image_region', defaultValue: 'cn-shanghai')
string(name: 'image_namespace', defaultValue: 'yizhan')
string(name: 'image_reponame', defaultValue: 'spring-cloud-a')
string(name: 'image_tag', defaultValue: 'gray')
string(name: 'branch', defaultValue: 'master')
string(name: 'number_of_pods', defaultValue: '2')
}
//pipeline的各个阶段场景
stages {
stage('代码打包') {
steps{
container("maven") {
echo "镜像构建......"
sh "cd A && mvn clean package"
}
}
}
stage('镜像构建及发布'){
steps{
container("kaniko") {
sh "kaniko -f `pwd`/A/Dockerfile -c `pwd`/A --destination=${IMAGE} --skip-tls-verify"
}
}
}
stage('灰度部署') {
steps{
container('kubectl') {
echo "灰度部署......"
sh "cd A && sed -i -E \"s/${env.image_reponame}:.+/${env.image_reponame}:${env.image_tag}/\" A-gray-deployment.yaml"
sh "cd A && sed -i -E \"s/replicas:.+/replicas: ${env.number_of_pods}/\" A-gray-deployment.yaml"
sh "kubectl apply -f A/A-gray-deployment.yaml -n default"
}
}
}
stage('结束灰度') {
input {
message "请确认是否全量发布"
ok "确认"
parameters {
string(name: 'continue', defaultValue: 'true', description: 'true为全量发布,其他为回滚')
}
}
steps{
script {
env.continue = sh (script: 'echo ${continue}', returnStdout: true).trim()
if (env.continue.equals('true')) {
container('kubectl') {
echo "全量发布......"
sh "cd A && sed -i -E \"s/${env.image_reponame}:.+/${env.image_reponame}:${env.image_tag}/\" A-deployment.yaml"
sh "cd A && sed -i -E \"s/replicas:.+/replicas: ${env.number_of_pods}/\" A-deployment.yaml"
sh "kubectl apply -f A/A-deployment.yaml -n default"
}
} else {
echo '回滚'
}
container('kubectl') {
sh "kubectl delete -f A/A-gray-deployment.yaml -n default"
}
}
}
}
}
}

2 构建 Jenkins 流水线

  1. 在 Jenkins 控制台单击流水线右侧的图标。

  2. 单击流水线的开始构建

说明:第一次构建因为需要从 Git 仓库拉取配置并初始化流水线,所以可能会报错,再次执行 Build with Parameters,生成相关的参数,填写相关的参数,再次执行构建。

查看部署状态,代码打包,镜像构建及发布,灰度部署阶段都已经完成,结束灰度阶段等待确认。

  • 如果验证结果符合预期,则执行全量发布,请参见后文的全量发布应用。
  • 如果验证结果不符合预期时,则执行回滚,请参见后文的回滚应用。

3 结果验证

  1. 登录容器服务控制台,在控制台左侧导航栏中,单击集群

  2. 集群列表页面中,单击目标集群名称或者目标集群右侧操作列下的详情

  3. 在集群管理页面左侧导航栏选择工作负载 > 无状态

  4. 无状态应用列表页面,spring-cloud-a-gray应用已经自动创建,并且它的镜像已经替换为spring-cloud-a:gray版本。

  1. 在集群管理页面左侧导航栏选择网络 > 服务,选择设置的命名空间,单击zuul-slb服务的外部端点,查看真实的调用情况。
  • 不带灰度 Header 进行调用,发现路由到 A 的正常节点。

    • Curl 命令:

curl http://182.92.XX.XX/A/a

- 执行结果如下:

A[10.4.XX.XX] -> B[10.4.XX.XX] -> C[10.4.XX.XX]%

  • 带上符合条件的参数进行访问,路由到 A 的灰度节点中。

    • Curl 命令:

curl http://182.92.XX.XX/A/a?name=xiaoming

- 执行结果如下:

Agray[10.4.XX.XX] -> B[10.4.XX.XX] -> C[10.4.XX.XX]%

  1. 登录 MSE 治理中心控制台,在应用详情页面,可以看到灰度流量已经进入到灰度的 Pod 中。

4 全量发布应用

结果验证通过之后,确认全量发布。

  1. 在 Jenkins 控制台中,单击目标流水线名称。

  2. 单击需要全量发布的阶段,在请确认是否全量发布对话框中输入 true,然后单击确认

  1. 在容器服务控制台,发现 spring-cloud-a-gray 应用已经被删除,并且 spring-cloud-a 应用的镜像已经替换为 spring-cloud-a:gray 版本。

  1. 在 MSE治理中心控制台,发现灰度流量已经消失。

5 回滚应用

如果发现验证结果不符合预期时,则回滚应用。

  1. 在 Jenkins 控制台中,单击目标流水线名称。

  2. 单击需要全量发布的阶段,在请确认是否全量发布对话框中输入 false,然后单击确认

  1. 在容器服务控制台,发现 spring-cloud-a-gray 应用已经被删除,并且 spring-cloud-a 应用的镜像仍然是老版本。

  1. 在 MSE 治理中心控制台,发现灰度流量已经消失。

04 总结

Aliware

在微服务治理架构中,全链路灰度功能能提供虚拟泳道,极大的方便了测试、发布时的快速验证,能够帮助 DevOPs 提升线上稳定性。

阿里云微服务引擎(MSE)能够给您带来全生命周期的、全方位的微服务治理能力,保障您的线上稳定性、提升开发、运维效率。

相关链接:

参考文档:

https://github.com/aliyun/alibabacloud-microservice-demo/blob/master/mse-simple-demo/helm/mse-simple-demo/README.md

示例代码仓库地址:

https://gitee.com/mse-group/alibabacloud-microservice-demo/tree/master/mse-simple-demo

容器服务控制台

https://cs.console.aliyun.com/#/k8s/cluster/list

MSE治理中心控制台

https://mse.console.aliyun.com/#/overview

使用 kaniko 构建和推送容器镜像:

https://help.aliyun.com/document_detail/106712.htm

文章目录
  1. 1. 01 整体架构
  2. 2. 02 部署应用&创建泳道
  3. 3. 03 Jenkins 流水线
  4. 4. 04 总结