大略先容CICD
持续集成(Continuous Integration)简称CI,持续集成强调开拓职员提交了新代码之后,急速进行构建、(单元)测试。根据结果,我们可以确定新代码和原有代码能否精确地集成在一起。持续集成过程中很重视自动化测试验证结果,对可能涌现的一些问题进行预警,以保障终极集成的代码没有问题。持续交付(Continuous Delivery)简称CD,持续交付在持续集成的根本上,将集成后的代码支配到更贴近真实运行环境的「类生产环境」(test,testing)中,然后交付给质量团队,以供评审。如果评审通过,代码就进入生产阶段。持续交付并不是指软件每一个改动都要尽快支配到产品环境中,它指的是任何的代码修正都可以在任何时候履行支配。有的人也把CD称为Continuous Deployment(持续支配),持续支配是指当交付的代码通过评审之后,可以支配莅临盆环境中。这里须要把稳的是,持续支配该当是持续交付的最高阶段,持续交付是一种能力,持续支配是一种持续交付的表现办法。
猪八戒网的CICD之路

1、背景先容
在提到ZBJ DevOps 流水线之前,先交代一下历史背景。2015年前,猪八戒网80%的项目都是用php措辞开拓的,剩下的少部分利用的是nodejs和java。2015年,ZBJ研发中央进行了自发性的“工业革命”——腾云七号行动——利用java措辞将核心业务代码进行了重构和拆解,建立了以dubbo为核心的SOA微做事框架,利用zookeeper+swoole为核心的业务调用供应机制。知足新业务利用java措辞编写、老业务仍旧利用php编写,同时支持两种措辞(nodejs&php)调用dubbo做事的能力。
之后,开始全面实行前后端分离,于是盛行了沿用至今的主流架构:
1、nodejs:卖力前端
2、java:卖力后端
3、php:卖力老项目掩护
剩余部分小系统或者边缘化的工具利用其他措辞开拓,或者在此三种措辞根本上的一些变种:
随着业务的重构和拆解,以前一个个弘大的系统被拆解成多少个独立的小系统,使得交付变得更加随意马虎。
而随着项目工程数量的快速增长,交付开始变得频繁,传统开拓模式的一两个月交付一次远远不能知足交付哀求,改变迫不及待。
2016年Q3季度,感想熏染到改变迫不及待,ZBJ研发中央经充分准备后决定抽调部分运维同学和开拓同学组建一支名为"DevOps取经团"的团队,力争打造属于ZBJ自己的以提高研发效率为目标的平台。
2、ZBJ CICD发展史
第一阶段 2015年以前
2015年以前,此时“工业革命”还未开始,ZBJ所谓的流水线先后经历了“大锅饭年代”、“公交车模式”
大锅饭年代 本图由DevOps团队供应
公交车模式 本图由DevOps团队供应
可以看到,无论是“大锅饭年代”,还是“公交车模式”都会面临很多问题:
1. 项目耦合度太高,随意马虎导致合并冲突,环境冲突等。
2.集成过程中未对代码进行审查,缺点代码发布到测试环境后,会影响依赖方的测试。
3.发布受限定,必须在专门韶光由专人发布。
4.发布非常时,回滚事情非常困难。
第二阶段(2016-2017)私家车模式
通过“工业革命”的变革,对系统的重构和拆解,同时引入工程任务制,给每个工程指定卖力人,对工程的各种权限进行了管控,业务范围和边界变得更加清晰,使得项目耦合度太高的问题得到了很大的缓解。
办理了项目耦合度高的问题,接下来办理如何实现随时由开拓团队自主发代码的问题
1)用jira做研发流程管理,制订针对zbj需求上线的流程
2)需求上线流程每个环节对应流水线的每个环境,只有到达某个环节,才能推送对应环境,每个环节会制订对应的准入准出,担保每走到的下一步都离成功支配更近一步。
推送环境示意图
3)每个环境制订不一样的实行任务,基本包括jira状态校验,代码审查(单元测试),编译构建,上传包到制品库,拉取制品库中的包支配到对应环境。
值得把稳的是,我们引入了docker发布,以是我们的流水线是支持容器和虚拟机的稠浊发布的。虚拟机发布办法的制品是存放在一个叫做文件做事器的地方,容器发布办法的制品是push到harbor仓库的。
容器发布&虚拟机构建打包示意图
4)采取的分支策略是:branches开拓,master发布,tags存档(我们利用gitlab作为源码管理工具)。在测试环境常日为非master分支,测试完毕后合并到master,推送预发布,并针对当前版本打一个tag。针对这种情形,我们的“一次构建,处处利用”指的是测试环境用测试环境构建好的包,其他环境用预发布构建好的包。
各环境利用制品示意图
5)在推送每一个环境(test环境除外)时,都会校验当前版本的代码是否为前置环境推送过的最新代码,担保不会将没有经由审查的代码交付到线上。
6)在测试环境每一次编译构建之前,都会对代码进行一次安全扫描,java措辞的工程通过解析pom文件对其所有的依赖进行递归扫描,nodejs措辞的工程通过对node_module里下载的包进行递归扫描,确保有安全漏洞的代码不会被带入莅临盆环境。
7)编译构建时,会根据开拓措辞的不同,实行不同的编译脚本,根据发布办法的不同(虚拟机发布或者容器发布),实行不一样的后续操作步骤。
8)我们将jenkins作为后台编译做事器,采取的是多master多slave的架构,我们并未直策应用Jenkins的流水线,而是开拓了一个叫pipeline的系统,与jenkins做对接(此时的对接办法是调用Jenkins的API),由pipeline系统供应jenkins作业所须要的全部信息,其余编写了全体过程须要详细实行操作的脚本,通过jenkins的job配置"Execute shell"的办法每次在构建之前导入到事情空间。
流水线标准生产过程大体如下:
流水线标准生产过程示意图
其余,针对回滚的情形,由于每次在上线前都会在预发布会构建一个稳定的版本,并打一个tag,并且记录下tag对应的制品(包或者镜像)版本,以是在回滚的时候,只要选择要回滚的版本,便能找到对应版本的制品,进行重新发布,以此达到回滚的目的。
至此,第二阶段大体实现了以下功能:
1)通过用jira需求上线流程和流水线做整合,以及多种推送前的校验,担保了上线过程的每一步都是可靠的
2)每一个环境的集成和发布都是自动化的
3)由于过程变得可靠且自动化,使得将发布过程开放给研发团队成为了可能,达到了随时自主上线的目的。
问题:
然而这样的流水线也有诸多问题
1)不足灵巧,如在推送测试环境时,全体过程实行的步骤是固定的的,即第一步做什么,第二步做什么都是固定的,不能新增也不能删减,如某些团队须要进行单元测试,有的不须要,但流水线都会去实行单元测试,常日情形下单元测试过程是一个花费韶光比较长的过程,这对付须要频繁变动和支配的业务是不友好的。
2)推送成功率不高,由于全体过程是串联的,某一个环节涌现缺点,将会导致本次推送失落败,而某些环节本不应该影响构建结果的,末了导致了构建失落败。
第三阶段(2017-2019) 拥有灵巧车道的私家车模式
考虑到前面提到的两点,ZBJ DevOps团队在17年底对流水线做了二次改造:
1)所有实行步骤拆解成独立原子任务,建立原子任务库;
2)将原子任务根据功能性分为两种,校验类以及实行类,校验类原子任务紧张是是做准入准出的判断,实行类紧张是编译构建,打镜像,上传hub仓库以及支配。
3)将原子任务根据实行载体分为两种,Java类和jenkins类,直接用java程序实行的任务为Java类,须要jenkins实行的任务为jenkins类。
4)根据开拓措辞、发布办法、业务类型的不同,从原子任务库中选取不同原子任务组成一条标准有序的实行流水线。
5)供应工程分外配置,如有些工程须要增强校验,有的工程须要减少校验,则可以通过启用和禁用的办法进行分外配置,如下图所示,根据1,2和3步骤后可最终生成一条本次实行的流水线任务列表。
原子任务一览表
实行效果图
6)根据原子任务的制订,我们将jenkins实行的job也拆分成了对应的几类,每一类拥有足够多数量的job进行任务的实行。
7)升级了pieline系统和jenkins通信架构,通过编写一个rabbitMQ的插件植入到jenkins master上,从原来调用API的办法,改成用rabbitMQ的办法进行通信,大大提高了效率和成功率.
通信示意图
8)升级了Jenkins 架构,构建一个能适配zbj所有开拓措辞的镜像,利用jenkins master的K8S插件,将原来的虚拟机slave节点全部更换成容器slave节点,并且这个slave集群完备由jenkins master的k8s插件调度,不论在高并发和低并发的时候都能及时扩缩容,知足业务需求。
第四阶段(2020-至今) 智能驾驶模式
可以看到,到第三个阶段为止,我们的每一次编译过程,都须要研发同学“推送一下”,而且这个过程也是须要花费一些韶光的,比如一个正常的nodejs工程均匀编译时长至少须要花费100+s以上,一个正常的java工程均匀编译时长至少也是须要30s以上,由于我们供应了推送过程“可视化”的功能,且没有实行结果的关照,导致用户必须关注推送过程以确保本次推送是成功的,大大摧残浪费蹂躏了研发同学的韶光。
在此根本上,我们进一步做出了以下优化:
1)为每一个gitlab上的工程添加一个webhook,每当开拓职员向仓库push一次,便会触发webhook,调用pipeline系统接口进行一次快速构建
把稳:并不是每次push都会进行一次快速构建,为了防止开拓同学频繁修正少量代码提交到版本库,我们规定了一个“暗号”,只有当开拓同学在commit message中添加这个“暗号”,才会触发一次快速构建。
auto_trigger_build便是暗号内容
2)快速构建的结果是构建一个包或者一个镜像,存放在前文提到过的文件做事器或者harbor仓库。不才一次用户“推送”的时候,便会根据分支和版本判断是否存在已编译过的包或者镜像,如果存在,则直策应用,跳过编译过程。
3)增加快速构建结果关照,由于全体快速构建过程是后台实行的,以是流水线系统通过企业微信的办法关照到用户本次快速构建的结果
快速构建前关照
快速构建完成后结果关照
4)除了增加快速构建的关照,我们还增加了推送的关照。用户再也不用关注推送过程,只须要在推送后连续做其他事情,推送结果由企业微信关照到用户。
值得把稳的是,当推送失落败后,流水线系统也会关照到用户,进行对应问题的排查。
至此,ZBJ的CICD实践之路基本先容完毕,当然,个中也还有很多细节方面,由于涉及的东西太多,不便铺开来讲。
总结三次重大改造的结果
第一次改造:奠定了ZBJ的CICD根本,打造了一条标准的流水线,解放了运维劳动力(过程全自动化),提高了研发效率,降落了研发本钱(运维同学由最多时候的三四十个减少到了不到十个人)。
第二次改造:流水线实现了高可用,同时其灵巧的配置能完美知足不同业务团队的需求。
第三次改造:提升了流水线效率,弱化推送过程,增强以人为本的体验,使推送过程更加智能化。
谈谈未来
CICD实践之路还在连续,由于不同公司有不同的业务场景,而同一公司的业务也会随着时期的发展不断变革,只有适宜自己的才是最好的,只有能拥抱变革的才是最好的,但万变不离其宗的,我以为该当有一下几点:
1、CICD该当因此提高研发效率为目标的实践,统统分开这个目标只是为了迎合什么口号而做什么的是都是耍牛氓。而实现这个目标是一个比较漫长的过程,一开始会比较随意马虎,后面就会越来越难,这须要不断思考和学习的过程。
2、CICD该当是紧贴业务的,由于业务的不同,哀求的技能架构也会有所不同,随之而来,哀求的交付办法也会有所不同。
3、CICD该当因此人为本的,我们该当尽可能地将统统繁琐的过程交给程序去实行,而人只须要“坐享其成”或者做少量的决策即可。
末了的末了,走过途经,千万不要错过,对上述过程有不同见地的可以进行互换,感谢不雅观看!