研发效能系列:如何做到低风险的部署与发布?
  BhowgpPG6JXh 2023年11月02日 28 0

将(功能)发布与(代码)部署解耦

作者:冬哥



传统的实践中,将代码部署到生产环境,也就意味着对客户开放了相关功能。因此部署也就意味着变更上线,而变更是造成线上事故的最主要来源;所以变更需要是受控的,需要通过层层的检查门禁;部署/发布是一个高风险的事情,需要运维同学放在业务不繁忙的夜间进行;此时恰好是开发同学力量最薄弱的时刻,出现问题又很难及时响应和定位;因此运维会严格控制上线的频度,这又进一步造成每一次的发布中包含了过多的变更,增加了发布的风险;发布的层层门禁进一步减缓了发布的流程,导致整个过程痛苦不堪;于是很多的功能发布伪装成了缺陷修复,绕开门禁机制,走快速发布流程,这让原本就名声不佳的生产上线简直是雪上加霜。

这样的“传统”至今依然在各企业频繁上演,让人谈虎色变。这也是持续交付试图去解决的问题,同样也是研发效能的效与能的目标之一,而且是绕不开的环节。

如何让部署与发布变成低风险的事情?需要将部署和发布解耦。我们前文讲过,部署是一个技术行为,而发布则是业务决策。两者的区别和定位分别是:部署是在特定的环境上安装指定版本的软件,部署可能与某个特性的发布有关,也能无关。发布是把一个/组特性提供给(所有或部分)客户。

《DevOps实践指南》的对于部署与发布的定义如下:


  •  部署是指在特定的环境中安装指定版本的软件(例如,将代码部署到集成测试环境中,或者部署到生产环境中)。


  •  具体的说,部署可能与某个特性的发布无关。


  •  如果部署与某个特性发布有关,部署后即时生效,即代表着发布,部署=发布。



  •  发布是指把一个特性(或者一组特性)提供给所有客户或者一部分客户(例如,向5%的客户群开放特性)。


  •  代码和环境架构要能够满足这种要求:


  •  特性发布不需要变更应用的代码。


Develop on Candence, Realease on Demand。按节奏开发,按需要发布。将(功能)发布与(代码)部署解耦,是持续交付的基本原则。将代码部署到生产环境,并不意味着对客户开放了相关功能。是与否开放,针对那些群体开放,什么时候开放什么时候关闭,都是业务和运维基于业务决策与应用运行状况做出的决策,与部署本身不直接相关。


发布的定义和目标




软件发布就是将开发好的应用程序正式公布出来的过程,ITIL中定义的发布管理目标包含:


  •  规划、协调软件和硬件的实施(或安排实施)


  •  针对分发和安装对系统实施的变更而设计和实施有效的程序


  •  确保与变更相关的硬件和软件是可追溯和安全的(正确的、经过批准和测试的版本才能被安装)


  •  在新发布的规划和试运行期间与用户进行沟通并考虑他们的期望


  •  保障发布软件的原始拷贝被安全地存放在最终软件库,配置信息存储在配置管理数据库


上述与软件相关的环境,包括环境、部署、配置、发布等,需要通过IaC基础设施即代码、部署流水线、软件配置管理、软件制品库、镜像仓库来等综合实践达成。


低风险发布



简单的讲,部署是技术动作,发布是业务行为。所以我们需要通过技术的手段,来实现低风险的发布。如果混淆部署和发布,就很难界定谁对结果负责。解耦部署和发布,可以提升开发人员和运维人员快速且频繁部署的能力,同时产品负责人承担发布成功的责任。按需部署,让特性发布成为业务和市场决策,而不是技术决策。

无需停机地发布,对于为客户持续提供服务是至关重要的。如果涉及停机,就会将其安排到非工作时间,这就要求系统管理员和运维人员要在非工作时间工作,这是避免停机的另一个原因,因为这不可持续,并且会影响人员士气。

低风险的发布有两大类实现方式,基于环境的发布模式和基于应用的发布模式。


  •  基于环境的发布模式实现机制是,关注两个或更多环境,但只有一个环境正在接受实时客户流量。


  •  将新代码部署到非生产环境中,将流量切换至此环境,让新版本开始接受流量,确认没问题,再升级另外的环境,逐步全网升级。


  •  基于环境的发布模式好处是只需要很少或者不需要更改应用程序。


  •  基于环境的发布模式包括:


  •  Blue-green蓝绿部署、Canary金丝雀发布、Cluster immune systems 集群免疫系统等。



  •  基于应用的发布,通过是通过Feature Toggle功能开关来启用特定应用程序功能的发布和展示。


  •  例如按照启用范围,分为开发团队、内部员工、1%的客户,直至到整个客户群。


  •  基于应用发布模式的优点是切换快速,可以通过界面直接进行功能的打开与关闭;


  • 缺点是有代码侵入,于此同时特性开关也是技术债务,需要定期清理,同时功能开关的存在也增加测试的复杂性,需要打开所有特性开关(也许需要排列组合),还需要测试特性开关功能本身是否正常。


  • l 基于应用的发布的例子还包括Dark Launching灰度发布。


我们来分别针对典型的低风险发布模式进行分析。

(需要说明的是,在下文中,我们可能会交叉使用部署与发布,甚至不严格进行区分。这是由于有很多约定俗成的名称,例如蓝绿部署,事实上是一个部署行为,但如果没有控制开关,它也带有部分发布的意味。关键还是记住,部署是技术动作,发布是业务行为。在这里,重要的是根据具体技术与业务的需要,来选择部署与发布的方式,具体叫部署还是发布反而不那么重要了。)


金丝雀发布




金丝雀发布是一种降低在生产中引入新软件版本风险的技术,它通过先将变更发布给一小部分用户,再逐渐推广到整个环境并使其对所有人可用。这项技术的名称来源于矿工,他们将笼子里的金丝雀放入矿井,由于金丝雀对毒气非常敏感,如果存在毒气体泄漏,它会在杀死矿工之前杀死金丝雀。在潜在问题影响整个生产环境或全体用户群之前,金丝雀发布提供了类似的警告。尽管这种技术的名称独特,但金丝雀发布的做法早已存在多时,被称为分阶段部署或增量部署。

研发效能系列:如何做到低风险的部署与发布?_生产环境

金丝雀发布机制是先将新版本应用部署到少量环境,但是并不直接将流量切过来,而是测试人员对新版本进行线上测试,而这个新版本应用设计的少量环境,就是我们的金丝雀。

当对新版本感到满意时,我们可以开始将一些选定的用户路由到新环境。选择哪些用户到新版本有不同的策略:一个简单的策略是使用随机样本;有些公司会选择先向内部用户和员工发布新版本,然后再向全网发布;另一种更复杂的方法是根据用户的个人资料和其他人口统计数据来选择用户,这个需要更复杂的标签机制以及切换策略控制。在大型分布式场景中,使用不同的分区策略也很常见,例如可以先将新版本发布到某个地区或特定位置。

随着我们对新版本越来越有信心,可以开始将其发布到更多的服务器,并将更多用户路由到新版本。推出新版本的一个好做法是使用不可变服务器方式配置新的基础设施并停用旧的基础设施。

金丝雀的优势是用户体验影响小,金丝雀发布过程如果出现问题只会影响少量用户。劣势是发布自动化程度不够,发布期间可能引发服务中断。此外我们必须一次管理多个版本的软件,甚至可能在生产环境中同时运行多个以上的版本。但建议将并发版本的数量保持在最低限度,否则管理的复杂度将极具上升,进而削减了金丝雀带来的好处。

金丝雀适用的场合包括对新版本功能或性能缺乏足够信心,用户体验要求较高的网站业务场景,缺乏足够的自动化发布工具研发能力等情况。

使用金丝雀发布的另一个好处是能够在发现问题时使用安全回滚策略在生产环境中对新版本进行容量测试。由于迁移阶段一直是将用户路由到新版本,如果发现新版本有任何问题,回滚策略只需要将用户重新路由回旧版本,直到解决金丝雀的问题,回滚会非常快速并且成本低廉。

由于技术实现的相似性,金丝雀发布也可用作实现 A/B 测试的一种方式,但是我们最好避免将这两个问题混为一谈:金丝雀的目的是隔离发布问题和快速检测并回滚,而A/B 测试是一种使用不同实现版本来测试不同设计假设的方法。由于目的不同,如果将金丝雀与A/B混在一起,确切的说,收集足够的数据以证明 A/B 测试可能需要数天时间,而我们希望金丝雀部署在几分钟或几小时内就能完成。


滚动发布




滚动发布是在金丝雀发布基础之上的进一步优化改进,是一种自动化程度较高的发布方式,用户体验平滑,是目前成熟型技术组织所采用的主流发布方式。

研发效能系列:如何做到低风险的部署与发布?_新版本_02


滚动发布一般是取出一个或者多个服务器停止服务,执行更新,并重新将其投入使用。周而复始,直到集群中所有的实例都更新成新版本。

一次滚动式发布一般由若干个发布批次组成,每批的数量一般是可以配置的(可以通过发布模板定义)。例如第一批1 台(金丝雀),第二批10%,第三批 50%,第四批100%。每个批次之间留观察间隔,通过手工验证或监控反馈确保没有问题再发下一批次,所以总体上滚动式发布过程是比较缓慢的。其中首批金丝雀版本的时间一般会比后续批次更长,因为需要检测的内容较多。

滚动式发布需要比较复杂的发布工具和智能负载均衡LB,支持平滑的版本替换和流量拉入拉出。实现步骤是先将老版本V1流量从 LB上摘除;清除老版本,发布新版本V2;再将LB 流量接入新版本。这样可以尽量保证用户体验不受影响。

滚动发布的优势是用户体验影响小,体验较平滑。劣势是发布和回退时间比较缓慢,发布工具比较复杂,LB需要平滑的流量摘除和拉入能力。滚动发布的适用场合是用户体验不能中断的网站业务场景,和有一定的复杂发布工具研发能力。


蓝绿部署




蓝绿发布,是一种可以保证系统在不间断提供服务的情况下上线的部署方式。蓝绿部署的模型中包含两个集群,部署过程中,并不停止掉老版本,而是直接部署一套新版本,等新版本运行起来后,再将流量切换到新版本上。


蓝绿发布适用于双服务器组发布,V1版本称为蓝组,V2版本称为绿组,发布时通过LB一次性将流量从蓝组直接切换到绿组,不经过金丝雀和滚动发布,蓝绿发布由此得名。蓝绿发布出现问题回退也很直接,通过LB 直接将流量切回蓝组。发布初步成功后,蓝组机器一般不直接回收,而是留一个待观察期,视具体情况观察期的时间可长可短,观察期过后确认发布无问题,则可以回收蓝组机器。

蓝绿发布的优势是升级切换和回退速度非常快。劣势是切换是全量的,如果V2 版本有问题,则对用户体验有直接影响,此外需要两倍机器资源,投入较大。适用场合:对用户体验有一定容忍度的场景;机器资源有富余或者可以按需分配(AWS云,或自建容器云);暂不具备复杂滚动发布工具研发能力。

蓝绿部署方法通过确保两个尽可能相同的生产环境来实现版本的快速切换。在任何时候,其中之一(例如以蓝色为例)处于活动状态。当准备软件的新版本时,将在绿色环境中进行最后阶段的测试。一旦软件在绿色环境中工作,就可以切换路由将所有传入的请求都进入绿色环境,此刻蓝色环境保持空闲。

蓝绿部署还提供了一种快速回滚的方法,如果出现任何问题,可以将路由切换回蓝色环境。在绿色环境处于活动状态时仍然存在处理遗漏事务的问题,但是根据设计,你可以将事务分别提供给两种环境,以便在绿色环境处于活动状态时将蓝色环境作为备份。为保证数据一致性,也可以在切换前将应用程序置于只读模式,在只读模式下运行一段时间,然后将其切换到读写模式。

一旦将绿色环境投入使用并且对其稳定性感到满意,就可以使用蓝色环境作为下一次部署的最后测试步骤的暂存环境。基本思路是保持有两个易于切换的环境,这种方法的优点是基本机制与热备份的基本机制相同。因此,我们可以在每个版本上测试灾难恢复过程,主动的灾难恢复测试应该比被动的灾难要来的频繁许多。

作为对蓝绿部署的一种简单优化,可以在发布时先从绿组拉入 1台金丝雀,待金丝雀验证通过再发全量,这样集合了金丝雀与蓝绿两种部署模式的优点。

研发效能系列:如何做到低风险的部署与发布?_灰度_03

双服务器组的滚动式发布是对上面的蓝绿和金丝雀发布的进一步优化,按批次增量滚动发布,提供更平滑的用户体验。



灰度发布




灰度发布是在金丝雀发布基础上进行延伸,不是将发布分成两批,而是将发布分成不同的阶段/批次发布,每个阶段/批次的用户数量逐级增加。如果新版本在当前阶段没有发现问题,就再扩展用户数量进入下一个阶段,直至扩展到全部用户。

灰度发布,可以结合滚动部署一起使用,通过分批部署,部署即发布,来让部分客群可见。结合特性开关、流量切换等技术,可以做到更复杂灵活的灰度设置。

研发效能系列:如何做到低风险的部署与发布?_新版本_04

以华为云DevCloud灰度发布的实践为例,整个DevCloud的产品中采取的灰度发布特点主要有三个方面:


  • l 根据用户画像,精准分层用户,灰度逐步递进,全部保证能够检测到所有的用户分群。



  • l 结合了多种灰度策略,如特性开关、AB测试、在线验收测试、友好用户测试等模式。



  • l 精准把控灰度批次比例,借助SLB服务,严格按照1%、9%、45%、45%,谨慎比例逐步放大灰度群体。


功能开关


功能开关利用代码中的开关(FeatureFlag/Toggle/Switch)来控制发布逻辑,一般不需要复杂的发布工具和智能LB 配合,是一种相对比较低成本和简单的发布方式。这种方式也是支持现代DevOps 理念,研发人员可以灵活定制和自助完成的发布方式。应用上线后开关先不打开,然后运维、研发或业务人员通过开关中心打开新功能,经过流量验证新功能没有问题后,则发布完成,如果有问题,随时可以通过开关中心切回老功能逻辑。


采用功能开关方式的优势是升级切换和回退速度非常快,相对于复杂的发布工具,实施比较简单,成本相对低廉,研发能够灵活定制发布逻辑,支持DevOps 自助发布。而劣势是切换是全量的,如果V2 版本有问题,则对用户体验有直接影响;另外对代码有侵入,代码逻辑会变复杂,需要定期清理老版本逻辑,维护成本变高。

功能开关的适用场合包括:对用户体验有一定容忍度的场景;已有配置中心或开关中心服务;暂不具备研发复杂发布工具能力等。

从实现角度,功能开关方式需要一个配置中心或者开关中心这样的一个服务支持,通过配置中心运维或研发人员可以在运行期间动态配置功能开关的值。功能开关发布只是配置中心的一种使用场景,配置中心还能支持其他动态配置场景,功能开关服务一般提供客户端的SDK方便开发人员集成,在运行期客户的SDK会同步最新的开关值。技术实现有推方式也有拉方式或者推拉结合方式,新功能和老功能住在同一代码中,新功能隐藏在开关后面,如果开关没有打开,则走老代码逻辑,如果开关打开则走新代码逻辑,技术实践上可以理解为一个简单的if else逻辑。

功能开关允许你持续地交付新发布,这些版本可以包含未完成的新功能——但这些不会影响应用程序,因为这些新功能还处于关闭状态。只有当这些功能可以发布并且成功地通过了所有所需的测试后,生产环境中的开关才会打开(即打开这个功能)。

功能开关是DevOps实践中非常重要的实践之一,我们将单起章节专门进行介绍。


A/B测试


简单来说,A/B测试是针对用户的需要,提供两个版本的功能,一部分用户能看到版本A,一部分用户能看到版本B,经过对比实验,得出哪个版本更优的测试过程。

A/B测试是用来测试应用功能表现的方法,例如可用性、受欢迎程度、可见性等等。A/B测试目的在于通过科学的实验设计、采样样本代表性、流量分割与小流量测试等方式来获得具有代表性的实验结论,并确信该结论在推广到全部流量可信。

A/B测试的优势是用户体验影响小,可以使用生产流量测试,可以做到针对某类特定目标用户进行测试。但A/B测试搭建复杂度相对高,有一定技术门槛,需要具备一定的A/B 测试平台研发能力

A/B测试示例如图所示,假设原来的PC 端和手机端都访问老版本V1 服务(也称A 组或控制组),当V2 新版本(也称B 组或实验组)发布以后,为了验证V2 的功能正确性,同时也为了避免V2 有问题时影响所有用户,先通过LB 将手机端的流量切换到V2 版本,经过一段时间的A/B 比对测试和观察(主要通过用户和监控反馈),确保V2 正常,则通过LB 将全部流量切换到V2。


基于LB 方式实现 A/B测试,LB 需要能够通过某种条件做流量路由,例如通过Client IP,设备类型,浏览器类型,甚至是定制的HTTP Header 或查询字符串。

通过功能开关的方式和AB测试有点相似,但功能开关一般是无状态和全量的,无法做到针对某类特定用户进行测试。而AB测试一般是有状态的,能够根据事物和用户级别的状态,可以实现针对某类特定用户进行测试。

虽然 A/B 测试名字中只包含 A、B ,但并不是说它只能用于比较两个版本的好坏,事实上,完全可以设计两个以上版本进行测试,即A/B/n测试。


暗启动


暗启动原意是指将新版本部署到生产环境后,对用户无感。所以暗启动意味着暗部署。当然,暗启动终极目的还是为了发布,对原有暗启动含义扩展之后,就会先让小部分用户感知新功能,再逐渐扩大感知到新功能的用户范围,那么暗启动就代表发布。

马丁·福勒(Martin Fowler)提到,暗启动针对的是后端行为,后端系统部署在生产环境之后,现有用户使用前端界面的时候,新部署的后端功能被调用,但是用户并没有感知,可以对新功能的性能进行监控。也就是说用户和系统的交互逻辑保持不变,用户在界面上没有地方选择新部署的功能,也就是对用户不可见。

暗启动的暗(Dark)代表用户无感知,也就是新版本的功能已经被部署到生产环境,但是用户无感知。例如百度的搜索框输入提升推荐,可以在客户界面不发送改变的情况下,对算法进行数据采集和训练,再与客户实际点击的链接结果集进行比对,便于更好的优化,在未来才正式推出输入时推荐的功能。

暗启动将部署与发布解耦,功能部署之后,对用户而言无感,这样可以获得部分真实用户的反馈,测试缺陷,评估基础设施性能、系统的额外负载和性能影响等。暗启动还可以启用重新实现的功能的并行运行。旧代码和新代码都可以调用并检查它们的结果以查看新算法是否有变化,但只有一个答案返回到界面。暗启动也可以选定公司内部员工作为用户,这样内部员工可以先吃自己的狗粮,对新功能进行测试,而真实用户并未真正使用新功能。这一场景事实上与灰度发布类似。


参考资料

https://martinfowler.com/bliki/ Martin Fowler的博客

一文看懂持续部署按需发布!DevOps部署和发布方法大全 —— 赵卫

《DevOps实践指南》

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  X5zJxoD00Cah   2023年11月02日   31   0   0 Vue服务器新版本
BhowgpPG6JXh