引言

持续集成、交付和部署,统称为 ci / cd,是现代开发的一个组成部分,旨在减少集成和部署期间的错误,同时提高项目速度。 Ci / cd 是一种哲学和实践集,通常通过强调软件管道的每个阶段的自动化测试的健壮工具得到增强。 通过将这些想法整合到您的实践中,您可以减少为一个发行版集成变更所需的时间,并且在将每个变更转移到生产环境之前对其进行彻底的测试。

Ci / cd 有许多潜在的好处,但是成功的实现通常需要大量的考虑。 确切地决定如何使用这些工具,以及您可能需要在环境或流程中进行哪些更改,这些都是具有挑战性的,无需进行大量的尝试和错误。 然而,虽然所有的实现都是不同的,但遵循最佳实践可以帮助您避免常见问题,并更快地实现改进。

在本指南中,我们将介绍一些关于如何实现和维护 ci / cd 系统以最好地满足组织需求的基本指南。 我们将介绍一些实践,它们将帮助您提高 ci / cd 服务的效率。 请随意阅读所写的内容,或者跳到你感兴趣的部分。

保持管道的快速运转

Ci / cd 管道通过自动化的测试周期帮助指导变更,最终到达临时环境,并最终到达生产环境。 您的测试管道越全面,您就越能确保更改不会在生产部署中引入不可预见的副作用。 但是,由于每个更改都必须经过这个过程,因此保持管道的快速和可靠性对于不抑制开发速度非常重要。

这两个要求之间的紧张关系可能难以平衡。 您可以采取一些简单的步骤来提高速度,比如扩展您的 ci / cd 基础结构和优化测试。 然而,随着时间的推移,您可能会被迫对不同测试的相对值以及它们运行的阶段或顺序做出关键的决定。 有时,通过删除低值或结论不确定的测试来缩减测试套件是保持大量使用的管道所需速度的最聪明的方法。

在做出这些重要的决定时,确保你理解并记录下你所做的权衡。 与团队成员和利益相关者协商,使团队对于测试套件负责什么以及主要重点领域应该是什么的假设一致。

隔离和保护您的 ci / cd 环境

从操作安全的角度来看,您的 ci / cd 系统代表了需要保护的一些最关键的基础设施。 由于 ci / cd 系统可以完全访问您的代码库,并且可以在各种环境中部署凭证,因此保护它以保护内部数据并保证站点或产品的完整性是至关重要的。 由于它作为目标的价值很高,因此尽可能地隔离和锁定 ci / cd 是很重要的。

Ci / cd 系统应该部署在内部受保护的网络上,不能暴露给外界。 建议设置 vpn 或其他网络访问控制技术,以确保只有经过身份验证的运营商才能访问您的系统。 根据您的网络拓扑 / 光盘的复杂程度,您的 ci / cd 系统可能需要访问几个不同的网络来将代码部署到不同的环境。 如果没有适当的安全或隔离,攻击者可以访问一个环境,可以进行岛跃迁,这种技术可以利用更宽松的内部网络规则来扩展访问权限,从而通过 ci / cd 服务器的弱点访问其他环境。

所需的隔离和安全策略将在很大程度上取决于您的网络拓扑、基础设施以及管理和开发需求。 需要记住的重要一点是,您的 ci / cd 系统是非常有价值的目标,在许多情况下,它们可以广泛地访问您的其他重要系统。 屏蔽对服务器的所有外部访问并严格控制允许的内部访问类型将有助于减少您的 ci / cd 系统被破坏的风险。

使 ci / cd 流水线成为生产部署的必由之路

使得 ci / cd 能够改进开发实践和代码质量的部分原因是,工具通常有助于执行测试和部署的最佳实践。 通过 ci / cd 管道推广代码需要每次更改都证明它符合组织编纂的标准和程序。 Ci / cd 管道中的故障立即可见,并阻止受影响的释放推进到周期的后期阶段。 这是一种网关保护机制,可以保护更重要的环境免受不可信代码的影响。

然而,要实现这些优点,您需要遵守纪律,以确保对生产环境的每一次更改都经过您的管道。 Ci / cd 管道应该是代码进入生产环境的唯一机制。 这可以在使用持续部署实践成功测试结束时自动发生,或者通过手动推广您的 ci / cd 系统批准并提供的测试更改。

通常,团队开始使用他们的管道进行部署,但是当出现问题并且有快速解决问题的压力时,他们会开始使用异常。 尽管停机时间和其他问题应该尽快得到缓解,但重要的是要理解 ci / cd 系统是一个很好的工具,可以确保您的更改不会引入其他错误或进一步破坏系统。 通过管道进行修复(或者只是使用 ci / cd 系统进行回滚)还可以防止下一次部署擦除直接应用于生产的特别热修复。 管道保护您的部署的有效性,无论这是一个定期的、计划的发布,还是一个解决正在发生的问题的快速修复。 使用 ci / cd 系统是保持流水线快速运行的另一个原因。

尽可能保持与生产的平等

Ci / cd 管道通过一系列测试套件和部署环境促进更改。 通过一个阶段需求的更改要么自动部署,要么排队等待手动部署到更严格的环境中。 早期阶段是为了证明继续测试和推动更改接近生产是值得的。

特别是对于后面的阶段,在测试环境中尽可能密切地再现生产环境有助于确保测试准确地反映变更在生产中的行为。 交付准备和生产准备之间的显著差异可以允许发布在测试中从未被观察到的有问题的更改。 您的实时环境和测试环境之间的差异越大,您的测试就越不会测量代码在发布时的执行情况。

阶段式和生产式之间的一些差异是可以预料的,但是保持它们的可管理性和确保它们被充分理解是至关重要的。 一些组织使用蓝绿色部署在两个几乎相同的环境之间交换生产流量,这两个环境在指定的生产环境和临时环境之间交替。 较不极端的策略包括将相同的配置和基础设施从生产环境部署到交付准备环境,但是规模较小。 像网络端点这样的项目在不同的环境中可能会有所不同,但是这种类型的可变数据的参量化可以帮助确保代码是一致的,并且环境差异是明确定义的。

一次性建设,通过流水线提升效果

Ci / cd 管道的主要目标是建立对变更的信心,并最大限度地减少意外影响的可能性。 我们讨论了保持环境间的校验的重要性,但是其中的一个组成部分非常重要,值得给予额外的关注。 如果您的软件需要构建、打包或捆绑步骤,那么该步骤应该只执行一次,并且结果输出应该在整个管道中重用。

这个准则有助于防止在多次编译或打包软件时出现问题,允许将轻微的不一致性注入到产生的工件中。 在每个新阶段单独构建软件可能意味着早期环境中的测试不是针对将在稍后部署的相同软件,从而使结果无效。

为了避免这个问题,CI 系统应该包括一个构建过程,作为在一个干净的环境中创建和打包软件的管道的第一步。 产生的工件应该被版本化并上传到工件存储系统,以便在随后的流水线阶段下拉,确保构建不会随着它在系统中的进展而改变。

尽早进行最快的测试

尽管保持整个流水线的速度是一个很好的总体目标,但是测试套件的某些部分将不可避免地比其他部分更快。 因为 ci / cd 系统是进入系统的所有更改的管道,所以尽早发现故障对于减少用于有问题的构建的资源非常重要。 为了达到这个目的,首先要优先考虑并运行最快的测试。 将复杂的、长时间运行的测试保存到使用较小的、快速运行的测试验证构建之后。

这个策略有许多好处,可以帮助您保持 ci / cd 过程的健康。 它鼓励您了解单个测试对性能的影响,允许您尽早完成大部分测试,并增加快速失败的可能性,这意味着有问题的更改可以在阻止其他成员的工作之前被恢复或修复。

测试优先化通常意味着首先运行项目的单元测试,因为这些测试往往是快速的、孤立的和以组件为中心的。 然后,集成测试通常表示复杂性和速度的下一个级别,接着是系统范围的测试,最后是验收测试,这通常需要一定程度的人工交互。

最小化版本控制系统中的分支

Ci / cd 的主要原则之一是尽早并经常地将更改集成到主共享存储库中。 当多个开发人员试图将大的、分歧的和冲突的更改合并到存储库的主分支中以准备发布时,这有助于避免代价高昂的集成问题。 通常,设置 ci / cd 系统是为了监视和测试只提交给一个或几个分支的更改。

为了利用 CI 提供的好处,最好限制存储库中分支的数量和范围。 大多数实现建议开发人员每天至少一次直接向主分支提交更改或从本地分支合并更改。

实际上,没有被 ci / cd 系统跟踪的分支包含未经测试的代码,这些代码应该被视为项目成功和发展势头的负担。 最小化为鼓励不同开发人员代码的早期集成而进行的分支有助于充分利用系统的优势,并防止开发人员否定其提供的优势。

在提交到 ci / cd 管道之前在本地运行测试

与早期发现故障的观点相关,应该鼓励开发人员在提交到共享存储库之前在本地运行尽可能多的测试。 这使得在阻止其他团队成员之前检测到某些有问题的更改成为可能。 虽然本地开发人员环境不太可能在类似生产环境的环境中运行整个测试套件,但这一额外步骤使个人更有信心,他们正在进行的更改能够通过基本测试,值得尝试与更大的代码库集成。

为了确保开发人员能够自己进行有效的测试,您的测试套件应该可以使用一个可以在任何环境中运行的命令来运行。 Ci / cd 系统应该使用开发人员在本地机器上使用的相同命令来启动对合并到存储库的代码的测试。 通常,这是通过提供一个 shell 脚本或 makefile 来协调的,以可重复的、可预测的方式自动运行测试工具。

在可能的情况下在临时环境中运行测试

为了确保您的测试在不同阶段运行相同的测试,在可能的情况下使用干净的、短暂的测试环境通常是一个好主意。 通常,这意味着在容器中运行测试,以抽象主机系统之间的差异,并提供一个标准的 API,用于将不同规模的组件挂接在一起。 由于容器以最小的状态运行,测试的剩余副作用不会被测试套件的后续运行继承,这可能会影响结果。

集装箱化测试环境的另一个好处是测试基础结构的可移植性。 使用容器,开发人员可以更容易地复制将在后面的管道中使用的配置,而无需手动设置和维护基础结构或牺牲环境保真度。 由于容器在需要时可以很容易地组装起来,然后销毁,因此用户在运行本地测试时,可以在测试环境的准确性方面做出较少的妥协。 一般来说,在执行期函式库的某些方面使用容器锁来帮助最小化流水线阶段之间的差异。

总结

虽然每个 ci / cd 实现都是不同的,但是遵循这些基本原则可以帮助您避免一些常见的陷阱,并加强您的测试和开发实践。 与持续集成的大多数方面一样,过程、工具和习惯的混合将有助于使开发变更更加成功和有效。

要了解更多关于常规 ci / cd 实践以及如何设置各种 ci / cd 服务的信息,请查看其他带有 ci / cd 标签的文章。