持续集成、交付和部署简介

来自菜鸟教程
跳转至:导航、​搜索

介绍

开发和发布软件可能是一个复杂的过程,尤其是随着应用程序、团队和部署基础设施的复杂性增加。 通常,随着项目的增长,挑战变得更加明显。 为了以快速一致的方式开发、测试和发布软件,开发人员和组织创建了三种相关但不同的策略来管理和自动化这些流程。

持续集成侧重于每天多次将单个开发人员的工作集成到主存储库中,以及早发现集成错误并加速协作开发。 持续交付关注的是减少部署或发布过程中的摩擦,自动化部署构建所需的步骤,以便可以随时安全地发布代码。 持续部署通过在每次进行代码更改时自动部署来更进一步。

在本指南中,我们将讨论这些策略中的每一个,它们如何相互关联,以及将它们整合到您的应用程序生命周期中如何改变您的软件开发和发布实践。 要更好地了解各种开源 CI/CD 项目之间的差异,请查看我们的 CI/CD 工具比较

什么是持续集成,它为什么有用?

持续集成 是一种鼓励开发人员尽早且经常地将其代码集成到共享存储库的主分支中的做法。 不是孤立地构建功能并在开发周期结束时将它们集成,而是由每个开发人员在一天中多次将代码与共享存储库集成。

这个想法是通过尽早考虑来最大限度地降低集成成本。 开发人员可以及早发现新代码和现有代码之间边界的冲突,而冲突仍然相对容易调和。 一旦解决了冲突,就可以放心地继续工作,因为新代码符合现有代码库的要求。

频繁集成代码本身并不能保证新代码或功能的质量。 在许多组织中,集成的成本很高,因为使用手动流程来确保代码符合标准、不会引入错误并且不会破坏现有功能。 当自动化方法与现有的质量保证措施不一致时,频繁的集成会产生摩擦。

为了解决集成过程中的这种摩擦,在实践中,持续集成依赖于强大的测试套件和自动化系统来运行这些测试。 当开发人员将代码合并到主存储库中时,自动化流程会启动新代码的构建。 之后,针对新版本运行测试套件以检查是否引入了任何集成问题。 如果构建或测试阶段失败,团队会收到警报,以便他们可以修复构建。

持续集成的最终目标是使集成成为一个简单、可重复的过程,成为日常开发工作流程的一部分,以降低集成成本并及早响应缺陷。 努力确保系统健壮、自动化和快速,同时培养一种鼓励频繁迭代和响应构建问题的团队文化,这是 CI 成功的基础。

什么是持续交付,它为什么有用?

持续交付是持续集成的扩展。 它专注于自动化软件交付过程,以便团队可以随时轻松自信地将其代码部署到生产环境中。 通过确保代码库始终处于可部署状态,发布软件成为一个不起眼的事件,无需任何复杂的仪式。 团队可以确信他们可以在需要时发布,而无需复杂的协调或后期测试。 与持续集成一样,持续交付是一种需要技术和组织改进相结合才能有效的实践。

在技术方面,持续交付很大程度上依赖于部署管道来自动化测试和部署过程。 部署管道 是一个自动化系统,它针对作为一系列顺序阶段的构建运行越来越严格的测试套件。 这会在持续集成停止的地方继续存在,因此可靠的持续集成设置是实施持续交付的先决条件。

在每个阶段,构建要么未通过测试,从而提醒团队,要么通过测试,从而自动升级到下一阶段。 随着构建通过管道,后续阶段将构建部署到尽可能接近生产环境的环境中。 这样,构建、部署过程和环境可以同时进行测试。 管道以一个构建结束,该构建可以在任何时候通过一个步骤部署到生产中。

持续交付的组织方面鼓励将“可部署性”作为主要关注点的优先级。 这会影响功能构建和连接到代码库其余部分的方式。 必须考虑到代码的设计,以便功能可以随时安全地部署到生产中,即使是不完整的。 已经出现了 数量的技术 来协助该领域。

持续交付之所以引人注目,是因为它将代码检查到存储库和决定是否向生产基础架构发布经过良好测试的功能构建之间的步骤自动化。 帮助断言代码的质量和正确性的步骤是自动化的,但关于发布什么的最终决定权仍留在组织手中,以获得最大的灵活性。

什么是持续部署,它为什么有用?

持续部署 是持续交付的扩展,它自动部署通过完整测试周期的每个构建。 持续部署系统无需等待人工看门人来决定将什么以及何时部署到生产环境,而是部署已成功遍历部署管道的所有内容。 请记住,当新代码自动 部署 时,新功能仍然可以在以后有条件地激活或为部分用户激活。 自动部署可以快速将功能和修复推送给客户,鼓励在有限范围内进行较小的更改,并有助于避免混淆当前部署到生产中的内容。

这种完全自动化的部署周期对于担心将发布内容的控制权交给他们的自动化系统的组织来说可能是焦虑的根源。 自动化部署提供的权衡有时被认为对于它们提供的回报来说太危险了。

其他团体利用这种方法作为确保始终遵循最佳实践的一种手段。 如果在部署一段代码之前没有最终的手动验证,开发人员必须负责确保他们的代码设计良好并且测试套件是最新的。 这将围绕什么和何时提交到主存储库以及什么和何时发布到生产环境的任何决策整合到开发团队的单个决策点中。

持续部署还允许组织从一致的早期反馈中受益。 功能可以立即提供给用户,并且可以在团队将大量精力投入到非生产性方向之前及早发现缺陷或无用的实现。 快速获得某个功能没有帮助的反馈可以让团队转移重点,而不是将更多精力投入到影响最小的领域。

连续过程的关键概念和实践

虽然持续集成、交付和部署的参与范围各不相同,但有一些概念和实践对于每个项目的成功至关重要。

小的迭代变化

采用持续集成时最重要的实践之一是鼓励小的更改。 开发人员应该练习将较大的工作分解成小块并尽早提交。 诸如 抽象分支 和功能标志(见下文)等特殊技术有助于保护主分支的功能免受正在进行的代码更改的影响。

小的变化可以最大限度地减少集成问题的可能性和影响。 通过在尽可能早的阶段提交到共享分支,然后在整个开发过程中持续进行,集成的成本就会降低,并且不相关的工作会定期同步。

基于主干的开发

使用基于主干的开发,工作在存储库的主分支(“主干”)中完成,或者定期合并回共享存储库。 短暂的特性分支是允许的,只要它们代表小的变化并尽快合并回来。

基于主干的开发背后的想法是避免违反上面讨论的小型迭代更改概念的大型提交。 代码可及早提供给对等方,以便在其范围较小时解决冲突。

发布是从主分支或专门为此目的从主干创建的发布分支执行的。 为了保持对主分支的关注,将其作为唯一的事实来源,不会在发布分支上进行开发。

保持快速构建和测试阶段

每个过程都依赖于自动化构建和测试来验证正确性。 由于必须经常执行构建和测试步骤,因此必须简化这些流程以尽量减少在这些步骤上花费的时间。

构建时间的增加应该被视为一个主要问题,因为每次提交都会启动构建这一事实加剧了影响。 因为持续的流程迫使开发人员每天都参与这些活动,所以减少这些领域的摩擦是非常值得的。

如果可能,并行运行测试套件的不同部分可以帮助更快地通过管道移动构建。 还应注意确保每个 类型 测试的比例有意义。 单元测试通常非常快并且维护开销最小。 相比之下,验收测试通常很复杂并且容易损坏。 考虑到这一点,严重依赖单元测试、进行大量集成测试并尽量减少更复杂测试的数量通常是一个好主意。

整个部署管道的一致性

因为持续交付或部署实施应该测试发布的价值,所以在流程的每个步骤(构建本身、部署环境和部署流程本身)中保持一致性至关重要:

  • 代码应该在流水线开始时构建一次:生成的软件应该被存储并且以后的进程可以访问而不需要重新构建。 通过在每个阶段使用完全相同的工件,您可以确定不会因为不同的构建工具而引入不一致。
  • 部署环境要一致:一个配置管理系统可以控制各种环境,环境变化可以通过部署管道本身来保证正确性和一致性。 每个测试周期都应提供干净的部署环境,以防止遗留条件损害测试的完整性。 暂存环境应尽可能与生产环境匹配,以减少升级构建时出现的未知因素。
  • 应该使用一致的流程在每个环境中部署构建:每个部署应该是自动化的,每个部署应该使用相同的集中工具和程序。 应消除临时部署,而只支持使用管道工具进行部署。

解耦部署和发布

将代码的部署与发布到用户分开是持续交付和部署的一个非常强大的部分。 代码可以部署到生产中,而无需最初激活它或让用户可以访问它。 然后,组织决定何时发布独立于部署的新功能或特性。

通过将业务决策与技术流程分开,这为组织提供了很大的灵活性。 如果代码已经在服务器上,那么部署就不再是发布过程中的一个微妙部分,从而最大限度地减少了参与者的数量和发布时所涉及的工作量。

有许多技术可以帮助团队部署负责功能的代码而不发布它。 功能标志设置条件逻辑以检查是否根据环境变量的值运行代码。 抽象分支允许开发人员通过在流程输入和输出之间创建抽象层来逐步重写流程。 仔细规划结合这些技术使您能够分离这两个过程。

测试类型

持续集成、交付和部署都严重依赖自动化测试来确定每个代码更改的有效性和正确性。 在这些过程中需要进行不同类型的测试,以确保对给定解决方案的信心。

虽然下面的类别绝不代表详尽的列表,并且尽管对每种类型的确切定义存在分歧,但这些广泛的测试类别代表了在不同上下文中评估代码的各种方法。

冒烟测试

冒烟测试是一种特殊的初始检查,旨在确保核心功能以及一些基本的实施和环境假设。 在运行更完整的测试套件之前,冒烟测试通常在每个测试周期开始时作为健全性检查运行。

这种类型的测试背后的想法是帮助捕捉实现中的重大危险信号,并引起对可能表明进一步测试不可能或不值得的问题的关注。 烟雾测试不是很广泛,但应该非常快。 如果更改未能通过冒烟测试,这是核心断言被破坏的早期信号,在问题解决之前,您不应再花时间进行测试。

可以在任何新阶段测试开始时使用特定于上下文的烟雾测试,以断言满足基本假设和要求。 例如,冒烟测试既可以在集成测试之前使用,也可以在部署到登台服务器之前使用,但每种情况下要测试的条件会有所不同。

单元测试

单元测试负责以独立且高度针对性的方式测试代码的各个元素。 单独的函数和类的功能是自行测试的。 任何外部依赖项都将替换为存根或模拟实现,以将测试完全集中在相关代码上。

单元测试对于在将单个代码组件放置在更复杂的上下文中之前测试其内部一致性和正确性的正确性至关重要。 测试的有限范围和依赖性的消除使得更容易找到任何缺陷的原因。 这也是测试以后可能难以重现的各种输入和代码分支的最佳时间。 通常,在任何冒烟测试之后,单元测试是在进行任何更改时运行的第一个测试。

单元测试通常由各个开发人员在提交更改之前在他们自己的工作站上运行。 然而,持续集成服务器几乎总是在开始集成测试之前再次运行这些测试作为保障。

集成测试

在单元测试之后,通过将组件组合在一起并将它们作为一个组件进行测试来执行集成测试。 虽然单元测试单独验证代码的功能,但集成测试确保组件在相互交互时相互协作。 这种类型的测试有机会捕获通过组件之间的交互暴露的完全不同类别的错误。

通常,在将代码签入共享存储库时会自动执行集成测试。 持续集成服务器检查代码,执行任何必要的构建步骤(通常执行快速冒烟测试以确保构建成功),然后运行单元和集成测试。 模块以不同的组合连接在一起并进行测试。

集成测试对于共享工作很重要,因为它们可以保护项目的健康。 更改必须证明它们不会破坏现有功能并且它们与其他代码按预期交互。 集成测试的第二个目的是验证更改是否可以部署到干净的环境中。 这通常是第一个不在开发人员自己的机器上执行的测试周期,因此在此过程中也可以发现未知的软件和环境依赖关系。 这通常也是第一次针对真实的外部库、服务和数据测试新代码。

系统测试

一旦执行了集成测试,就可以开始另一个称为系统测试的测试级别。 在许多方面,系统测试充当集成测试的扩展。 系统测试的重点是确保组件组作为一个有凝聚力的整体正确运行。

系统测试通常不会关注组件之间的接口,而是评估完整软件的外部功能。 这组测试忽略了组成部分,以便将组成的软件作为一个统一的实体来衡量。 由于这种区别,系统测试通常侧重于用户或外部可访问的界面。

验收测试

验收测试是交付前对软件执行的最后一类测试。 验收测试用于从业务或用户的角度确定一个软件是否满足所有需求。 这些测试有时是根据原始规范构建的,并且经常测试一些预期功能和可用性的接口。

验收测试通常是一个更复杂的阶段,可能会延伸到软件发布之后。 自动化验收测试可用于确保满足设计的技术要求,但手动验证通常也发挥作用。

通常,验收测试从将构建部署到镜像生产系统的登台环境开始。 从这里,自动化测试套件可以运行,内部用户可以访问系统以检查它是否按照他们需要的方式运行。 在发布软件或向用户提供 beta 访问权限后,通过评估软件在实际使用中的功能以及收集额外的反馈来执行进一步的验收测试。

附加术语

虽然我们在上面讨论了一些更广泛的想法,但是当您了解持续集成、交付和部署时,您可能会遇到许多相关概念。 让我们定义一些您可能会看到的其他术语:

  • 蓝绿部署:蓝绿部署是一种在类生产环境中测试代码并以最少的停机时间部署代码的策略。 维护了两组具有生产能力的环境,并将代码部署到可以进行测试的非活动环境中。 准备好发布后,生产流量将通过新代码路由到服务器,从而立即使更改可用。
  • Branching by Abstraction:Branching by abstraction 是一种在活动项目中执行主要重构操作的方法,而源代码存储库中没有长期存在的开发分支,持续集成实践不鼓励这种方法。 在现有实现中构建和部署一个抽象层,以便可以在抽象之后并行构建新实现。
  • Build(名词):构建是从源代码创建的特定版本的软件。 根据语言的不同,这可能是编译代码或一致的解释代码包。
  • Canary Releases:Canary 版本是一种向有限的用户子集发布更改的策略。 这个想法是确保一切都与生产工作负载正常工作,同时最大限度地减少出现问题时的影响。
  • 暗启动:暗启动是将代码部署到生产的做法,接收生产流量但不影响用户体验。 新更改与现有实现一起部署,并且通常将相同的流量路由到两个地方进行测试。 旧实现仍然与用户界面挂钩,但在幕后,可以使用生产环境中的真实用户请求评估新代码的正确性。
  • 部署管道:部署管道是一组组件,它们通过越来越严格的测试和部署场景移动软件,以评估其发布准备情况。 管道通常以自动部署到生产或提供手动部署的选项结束。
  • Feature FlagsFeature Toggles:功能标志是一种在条件逻辑后面部署新功能的技术,它根据环境变量的值确定是否运行。 通过适当地设置此标志,可以将新代码部署到生产中而无需激活。 功能标志通常包含允许用户子集访问新功能的逻辑,从而创建一种逐步推出新代码的机制。
  • Promoting:在连续过程的上下文中,提升意味着将软件构建移动到测试的下一个阶段。
  • Soak Test:Soak 测试涉及在大量生产或类似生产的负载下长时间测试软件。

结论

在本指南中,我们介绍了持续集成、持续交付和持续部署,并讨论了如何使用它们来安全、快速地构建和发布经过良好测试的软件。 这些流程利用广泛的自动化并鼓励持续的代码共享以及早修复缺陷。 虽然实施这些解决方案所需的技术、流程和工具是一项重大投资,但精心设计和正确使用的系统的好处可能是巨大的。

要了解哪种 CI/CD 解决方案可能适合您的项目,请查看我们的 CI/CD 工具比较指南 了解更多信息。