持续集成、交付与部署

如果您从事软件开发已有一段时间,那么您对 CI/CD 这个术语应该并不陌生。

持续集成、交付和部署,是寻求通过缩短反馈循环和自动化重复性任务来加快软件发布流程的做法。 对于经常向用户交付有价值并且行之有效的软件的敏捷原则,这些做法在其实现中起到关键作用。

对于已经找到自己的节奏并采用适当 CI/CD 工具和流程来支持定期发布周期的团队而言,运作良好的 CI/CD 管道是骄傲的源泉;这代表开发者正在使用工具来改善环境和他们创建的最终产品。

但是,对于新手来说,将构建、测试和部署流程转换为自动化系统似乎令人生畏且不可实现。 事实上不必到这一步。 构建 CI/CD 管道的好处在于,它非常适合被分解成独立的阶段,每个阶段都建立在前一个阶段之上。 我们来依次查看各个阶段。

让我们来看看什么是 CI 与 CD,以及各自的主要特点是什么。

持续集成、交付与部署

什么是持续集成?

持续集成是指在整个开发过程中少量多次地运行传统“集成”步骤,而非等到代码完成后再全部集中测试。

假设您有多位开发者同时开发一款软件产品(这是大多数商业和开源软件的常态),在某个时候,您需要合并所有开发者的成果,并检查最终结果是否按预期运作。 通过持续集成,这一点每天至少发生一次。

道理很简单。 如果您将集成留到所有代码写完之后,那么您很有可能要花费大量时间去拆解和重写部分代码,然后才能让解决方案得以构建,更不用说让它按照预期工作了。 代码很复杂。 即使进行了详细的前期设计,也很难准确预测逻辑将如何交互并避免问题。 代码越多,复杂性越大,出现问题时需要拆解的地方也就越多。

通过持续集成,您的开发者可以定期(至少每天一次)将更改提交到源控制中共享,并检查解决方案是否可以构建并通过测试。 这意味着,如果出现问题,可以通过更少的变动查找问题的根源。 快速获得反馈也使问题修复更加轻松,因为您尚未远离先前的环境。

高效的 CI 流程需要一些基本要素:

使用源代码控制

源代码(又称版本)控制系统是绝对必要的。 如果您还没有这样的控制,或者只有部分代码处在源控制中,那么第一步就是将一切都纳入其中,并让所有人开始使用。

更早提交,更常提交

在您开始使用源控制后,要让所有人养成尽早和经常提交的习惯。 任务大小会在这里产生影响;将每项工作分成小块,可以更轻松地在本地完成和测试一组更改以供提交。

在每次提交时构建解决方案

定期与项目中的每个人共享代码只是一个开始。 下一步是检查是否仍可以使用最新更改构建解决方案。 虽然这可以手动完成,但自动触发构建更轻松也更高效,这就是 CI 服务器的用武之地。

自动化测试

成功的构建是一个好兆头,但要让其更加可靠,还应运行一些测试。 同样,自动运行测试比手动运行更容易、更高效。 尽管编写自动化测试可能会耗费大量人力,但当您在每次构建中由此获得快速反馈时,很快就能收回成本。

倾听反馈

只有当您打算利用所得信息进行某些操作时,才需要将构建和测试自动化。 CI 工具提供了一系列反馈机制,从仪表板和辐射器到与即时通讯平台的集成。

打造 DevOps 文化

为了真正获得持续集成的好处,您需要营造一种团队文化,让每个人都对修复错误的构建或失败的测试负起责任。 将责任归咎于最后提交的人只会适得其反,因为这通常会阻碍团队尽早和频繁地提交更改,从而损害所有人的利益。

将所有要素组合起来,可以让您的代码得到快速且频繁的反馈。 检查对代码库的任何更改(无论是错误修复、重构还是新功能的一部分),至少能够得到通过测试的纯净构建,团队可以避免不良基础上的新构建以及随后不可避免的返工。 单独实现持续集成是朝着加快向用户交付行之有效的软件的流程迈出的一大步。

了解持续交付

持续交付以由持续集成建立的构建和测试自动化为基础。

通过持续交付,您可以将软件构建到生产所需的手动发布步骤转变为自动化流程。

过去可能是从开发者到测试人员,再从测试人员到发布经理的交接,而有了持续交付,您的团队(可能包括多个学科的人员)将掌控构建、测试和发布产品的整个过程。 这有几个优点:

  • 通过避免传统的孤岛,您的开发团队可以更好地了解将产品交付给用户的业务和运营需求。
  • 反过来,这也让开发做法有机会进入通常相当漫长的传统手动流程。
  • 将产品交付上线的相关步骤自动化,不仅可以加快流程,还能降低出错的风险,使其更加稳定可靠。

根据用户和业务需求的差异,向用户交付软件所涉及的确切步骤(以及交付管道中的必需阶段)会有所不同,但通常的做法是先部署到至少一个预生产环境,然后再向外发布。

这些环境可以是额外测试层的测试环境,例如安全、负载和性能测试;可以是支持和销售团队熟悉新功能的沙盒环境;也可以是 QA 和产品专员的验收测试环境,用于验证更改是否按预期运作。

通过持续交付,每一个成功构建都将自动部署到每个预生产环境中,每经过一个阶段,质量的可靠性也随之提高。

这是一个值得实现的目标,需要一定的投入才能付诸实践:

构建一次

只有让相同的构建工件经过管道的每个阶段,您才能确信它已通过了先前所有阶段的测试。

在源控制中存储配置

在源控制中保留所有配置文件有助于确保部署的一致性和可重复性。

自动化每个部署

每个环境的部署都应脚本化,以便实现自动运行,并且每次都以完全相同的方式运行。 出于同样的原因,发布上线也应脚本化,但对于持续交付,最后这一步不是自动的。

清理环境

为实现完全一致的方法,应在每次新部署中将环境本身重置为相同的条件。 借助容器,现在无论是在本地基础架构还是在云端,这都易于实现。

分离环境关注点

为了将同一工件自动部署到每个环境,需要明确分离应用程序本身和环境特定的变量或参数。

维护管道

和持续集成一样,只有得到维护的自动化交付管道才值得投资。 CI/CD 既关乎团队文化,也关乎流程和工具。 为了提高效率,您的团队需要负责维护管道并修复问题,无论是由于代码本身的错误还是自动化部署或测试的问题。

通过持续交付,您的团队对软件的交付负责,并受益于全程及时反馈。 与持续集成一样,持续交付做法也可以随着时间积累和改进。

持续部署说明

持续部署将持续集成和交付的做法推进到合理的结论:

如果构建成功通过管道中的所有先前阶段,它将自动发布到生产。 这意味着,只要软件的任意更改通过了所有测试,便将立即交付给用户。 持续部署缩短了从代码更改到在生产中使用的反馈循环,可让您的团队成员及时了解其更改在现实世界中的表现,而不必牺牲质量。

尽管将软件部署到生产的自动化并不适合所有产品和组织,但达到目的所需的步骤仍然值得思考,因为每一个单独的要素本身都有其价值:

相信您的测试

自动部署到生产需要对管道(尤其是自动化测试)高度信任。 良好的测试文化至关重要,在这种文化中,您的团队将专注于测试覆盖率和性能,并优先修复构建和管道,而不是新功能。

监控生产

即使采取了上述所有措施,持续部署仍会被视为一种冒险的做法 - 如果一个错误在测试中没有被发现,却在生产中出现该怎么办? 时间、金钱和声誉都有可能受到影响。 虽然同样的问题可以通过手动部署解决,但被“系统”自动发布的重大缺陷显然会极大地减损利益相关者的信任。 因此应该主动寻找问题的征兆,而不是等待错误报告。 监视统计数据是否出现异常,特别是在刚刚发布之后,可以在问题引起用户明显注意之前向您发出提醒。

选择要发布的内容

新接触持续部署者的常见反对意见是,如果开发者过早地、频繁地提交,并且在没有手动监管的情况下将工作放行,那么用户会遇到尚未准备就绪的未完成或半成品功能。 应对的方法是使用功能标志,而非转向分支并错失持续集成的优势。 随后,开发者在编写代码时可以控制对用户可见的内容和对用户隐藏的内容。

简化管道

如果生产中出现问题,您需要快速响应。 在某些情况下,可以将发布回滚到先前版本。 然而,通常情况下,事情并没有那么简单 - 数据库迁移和对已知问题的修复都可能成为阻碍,而唯一的选择是提供修复方案。 跳过管道中的步骤可能得不偿失,因为您很可能会引入其他问题,而这些问题本身能够通过测试发现。 更好的选择是投资简化管道,从构建速度覆盖到测试性能。 这不仅意味着您可以根据需要快速部署更改,还能缩短全程的反馈循环。

控制推出

尽管持续部署意味着通过先前所有阶段便自动发布,但这并不表示放弃所有控制。 可以通过多种部署做法来最大程度地降低风险并控制推出。 Canary 发布允许您最初以一小部分用户试水,而蓝绿部署可用于管理向新版本的过渡。

持续集成、交付和部署都是为了经常向用户提供有价值并且行之有效的软件。 对集成和发布采取少量多次的方法可使流程更易于管理,也意味着团队会定期执行这些步骤并做得越来越好。

将自动化引入其中,不仅加快了流程,也使其更加可靠。 管道中的每一步都建立在前一步的基础之上,您可以在任何时间选择适合自己的程度,在以后返回并在其基础上继续构建。

CI 和 CD 的主要区别

持续集成、交付与部署

持续集成、交付和部署是软件交付过程的顺序阶段。 他们帮助团队更快地发布软件,缩短反馈循环,并自动执行重复性任务。 理解持续集成、交付和部署之间的关键区别,其重要性不亚于理解这三个步骤如何以可靠和稳定的方式向用户交付软件。

持续集成是将任何新代码更改合并到主分支的做法。 持续交付自动化构建和测试软件所需的手动任务(例如,通过自动测试). 持续部署是自动化构建和测试步骤实践的逻辑延续。在这个阶段,一旦软件通过所有必要的检查点,就会自动部署。

一般来说,这不是一个 CI 与 CD 的问题,而是所有这些组件如何共同构成一个稳定、可靠的管道。