CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法。CI/CD 的核心概念是持续集成、持续交付和持续部署。
作为一种面向开发和运维团队的解决方案,CI/CD 主要针对在集成新代码时所引发的问题(亦称:“集成地狱”)。
具体而言,CI/CD 可让持续自动化和持续监控贯穿于应用的整个生命周期(从集成和测试阶段,到交付和部署)。这些关联的事务通常被统称为“CI/CD管道(Pipeline,一般也称为管线或流水线)”,由开发和运维团队以敏捷方式协同支持。
1、CI持续集成(Continuous Integration)
现代应用开发的目标是让多位开发人员同时处理同一应用的不同功能。但是,如果企业安排在一天内将所有分支源代码合并在一起(称为“合并日”),最终可能造成工作繁琐、耗时,而且需要手动完成。
这是因为当一位独立工作的开发人员对应用进行更改时,有可能会与其他开发人员同时进行的更改发生冲突。如果每个开发人员都自定义自己的本地集成开发环境(IDE),而不是让团队就一个基于云的 IDE 达成一致,那么就会让问题更加雪上加霜。
持续集成(CI)可以帮助开发人员更加频繁地(有时甚至每天)将代码更改合并到共享分支或“主干”中。一旦开发人员对应用所做的更改被合并,系统就会通过自动构建应用并运行不同级别的自动化测试(通常是单元测试和集成测试)来验证这些更改,确保这些更改没有对应用造成破坏。
这意味着测试内容涵盖了从类和函数到构成整个应用的不同模块。如果自动化测试发现新代码和现有代码之间存在冲突,CI 可以更加轻松地快速修复这些错误。
2、CD持续交付(Continuous Delivery)
对于一个成熟的 CI/CD 管道来说,最后的阶段是持续部署。作为持续交付——自动将生产就绪型构建版本发布到代码存储库——的延伸,持续部署可以自动将应用发布到生产环境。由于在生产之前的管道阶段没有手动门控,因此持续部署在很大程度上都得依赖精心设计的测试自动化。
实际上,持续部署意味着开发人员对云应用的更改在编写后的几分钟内就能生效(假设它通过了自动化测试)。这更加便于持续接收和整合用户反馈。总而言之,所有这些 CI/CD 的关联步骤都有助于降低应用的部署风险,因此更便于以小件的方式(而非一次性)发布对应用的更改。不过,由于还需要编写自动化测试以适应 CI/CD 管道中的各种测试和发布阶段,因此前期投资还是会很大。
云化流水线是交付新版本软件必须执行的一系列步骤,是一种专注于通过自动化在整个软件开发生命周期中改进软件交付的实践,根据用户需要的场景,如开发测试环境应用部署、生产环境应用部署等,对这些自动化任务进行自定义编排,一次配置后就可以一键自动化触发调度执行,避免频繁低效的手工操作。
通过在软件开发生命周期的整个开发、测试、生产和监控阶段自动执行 CI/CD,能够更快、更安全地开发更高质量的代码。尽管可以手动执行 CI/CD 管道的每个步骤,但 CI/CD 管道的真正价值是通过自动化实现的。
流水线是通过生成、测试和部署代码的路径(也称为 CI/CD)推动软件开发的过程。通过自动化该过程,目标是最大限度地减少人为错误,并维护软件发布方式的一致过程。其中包含的工具可能包括编译代码、单元测试、代码分析、安全性和二进制文件创建。
从上面我们可以得知,流水线服务本质上是一个可视化的自动化任务调度平台,需要配合软件开发生产线中编译构建、代码检查、测试计划、部署等服务的自动化任务使用。
而流水线内置了一系列常用的插件,供用户在流水线进行编排时使用作为整个流程的某个环节。这样的插件是可扩展、可自定义的。利用流水线在执行过程中串行、并行的不同执行类型,以及顺序执行场景下对于各个步骤是否执行成功与否的判断,流水线插件在CI/CD的过程中可以起到重要作用。
1、代码检查
在服务开始尝试将代码部署到机器上时,首先必须要执行的就是将代码从代码仓中拉取、构建、打包等操作。
而对于代码本身而言,除了本地的一些代码检查规范外,我们还会在流水线中添加这样的检查步骤,对全量代码进行诸如规范性、安全性、圈复杂度、CleanCode等一系列内容的检查。
当服务尝试部署的代码中可能存在影响质量的严重问题时,代码检查中所暴露的问题会在该步骤的门禁检查中发现并直接拦截,禁止流水线进一步的向下执行,避免引入可能的风险和问题。
2、安全病毒检查
除了代码层面的检查外,我们还会对构建产物进行安全与病毒扫描,这里会直接与中央的病毒样例库连接做病毒的扫描和查杀,避免存在恶意病毒文件连同代码一起被打包上传到现网机器。
3、开源依赖检查
对于开源漏洞与依赖层面,我们也会进行相关的扫描与检查。毕竟对于三方依赖而言,服务自身在做开发使用的过程中可能并不关注该依赖是否有开源问题、当前版本是否已经过时存在漏洞等,因此对于这一系列依赖,我们会直接与自身的中心仓库做版本比较,其中包含三方库与二方库等,支持Maven、Pypi、Npm、Go等类型。
对于每一个依赖包而言,我们都会给出其对应的每个版本号是否为优选、可选或禁选。对于不再中心仓库的依赖包或者版本为禁选类型,同样的开源依赖检查会无法通过、流水线也自然无法进一步向下执行。
对于众多的检查与插件配置,上千个微服务、上万条流水线,我们如何才能保证所有的流水线都能配置了对应的具体插件呢?
对于高度自定义化的流水线而言,虽然可以提供某些模板机制,但本身插件配置对于不同环境、不同编程语言都会有各自不同的需求,由中央统一全量修改流水线虽然理论上可行,但过于机械、大费周章,被修改流水线的服务也有可能一头雾水、甚至流水线都被修改的无法执行,并不是最好的策略。
这个时候,我们一般会有更加直接且简单的措施:生产准入门禁卡点机制。
除了上述的一些常见流水线插件外,笔者方面同样基于插件开发规范、提供了相关流水线插件,旨在提升服务质量提升与问题提前拦截。
在基于云化测试平台的功能拨测与告警中我们提出,将服务在云化测试平台中所撰写的测试用例有效的组织起来,以不同的形式调度、检查,对服务的在线功能质量能够起到重要作用。
这里同样地,服务将当前所有认为较为重要的功能测试用例统一归纳在一个测试任务中,并在每个部署阶段完成后全量执行该测试任务,以检查新版本代码是否引入新的问题、是否对已有功能造成影响。
具体实现层面则较为简单,直接以任务执行是否达到100%为标准即可。对于存在失败用例的情况,流水线层面不允许向下执行。
在第一点中我们提出了用例通过率插件用以衡量功能可用性,但是这其中还存在另外一个问题:
对于用例的覆盖率而言,一般有很多评判标准:例如分支覆盖、代码覆盖等等。由于我们云化在线测试本质上是对服务接口的测试,因此这里我们引入了接口覆盖率来作为评判标准。
在具体实现上:
ActionWord
信息。ActionWord
,我们会逐个做内容解析、并汇总全量的测试任务覆盖API,同时与对应的API基线做比照,以此来计算整体的覆盖情况。
除了必要的功能可用性与测试覆盖率,我们还对接口本身的健壮度提供了相应的自动化测试与评估插件。
在具体实现与原理上:
接口健壮性测试可以协助服务提前返现代码中可能存在的异常情况判断与接口状态码规范问题,检查的结果也主要起到参考作用,并不会直接参与门禁卡点与强制拦截。
在CI/CD流水线的大背景下,虽然插件只是其中很小的组成部分,但合理的开发、运用与推广插件,不仅能够极大程度降低质量看护与运营门槛、提升效率,而且还能为服务带来很多额外的质量看护视角,从而提升服务在研发段的质量看护能力,降低现网的故障产生。
参考文章:
什么是 CI/CD - RedHat