一、CI/CD & Pipeline
随着 DevOps 的理念在泛滥公司的驳回,CI/CD 也慢慢落地。
- CI(Continuous Integration)继续集成,是把代码变更主动集成到骨干的一种实际。CI 的呈现解决了集成天堂的问题,让产品能够疾速迭代,同时还能放弃高质量。它的外围措施是,代码集成到骨干之前,必须通过一系列自动化测试,比方编译、单元测试、lint、代码格调查看。
- CD 包含继续交付和继续部署。继续交付(Continuous Delivery)指的是团队主动地、频繁地、可预测地交付高质量软件版本的过程,能够看做继续集成的下一个阶段,强调的是无论代码怎么更新,软件都是随时能够交付的;继续部署(continuous deployment)更强调的是应用自动化测试来保障变更的正确性和稳定性,以便在测试通过后立刻部署,是继续交付的更进一步。二者的区别是,继续交付须要人为染指,须要确保能够部署到生产环境时,才去进行部署。
图 1 继续集成 & 继续交付 & 继续部署
CI/CD Pipeline 是软件开发过程中避免浪费的一种实际,展示了从代码提交、构建、部署、测试到公布的整个过程,为团队提供可视化和及时反馈。Pipeline 举荐的施行形式是,把软件部署的过程分为不同的阶段 (Stage),其中工作(Step) 在每个阶段中运行。在同一阶段,能够并行执行工作,帮忙疾速反馈,只有一个阶段中所有工作都通过时,下一阶段的工作才能够启动。比方图中,从 git push 到 deploy to production 的整个流程,就是一条 CD Pipeline。能够利用 Pipeline 工具,如 Jenkins、Buildkite、Bamboo,来帮忙咱们更不便的施行 C /ICD。
图 2 CI/CD Pipeline
二、CI/CD Pipeline 的反模式
尽管有 Pipeline 宽泛的利用,但咱们却会听见开发人员埋怨蹩脚的 Pipeline 对他们的挫伤,如阻塞开发流程,影响变更的部署效率,升高交付品质。咱们收集了我的项目上经常出现的 Pipeline 的八大反模式,依照呈现频率排序,别离论述这些坏滋味,剖析可能产生的起因、影响及解决形式,心愿可能缩小埋怨,让 Pipeline 更大程度上晋升工作效率。
2.1 没有代码化
反模式:Pipeline 的定义没有齐全代码化,进行版本控制,存储在代码仓库,而是在 Pipeline 工具上间接输出 shell 脚本定义 Pipeline 的运行过程。
起因:因为晚期的 CI 工具不反对代码化,始终可能保留到当初,没有做重构和降级。
影响:Pipeline 的创立和治理都是通过 CI 工具的界面交互来的,难以保护,因而须要专门的管理员来保护,而有人工操作的局部就会出错,因而会升高 Pipeline 的可靠性。如果 Pipeline 因为一些起因失落就没有方法很快复原,就会影响交付速率。
解决方案:Pipeline as code 这个理念曾经提了很多年了,在 ThoughtWorks 2016 年的技术雷达里就曾经驳回了,须要强调的是,用于构建、测试和部署咱们应用程序或基础设施的交付 Pipeline 的配置,都应以代码模式展示。随着组织逐步演变为构建微服务或微前端的去中心化自治团队,人们越来越须要以代码模式治理 Pipeline 这种工程实际,来保障组织外部构建和部署软件的一致性。
通常,针对某个我的项目的 Pipeline 配置,应和我的项目代码放在我的项目的源码治理仓库中。同业务代码一样要做 code review。这种需要使得业界呈现了很多反对 Pipeline 工具,它们能够以规范的形式构建、部署服务和利用,如 Jenkins、Buildkite、Bamboo。这些工具用大多有一个 Pipeline 的蓝图,来执行一个交付生命周期中不同阶段的工作,如构建、测试和部署,而不必关怀实现细节。以代码模式来实现构建、测试和部署流水线的能力,应该成为抉择 CI/CD 工具的评估规范之一。
2.2 运行速度慢
反模式:一条 Pipeline 的执行工夫超过半小时,就属于运行速度慢的 Pipeline。(这里的运行速度与交付的产品无关,在不同的我的项目中,运行时长的限定也有所不同)
起因:很多起因都会导致运行一次 Pipeline 工夫很长,比方:
- 该并行的工作没有并行执行,期待的工作拉长了执行工夫;
- 执行 Pipeline 的 agent 节点太少,或者性能有余,导致排队工夫太长,效率太低;
- 执行的工作太重,雷同测试场景被不同的测试笼罩了很屡次。比方同样的逻辑在不同测试中都测了一遍;
- 没有正当利用缓存,比方每个工作里都要下载全副依赖,在构建 Dockerfile 时没有正当利用 layer,每次都会构建一个全新的 image。
影响:这是开发人员埋怨最多的一个反模式。麻利开发模式须要 Pipeline 疾速反馈后果,受这一反模式制约,在个性开发过程中,经常出现开发人员改一行代码,等半天 CI 的成果。如果呈现一个线上事变须要批改一行代码来修复,最终须要很长的周期能力让这一更改利用在生产环境。
解决:不同的起因导致的 Pipeline 速度慢,有不同的解决办法。比方针对下面的问题,咱们能够去:
- 查看 Pipeline 的设计是否正当,尽可能让工作并行;
- 对代码的各种测试深刻理解,让测试尽量正交,防止过多的反复;
- 查看代码中的依赖,正当利用好缓存。包含 Docker Image、Gradle、Yarn、Rubygem 的缓存,以及 Dockerfile 是否正当的设计,最大化的将不可变的 layer 集中的开始阶段;
- 查看执行构建的节点资源是否短缺,是否在任务量大时做弹性伸缩,缩小期待和执行工夫。
2.3 执行后果不稳固
图 3 执行屡次后果不稳固
反模式:构建雷同代码的 Pipeline 运行屡次,失去后果不同。比方,基于同一代码基线,一条 Pipeline 构建了 5 次,只有最初一次通过了。
起因:呈现执行后果不稳固的起因也多种多样,比方测试用例的实现不合理,导致测试后果时过期不过;代码中应用了不牢靠的依赖源,比方来自国外的依赖源,下载依赖常常超时;由或是在 Pipeline 运行过程中没有正当设计各个阶段,导致有些工作同时运行抵触了。
影响:Pipeline 作为代码公布的最初一道防火墙,最根本的个性是幂等性,即在一个雷同的代码基线,执行 Pipeline 的任意工作,不论是 10 次、100 次,失去的后果都雷同。Pipeline 不稳固会间接导致代码的部署速率升高。更重要的是,影响开发人员对 Pipeline 的信赖。如果不稳固 Pipeline 不及时解决,缓缓这条 Pipeline 会失去保护,开发最初会转向手工部署。
解决
- 要构建幂等的、牢靠的 Pipeline,就要剖析这些不稳固因素呈现的起因。
- 晋升测试的稳定性,比方用 mock 代替不稳固的源。
- 采纳 Pipeline 的重试性能,或者采纳稳固的镜像源,或者提前构建好根底镜像。
- 引入 Pipeline 的插件保障工作不会并行执行。
2.4 滥用 job 解决生产环境数据
反模式:应用 Pipeline 的定时工作的个性,运行生产环境的负载。比方常常会定期做数据备份、数据迁徙,数据抓取。
起因:因为对 Pipeline 的意识不够清晰,将重要的工作交由 Pipeline 做。Pipeline 一旦有了某个生产环境的拜访权限,做这些数据处理相干的工作就很不便,缩小了很多人为的操作。
影响:Pipeline 是用来做构建、部署的工具,不能用于业务逻辑的执行。因为 Pipeline 是一个外部服务,他的 SLO/SLI 必然和生产环境不同,如果强依赖势必影响生产环境的 SLO。如果某天 Pipeline 挂掉了,生产环境就无奈失去想要的数据。另外,工作和 Pipeline 严密耦合,是咱们前面会探讨的另一个反模式。
解决办法:用生产环境本身的工具解决这种数据问题,比方 采纳 AWS 的 lambda,定时触发数据处理工作。
2.5 简单难懂
图 4 Pipeline 的定义逻辑简单
反模式:Pipeline 的定义蕴含了太多的逻辑,简单难懂。只有在一条 Pipeline 运行起来能力晓得这里会运行哪些步骤,会将这个版本部署到哪些环境。
起因:Pipeline 的代码不够整洁。有人认为 Pipeline 只是给 CI 工具提供的,就随便编写,认为能实现指定的工作就够了。
影响:Pipeline 的复杂性,会间接晋升学习老本。如果想反复执行上一次构建,会破费较长时间。
解决:Pipeline 的代码要简洁,把复杂性放在部署脚本或代码侧。通过每个阶段的的题目能够间接理解所要执行的工作。如果存在很多雷同的逻辑,能够通过开发 Pipeline 的 Plugin 来简化配置。
2.6 耦合太高
图 5(左)耦合太高的 Pipeline 定义(右)期待的 Pipeline 定义
反模式:Pipeline 跟运行它的 CI 工具严密耦合,以至于无奈在本地反复雷同的步骤。
体现可能多种多样:
- Pipeline 的定义跟构建工具严密耦合,蕴含了 Pipeline 工具特有的参数以及 CLI 命令。比方在配置中应用 BUILDKITE\_BUILD_NUMBER,BUILDKITE\_QUEUE 等等。后果就是本地运行的形式或后果和 Pipeline 上运行的形式以及后果不统一。
- 在 Pipeline 的工作中写了一大段脚本,或者间接应用命令加上一堆参数,以至于在本地想跑测试须要在 Pipeline 的配置中找命令并且在本地粘贴。
- 不做环境隔离,测试,编译,部署等都依赖于运行时环境。可能呈现 Pipeline 因依赖的软件 / 库等版本不统一而导致的不统一的状况,通常还很难排查。
影响:因为本地不不便调试,所变更的失败概率会大大增加。如果变更用来修复一个 Bug,因为不做环境隔离,会导致故障修复周期拉长。
解决:Pipeline 的每个 step 都用脚本封装起来,脚本里不应用 Pipeline 工具特有的参数,并且保障本地运行时和 Pipeline 上保持一致。
2.7 僵尸 Pipeline
反模式:一条 Pipeline 年久失修,很久没有执行过,而且最初一次的构建是失败的。
起因:这种反模式通常呈现于不再沉闷开发的我的项目上,因而很久没有执行过 Pipeline。
影响:Pipeline 的后果反馈的是一个我的项目的状态。因为软件产品迭代速度快,这个软件的依赖可能曾经产生了微小的变动,一旦运行,大概率会出错。如果这个我的项目目前呈现了一个事变,须要提交代码,就得先修复我的项目的 Pipeline,能力确保提交修复代码。
解决:针对长年没有提交的 Pipeline,咱们倡议让 Pipeline 周期的执行,呈现问题立刻修复。如 Github 的 Dependabot,能保障我的项目的依赖始终是是最新的,而且能让 Pipeline 执行,提前发现问题。
2.8 须要人工染指
反模式:通常我的项目上会有一个专职 Ops,在我的项目能够公布的时候手动触发部署流程,或者须要传递很多参数,让 Pipeline 运行起来。
起因:包含我的项目的流程繁琐,须要重复确认;DevOps 成熟度不够,没有实现继续部署;或者 CI 的测试笼罩不够,CI 通过后还要进行更多的测试能力部署。
影响:这些 Pipeline 须要专人盯着,去点某些按钮。会间接影响产品的交付速率和代码部署频率。
解决:让我的项目的运行更加麻利,缩小 Pipeline 定义中的阻塞按钮,将手工测试自动化后集成到 Pipeline 中。
三、最初
心愿通过本篇文章,意识到我的项目中 CI/CD Pipeline 的问题,使其施展更大的价值。
起源:Thoughtworks 洞见
作者:冯炜
原文发表:原文发表于:https://www.rea-group.com/blo…
申明:文章取得作者受权在 IDCF 社区公众号(devopshub)转发。优质内容共享给思否平台的技术伙伴,如原作者有其余思考请分割小编删除,致谢。
IDCF DevOps 黑客马拉松👉 9 月 11-12 日,上海站,11 月 20-21 日,深圳站,企业组队参赛 & 集体参赛均可,一年等一回,错过等一年,连忙上车~ 公众号回复“黑马”退出