什么是 CI/CD ?持续集成,持续交付,持续部署
什么是 CI/CD
CI、CD 其实是三个概念,包含了一个 CI 和两个 CD,CI全称 Continuous Integration,表示持续集成,CD包含 Continuous Delivery和 Continuous Deployment,分别是持续交付和持续部署。这三个概念之间是有前后依赖关系的。
CI/CD 并不是一个工具,它是一种软件开发实践,核心是通过引入自动化的手段来提高软件交付效率。CI/CD 最终目的:让工程师更快 & 更高质量 & 更简单的交付软件!
持续集成 & 持续交付 & 持续部署
持续集成(Continuous Integration)
什么是持续集成?
定义:
持续频繁的(每天多次)将本地代码“集成”到主干分支,并保证主干分支可用
持续集成这个词,起源于极限编程,是当时原始的12种实践之一,持续集成的目的快速反馈问题让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过编译、代码扫描、安全扫描、自动化测试等。只要编译失败、扫描出高级别问题或测试用例失败,就不能集成。
Martin Fowler 说过,“持续集成并不能消除Bug,而是让它们非常容易发现和改正。”
好处?
(1)通过自动化手段提高集成速度
在传统的研发过程中,一般通过手动方式执行编译、测试、部署,自动化后,可大幅提高集成频次,同时可以减少维护手工脚本带来的低级问题
(2)将问题前置
在每次 commit 时就触发编译、测试,更快的发现问题
(3)防止本地代码大幅偏离主干
如果不是经常集成,主干又在不断更新,会导致以后集成的难度变大,甚至难以集成。
触发方式?
自动触发,通过自动化的 CI 服务或工具,自动监听代码库 Git Push & MR 等事件触发
常见的工具如 Jenkins、GitlabCI、CircleCI、GithubActions 等等
蚂蚁支持持续集成平台有:雨燕(前端)、LinkE CI(后端)、伙伴(终端)、ACI(多语言)等
面临的问题 & 阻碍?
理想很丰满,现实很骨感,持续集成理念虽好,但实践过程中却有非常多的问题和阻碍,远没有想象中那么简单!
常见的问题如:
(1)执行环境异构导致结果差异
比如Java测试,用户执行测试一般是本地通过IDEA右击执行测试或 mvn 命令,但是 CI 服务上的环境&机器规格和本地有很多差异,比如 JDK 不一样、Maven 版本不一样、Mac 和 Linux 差异等等会造成很多本地执行可以通过但是 CI 上执行不通过,或者 CI 上执行明显比本地慢的现象。
解决此类问题本质还是减少异构,比如通过容器化方式让执行环境标准化,通过 Maven 缓存提高测试时间等等,同时作为 CI/CD 平台方,也最好将测试、构建的过程透明化(执行机制、清晰的错误码和解决方案),方便在出现问题的时候开发可以很方便的自助排查。
(2)没有严格的测试要求
持续集成的理念是只要有问题一定要及时修复,比如执行测试,必须保证所有case全部通过才能集成到主干,但是在现实中的场景,特别是一些规模大的历史项目,由于历史债等原因,导致测试case无法全部通过或者必须通过重试解决,开发很难有动力去改,导致集成质量低效。
所以,持续集成的前提是,需要有一个心里准备花大精力去治理项目中的一些历史债,尤其是改善历史 case ,补充新 case ,降低 case 噪音,确保每次自动化触发的测试可以准确反馈集成质量!
(3)非常慢的构建 & 测试速度
在 CI 上执行构建或测试的速度非常慢,导致集成效率非常低,这里的慢有两种原因,一种是本身测试&编译就慢,这时需要深入分析,需要结合并行分组、分布式缓存等技术解决。
这里的自动化测试中的集成测试可能会非常慢,所以一般保证在持续集成阶段先让单元测试通过,集成测试放在在持续交付阶段完成。
持续交付(Continuous Delivery)
什么是持续交付?
定义:
是持续集成的下一步,持续频繁地将软件的新版本交付到类生产环境(类似于预发),交付给测试、产品验收。
持续交付强调的是“交付”,不管怎么更新,软件是随时随地可以交付的,相比持续集成,持续交付除了交付到类生产环境之外,还会执行一些集成测试、API测试等等,确保交付的产物可以直接交付部署。
触发方式?
手动触发,通过研发平台手动触发(如触发LinkE预发部署流水线),一般交付结果是一个二进制包或者镜像
面临的问题 & 阻碍?
(1)很难保证和线上环境完全一致
由于持续交付的环境很难和线上环境一致,所以可能导致一些问题无法验证,使得交付的产物具备一定风险
探索方案:仿真环境
(2)大量脑壳疼的联调环境问题
经常遇到的场景是虽然本系统开发好了,但是由于各种原因导致上下游系统没有 ready 导致无法持续交付,针对上下游依赖非常多的系统,对联调环境稳定性、效率有非常强的依赖
(3)很难保证严格充分的自动化测试
持续交付最终要做到交付的产物可直接部署线上,那么对代码的质量要求就非常高,需要覆盖全场景充分的测试 case
持续部署(Continuous Deployment)
什么是持续部署?
定义:
是持续交付的下一步,“自动”将代码部署到生产环境
持续部署强调的是“部署”,它的目标是,代码在任何时刻都是可部署的,可以进入生产阶段。
持续部署和持续交付触发方式的区别是,持续部署是自动完成的,持续交付是手动完成的
触发方式?
自动触发,通过研发平台配置定时任务,自动获取交付产物进行自动部署。
目前即使在蚂蚁,应该很少有团队和研发平台能够真正做到持续部署,因为持续的部署的条件更加严苛
面临的问题 & 阻碍?
(1)发布条件受限
部分场景上线需要严格的审批的流程 & 频繁的封网
(2)低效手工发布流程
发布过程需要人工一次次确认,灰度和线上发布过程多分组场景下,需要一次次人工确定,不放心自动发布
目前蚂蚁解决方案:无人值守
(3)缺乏线上问题快速准确的反馈机制( 精准 OPS 能力)
没有 OPS 或者 OPS 噪音太大都会导致反馈不及时,这样研发就不敢把部署过程直接交给系统,也是上面发布需要人工确认的根因
目前公司对线上安全要求非常高,持续部署现阶段很难在蚂蚁大规模落地,特别针对类似金融核心这些安全要求非常高的系统,不过其实也未必要“一刀切”,公司还有很多级别不是特别高的应用,可以尝试小范围针对这些应用试点,同时不断持续改进周边 OPS 工具
最后
最后,我们来畅想一下,一个优秀的 CI/CD 研发过程应该是什么样子的?
假设开发同学小蚂第一天入职,他打开电脑,通过以下几步完成上线:
第一步:从 AntCode clone 代码到本地,修改了几行代码,本地测试后,通过git commit & push到代码仓库
第二步:push 过程自动触发了 CI 流水线,5 min 后,执行结束,通过钉钉通知告诉小蚂某个测试case失败了
第三步:小蚂本地修改失败 case ,重新 commit & push ,再次触发 CI 流水线,自动执行编译、测试、扫描等,收到钉钉消息,执行通过
第四步:小蚂将功能交给测试&产品验收,发现问题或收到建议,重新到第二步修改代码。
第五步:测试&产品验收没有问题后,手动触发预发部署流水线,并自动生成部署产物交付,后面流程就不用管啦。
第六步:持续部署流水线每几分钟自动检测交付产物包,发现更新后,自动将产物部署到线上。发布成功后,小蚂收到通知小蚂的功能生效啦。
理想状态?
(1)由于发布而导致的加班频次应该大幅减少
(2)开发大部分精力是花在写代码和思考如何写好代码,扫描、部署的事情交由平台自动化完成,并且体验良好,反馈精准。
需要注意的是,CI/CD并不仅仅是一种工具或技术,而是一种开发和运维的文化和方法论,需要全员参与和支持,才能真正实现持续集成和持续交付的目标。
CI/CD与devops区别
DevOps是一种思想,是一种文化,主要强调软件开发测试运维的一体化,目标是减少各个部门之间的沟通成本从而实现软件的快速高质量的发布。
cicd是指持续集成发布部署,是一套流程实现软件的构建测试部署的自动化。
DevOps与cicd紧密相关,是理论与实践的结合,DevOps要实现人员一体化,必须要借助cicd工具来自动化整个流程。
DevOps 是 CI、CD 思想的延伸,CI、CD 是 DevOps 的基础核心,如果没有 CI、CD 自动化的工具和流程,我们谈 DevOps 是没有意义的;DevOps 是一种重视软件开发人员(Dev)和IT运维技术人员(Ops)之间沟通合作的文化、运动或惯例,通过自动化软件交付和架构变更的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠;