提到DevOps,很多人就想到了CI/CD Pipeline,甚至很多个人或者企业认为完成了CI/CD Pipeline就等于实现了DevOps,虽然这种观点有失偏颇,但是从侧面反映了CI/CD Pipeline在DevOps中扮演着举足轻重的地位。CI/CD 是DevOps 的两大关键核心能力。CI/CD Pipeline的真正实现会加速企业向DevOps转型的进程。本文将揭开CI/CD Pipeline的神秘面纱,来一探究竟。
一、什么是 CI/CD Pipeline
Pipeline 指管道或者流水线,类似于工厂里的生产线,原料从一端输入,中间经过多个工作中心,一个工作中心的输出作为下一个工作中心的输入,最终在另一端输出高质量的产品。CI/CD Pipeline 指CI/CD的流水线,在输入端输入源码,经过既定工作流,最后在输出端输出对用户有价值的产品。从字面就能看出侧重点持续、流水线。
CI/CD Pipeline的简单示意图如下。
开发人员提交完代码,经过一系列的流程,最后生产出有价值的应用程序。
二、为什么需要 CI/CD Pipeline
DevOps的出现就是为了解决实际问题:打破横亘于开发人员与运维人员之间的壁垒。CI/CD Pipeline 可以帮助实现这个目的:开发人员在代码提交之后,就有CI/CD 流程来对所开发代码的功能性,健壮性,安全性等进行验证,如果验证失败,就返回至开发人员处,继续修改;如果通过既定流程,就可以进行生产部署。
当然,整个流程必须是完备的,测试环节必须是严谨的,开发环境,测试环境,生产环境应尽量保持一致,以此来避免环境不一致导致的上线失败。且整个过程中所有的变更,包括代码变更,部署脚本变更,环境配置变更都是可追踪的,便于出现问题之后进行回溯与复盘。这样,开发人员就不会担心代码不能够及时部署到生产线,而运维也不必担心新上线的代码会导致系统崩溃。
此外,CI/CD pipeline 有助于缩短应用程序的发布周期,提高应用程序的发布频率,快速获得市场反馈,及时作出响应。这种良性循环有助于应用程序抢占市场,给企业带来效益。
《凤凰项目: 一个IT运维的传奇故事》中比尔团队的故事就是对上述过程的一个很好佐证:当比尔团队将凤凰项目的部署流程梳理清楚之后,进行了"流水线"(书中虽不叫CI/CD Pipeline,但是内容却是一样,可以认为是CI/CD Pipeline的雏形)改造,在大大提高凤凰项目发布频率的同时,业务部门与IT部门之间的矛盾也变得越来越少,公司盈利了,也就避免公司被拆分,IT部门被外包的风险。
基于此,CI/CD Pipeline 一般具有以下几个特点:
- 标准化的步骤:应用程序交付流水线中的构建,测试等步骤,一个都不能少,而且环环相扣。
- 可自动部署:从代码提交那一刻起,一切流程都应该是自动的,自动化的好处毋庸置疑:节省时间,减少人为干预,避免人为误操作;"一键式"部署让部署变得简单。
- 适用多种语言:CI/CD Pipeline 应该适用于大多数甚至全部语言类型的应用程序,java,php,python。可能只需针对不同语言做少量调整。而不需要每种语言对应自己的CI/CD Pipeline。
- 具备可移植能性:应用程序在不同部署环境下(比如从公有云到私有云,从AWS的Kubernetes 平台到IBM的Kubernetes 平台)迁移的时候,Pipeline 可以在不改动或者少量改动的前提下,完成迁移,这样提高了灵活性,减少了工作量。
三、CI/CD Pipeline 包含的阶段
一般来讲应用程序交付流水线有如下图所示的几个阶段:
3.1 计划阶段
此阶段主要是项目经理或产品经理从用户处获取应用程序的相关信息,从而制定开发计划,来对后期开发进行指导。在敏捷盛行的今天,很多公司在此阶段都用敏捷来进行开发管理,以迭代的方式来完成用户故事的开发。
3.2 编码阶段
这个阶段主要是开发人员通过IDE来进行代码开发,开发人员借助于安装在IDE内的一些插件,来编写符合公司编码规范和安全需求的代码。
3.3 构建阶段
构建阶段是可以算是CI/CD Pipeline的真正开始阶段,开发人员在本地完成代码开发,并将代码提交到源码控制工具(比如git),此时会触发CI流程,进行代码扫描,编译,单元测试及覆盖率测试等工作。如果流程是成功的,那么代码就会被合入主干分支(合并可以是手动,也可以是自动,这取决于项目的开发模式与规定)。而一旦某个环节出现失败,都会使得整个流程中断,并将相应信息反馈至开发人员处。
3.4 测试阶段
代码被部署到测试环境并展开一系列的测试工作,包括手动的,自动的;功能的,性能的,安全的。需要注意的是,此阶段测试所需环境最好与生产环境保持一致,避免因环境不一致导致的上线失败。
3.5 版本准备阶段
测试阶段验证成功以后,可以认为代码已具备上生产的能力,测试通过的版本被标记为可以上生产,只需要手动或者自动操作(取决于项目规定)就可以将版本推送至生产线上。
3.6 部署阶段
将应用程序部署到生产线上。可以采用手动或者自动的方式来完成部署,同时可以采用蓝绿部署,金丝雀部署等方式来实现"零宕机"、安全部署。
3.7 维护阶段
应用程序上线后,运维团队需要确保应用程序运行环境的稳定,在访问量高的时刻能够自动扩容来应对峰值,访问量低的时候缩容以减少资源消耗。
3.8 监控阶段
监控应该包含两方面的:应用程序的监控和Pipeline的监控,借助于监控工具来获取一些有效数据,然后反馈给开发团队,或者运维团队,以此来进一步提高应用程序及Pipeline的稳定性,安全性。
CI/CD Pipeline 几乎等同于应用程序交付流水线,它与之相对应阶段的关系如下图所示。应用程序交付流程从计划阶段开始,而CI/CD Pipeline开始于应用程序开发阶段。
四、CI/CD Pipeline 的实现
CI/CD Pipeline 也可以用三步工作法来实现:
- 第一步:实现从输入端源码到输出端产品的正向流程,将源码构建,测试,版本准备,部署,运维几个步骤串起来;
- 第二步:实现从各个阶段至开发阶段的持续反馈;
- 第三步:在运行过程中与开发,安全等团队合作进行持续改进。比如,让部署流程、检测报告、监控信息可视化。
CI/CD Pipeline 的实现要依赖于一些工具,这也就是为什么很多人说DevOps是工具的合集的一个重要原因。虽然观点不全面,但是工具确实是实现DevOps不可缺少的一环。
工具的选择可以遵循以下几个原则:
- 拥抱开源
拥抱开源俨然已成为IT行业的一种新趋势,开源意味着免费,这可以进一步降低企业成本,另外开放的源代码对软件问题的追根溯源有很大帮助,最重要的一点是,可以借助于开源来快速推出有价值的商用产品,比如借助于开源的Linux,Redhat公司推出企业级的Linux产品;借助于开源的Docker和Kubernetes,亚马逊,微软,谷歌,IBM等公司都加速完成了自己企业级云产品的商用。
- 社区强大,用户数多
开源工具的选择必须要考虑社区的大小和用户的多少,社区大,用户多,开源工具的迭代就快,功能就强大,出问题也能找到相应的解决方法。比如 Jenkins,强大的中英文社区,超过千万的用户,让其变成了最后欢迎的一款持续集成工具。
- 丰富的API
CI/CD Pipeline 是工具的集合,工作中心与工作中心的就是工具与工具之间的交互,也就是API的相互调用,如果一款工具具有丰富的API,那么就比较容易将其整合进CI/CD Pipeline。比如Github,就有关于release,commit,pull request等各种API。
- 易学易用
一款工具能够快速上手,容易使用,就能够加速CI/CD Pipeline的开发,降低CI/CD Pipeline的维护难度,大大减少了工作量。
五、CI/CD Pipeline 发展趋势
CI/CD Pipeline 一直在发展演进,其主要的发展变化有以下几点:
5.1 云原生
CI/CD Pipeline 的发展方向跟应用程序是一样的:云原生。有一些云原生的CI/CD Pipeline工具,比如Jenkins,Tekton等已经出现,它们能够进一步提高CI/CD Pipeline的效率,加速云原生应用程序的构建。
5.2 GitOps 和ChatOps
GitOps 和 ChatOps 将占据重要的戏份。GitOps 和ChatOps 可以将团队,工具,流程,自动化等组成一个高效的、透明的工作流,工作进度一目了然,所有变更可控、可回溯跟踪,产品的研发效率会随着团队之间沟通协调效率的增加而提高。
Github Action就是GitOps的一个典型例子。Slack 的bot 就是ChatOps的一个典型例子。
5.3 平台化
平台化的好处毋庸置疑:通过将工具,流程的有效整合,使得软件开发生命周期的整个流程透明化,数据可视化,部署流程自动化,为持续反馈,持续改进提供重要依据。
六、CI/CD Pipeline 的一些反模式
6.1 与开发没有关系
开发人员对于Pipeline的认识不足,开发模式不做任何改变。代码提交频率没有提升,可能是三天一次,甚至是一个新功能提交一次。这样就不能充分发挥Pipeline所带来的优势,产品发布频率就不高。此外,开发认定的工作范围只是到提交完代码的那一刻,不去关心整体流程的成功与否,不去获得持续反馈信息。一旦出问题了,就直接找运维。一次次的 "穿新鞋,走老路" 也就导致DevOps 转型的失败。
6.2 构建时间太长
为了保证代码质量,实现一键式部署,Pipeline会集成所有的步骤,Pipeline就显得格外臃肿,一次构建需要几十分钟,甚至几个小时(比如采用appscan完成代码的动静态扫描)。开发人员不愿意提交一次代码,等待如此长时间的构建。就会降低代码提交频率,一次提交多个变更。由此,Pipeline成了提高产品发布频率的瓶颈,持续集成和持续部署就更无从谈起了。Pipeline应支持产品随时随地部署,可以一天完成多次部署要求。就好比一条路,不限制上面跑的是人还是车,跑多快,有多少。
6.3 反馈信息简单
当某个步骤的失败导致整个流程终止时,仅仅用一句构建失败来通知相关人员。这种不明确的通知就需要相关人员齐上阵一起查处问题的根源,这是一种浪费。构建过程中产生的信息应尽量详细,比如代码编译失败,单元测试失败,镜像检测有漏洞等。如果是微服务,还应该明确是哪个服务。这样在第一时间就有相应的责任人去快速修复。
6.4 漏洞是安全团队的事情
当扫描出安全漏洞时,都认为是安全团队的工作范畴。报告在,没人管。其实,安全的范围很大,错误的配置信息,代码中的敏感信息,都算是漏洞。不同层面的漏洞应该有不同的团队来负责,比如与应用程序代码相关的应该是开发团队负责,与基础设施相关的应该是运维团队负责,而且两个团队应该与安全团队协调合作,共同修复漏洞。
6.5 不合理的人工干预
当修复紧急故障的代码覆盖率不达标,但又不得不上线时,通过降低,甚至取消代码覆盖率检测来使Pipeline成功;当Pipeline在最后一步失败时,为了节省时间,避免重新构建时,通过手动修改流程或者配置来完成Pipeline。这种为了节省时间而引入的不合理的人工干预,破坏了Pipeline的完整性,人工干预是不可追踪的,引起的故障很难回溯。Pipeline 是一个流程,既然是流程,就应该根据流程走。
6.6 害怕失败
害怕构建失败,失败就意味着代码有问题,大家集体炸锅。为了每次构建都得到绿色的结果,调低检测阈值,剪掉经常出错的步骤,最后是开发happy,运维happy,测试happy,大家集体happy。其实,失败是持续改进的推动力。持续改进的Pipeline才是实用的Pipeline。
七、结束语
可以看到,"流程 + 工具 + 自动化 ≈ CI/CD Pipeline" 。也就不难理解,为什么会有DevOps就是流程,就是工具的集合,就是自动化等这些误区的存在。DevOps是一场文化运动,CI/CD Pipeline是这场运动在企业落地实践的强有力手段。
附录
下图是基于Kubernetes平台的一个CI/CD Pipeline 示例,仅供参考。
图中出现的工具均为开源工具,但不是说图中出现的工具就是最好的,必选的,工具的选择需根据前述原则来进行。
最下面的属于监控系统,通知系统,每套环境都用到了,而且贯穿整个流程。所以只画一次。
CI 流程如果成功,既可以手动也可以自动部署测试环境;同样的,如果测试环境测试成功,既可以手动也可以自动部署生产环境。以此完成CD流程。
作者:马景贺
马景贺,人称小马哥,花名逍遥子。曾做过LTE 4G网络协议开发,后转向 DevOps,对于Cloud Native DevSecOps进行布道,喜欢研究docker,kubernetes,istio等Cloud Native相关技术,乐于分享,运营着DevOps SIG公众号。曾在大连DevOps社区活动上,举办DevOps Workshop活动。
参考资料
- 《凤凰项目 一个IT运维的传奇故事》作者 (Gene Kim, Kevin Behr,George Spafford),人民邮电出版社
- 《DevOps 实施手册 在多级IT企业中使用DevOps》作者 (Sanjeev Sharma),清华大学出版社
- https://opensource.com/articl...
- https://www.red-gate.com/simp...
- https://devops.com/continuous...
- https://www.plutora.com/devop...
- https://medium.com/taptuit/th...
来源:CIO Talk
5月每周四晚8点,【冬哥有话说】质量与测试专场。公众号留言“质量”可获取地址
- 0506 朱少民 《如何最大化软件测试效能》
- 0513 神秘嘉宾 神秘话题
- 0520 陈霁 《没错,去QA是提高质量最有效的方法!》
- 0527 施慧斌 《DevOps实践之持续测试》