灰度发布与回滚
# 灰度发布与回滚
线上的系统通常情况下会一直迭代更新下去,这意味着我们需要不断发布新版本来替换老版本。如何保证新版本稳定运行呢? 必要的测试必不可少,但灰度发布与回滚也是两个制胜法宝!
# 灰度发布
# 灰度发布介绍
灰度发布(又名金丝雀发布) 是一种平滑发布新版本系统的方式。
我举一个简单的例子,大家一看应该就明白灰度发布的思想了。
假如我们有一个服务器集群,每个用户固定访问服务器集群中的某一台服务器,当我们需要发布新版本或者上新功能的时候,我们可以将服务器集群分成若干部分,每天只发布新版本到一部分服务器,这样的话,就有一部分用户可以使用最新版本。发布之后,我们需要观察新版本的服务器运行是否稳定且没有故障。如果没问题的话,我们第二天继续发布一部分服务器,通常需要持续几天才把整个集群全部发布完毕。期间如果发现有问题的话,只需要回滚已发布的那部分服务器即可。
上面列举的这个例子其实是灰度发布常用的一种方式 - AB 测试。AB 测试的思想就是就是把用户分成两组,一组用户使用 A 方案(新版本),一组用户使用 B 方案(老版本)。
另外,这个例子是通过服务器来区分的用户,比较粗暴,而且在一些情况下无法使用。一般情况下,我们是建议在进行灰度发布之前对系统用户进行筛选,根据用户的相关信息和各项指标(比如活跃度,违规次数)来筛选出一批可以优先使用新版的用户。我们只需要通过一些手段将这些用户的请求定向到新版本服务即可!为了直观对新版本服务的稳定性进行观测,灰度发布的正确完成还需要依赖可靠的 监控系统 。
好了!相信前面的介绍已经让你搞清了灰度发布是个什么东西。下面,我们来简单总结一下灰度发布的思想: 简单来说,灰度发布的思想就是先分配一小部分请求流量到新版本,看看有没有问题,没问题的话,再一点点地增加流量,最终让所有流量都切换到新版本。
# 为什么灰度发布又被称为金丝雀发布呢?
金丝雀也被称为瓦斯报警鸟,对于有毒气体非常敏感,在 90 年代的时候经常被拿来检测毒气(有点残忍,后来被禁止了)。为了避免金丝雀直接被毒死了,人们想到了一个办法,把金丝雀放在一个可以控制通气口气体流量的笼子,需要金丝雀预警的时候把通气口慢慢打开,如果笼子中的金丝雀被毒气毒晕,关闭通气口然后让往笼子里充氧气抢救一下金丝雀。
金丝雀预警毒气通过控制通气口气体流量来减小潜在的毒气对金丝雀的影响,金丝雀发布通过控制发布的新版本的使用范围来减小潜在的问题对整体服务的影响,两者思想非常类似。
很多程序员有可能也是为了纪念那些因为毒气而牺牲的金丝雀才把这种发布方式冠上了金丝雀的名称。
# 几种发布方式解析
在项目迭代的过程中,不可避免需要”上线“。上线对应着部署,或者重新部署;部署对应着修改;修改则意味着风险。目前有很多部署发布的技术, 这儿将常见的做一个总结。
上面所说难免有些抽象, 举一个情景例子, 加入你是微博项目负责人员, 现在新版本较原来的老版本有很大的改变, 这设计到服务架构、前端UI等等, 经过测试功能没有障碍, 那么这时候如何让用户切换到新的版本呢?
显而易见, 第一次发布的应用是没有所谓的这个问题的, 这种如何发布的思考只会出现在后面的版本迭代中。
# 1. 蓝绿发布
蓝绿部署中,一共有两套系统:一套是正在提供服务系统(也就是上面说的旧版),标记为“绿色”;另一套是准备发布的系统,标记为“蓝色”。两套系统都是功能完善的,并且正在运行的系统,只是系统版本和对外服务情况不同。正在对外提供服务的老系统是绿色系统,新部署的系统是蓝色系统。
蓝色系统不对外提供服务,用来做啥?
用来做发布前测试,测试过程中发现任何问题,可以直接在蓝色系统上修改,不干扰用户正在使用的系统。
蓝色系统经过反复的测试、修改、验证,确定达到上线标准之后,直接将用户切换到蓝色系统, 切换后的一段时间内,依旧是蓝绿两套系统并存,但是用户访问的已经是蓝色系统。这段时间内观察蓝色系统(新系统)工作状态,如果出现问题,直接切换回绿色系统。
当确信对外提供服务的蓝色系统工作正常,不对外提供服务的绿色系统已经不再需要的时候,蓝色系统正式成为对外提供服务系统,成为新的绿色系统。原先的绿色系统可以销毁,将资源释放出来,用于部署下一个蓝色系统。
# 蓝绿发布特点
- 蓝绿部署的目的是减少发布时的中断时间、能够快速撤回发布。
- 两套系统没有耦合的时候才能百分百保证不干扰
# 蓝绿发布注意事项
蓝绿部署只是[上线策略中的一种,它不是可以应对所有情况的万能方案。蓝绿部署能够简单快捷实施的前提假设是目标系统是非常内聚的,如果目标系统相当复杂,那么如何切换、两套系统的数据是否需要以及如何同步等,都需要仔细考虑。
当你切换到蓝色环境时,需要妥当处理未完成的业务和新的业务。如果你的数据库 (opens new window)后端无法处理,会是一个比较麻烦的问题;
- 可能会出现需要同时处理“微服务架构应用”和“传统架构应用”的情况,如果在蓝绿[部署中协调不好这两者,还是有可能会导致服务停止。
- 需要提前考虑数据库与应用部署同步迁移 /回滚的问题。
- 蓝绿部署需要有基础设施支持。
- 在非隔离基础架构( VM 、 Docker 等)上执行蓝绿[部署,蓝色环境和绿色环境有被摧毁的风险。
# 2. 滚动发布
一般是取出一个或者多个服务器停止服务,执行更新,并重新将其投入使用。周而复始,直到集群中所有的实例都更新成新版本。
发布流程:
相对于蓝绿发布需要一套完备的机器不同, 滚动发布只需要一台机器(这儿这是为了理解, 实际可能是多台), 我们只需要将部分功能部署在这台机器上, 然后去替换正在运行的机器, 如上图, 将更新后的功能部署在Server1 上, 然后Server1去替换正在运行的Server, 替换下来的物理机又可以继续部署Server2的新版本, 然后去替换正在工作的Server2 , 以此类推, 直到替换完所有的服务器, 至此 ,服务更新完成。
# 滚动发布特点
- 这种部署方式相对于蓝绿部署,更加节约资源——它不需要运行两个集群、两倍的实例数。我们可以部分部署,例如每次只取出集群的20%进行升级。
- 回滚困难
# 滚定发布注意事项
- 滚动发布没有一个确定可行的环境。使用蓝绿[部署,我们能够清晰地知道老版本是可行的,而使用滚动发布,我们无法确定。
- 修改了现有的环境。
- 回滚困难。举个例子,在某一次发布中,我们需要更新100个实例,每次更新10个实例,每次部署需要5分钟。当滚动发布到第80个实例时,发现了问题,需要回滚,这个回滚却是一个痛苦,并且漫长的过程。
- 有的时候,我们还可能对系统进行动态伸缩,如果部署期间,系统自动扩容/缩容了,我们还需判断到底哪个节点使用的是哪个代码。尽管有一些自动化的运维 (opens new window)工具,但是依然令人心惊胆战。
- 因为是逐步更新,那么我们在上线代码的时候,就会短暂出现新老版本不一致的情况,如果对上线要求较高的场景,那么就需要考虑如何做好兼容的问题。
# 3. 灰度发布
灰度发布, 也叫金丝雀发布。是指在黑与白之间,能够平滑过渡的一种发布方式。AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度,而我们平常所说的金丝雀[部署也就是灰度发布的一种方式。
具体到服务器上, 实际操作中还可以做更多控制,譬如说,给最初更新的10台服务器设置较低的权重、控制发送给这10台服务器的请求数,然后逐渐提高权重、增加请求数。一种平滑过渡的思路, 这个控制叫做“流量切分”。
17世纪,英国矿井工人发现,金丝雀对瓦斯这种气体十分敏感。空气中哪怕有极其微量的瓦斯,金丝雀也会停止歌唱;而当瓦斯含量超过一定限度时,虽然鲁钝的人类毫无察觉,金丝雀却早已毒发身亡。当时在采矿设备相对简陋的条件下,工人们每次下井都会带上一只金丝雀作为“瓦斯检测指标”,以便在危险状况下紧急撤离。
过程:
- 准备好部署各个阶段的工件,包括:构建工件,测试脚本,配置文件和部署清单文件。
- 将“金丝雀”服务器部署进服务器中, 测试。
- 从负载均衡 (opens new window)列表中移除掉“金丝雀”服务器。
- 升级“金丝雀”应用(排掉原有流量并进行[部署)。
- 对应用进行自动化测试。
- 将“金丝雀”服务器重新添加到负载均衡列表中(连通性和健康检查)。
- 如果“金丝雀”在线使用测试成功,升级剩余的其他服务器。(否则就回滚)
# 4. A/B测试
A/B测试和蓝绿发布、滚动发布以及金丝雀发布,完全是两回事。
蓝绿发布、滚动发布和金丝雀是发布策略,目标是确保新上线的系统稳定,关注的是新系统的BUG、隐患。
A/B测试是效果测试,同一时间有多个版本的服务对外服务,这些服务都是经过足够测试,达到了[上线标准的服务,有差异但是没有新旧之分(它们[上线时可能采用了蓝绿部署的方式)。
A/B测试关注的是不同版本的服务的实际效果,譬如说转化率、订单情况等。
A/B测试时,线上同时运行多个版本的服务,这些服务通常会有一些体验上的差异,譬如说页面样式、颜色、操作流程不同。相关人员通过分析各个版本服务的实际效果,选出效果最好的版本。
# 灰度发布常见方案
这里介绍几种比较常见的方案,对于 Java 后端开发来说,我觉得了解就行了,一般在公司里这种事情一般是由 Devops 团队来做的。
1、基于 Nginx+OpenResty+Redis+Lua 实现流量动态分流来实现灰度发布,新浪的 ABTestingGateway (opens new window) 就是这种基于这种方案的一个开源项目。
2、使用 Jenkins + Nginx 实现灰度发布策,具体做法可以参考:手把手教你搭建一个灰度发布环境 (opens new window) 。这种方案的原理和第一种类似,都是通过对 Nginx 文件的修改来实现流量的定向分流。类似地,如果你用到了其他网关比如 Spring Cloud Gateway 的话,思路也是一样的。另外, Spring Cloud Gateway 配合 Spring Cloud LoadBalancer(官方推荐)/Ribbon 也可以实现简单的灰度发布,核心思想也还是自定义负载均衡策略来分流。
3、基于 Apollo (opens new window) 动态更新配置加上其自带的灰度发布策略来实现灰度发布。
这种方法也是通过修改灰度发布配置的方式来实现灰度发布,如果灰度的配置测试没问题的话,再全量发布配置。
具体做法可以参考:
●灰度发布使用指南 - 官方文档 (opens new window)
●灰度实战基础之 Apollo (opens new window)
4、通过一些现成的工具来做,比如说 Rainbond (opens new window)(云原生应用管理平台)就自带了灰度发布解决方案并且还支持滚动发布和蓝绿发布。
5、Flagger
这是之前看马若飞老师的《Service Mesh 实战》这门课的时候看到的一个方法。
Flagger 是一种渐进式交付工具,可自动控制 Kubernetes 上应用程序的发布过程。通过指标监控和运行一致性测试,将流量逐渐切换到新版本,降低在生产环境中发布新软件版本导致的风险。
Flagger 可以使用 Service Mesh(App Mesh,Istio,Linkerd)或 Ingress Controller(Contour,Gloo,Nginx)来实现多种部署策略(金丝雀发布,A/B 测试,蓝绿发布)。
# 回滚机制
光有灰度发布还不够,如果在灰度发布过程中(灰度期)发现了新版本有问题,我们还需要有回滚机制来应对。类似于数据库事务回滚,系统发布回滚就是将新版本回退到老版本。
# 回滚通常的做法是怎样的呢?
1提前备份老版本,新版本遇到问题之后,重新部署老版本。
2同时部署一套新版本,一套旧版本,两者规模相同新版本出问题之后,流量全部走老版本(蓝绿发布)。
是银弹,毕竟计算机世界压根不存在银弹。
在一些要求非常严格的系统(如交易系统、消防系统、医疗系统)中,灰度发布和回滚使用不当就会带来非常严重的生产问题。