CI/CD 流水线如何成为自动化发布负责人

SEO 摘要: 本文介绍 CI/CD 流水线如何取代传统发布负责人,自动完成代码变更构建、测试、生产发布、部署工件管理和自动回滚。文章重点讨论基于主干的开发、自动化生产发布、多个在途版本并行发布、不可变部署工件和 CI/CD 回滚机制,帮助团队提升持续交付效率与发布可靠性。

CI/CD 流水线如何成为自动化发布负责人

简介

在某些海外大型科技公司采用持续交付之前,许多团队的开发人员都曾轮流承担一个角色:发布负责人。发布负责人负责协调团队服务的代码变更发布,并将版本部署到生产环境。

如今,随着这些团队在内部广泛实践持续交付,发布负责人这一角色已经基本消失。CI/CD 流水线不再只是辅助发布的工具,而是成为了自动化的发布负责人。在撰写本文的过程中,我偶然看到一篇旧团队 Wiki 中关于发布管理的注释,其中一句话很好地概括了团队采用 CI/CD 之后发生的变化:“我们已经转向使用流水线,不再管理单独的版本发布。”这确实是一个令人欣喜的变化。

开发人员通常并不喜欢承担发布负责人的角色。这个角色非常耗时,也会分散开发人员的精力,让他们无法专注于构建服务和为客户开发新功能。因此,发布负责人通常会由团队中的不同开发人员按周轮换担任。

协调每次发布都需要大量工作:发布负责人需要安排发布日期,确定发布版本中应包含哪些变更,分配版本号,在源代码仓库中创建发布分支,并构建和测试候选版本。之后,发布负责人还需要编写一份详细的手动部署步骤清单并获得批准。这份清单通常包括:要部署哪个候选版本、部署到不同生产环境的顺序,以及如果新版本引发运维问题,应如何回滚每个生产环境。

如今,开发人员不再需要考虑某个特定版本应包含哪些变更,也无需管理发布分支或协调发布交付。开发人员只需提交代码,CI/CD 流水线就会持续处理这些变更的构建、测试、生产发布和回滚准备。在研发管理层面,团队也可以借助 PingCode 这类智能化研发管理工具,将目标、需求、开发、测试、发布上线和 Wiki 知识沉淀串联起来,让 CI/CD 之外的研发协作过程更加自动化、数据化和可追踪。

本文将详细介绍持续交付实践和 CI/CD 流水线如何自动化发布负责人的职责,让开发人员能够专注于构建产品。文章将说明,团队如何通过以下方式持续向生产环境发布变更:采用基于主干的开发模式;使用 CI/CD 流水线管理部署工件,并协调跨多个生产环境的发布;以及实施主动和自动化回滚机制。

如需进一步了解持续交付相关实践,可以参考以下技术实践主题:

  • 通过持续交付加快软件交付,介绍团队如何开始采用 CI/CD 流水线;
  • 自动化、安全且无需人工干预的部署,介绍如何构建 CI/CD 流水线和部署安全检查;
  • 确保部署期间能够安全回滚,介绍如何设计可由流水线自动回滚的软件变更。

基于主干的开发:CI/CD 持续交付的基础

在成熟的持续交付实践中,代码变更会持续部署到生产环境。这意味着,一旦代码审查通过并完成合并,变更就会被 CI/CD 流水线捕获,并立即进入生产环境发布流程。作为开发人员,我们无需安排单独的发布计划,也无需花费时间判断哪些变更应该包含在某次具体的生产部署中。

过去,发布负责人需要创建发布分支,并谨慎管理合并到该分支的变更,直到预定发布日期到来。现在,开发人员几乎只需要与 Git 仓库中的主分支交互。由于 CI/CD 流水线会在新的代码变更合并到仓库主分支后自动发布,因此发布分支不再是日常发布流程中的必要环节。

大多数团队会采用基于主干的开发模式。它是团队摆脱手工版本管理、让 CI/CD 流水线持续发布变更的核心实践。基于主干的开发是一种源代码版本控制实践:开发人员通过频繁地向源代码仓库中的单个共享分支提交小规模变更来修改代码,而不是像传统做法那样,将长期存在的特性分支中的大量代码变更一次性合并到共享分支。

这个共享分支在不同版本控制系统中有不同名称。在某些系统中,它通常被称为 trunk;在 Git 中,它通常被称为 main;在一些内部代码管理系统中,也可能被称为 mainline。采用基于主干的开发后,开发人员无需管理长期存在的特性分支来协作修改代码,也无需管理发布分支来交付代码。相反,开发人员只需围绕源代码仓库的主分支进行协作,并在自己的仓库克隆、派生仓库或临时分支中独立完成各自的代码变更。

在这种模式下,开发人员通常不会将分支视为日常开发流程的核心部分。新代码的本地开发一般在 Git 仓库主分支的本地克隆上完成。开发人员可以配置开发环境,让本地提交在后台自动备份到个人分支;除此之外,本地代码变更通常不会推送到特性分支或 fork 等长期分支中。

当接手新任务或新项目时,开发人员会将工作拆分成小的、增量式代码变更。每个变更都应当足够小,能够在完成后尽快进入代码审查、合并和发布流程。通常情况下,开发人员在提交代码审查之前,只会在本地处理单个代码变更几天,甚至几个小时。

在这种工程实践中,所有代码变更都必须通过代码审查,才能合并到主分支。当本地代码变更准备好接受审查时,开发人员首先会从主分支获取最新提交,将本地变更基于最新代码进行变基,并根据需要解决合并冲突。然后,开发人员创建代码审查请求,以获得将变更合并到主分支的批准。

代码审查工具会自动将开发人员的本地提交推送到一个新的、唯一的 Git 引用中,该引用会在底层与代码审查请求关联。这类 Git 引用的生命周期非常短,因为它们只用于一次代码审查。代码审查获得批准且变更合并到主分支后,该代码审查对应的 Git 引用就不再使用,CI/CD 流水线随后会开始构建、测试并部署该变更。

在极少数情况下,团队可能需要创建一个短期发布分支,以部署非常紧急的变更,例如需要尽快部署到所有生产环境的安全修复。团队会将安全修复所需的最小代码变更合并到发布分支中,并排除主分支上可能已经存在、但尚未部署到生产环境的其他无关变更,以降低加速发布分支部署到所有生产环境时的风险。

在这种情况下,发布分支必须经过严格审查。团队需要与经验丰富的运维和安全专家一起审查代码变更,并评估变更的紧迫性和潜在风险。修复程序完成全量部署后,该发布分支就不再使用。

安全、自动化的生产发布

在采用 CI/CD 流水线之前,将版本部署到生产环境需要发布负责人做大量准备工作。发布负责人会编写一份详细的部署计划,其中包括要部署的代码变更、版本部署到各个生产环境的顺序,以及用于判断是否可以安全部署到下一个环境的指标。随后,发布负责人还需要与团队其他成员一起审核该计划并获得批准,然后才能开始漫长而繁琐的手动部署流程。对于仍需要较多人参与的发布协调场景,团队可以使用 Worktile 这类通用项目协作系统统一管理任务、项目、文档、日历、甘特图和审批流程,减少发布准备阶段的信息遗漏和沟通成本。

现在,开发人员的 CI/CD 流水线会自动将变更发布到生产环境。开发人员无需创建发布计划,也无需主动监控每一次生产部署。

CI/CD 流水线会将跨环境的自动化发布流程建模为一系列阶段、审批和推进操作。当流水线构建出一个新版本后,该版本会依次经过各个阶段的审批,然后被推进到流水线的下一阶段。流水线中的每个阶段会并行部署到一个或多个环境,然后对每个环境运行一系列审批步骤,例如集成测试和告警监控。

如果某一阶段的所有部署和审批步骤都成功,该版本就会获得该阶段的批准,并被推进到流水线的下一阶段。如果该阶段的任一部署或审批步骤失败,该版本就不会获得该阶段批准,也不会被推进到下一阶段。当部署或审批步骤失败时,生产环境通常也会自动回滚到正常状态。

为了尽可能降低生产部署风险,团队会通过 CI/CD 流水线谨慎、安全地将变更发布到生产环境。降低部署风险的一种策略,是将生产环境拆分为多个较小的生产环境,有些环境甚至小到只包含单台虚拟机或单个容器,通常称为单机环境。

这样,每次发布就不再是一次规模庞大且风险极高的生产部署,而是由 CI/CD 流水线依次部署到这些较小的生产环境中。将每次生产部署的范围限制在一个较小环境中,可以把每次部署的潜在风险控制在该环境所服务的一小部分客户工作负载或请求范围内。

在某些海外云服务实践中,团队通常会先按区域拆分生产环境,再进一步将每个区域拆分为每个可用区一个生产环境,以及每个可用区一个单机环境。CI/CD 流水线负责通过一系列阶段和审批步骤,在多个生产环境中谨慎地部署和推进版本。

当新版本在 CI/CD 流水线中的前几次生产部署成功后,团队通常会更有信心认为该版本后续的生产部署也能成功。这一经验也会体现在 CI/CD 流水线架构中:部分生产环境会被分组到称为“波次”的并行部署中。

波次机制可以在降低部署风险和提升部署速度之间取得平衡。每个波次由一个或多个流水线阶段组成,这些阶段会并行部署到一组生产环境,然后运行这些环境对应的审批步骤。流水线中较早的波次通常每次只部署到一个生产环境,以限制风险,并逐步增强团队对版本安全性的信心。随着版本在流水线中不断推进,每个波次都会进一步增强团队对版本的信心。因此,流水线中较晚的波次可以并行部署到越来越多的生产环境。

下图展示了一个示例流水线:源代码变更被构建为新版本,并在预生产环境中完成测试后,流水线会通过五个规模逐渐增大的波次,将该版本部署到 26 个区域。

CI/CD 流水线如何成为自动化发布负责人

下图放大展示了示例流水线中的第三个波次。该流水线会将每个区域拆分为生产环境和单机环境,每个可用区对应一个生产环境和一个单机环境。因此,每个波次实际上由多个流水线阶段组成。

在第三个波次中,第一阶段会并行部署到每个区域第一个可用区的单机环境;第二阶段会部署到每个区域第一个可用区的生产环境;第三阶段和第四阶段会部署到每个区域的第二个可用区;第五阶段和第六阶段则会部署到每个区域的第三个可用区。

流水线中,第三个波次的发布如何从第一阶段推进到第二阶段。阶段 1 和阶段 2 之间的推进关系用箭头表示。阶段 1 会将发布版本并行部署到一组区域单机环境中。当这些单机环境成功部署且未触发任何告警后,阶段 1 会批准该发布版本。随后,该发布版本被推进到阶段 2。阶段 2 会将发布版本并行部署到一组区域环境中,然后对每个环境运行集成测试和告警监控。

多个在途版本的并行发布

在采用持续部署之前,团队通常一次只向生产环境发布一个版本。对于发布负责人而言,手动协调同一服务在不同生产环境中的多个并行版本发布既复杂又容易出错。他们需要仔细跟踪每个版本中包含的源代码变更、哪些版本已经过测试、哪些版本当前部署到了各个生产环境,以及哪些版本已经准备好部署到下一个生产环境。

然而,一次只向生产环境发布一个版本,会增加代码变更部署到生产环境并服务客户工作负载所需的时间。在当前版本仍处于发布过程中时,任何新的代码变更都必须等待下一个版本部署到生产环境后才能生效。

如今,CI/CD 流水线能够自动协调生产环境中的多个在途版本发布,从而最大限度减少代码变更在流水线中等待部署的时间。只要开发人员将新的代码变更合并到主分支,流水线就会立即构建一个新版本,并开始在流水线中推进。由于采用基于主干的开发模式后,开发人员会频繁合并新的代码变更,因此每天都会构建多个新版本并进入流水线。

如前所述,CI/CD 流水线会将部署到多个环境的过程建模为一系列阶段和推进操作。流水线中的各个阶段可以并行执行。可以将流水线中的每个阶段看作一个独立流程,它负责部署、审批并推进当前版本。

一旦某个流水线阶段完成当前版本的部署和审批,它就可以开始处理下一个等待推进到该阶段的版本。该阶段无需等待流水线下游的任何阶段完成当前版本的部署和审批。由于各个阶段可以并行运行,因此流水线中可以同时存在多个版本的部署、审批和推进过程,每个阶段负责处理不同的版本。

流水线会确保版本按照正确顺序推进。如果一个版本在流水线中追上了另一个版本,较新的版本会取代较旧的版本,并继续向下游推进。

例如,如果某个版本在预生产阶段的集成测试中失败,那么修复了错误的新版本可以取代这个失败的旧版本,并继续推进。再举一个例子,某个生产环境的部署时间可能比流水线中的其他环境更长,这有时是由环境规模差异造成的。当该环境的部署或审批步骤仍在进行时,流水线中的较新版本无法推进到该阶段,只能等待审批完成。

如果该环境的部署和审批步骤耗时过长,可能会有多个版本已经获得前一阶段批准,并等待推进到该阶段。但是,较新的批准版本会取代任何等待推进的旧版本。最终,只有最新获得批准的版本,会在该阶段完成当前部署和审批步骤后推进到该阶段。

流水线如何协调多个在途版本,并将其依次推进到三个阶段。在这个示例中,第三阶段的部署耗时较长,因为第三阶段包含一个规模非常大的生产环境,其云服务器实例数量远多于前几个阶段。在第三阶段部署进行期间,多个版本已经获得前一阶段批准,但必须等待第三阶段部署完成后才能继续推进。新获得批准的版本会不断取代旧的等待版本,直到最新获得批准的版本在当前部署和审批步骤完成后,最终进入第三阶段。

流水线能够协调多个生产环境中的在途版本,从而帮助团队同时优化部署安全性和部署速度。

例如,如果一条流水线每次只向生产环境发布一个版本,并且每个版本都需要一周时间才能安全、谨慎地部署到所有生产环境,那么开发人员在这一周内合并的任何新代码变更,都必须等待流水线的下一个版本才能部署到生产环境。这种等待会降低变更交付到生产环境的速度。

同时,将一周内的代码变更集中在一起等待下一个版本发布,也会增加下一个版本部署到生产环境时的风险。将大量变更集中到一个版本中,会提高其中任意一个变更影响生产环境的可能性。

通过协调多个在途版本,流水线通常可以让每次发布只向生产环境引入少量新代码变更。这样既能降低任意一次生产部署造成影响的风险,也能更快地将代码变更交付到生产环境。

透明且不可变的部署工件

CI/CD 流水线不仅负责协调发布,还负责管理每次发布实际部署的内容,也就是部署工件。

过去,发布负责人会从发布分支上的源代码创建构建,为构建出的工件分配发布版本号,然后在执行发布时谨慎确保将正确的工件部署到每个生产环境。现在,流水线会完整管理发布和部署工件。对开发人员来说,这个过程几乎完全透明。开发人员无需关心如何计算版本号,也无需跟踪部署工件 ID 或构建 ID。

每当新的源代码变更推送到主分支时,流水线都会创建一个新的、不可变的部署工件。流水线会跟踪该发布工件基于哪个源代码提交构建,以及该发布工件已经部署到了哪些环境。

由于流水线会跟踪发布、部署和源代码提交之间的关系,开发人员无需理解底层部署工件或发布对象的细节,也可以查看哪些代码已经部署到哪些环境。在流水线用户界面中,开发人员可以查看每个环境的部署历史记录,包括每次部署中新部署到该环境的源代码变更。开发人员还可以查看某个特定源代码变更的部署位置,例如查看自己编写的错误修复是否已经部署到所有生产环境。

以下示例视图展示了某个环境的部署历史记录。流水线可以基于其发布、部署和源代码提交记录生成这一视图。

CI/CD 流水线如何成为自动化发布负责人

流水线还可以使用同样的发布、部署和源代码提交数据,为特定源代码提交生成部署历史记录视图。

不可变部署工件有助于确保流水线能够准确跟踪版本在多个环境中的部署历史记录,以及这些版本对应的源代码。当主分支上的新源代码变更触发流水线时,流水线会创建一个新的、唯一的部署工件。这个部署工件包含部署所需的一切,并会被分配一个唯一 ID。

这些部署工件可能包括机器镜像、容器镜像、函数计算部署包和云资源编排模板。流水线构建出版本部署工件后,不会在后续任何阶段修改它。

例如,对于容器化应用程序,流水线可能会构建应用程序源代码,创建一个带有唯一标签的容器镜像,并将该镜像推送到容器注册表。流水线还可能生成一个基础设施即代码(IaC)模板,该模板会使用唯一标签部署新的容器镜像,并以唯一名称将该模板存储到对象存储中。随后,流水线中的部署阶段会从容器注册表和对象存储中部署这些不可变部署工件,而不会直接与源代码仓库交互。

自动回滚:CI/CD 流水线降低发布风险的关键机制

回滚是成熟运维文化中至关重要的一部分。值班工程师在处理运维事件时,通常会首先被问到一个问题:“最近是否有需要回滚的部署?”

这种运维实践优先考虑缓解问题:先尽快减轻对客户的影响,再进行深入故障排查。实践表明,在运维问题发生前回滚所有近期部署,通常是缓解问题最快的方式。即使团队尚未确定这些部署中的代码变更是否触发了问题,也通常会先采取回滚操作。

花时间确认具体是哪一项代码变更触发了问题,或者尝试立即部署新的代码变更来修复问题,都可能延长客户受到影响的时间。因此,团队的首要行动通常是主动回滚相关微服务中的所有近期部署。

在采用 CI/CD 流水线之前,发布负责人需要花费大量时间,为每次发布编写详细的回滚计划,以应对新版本可能引发的运维问题。发布负责人需要仔细记录当前部署到每个生产环境的版本和部署工件,并记录重新部署先前工件的步骤,确保能够正确地将环境回滚到之前的状态。

由于运维实践高度依赖回滚机制,因此 CI/CD 流水线系统既需要能够自动回滚生产环境,也需要让开发人员能够快速、轻松地发起生产环境回滚。

如今,开发人员不必在运维事件发生时浪费宝贵时间,临时摸索如何手动将环境回滚到旧版本。流水线会监控告警,并在告警触发时自动回滚任何正在进行的部署。很多情况下,当值班工程师开始介入时,流水线已经启动了部署回滚。

如果值班工程师确实需要手动回滚某个环境,也只需在 CI/CD 流水线用户界面中完成几个简单步骤即可启动回滚部署。流水线中的回滚操作本质上会启动一次常规部署。不同之处在于,常规部署会部署新版本,而回滚部署会重新部署此前已经成功部署到该环境的旧版本。

回滚部署会有效地将系统恢复到环境正常运行时的某个时间点,包括回滚应用程序、基础设施即代码模板,以及旧版本部署工件中包含的配置文件。

通过使用不可变工件和不可变环境,可以确保回滚部署与常规部署遵循完全相同的机制,并尽量避免副作用或意外变更。

例如,每次部署都将代码部署到云服务器实例上的同一目录,就属于可变环境。即使执行了回滚,部署到这种环境也可能导致目录中残留较新的文件,从而影响旧代码的行为,并引发运维问题。

相较之下,通过使用基础设施即代码,并部署不可变的机器镜像、容器镜像和函数计算部署包,团队可以确保在回滚部署后,应用程序环境被旧版本完整替换。即使团队需要将代码部署到现有云服务器实例上,而不是用新的机器镜像替换这些实例,也应尽可能追求不可变性。

一种做法是,每次部署都创建一个全新的目录来部署新代码,然后更新符号链接,使其指向当前版本所在目录。在回滚部署期间,也执行同样的步骤:将旧代码部署到新目录,并更新符号链接。这样可以降低回滚造成副作用的可能性。

开发人员可以在流水线用户界面中快速回滚一个或多个环境。当开发人员在流水线用户界面中启动回滚操作时,流水线会自动选择这些环境中最后一个已经成功部署、并获准重新部署的版本。然后,开发人员可以预览当前版本与所选回滚版本的部署工件之间的差异,例如源代码变更和库版本变更。

当开发人员在流水线用户界面中批准回滚后,流水线会使用所选回滚版本的部署工件,开始向所选环境发起新的部署。回滚部署遵循与常规部署相同的步骤,只是使用的是较旧的工件。

在某些情况下,引发运行问题的代码变更可能早在多次部署之前就已经进入生产环境,只是直到现在才开始影响客户。这类变更通常被称为潜在变更。

例如,一个被判断为当前影响客户的变更,可能在一周前就已经部署到某个环境中,而该环境在此后又成功部署了多次新的变更。此时,回滚到最近一次部署并不能将该问题变更从环境中移除。

要回滚潜在变更,开发人员可以在流水线用户界面中选择更早的部署版本,而不是使用系统默认选择的最近可回滚版本。不过,在这样做之前,开发人员需要先权衡利弊:是回滚潜在变更以及这一周内其他可能包含新功能和错误修复的代码变更,还是等待流水线向前推进一个包含错误修复的新版本。

为了帮助开发人员及其团队做出决策,流水线用户界面会显示已经部署到环境中的版本历史记录,包括每个版本之前的部署时间、每个版本中的代码变更,以及每个版本是否通过了成功的部署和审批步骤,例如集成测试。

当开发人员发起回滚部署时,流水线会自动禁用所选环境的版本推进,以防止较新的版本再次部署到这些环境中。此时,在回滚操作已经缓解对客户的直接影响后,开发人员可以根据具体情况选择后续步骤。

根据问题性质,开发人员可能需要主动回滚更多可能受影响的环境,即使这些环境当前尚未对客户造成明显影响。或者,如果问题似乎仅限于特定环境,开发人员也可以选择等待流水线发布包含错误修复的新版本。

源代码仓库不会因为开发人员发起回滚操作而发生变化。因此,任何已经对生产环境造成影响的源代码变更,仍然保留在仓库主分支中。一旦确定了影响客户的代码变更,开发人员可以选择修复错误,也可以创建一个反向 Git 提交来移除这些变更,然后进行代码审查,并将新的提交合并到主分支。

当错误修复或反向提交合并到仓库后,流水线会构建并部署这些变更。当流水线准备好将修复程序部署到已回滚环境时,开发人员需要重新启用这些环境的部署推进权限。

开发人员使用流水线用户界面回滚单个生产环境,以缓解该环境中对客户的影响。在这个示例中,流水线通过七个阶段,将函数计算应用部署到每个区域。开发人员决定回滚几个可能受问题影响的生产环境。随后,开发人员创建错误修复程序,并将其合并到源代码仓库中。流水线再将该错误修复程序向前推进。之后,开发人员根据需要重新启用阶段之间的推进关系,以安全地将错误修复程序部署到所有环境。

结论:用 CI/CD 流水线提升持续交付与发布可靠性

持续部署实践与 CI/CD 流水线系统的结合,使许多团队能够基本摆脱传统发布负责人的角色。当然,有些团队仍然需要交付版本化软件,例如移动应用和设备固件,因此这些团队仍会采用更传统的发布方式,并谨慎管理发布分支、发布计划和版本控制。

不过,对于大多数后端服务和云原生系统而言,开发人员已经可以专注于构建,而不必再手动管理发布。现在,CI/CD 流水线会在新的代码变更推送到源代码仓库主分支时自动触发,创建新的版本和部署工件,协调多个版本向生产环境部署,并实现快速、便捷的自动回滚。

为了让 CI/CD 流水线真正承担发布负责人的角色,团队需要通过基于主干的开发持续发布代码变更,并使用不可变工件、不可变环境和基础设施即代码来部署应用程序。

实践表明,持续部署方法和 CI/CD 流水线系统,对于让开发人员信任流水线能够妥善处理代码的生产发布至关重要。当发布协调、部署验证、工件管理和回滚机制都被流水线自动化承担后,开发人员就能把更多精力投入到真正重要的事情上:持续构建可靠的软件,并更快地为客户交付价值。

文章包含AI辅助创作:CI/CD 流水线如何成为自动化发布负责人,发布者:shang,转载请注明出处:https://worktile.com/kb/p/3974478

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
shang的头像shang

发表回复

登录后才能评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部