软件开发生产线 CODEARTS-基于Pipeline的DevOps核心实践:不同研发模式下流水线的应用与思考
不同研发模式下流水线的应用与思考
第二部分重点讲述基于华为的流水线支撑的实践,支持三种主流模式:
- 第一种模式:大规模开发
华为起家的核心是交换机,交换机本身业务分成多层架构,例如上面的控制层到下面的数据传送层等。在自我分层的基础上,向上对接网管等各种监控工具,再横向和后端的传送网、骨干网对接,进行数据的传递和核心的传递。在这个基础之上,华为做了一个2012实验室——这是一种大平台战略,几乎所有的产品线产品都会用到的公共平台,而且这个平台的能力是重平台薄产品,平台会达到80%的代码量,可能会越来越大。这时候如果产品要用到另外一个BG产品线的平台就是一个非常大的困难了,在产品线内部也会尽量把一些公共特性下沉为小平台,所以一个核心网络产品从各个角度来看,复杂是最核心的特点。
产品的代码量是非常大的。一般来说,一个产品一百万行或者几百万行是非常正常的,需求一千万行也是非常正常的。这么大规模的代码不可能由一个团队开发,CodeArts是由产品线以及各种周边配合,涉及的团队非常复杂。基于时代背景来看,核心网络产品要交付出来,在以前经常需要一年多以上,基本是一年一个版本,半年的时间做线上验证,包括到客户的机房验证,那个时候升级都需要选访问量最低的时候进行半夜断网升级。
怎么保证迭代的速度加快,迭代的质量逐步变得更好呢?后来我们探索了一套模式是分层分级流水线,进行大规模开发的持续交付模式,建立一个合理的结构,我们通常会分成四层。
个人级流水线:团队一般每天提交几次到数十次不等。这时候在本地会先做代码的增量静态检查、增量单元测试,以及功能测试。如果这些检查都没有问题,全部通过,代码会上传到云端配置库。此时触发一个提交构建,就到了项目级流水线。
项目级流水线包括提交构建、滚动构建和全量构建。提交构建通常需要做的是全量的静态检查和冒烟用例。个人级和项目级流水线提交构建,随时提交就能够触发整个构建和流水线的运行和执行,属于随机发生模式。滚动构建和全量构建属于班车模式。班车是定点定时发,无论是坐地铁还是公交车、火车、飞机,时间是固定的,每个人去赶飞机、地铁、公交,如果迟到就需要等待下一趟。对于一个研发团队或者一个产品,一天内代码提交通常有三个峰值,上午10-11点是一个峰值,下午5点左右是一个峰值,晚上8点多有一个属于加班同事的小高峰。所以一般来说,一个项目级流水线会发三个班车,就是中午12点、下午6点、晚上9点半,这三个班车永远是固定的,团队无论有无提交都会发车,定点执行。
这就实现了一个协同,有多个人提交或者每个人提交都会执行,执行的时候会看结果如何。这种时候一般会做基础用例、拉通用例、滚动用例模式。如果定点发车了,会推送到全量构建,解决他们的协同发布。通常是晚上12点会执行一轮,第二天早上整个项目组的同事就收到了流水线测试的结果。如果成功了,大家欢庆一下;如果不成功,就赶快解决问题,因此所有人一早就要解决持续交付流水线的问题。
滚动构建成功之后,还会把这个包归到版本级流水线的构建里面,在版本级流水线里面滚动构建并测试,当这些全部执行成功后,就会再向下游拉通全链条测试。对于版本级流水线,滚动构建也会投入流水线当中,会比项目级构建晚两个小时,如果自动化率足够高,大部分问题都可以解决。
所以,对于一个典型的大规模敏捷产品,我们有四层分级的流水线,里面有随机发车和定点发车的模式,也有实现这样的高速流转的对应解决方案。
在此过程中,流水线在每一个执行阶段都会有一些门禁的判断,任何一个任务跑完了,都有门禁进行把控。只有通过项目组设定的门禁,才能向下走;如果不通过,流水线就终止了,先把基于静态检查的问题解决完,才能继续向下走。这种方式,不像过去有最终的发布评审,到最后的上线环节再搞发布评审,而是在每一个部分就会把所有的门禁做上去,由此来保证在每一个任务的成功和每一个阶段的成功,以保证最终的成功。
此处与传统的交互模式做一下结构比较,传统交付模式越向后的环节越容易出现问题。例如产品级或者解决方案级一集成,越向后,问题会越来越多、越来越大,再返回来到每一个小团队解决问题,实际上这已经比较晚了,解决的成本也很高。使用了分层分级流水线之后,越向前的环节发现越早,就把问题拦截下来了。
从我们的分析和实践结果来看,假设有四层流水线,个人级提交一定最多,因为每天有几次几十次,每个人提交到代码仓的构建在两次左右,除非BUG多一些。再向后就到了班车模式,一般来说,每天进行三次滚动构建。到最后的全量测试,每天执行一次即可。通常越前端的流水线会越早发现问题,原来是最后进行发布评审,现在如果是有了每个任务的质量门禁,每次执行的时候,越在流水线的前端环节,被执行的次数越多,发现问题的概率也越高,符合分层分级流水线的理念结果。
当然,分层分级持续交付的模式下面,会有很多其他构想。包括如何快速搭建第一条流水线,不同层级的流水线如何快速复制,并且搭建自己对应层级的流水线,以及上一级流水线成功后如何自动触发下一级流水线的执行,这些是最基本的思考。
- 第二种模式:微服务开发
CodeArts团队本是一个微服务化的实践者,有100多个微服务,基本全部微服务化,前端已经全部拆解完。在这个模式下面,首先,架构解耦;其次,结构上最终一定要实现每一个组件足够小,而且尽量没有依赖的。在这个基础上,每一个团队能够比较自由地自我裁决、自我决定。比如发布,以前在传统的模式下,一个团队肯定是要分运维团队、测试团队或者是开发团队、产品团队、QA团队(都是单独的),真正在微服务开发模式下,做成一个全功能团队之后,已经没有非常明显的角色分工,很多功能测试等等都是由开发人员自己去实现的,这个时候对于开发人员来说,既是开发人员也是测试人员、运维人员,会对运维服务的开发、测试、上线、结果,会端到端负责。所以我们针对微服务会做权限的设置,去匹配新的角色模式,一个人可以端到端的执行完整条流水线。上线之前还可以有一个环节,例如和产品经理一起看一下是否满足客户需求等等,如果后续流水线承载的自动化测试的手段都能够完全达到质量发布的条件,届时也不需要评审了。整个过程有40-50%做到不需要人工干预,下一步这个比例还会继续放大。
因为微服务化了,这100多个组件中间还要发一些补丁,一天内都上线是很糟糕的事情,每个微服务中断几分钟,一天下来是几百分钟,整个服务就不可用了。因此微服务模式下一定要实现灰度发布,最基本不能中断业务。
CodeArts团队在最早的时候,每个星期五晚上要12点开放升级,把测试和研发团队、领导都喊起来,整个团队从2点到4点进行测试;测试完成后,4点之前我们决定BUG修复完,再回溯一遍。这个过程每周一次,那时团队成员很痛苦、疲惫,第二天一整天什么也做不了。
后来通过微服务实践和灰度发布实践,才把团队从超级繁忙的、每周一次的超级作战中解放出来,这对团队整体的士气和工作效率的提升都是非常明显的。如果真的发现在灰度测试中出现问题,或者版本有重大的缺陷,要能够触发自动回滚或者手动回滚。这时候运维人员会选前一个包直接启动流水线部署,把灰度测试灰度过的环境全部覆盖掉。
在微服务开发模式下,管理很重要。使用K8S时,如果版本号不增长就不会部署(只要版本不变,就认为是同一个包,因此不会启动部署)。所以版本管理、版本增长等方面都要在流水线上做到位。同时因为这种发布模式时间非常短,我们可以做到小时级、分钟级发布。这种情况下,我们会通过线上A/B、加大测试,在线做各种自动化测试,包括拨号测试、性能测试、压力测试、安全测试等等。在真正大规模灰度之前,就已经把基于真实环境的质量构建好了,其中在线测试、前置测试的比重都要加大。
- 第三种模式:静态资源部署
静态资源部署不需要重新编译构建出包。通过部署流水线,把静态资源拉包,部署到北京、上海、广州、成都等等各个CDN去。在这个过程中,多地区的并行部署以及跨地域的部署是CodeArts重点支持的方向。