在前一篇讲Capital One如何成功进行DevOps转型的文章中,我提到了他们公司总结出的DevOps转型目标是“Delivery High Quality Working Software Faster”,即更快速地交付高质量的可工作系统。
其中的“可工作”是指跨产品线、共享服务和依赖的第三方,确保系统端到端必须可用。持续交付和DevOps的难点问题之一就在于跨系统,尤其是银行这类多个复杂系统共同协作的场景下,如何做好系统间的对齐,如何更有序的发布版本,是整个交付过程中非常关键的环节。
一、常见的发布管理模式
常见的发布管理模式主要有以下几种:
目前很多大型企业的系统开发还是按照项目的模式开展,比如有时分为新建类项目(如新建系统)或延续性项目(如增强或优化系统),每个项目都需要完成从立项、项目启动、项目实施到项目验收等一系列较为完整的过程,实施流程繁琐、参与人员众多、普遍交付周期较长。
由于事先约定了项目所包含的需求或特性集合,当所有需求或特性全部开发完成,并通过验收测试后,才能批量进行版本发布。过程中如果出现需求变更或某些需求交付遇到阻碍,常常会导致项目的延期发布。
另外,由于项目大小不一,发布周期不固定,缺少稳定的交付节奏,加之周期通常较长,可能导致项目交付的可预见性较差。
2) 发布窗口模式
发布窗口是指一个特定的时间段,在这个时间段内一个或多个团队可以发布产品到生产环境。
发布窗口一般选择系统负载较低的时候进行,尽管现在大多数应用系统的用户都希望这些系统能够提供7*24小时不间断的服务。
在大型企业中,受到系统复杂度、研发流程和风险控制等因素的影响,常常选择周期跨度较大的发布窗口,比如每季度一次常规投产、每个月一次常规投产,做的好一些的可以达到每两周一次常规投产。
发布窗口模式的优点:
- 对业务部门及用户:提供了始终如一的发布节奏;
- 对交付团队:提供了始终如一的发布日期目标;
发布窗口模式的缺点:
- 少量的发布窗口需要同时集中处理多个团队的发布需求,发布风险很高;
- 不同团队争抢有限的发布窗口,带来大量沟通和协调成本;
- 不同系统之间存在相互依赖的情况,需要大量时间统一规划和协调;
- 时常出现相互依赖的系统没有及时对齐,集成时问题集中爆发,无法在原定的发布窗口顺利发布的情况,如下图所示:
3) 发布火车模式
发布火车是指组成复杂系统的每个团队都参与到统一发布节奏的“火车”中来。每列发布火车采用固定的“发车”时间,特性的发布取决于该特性是否赶上最近的火车发车时间。如果某个团队错过了发布日期,即错过了这列火车,火车还是会按时发出,这个团队可以等待下列火车的到来。
许多大型企业都在使用发布火车的发布模式,这种模式适用于不同团队有各自负责的子系统或组件,但需要整体进行对齐和集成的场景。发布火车模式的提出最早是一些大型软件公司组合不同的软件产品,但近些年来SAFe等大规模敏捷框架的推广让发布火车模式更为流行。
当然,同样是发布火车,不同场景下的展现形式可能不同。比如有的框架介绍发布火车一般8~12周完成一个大型产品的增量发布,有些企业实现的小型发布火车可以做到1~2周级别的发布(也有做的更快的,他们叫做班车模式)。
我们这里仅是从管理模式上和技术实现上考虑,发布火车可以实现多个子系统或组件团队之间的高效协同,以及发布包的递次晋级,我们讨论的是一个广义上的概念,具体的发布周期是可以按需求调整的。
发布火车模式的优点:
- 发布火车让参与的团队达成统一的发布节奏;
- 所有参与的团队可以有效对齐该版本的各个实施阶;
- 发布火车可以更有效的协调多团队的发布;
- 火车的间隔周期通常可以设置的相对较短,即便错过一列火车还可以等待下一列,缓解了争抢发布窗口的问题;
发布火车模式的缺点:
- 统一的发布火车时刻表同时也约束了开发团队,没有做到持续交付;
- 如果发布火车间隔时间设置的很长,一样会出现集成的瓶颈;
4) 持续交付模式
持续交付是DevOps的核心工程实践,也是众多互联网公司采用的交付模式。持续交付的思路是开发以小批量工作在主干上,或者每个人工作在短Feature分支上,有规律的合并主干。主干一直保持可部署状态,可以做到通过一键式操作的方式在正常业务时段按需发布。
在流水线上,开发可以得到快速反馈,包括缺陷、性能问题、安全问题、易用性问题等,当问题被发现,他们快速修复,以保证主干一直保持可部署状态。
关于持续交付的实施框架和细节技术实践,我曾经做过多次分享,但这并不是今天讨论的重点,所以我们暂不展开。
持续交付可以做到行云流水一般,快速、按需发布到生产环境,相当于我们的发布窗口是7*24小时!以互联网为代表的一些高绩效IT公司,通过持续交付可以做到每天成千上万次高质量的发布。但是,做到持续交付需要非常多的技术实践,包括高度自动化的流水线,自动化构建,自动化测试,自动化部署,低风险的发布技术等等。
在大型复杂系统中实现持续交付,还需要考虑系统之间相互依赖的问题。正确的思路应该是让架构尽量做到解耦,使得每个系统能够独立的开发、测试、部署和发布,而不依赖其他系统。每个系统独立演进的过程中,可以通过契约测试的方式验证相互接口的正确性,同时还需要实现服务提供方的向下兼容以及服务消费方的容错性设计。
二、发布管理模式的综合应用
我的经验是很多传统一些企业都在使用发布窗口模式或发布火车模式,但也都在积极尝试持续交付的发布模式。通常引入敏捷和DevOps的方法和实践都会促进发布频率的提升和发布周期的缩短。
那么如何综合应用以上几种发布管理模式,取长补短,即能够提升单个系统的发布效率,又能兼顾系统之间的依赖关系呢?这个是我们接下来要讨论的话题。
综合应用的策略-需要根据发布频率的实际需求来选择和搭配不同的发布模式。
在上图中,我们可以看到有不同类型的发布需求,比如Major Release(可能是产品级的功能整体升级),或者Subsystem Release(可能是某个子系统内部的功能优化),也有为了满足特定合规性需求或解决线上问题的紧急修复等。
不同的发布需求对应了不同的发布节奏。首先我们要按特定的节奏规划产品级增量发布,此时可以应用发布火车的模式;然后是在产品级增量发布的中间,规划粒度更细的子系统级发布,以及穿插其中不定期的紧急发布,此时可以应用持续交付的发布模式。
所以我们提出的整体策略就是“按节奏开发,按需进行发布”。
- 按节奏开发是指以固定的节奏安排产品级发布规划,同步和对齐不同团队之间工作,主动管理风险并限制非预期的差异;
- 按需进行发布是指构成复杂产品的不同子系统或组件,可以各自按需灵活安排自己的发布活动,只要合理、合规就可以在任意适合的时间进行发布。
发布火车的实现细节
发布火车的实现细节如下图所示(引用自EXIN DevOps课程的TTT讲师 Bart de Best):
使用发布火车将发布包从构建状态逐步发布到测试及生产环境。
- 发布火车传输的内容是发布包,而非代码(曾经遇到有些团队用发布火车模式来传递代码,这种方式问题较多,而且不符合持续交付的单一制品原则);
- 只有出示了“车票”,才被允许上火车;
- “车票”是指有效的测试结果;
- 在发布之旅中有很多的“站点”;
- “站点”可以理解为不同的环境(开发环境、集成测试环境、验收测试环境、生产环境);
- 每个站点上特定的“关卡”,指的是特定环境上不同级别的测试;
- 火车会一站接一站的运行,从开发到测试,从测试到验收,从验收到生产,递次运行;
- 每列火车有一个火车司机,火车司机就是发布经理;
- 火车司机(发布经理)负责判断是否可以上车,除了检查是否有车票,还要关注系统间的依赖和冲突;
- 如果发布包没有赶上这列火车,或者有Bug,将会被放置在站点上等待;
- 直到修复Bug、通过测试(取得车票),并且满足依赖之后,才能通过关卡,并搭乘下一列到达站点火车,奔向下一站;
下图形象的展示了整个过程:
发布模式的支撑技术
为了做到更快速、更稳健的发布,仅仅引入相关的方法是不充分的,还需要在自动化发布技术、架构解耦、可部署性、可靠性、快速恢复能力等方面进行建设。
除此之外,以下技术实践的使用有助于实现更为灵活的发布模式:
- 功能开关。功能开关打开或关闭,可以控制在生产环境上的功能是否对最终用户可见。比如刚才提到的多种发布节奏混合的场景下,可能需要采用多分支的模式匹配不同的发布版本。 使用功能开关的技术,就可以转变为主干开发模式,并有效规避并行多分支的问题。
如下图所示,Spotify公司在使用发布火车模式时,利用功能开关把未完成功能在发布时做隐藏处理,这样可以尽早暴露集成问题、最小化对并行分支的需求,并降低发布火车模式下分支管理的复杂度。
- 金丝雀发布。在发布变更到所有用户之前,可以先发布到一小部分用户,降低直接发布到生产环境所带来的风险。
比如依次发布变更的功能到10%、20%、50%的用户,并在每个节点验证一段时间,最后再进行全量发布。
在发布火车模式中,对生产环境的发布可以按金丝雀发布的模式,拆分为数个更小的发布阶段来控制风险,如下图所示:
三、总结
今天介绍了几种常见的发布管理模式,在不同场景下综合应用这些模式可以在更快速地交付高质量的可工作系统。
发布管理模式的一些核心要点如下: