概念梳理
概念
CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法。CI/CD 的核心概念是持续集成、持续交付和持续部署。作为一个面向开发和运营团队的解决方案,CI/CD 主要针对在集成新代码时所引发的问题(亦称:“集成地狱”)。
具体而言,CI/CD 可让持续自动化和持续监控贯穿于应用的整个生命周期(从集成和测试阶段,到交付和部署)。这些关联的事务通常被统称为"CI/CD 管道",由开发和运维团队以敏捷方式协同支持。可由下图显示CICD流水线原理:
归根结底,我们没必要纠结于这些语义,您只需记得 CI/CD 其实就是一个流程(通常形象地表述为管道),用于实现应用开发中的高度持续自动化和持续监控。
CI 持续集成(Continuous Integration)
现代应用开发的目标是让多位开发人员同时处理同一应用的不同功能。但是,如果企业安排在一天内将所有分支源代码合并在一起(称为"合并日"),最终可能造成工作繁琐、耗时,而且需要手动完成。这是因为当一位独立工作的开发人员对应用进行更改时,有可能会与其他开发人员同时进行的更改发生冲突。如果每个开发人员都自定义自己的本地集成开发环境(IDE),而不是让团队就一个基于云的 IDE 达成一致,那么就会让问题更加雪上加霜。
持续集成(CI)可以帮助开发人员更加频繁地(有时甚至每天)将代码更改合并到共享分支或"主干"中。一旦开发人员对应用所做的更改被合并,系统就会通过自动构建应用并运行不同级别的自动化测试(通常是单元测试和集成测试)来验证这些更改,确保这些更改没有对应用造成破坏。这意味着测试内容涵盖了从类和函数到构成整个应用的不同模块。如果自动化测试发现新代码和现有代码之间存在冲突,CI 可以更加轻松地快速修复这些错误。
CD 持续交付(Continuous Delivery)
完成 CI 中构建及单元测试和集成测试的自动化流程后,持续交付可自动将已验证的代码发布到存储库。为了实现高效的持续交付流程,务必要确保 CI 已内置于开发管道。持续交付的目标是拥有一个可随时部署到生产环境的代码库。
在持续交付中,每个阶段(从代码更改的合并,到生产就绪型构建版本的交付)都涉及测试自动化和代码发布自动化。在流程结束时,运维团队可以快速、轻松地将应用部署到生产环境中。
CD 持续部署(Continuous Deployment)
对于一个成熟的 CI/CD 管道来说,最后的阶段是持续部署。作为持续交付——自动将生产就绪型构建版本发布到代码存储库——的延伸,持续部署可以自动将应用发布到生产环境。由于在生产之前的管道阶段没有手动门控,因此持续部署在很大程度上都得依赖精心设计的测试自动化。
实际上,持续部署意味着开发人员对应用的更改在编写后的几分钟内就能生效(假设它通过了自动化测试)。这更加便于持续接收和整合用户反馈。总而言之,所有这些 CI/CD 的关联步骤都有助于降低应用的部署风险,因此更便于以小件的方式(而非一次性)发布对应用的更改。不过,由于还需要编写自动化测试以适应 CI/CD 管道中的各种测试和发布阶段,因此前期投资还是会很大。
个人理解
CICD解决问题
软件交付缓慢:手动构建和部署软件,对于开发和运维人员来说是乏味且令人沮丧的。
这些手动任务会减缓交付过程,并最终阻碍创新。如果其他组织都使用自动化而你没有,那么在工作效率上就输掉了。
如果使用CICD,借助自动化,你可以更快地交付产品,并且可以获得最终用户的反馈,因为需要完成的手动任务较少,并且你可以更频繁地发布较小的变更到生产环境。
缺乏可见性:“错误发生在哪里?是什么原因造成的?每个环境中部署了什么?我们可以回滚吗?”
如果没有CI/CD,这些是你每天都会问并试图回答的问题。
如果使用CICD,测试和部署的过程是透明的,哪一步有问题可以立马发现,从而快速的找到解决该问题的最佳人选。增加了系统正常运行时间。
出错增多和客户不满:现代的软件功能,项目和应用程序都很复杂,错误也很复杂。不经常合并大量代码,因此在漫长的开发周期结束时才会发现错误,并且错误修复起来可能极具挑战性,或者对难以解决的代码库其他部分有影响。另外没有自动化就意味着手动操作出错概率增加。每个手动任务都为错误打开了大门。手动操作,使得错误经常发生并且难以解决。
如果使用CICD可以减少错误,释放人力资源。持续集成的两个主要原则是,频繁运行代码以及自动执行软件交付生命周期的构建和测试部分。每天多次运行代码集成意味着可以更快地发现错误,然后可以更快地纠正错误,因为每次要做的事很少。频繁运行代码相当于将大量代码拆分成少量代码多次合入多次发布,减少问题影响范围,增加成果可能性。另外自动执行软件交付生命周期的构建和测试部分意味着手动任务少,减少了人为错误发生几率,也大大减少重复得可以预测得任务量,解放开发人员人力资源。
CICD概念
CICD是一个已经实现流水线配置的管道,里面包含代码合并,代码检查,卡点检查,ticket状态检查与维护,测试自动化,部署等自动化功能。这些功能可能由负责CICD维度的团队提供,或者由业务团队自行开发openapi 自主配置。
CICD常见问题
1.在不稳定的CI上构建CD
否则需要做好应对故障的准备,如CD流程中断。
2.自动化带来的高成本和潜在风险
很多步骤都通过自动化实现,但是完成自动化需要人力成本,例如测试的接口自动化项目,手工测试时间可能大大少于自动化维护时间,又例如前端和客户端大量UI,自动化成本过高。这种我们可以考虑接入一部分CICD,而不是完整的。
3.将持续部署等同于持续交付
持续部署是将代码库中的任何更改都应该自动且快速地投入生产环境。
持续交付在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境的「类生产环境」(production-like environments)中。比如,我们完成单元测试后,可以把代码部署到连接数据库的 Staging 环境中更多的测试。如果代码没有问题,可以继续手动部署到生产环境中。
持续部署(continuous deployment)则是持续交付的下一步,代码通过评审,自动化部署到生产环境。其目的是可以随时部署,迅速投入生产阶段。持续部署这一步,意味着产品和观众见面,但是要通过重重考验,测试、构建、部署等步骤,而且每一步都是自动的。
4.不可靠的测试系统
可靠的测试是 CI/CD 的基础。它们保证代码正常工作,并允许你进一步发布流程。如果不信任自动化测试,团队要么需要大量重复性的手动测试工作(这贬低了自动化测试的工作),要么在生产阶段面临大量错误(这将直接损害产品)。
5.缺乏有意义的仪表盘和指标
有时,敏捷团队根本没有跟踪重要的指标,并且将大量时间花在记录不会带来任何好处的指标上。
尽管敏捷和 CI/CD 的目标不同,但它们应该互相帮助。这两种方法都基于持续改进的实践。实现它的最简单方法是使用指标和仪表板很好地覆盖所有流程。团队必须能够看到和跟踪当前状态,及时发现问题。
业务实操
背景
随着公司的高速发展,单一项目内部需要更多的开发人员协同开发,外部需要越来越多的团队协作,一些系统发布的相关问题开始浮现。例如:
1.发布内容有缺陷,该发布的内容并没有发布,不该发布的内容却发布了;
2.合作需求,涉及多个团队协同开发,没有统一上线时间,导致兼容问题;
3.审计等操作需要投入大量人力,而且难以追踪和回溯历史上线记录。
因此团队开始尝试和推行统一的发布管理流程,帮助团队管理项目,我们团队也是因此接入了CICD管理工具,其中包含自动化验证,自动代码合并,自动部署等,而且版本状态与jira高度绑定,清晰可见且可追踪。
流程改进
日常版本:每周周四发布,每周都有正常版本
周一 | 周二 | 周三 | 周四 | 周五 | |
---|---|---|---|---|---|
发版前两周 | feature CR&CI | feature CR&CI | feature CR&CI | feature CR&CI | code合入test分支完成,进入测试阶段 |
发版前一周 | 测试&bug fix | 测试&bug fix | 测试&bug fix | 测试&bug fix | test分支合入master |
发版周 | master code 封板,不可再提merge | 回归 | 回归 | master合入release分支,创建tag,版本发布 | live验证 |
这里需要注意:
1.因为每周都有版本,所以跟不上预期版本,不可强合,顺延一周即可;如若不得不合,feature验证通过直接合入master,不走test分支流程;
2.大的feature需求首先判断是否可以拆解成多个小需求分批上,如果不行,则feature进行CR,测试,完成后直接合入master进行回归流程;
3.hotfix 修复BUG流程跳出日常版本流程:从release分支拉取代码,然后fix+测试,完成后合入release,打tag发布,完成后再将release代码同步至master。
关键指标引入
前提:需求代码或者fix分支代码 merge必须带jira单号,用这种方式让代码和jira单关联起来,无单号不允许代码合入。
1.发版版本号:每周的版本由日期和版本序号构成,日期可以帮助做检查。一个需求带上发版版本号才允许合入test分支进入测试(冲突解决也在这步),合入后根据feature带的jira号,做对比操作,避免少合和漏合的情况发生。在发版前一周周五,测试通过的test分支合入master。
2.增加jira发版状态,如果到发版周周一12:00,jira单状态仍然不是等待合入,则会被踢出该版本。
CICD自动化建设
1.jenkins状态查询,jenkins自动部署;
2.批量操作jira单,包括信息获取和状态改变;
3.批量代码合入,打tag,且输出结果;
4.部署后自动触发接口自动化并输出结果;
另外例如:代码静态检查,安全缺陷扫描都是集成在代码合入里,只要有代码合入便会自动进行。