原文:
annas-archive.org/md5/ec167da03c90d6a18edd50835461d337译者:飞龙
第十一章:解决方案开发的持续集成
在 PI 规划后,ART 上的团队开始工作。他们将查看持续探索的产出以及为 PI 选择的功能,并将其带入持续交付管道的下一个阶段,即持续 集成(CI)。
本章将介绍在持续交付管道的 CI 阶段中进行的以下活动:
-
开发解决方案
-
构建解决方案包
-
执行端到端测试
-
将包移到预发布环境
我们还将发现,持续交付管道中描述的过程将在 CI 阶段与自动化相结合,形成CI/持续部署(CD)管道。
现在,让我们加入 ART,随着他们根据持续探索阶段创建的功能开发解决方案。
开发解决方案
ART 团队的工作方式与使用瀑布方法的产品开发团队有很大不同。强调精益思维并聚焦于系统决定了新的工作方式。
我们将研究今天敏捷团队使用的以下工程实践:
-
将工作分解
-
协作开发
-
在构建质量
-
版本控制
-
面向系统的设计
这些实践旨在实现工作流的持续流动,为下一个构建状态做好准备。
将工作分解为故事
我们在第四章中学习到的精益流程的重要部分是保持批次规模小。一个功能,在 PI 规划之前呈现给我们,是一个大批次的工作,计划在 PI 结束时完成。为了确保工作流的顺畅,功能必须分解成更小的工作批次。
用户故事通常描述了在冲刺或迭代结束时需要交付的小块用户功能,通常为两周。它们通常以用户语气的形式表达,简要说明该故事是为谁准备的,以及所需的功能和预期的价值。以下是用户语气形式的示例:
作为客户,我想要每月收到一份详细的服务收据,以便我可以了解并整理我的开支。
故事的一个关键部分是其接受标准。接受标准概述了故事的正确行为,是团队判断故事是否完成的方式。
接受标准可以使用 Gherkin 格式编写。这有助于概述前置条件、输入、所需的行为和输出。这些在以 GIVEN-WHEN-THEN 开头的条款中进行描述。
以下是我们故事的接受标准示例,采用 Gherkin 格式编写。注意它是如何描述初始条件、输入和输出的:
| 初始条件 | 假设我已经配置了 通知日期… |
|---|---|
| 输入 | …当通知日期过去时… |
| 输出或期望的行为 | …然后我收到一封包含我项目清单的电子邮件通知。 |
表格 11.1:Gherkin 格式的验收标准
使能故事也可以来自功能。这些故事不直接为用户提供价值,但为未来用户故事的开发和架构能力提供便利,从而创造未来的业务价值。SAFe®列出了以下四种类型的使能者。
-
基础设施
-
架构
-
探索
-
合规性
将一个功能拆分成用户故事和使能故事可以通过多种方式完成。以下方法可以用来创建可以在短冲刺中完成的故事。
-
工作流步骤:首先设置故事来执行工作流的必要步骤。其他步骤可以在后续冲刺中发布。
-
业务规则的变异:根据不同的业务规则划分故事,例如不同的服务等级、不同的产品线等。
-
重大工作量:检查可以遵循的可能故事。首先选择看起来最难完成的故事。
-
简单与复杂:在评估功能时,是否有一个可以编写的故事来提供核心功能?那就是要先做的第一个故事。后续的故事将进一步详细说明核心功能。
-
数据中的变异:从一个适用于某种数据类型的故事开始,然后转到处理其他数据类型的不同故事。
-
不同的数据输入方法:首先创建一个手动输入数据的故事,然后逐步推进自动化数据输入的后续故事。
-
不同的系统特性:系统特性的一种示例可能是我们的应用程序将与不同的设备或接口配合使用,并为每个设备或接口建立一个故事。
-
按操作:将故事划分为处理不同操作的部分。常见的划分方法是创建、读取、更新和删除(CRUD)。
-
使用场景:为每个使用场景创建一个故事。
-
设置突发任务与后续工作:突发任务是用来安排开发时间,研究一种技术方法或解决未知问题。一旦研究完成,就继续进行实现该方法的故事。
请注意,可能需要进一步拆分大型故事,以便在短冲刺结束时完成并交付该故事。前述方法可以用来将较大的故事拆分成较小的故事。
协作开发
虽然团队可以选择如何开发他们的故事,但高效能团队发现,与其单独工作,不如团队成员一起合作,能够生产出更高质量的产品,并实现有效的知识共享,从而创造出更强大、更具协作性的团队。
在本节中,我们将讨论两种允许团队共同开发产品的实践,促进更好的质量和更强的团队凝聚力:配对编程和集体编程(或集群编程)。
配对编程
对偶编程是一种源自极限编程(XP)的实践。与其让两位开发者在两台电脑前分别工作,不如让他们在一台共享电脑前共同工作,相互交换想法,同时进行编码和审查工作。
当两位开发者一起工作时,以下模式是他们协作的体现。
-
驾驶员/导航员:在这种模式中,一位开发者掌控电脑(驾驶员),而另一位开发者通过评论屏幕上输入的内容来审查并提供指导(导航员)。在会议的某些时段,角色会进行交换。这是对偶编程中最常用的模式。通常,当一位开发者是专家级程序员,而另一位是新手时,这种模式尤其有效。
-
无结构模式:在这种临时的对偶编程风格中,开发者之间没有固定的角色。协作往往是没有明确指导和松散的。通常,在两位开发者都不确定哪种方法有效时会采用这种模式。这种模式适合技术水平相近的开发者,但对于两位初学者来说,可能会遇到一些问题。
-
乒乓编程:这种模式通常由一位开发者编写测试,另一位开发者则为通过测试而进行工作。两位开发者在编写测试和编写通过测试的代码之间频繁切换角色。这种风格适合两位经验丰富的开发者。
对偶编程已被证明是一种有效的协作方式。在对偶编程过程中编写的代码通常会进行审查和调试,从而产生高质量的代码。知识在开发者之间共享,加速了初学者或不熟悉代码库的开发者的学习。如果代码出现问题,通常不仅仅有一个开发者了解代码,可以帮助修复问题。
一个常见的误解是对偶编程需要双倍的努力或资源。然而,这一观点并没有得到对偶编程有效性研究的支持,包括犹他大学进行的一项研究(collaboration.csc.ncsu.edu/laurie/Papers/XPSardinia.PDF),该研究发现,虽然开发成本增加了 15%,但在后期阶段发现的缺陷减少了 15%,且代码功能实现时所用的代码行数更少,这表明设计质量更高。
团队编程或集体编程
集体编程可以看作是对偶编程的最高级形式。不同于只有一对开发者,整个团队都围坐在一台电脑前进行操作。团队成员们在相同的时间和空间里,在同一台电脑上共同工作。
这种典型的模式是一种驱动者/导航者模式的变体。团队中的一个人控制计算机,输入并创建代码或其他工作部分。团队的其他成员作为导航者审查并指导驱动者。经过一段时间(通常为 10 分钟),控制权会轮换到团队中的另一成员。轮换会持续进行,直到所有团队成员都有机会担任驱动者。
集体编程有利于整个团队。代码的知识共享适用于整个团队,而不仅仅是一对开发人员。整个团队都在场时,沟通变得更容易。决策基于最当前和相关的信息。
通过“向左转移”来构建质量
在此期间,不仅产品在开发中,同时确保产品质量的方法也在同时开发。这与传统开发方式有所不同,传统开发是在代码开发后才创建并运行测试。这一变化通常被称为向左转移,如下面的开发过程表示所示。这是 SAFe 中的一项重要实践,更多细节可参考 SAFe 文章《内建质量》(www.scaledagileframework.com/built-in-quality/):
图 11.1 – 与“向左转移”比较的测试(© Scaled Agile, Inc.,版权所有)
在前面的图示中,我们可以看到,传统的测试可能在故事和功能最初构思后很长一段时间才进行测试。这个延迟的反馈可能需要长达 3 到 6 个月的时间,这可能太晚了,无法知道我们是否朝着正确的方向前进。
从右侧的图示中,我们看到可以通过 TDD 和 BDD 测试加速反馈,以评估功能和故事的行为是否符合预期。理想情况下,这些测试应当自动化,以便能够反复快速运行。
我们还可以从前面的图示中看到,测试有多个层级,其中一些应通过自动化反复运行,而另一些可能需要一些时间或只能手动运行。我们如何知道哪些测试应该自动化,哪些测试应该频繁运行呢?
Mike Cohn 在他的书《成功的敏捷》中将测试层级描述为“测试金字塔”。他最初描述了以下三个从下到上的层级。
-
单元测试
-
服务测试
-
UI 测试
其他类型的测试可以添加到测试金字塔中并加以应用。这使得我们可以如下图所示查看测试金字塔:
图 11.2 – 测试金字塔
请注意,在金字塔的底部,单元测试是执行速度最快且成本最低的。将它们的执行自动化并频繁运行是明智之举,理想情况下应该在每次提交版本控制时,尤其是在构建阶段执行。
随着你向金字塔的上方移动,测试的执行时间逐渐增加,成本也变得更高。这些测试可能不会像单元测试那样频繁运行。它们可能通过自动化执行,但只会在进入测试阶段时运行。这些测试的例子包括来自 BDD 的故事测试、集成测试、性能测试和安全测试。
金字塔顶部的测试需要最久的执行时间,且也是最昂贵的。这些大多是手动测试。这些测试可能会在发布前运行。此处的测试示例包括用户验收测试和由客户进行的探索性测试。
大多数测试旨在验证代码的正确性和功能性,以及验证故事和特性的行为。创建测试以衡量这些标准的主要方法包括:TDD 和 BDD。让我们来看看这些测试是如何开发的。
TDD
TDD 是源自 XP 的一种实践。在 TDD 中,你会遵循以下流程:
-
创建测试。这是为了理解行为。
-
观察测试失败(即使没有写任何代码)。这让我们对测试执行环境有信心,并展示了测试失败时系统的行为。
-
编写通过测试所需的最简单代码。
-
确保所有测试通过。这意味着任何新创建的代码都需要经过修订,直到测试通过为止。
-
根据需要重构测试和代码。
随着新功能的开发,这个流程会重复进行。这个流程的图形表示如下:
https://en.wikipedia.org/wiki/Test-driven_development#/media/File:TDD_Global_Lifecycle.png 根据 CC BY-SA 许可证授权)](https://github.com/OpenDocCN/freelearn-devops-pt3-zh/raw/master/docs/safe-dop-prac/img/B18756_11_03.jpg)
图 11.3 – TDD(en.wikipedia.org/wiki/Test-driven_development#/media/File:TDD_Global_Lifecycle.png 根据 CC BY-SA 许可证授权)
通常使用 TDD 编写的测试是单元测试;小型、易于执行的测试,旨在验证代码模块的正确功能。更广泛的测试使用 BDD 来开发验证特性和故事的系统行为的测试。现在让我们来看看 BDD。
BDD
BDD 通常被视为 TDD 的扩展,但与 TDD 侧重于验证单个代码功能和组件的正确行为不同,BDD 力求验证系统作为可执行规格的正确行为,这些规格通过特性和故事来表达。在本章的早些时候,我们创建了故事的接受标准,这是 BDD 的一种应用。
查看正确的系统行为涉及三个互相协作的视角,这些视角帮助确定最终的规格、开发内容以及作为正确测试的内容。以下是这三种视角:
-
了解业务需求并寻找新功能的可取性和可行性的客户
-
了解可行技术方法的开发人员
-
查看系统行为的边界条件和边缘案例的测试人员
BDD 通过使用规范将这三种视角结合在一起。这些规范使用领域特定语言(DSL)编写,采用自然语言语法,使技术人员和非技术人员能够协同开发规范。这些 DSL 之一是 Gherkin,它将行为划分为以下三个部分:
-
GIVEN 概述了场景中期望行为所需的初始条件
-
WHEN 描述了触发场景的输入
-
THEN 描述了场景的期望行为
可以使用AND将多个 GIVEN、WHEN 和 THEN 条款连接在一起,以表示多个条件、输入和行为。
使用 DSL 的规范可以变成多个工件。产品负责人和产品管理人员与开发团队的其他成员一起创建功能和故事的验收标准。验收标准的创建可以看作是对期望系统行为的发现。
创建规范的下一个阶段是制定。在此阶段,开发人员和测试人员共同合作,创建验收测试。他们可以根据写好的验收标准,详细阐述每个条款中的具体标准,包括允许的初始条件和测量输入与输出的值,从而使得某一特定场景的规范变成一项测试。理想情况下,验收测试应使用与验收标准相同的领域特定语言(DSL)编写。
我们可以通过采用故事的验收标准,并添加特定的前置条件、输入和期望的输出或行为,来创建自动化测试。让我们看看之前看到的验收标准如何转化为测试,见下表:
| 验收标准 | 测试 |
|---|---|
| GIVEN 我已配置通知日期… | 给定日期状态不是 x… |
| …WHEN 通知日期过去… | …当日期状态变为 x 之后一个工作日… |
| …THEN 我收到一封包含明细收据的电子邮件通知。 | …然后向所有用户发送包含 xxx 内容的电子邮件通知。 |
表 11.2 – 将验收标准转换为测试
规范的最后一个阶段是自动化。用 DSL 编写的验收测试可以在支持自动化测试的工具中执行。用 Gherkin 编写的验收测试可以通过如 Cucumber、JBehave、Lettuce Behave 和 Behat 等工具执行。
版本控制
版本控制软件允许团队中的多个开发者在相同的代码库、测试脚本或其他文本上并行开发,而不受其他开发者更改的干扰。版本控制系统中的每个更改都会被记录。通过合并操作整合更改,解决工作内容中的变动。
使用版本控制的重要实践包括以下几个方面:
-
将所有内容都保存在版本控制中:许多设计决策作为工件被记录在版本控制中,超越了源代码的范畴。代码、测试脚本、配置文件以及任何其他基于文本的工件可以一起标记,表示它们是同一个发布版本的一部分。版本控制还允许检索先前的版本,回滚任何更改或查看设计决策的演变过程。
-
每个人都使用相同的版本控制系统:正如我们在第一章《引入 SAFe®与 DevOps》中看到的,照片分享网站 Flickr 的开发和运维人员之间使用的是相同的版本控制系统。这使得当生产故障发生时,任何人都可以轻松检索工件。
我们将在下一部分中介绍构建过程中进行的其他版本控制最佳实践。
面向系统的设计
特性和故事并不是团队在为其产品开发新能力时唯一需要考虑的标准。非功能需求(NFRs)是可能影响每个特性和故事的质量,它们作为一种约束或限制。这些 NFRs 可能涉及安全性、合规性、性能、可扩展性和可靠性等方面。
有两种实践可确保符合某些 NFRs:面向运维的设计和威胁建模。让我们来看看这些实践。
面向运维的设计
开发与运维之间的协作是 DevOps 运动的一个标志。确保运维可以轻松检查系统资源,是在开发初期容易纳入的内容,而不是事后才考虑的。
确保产品维护所需能力的关键部分是应用遥测。作为一个系统,产品必须允许轻松衡量系统资源,包括应用程序如何使用服务器内存和存储等资源。除了系统度量,应用遥测还应允许衡量商业数据,用作验证收益假设的领先指标。
其他考虑因素包括确保新特性带来的变化可以轻松回滚,或者修复可以通过持续交付管道向前推进。在进行这些操作时,需要注意可能代表系统状态的组件,例如数据库。这些组件可能无法轻松回滚。
威胁建模
向 DevSecOps 方法迈进需要一种向左转的安全思维方式。这种思维方式可以在持续交付流水线的设计和开发阶段考虑安全问题,从而对产品有一个更全面的视角。
我们首先在第十章《持续探索与发现新特性》中看到,威胁建模是架构系统的一部分。作为持续集成过程中威胁建模的一部分,我们可能会问以下问题:
-
我们在做什么?这有助于你了解工作的范围。
-
这可能会出什么问题?这让你可以通过头脑风暴或结构化的威胁建模过程(例如应用安全框架(ASF)或欺骗、篡改、拒绝、信息泄露、服务拒绝或特权提升(STRIDE))开始你的评估,后者识别可能的网络安全威胁类型。
-
我们能做些什么来解决出现的问题?根据评估,制定对策或缓解步骤。
-
到目前为止,我们为现有系统做得够好吗?持续评估评估、对策和缓解步骤。
向 DevSecOps 发展基于评估过程中识别的对策和缓解步骤。
随着开发更改的完成,它们必须与现有产品集成并进行测试。这可能会开始将自动化纳入 CI/CD 流水线。接下来,让我们看看如何通过构建过程开始进入 CI/CD 流水线。
构建解决方案包
CI/CD 流水线可以通过版本控制系统中的操作触发,例如将新更改保存为提交。在版本控制系统接受更改之前,它们应该经过测试过程,以确保不会对当前的代码库产生不良影响。这个测试和版本控制集成的过程是 CI 过程中的一个重要部分,其中实践分为版本控制视角和测试视角。
让我们来看看这些视角以及其中的实践。
版本控制实践
良好的版本控制实践确保在将更改引入版本控制之前,通过测试对其进行评估,然后再将其保存并与现有代码库合并。这确保了代码库的健壮性,不会出现阻止代码库正确构建或打包的更改。
版本控制实践可以进一步分为三种类型,帮助确保随着更改的引入,代码库保持健壮。让我们详细看看这些实践是什么。
代码的持续集成(CI)
CI 实践源于通过自动化构建脚本或 CI 工具优化构建过程。通过提交操作将更改保存到版本控制中,会触发以下一系列步骤:
-
应用程序将被构建,并整合保存的变更。如果构建过程中出现错误,将发送关于该错误的通知。变更将无法与代码库合并。
-
如果构建成功,测试将会在包含代码变更的构建上运行。这些测试通常是小型测试,测量功能的一个小部分,可以快速执行且不占用太多时间。如果检测到测试失败,将会发送通知,并且变更将无法与代码库合并。
-
另一种可以执行的测试是对代码库的扫描。扫描可以查找代码风格标准的偏差、语法错误以及已知的安全漏洞。根据发现的严重性,变更将无法与代码库合并,并且会就所有发现的内容发送通知。
-
在构建、测试和扫描步骤成功完成后,代码变更将被记录到版本控制系统中。代码变更将通过版本控制系统合并到主干,整合到代码库的其余部分。
上述步骤在下图中进行了概述:
图 11.4 – CI 自动化
在执行上述一系列步骤时,团队最终意识到,成功的代码集成依赖于以下因素:
-
频繁执行集成:许多团队最初通过每晚执行构建和测试过程,检查前一天保存的变更。随着变更越来越多,夜间构建通常会增长,直到无法在第二天或更晚之前完成。更频繁的构建,通常是每天多次执行,允许团队成员看到构建结果并迅速采取行动。
-
在较少变更上执行集成:一个包含多个开发者变更的夜间构建会在构建失败时产生问题。诊断哪个开发者的变更导致了构建失败变得更为复杂。基于较少变更执行构建,每次构建都基于保存的变更,可以在出现错误时更快速地进行故障排查。
无论成功与否,CI 都会产生以下输出:
-
快速反馈:CI 的结果应该在几分钟内产生。任何导致 CI 无法成功完成的错误都会在短时间内给出反馈,从而减少延迟。
-
成功时可部署的工件:通过成功构建,将生成一个可以部署到非生产环境中的构建包。
CI 工具,如 Jenkins、GitLab 管道和 GitHub Actions,构成了实现代码持续集成(CI)的自动化基础。
主干开发
一个团队中的多个开发人员,甚至多个团队(如 ART 中的团队)通常必须在同一个代码库上工作,该代码库保存在版本控制中。版本控制系统通过允许更改分支出来,支持同一代码库的并行开发。开发人员或团队可以在分支上工作,直到准备好合并并与其他开发人员或团队共享之前,他们的更改不会影响其他团队或 ART。
图 11.5 – 分支结构示例
在前面的示例中,团队 1和团队 2都有自己基于主分支不同版本的代码库分支(通常称为主干)。团队 1的开发人员创建了一个更改(D1)并将其作为更改T1-2合并回团队 1的分支。在独立的团队分支下,我们如何知道团队 2的必要更改是否可见,并且能被团队 1使用呢?
另一个问题出现在团队 1和团队 2在各自的分支上开发,但没有从主干接收更新,直到他们发布或冲刺结束时才合并。跟踪多个团队的多项更改,并解决大量合并冲突,带来了巨大的挑战。
为了保持简单并确保所有团队都能看到变化,我们希望避免出现长期存在的或永久性的分支。开发人员和团队可以创建分支以支持并行开发,但当准备好后,必须将其合并回主分支,并在此过程中销毁分支。这一过程被称为基于主干的开发。下图展示了基于主干的开发流程:
图 11.6 – 基于主干的开发分支结构
基于主干的开发使得合并操作更容易进行,因为每个验证过的更改都会合并到主分支,而不是一组更改。
有门控的提交
使用基于主干的开发,我们尽可能频繁地将更改合并到代码库的主分支中。这个主分支是 ART 上所有团队使用的。由于主分支的完整性对多个团队至关重要,我们如何确保任何错误的更改不会破坏当前的代码库呢?
为了确保代码库的健壮性,我们必须遵循一个有门控的提交过程,在允许更改合并到主分支之前,必须成功通过构建和测试过程。也可以采取额外的措施,比如对更改进行审查。
在基于 Git 的环境中,Bitbucket、GitLab 和 GitHub 等 Git 服务器将有门控的提交定义为拉取请求或合并请求,这些请求允许在请求合并操作时进行更严格的审查。
测试实践
我们看到,构建过程依赖于测试来确保对代码库的更改不会对产品的功能或安全性产生不利影响。执行的测试证明是非常重要的,因为理想情况下,构建过程应该在每次保存的更改后执行,如果成功,下一步将是将更改合并到主分支,对于 ART 来说,这个分支对团队或多个团队是可见的。
构建过程涉及两种类型的测试,这些测试会针对潜在的新版本代码库运行:自动化单元测试和静态应用安全分析。
让我们更深入地了解作为构建过程一部分的每种测试类型。
自动化单元测试
单元测试通常与代码同时编写,如果不是提前编写。这些单元测试可能由个人开发者在其工作站上运行,在代码开发过程中进行。如果是这种情况,为什么还要在构建过程中再次运行它们呢?
CI 的主要思想是确保一个标准、可靠的流程。通过 CI/CD 流水线实现自动化,确保所有开发者都遵循这一流程。在构建过程中增加单元测试,并在自动化的 CI/CD 流水线上运行,确保每个开发者的代码变更都会每次执行单元测试。
同时确保任何已更新的单元测试也是潜在代码变更的一部分,并且被纳入版本控制中的代码库。这可以确保代码更改能够通过正确的测试进行验证,防止因为不正确的测试导致 CI/CD 流水线停止。确保代码创建者和测试创建者之间的协作开发是必要的,以确保这种情况不发生。
应用安全的静态分析
静态分析是一种通过工具扫描代码库文本(包括正在检查的潜在代码更改)来查找特定文本模式的过程。这些文本模式可以用于识别以下问题:
-
编码错误
-
已知的安全漏洞
-
不遵守编码指南或编码标准
这种分析是在无需执行应用程序的情况下进行的。因此,静态分析是一种高效的检查构建过程中问题的手段。
正如我们在第三章《提高效率和质量的自动化》中所看到的,静态分析可以分为以下两类:
-
静态代码分析:查看代码中可能存在的编码错误。Linting 就是静态代码分析的一种示例。
-
静态安全分析:查看代码中可能存在的安全漏洞和攻击向量。执行静态安全分析的应用程序可能进行以下扫描:
-
依赖扫描:扫描代码依赖和对第三方库的引用,以查找漏洞
-
静态应用安全测试(SAST):扫描代码以查找攻击向量和漏洞
-
许可合规:扫描库以确定其开源许可模型
-
容器扫描:扫描 Docker 容器以查找嵌入的漏洞
-
秘密检测:扫描代码以查找嵌入的凭证、密钥和令牌
-
我们的应用程序已经通过了第一组测试,但它是否已经准备好应对生产环境中的严苛要求?为了回答这个问题,我们需要进行系统级测试。接下来的部分将探讨支持系统级测试的实践。
端到端测试
此时,我们已经对单独的代码片段进行了测试,并确保了功能的正确性,同时保持了安全性。在此,我们开始将新的代码变更与现有代码库集成,并通过端到端测试来评估整个系统。
允许对系统进行真实端到端测试的实践将在接下来的部分中讨论。让我们深入了解。
等效的测试环境
系统级测试应在尽可能接近生产环境的环境中进行。尽量在与生产环境相似的环境中测试解决方案,可以更有信心地确保解决方案在实际投入生产环境时能够正常工作。测试环境与生产环境的相似性越高,发现问题并开始排查根本原因时,涉及的变量就越少。
确保测试环境与生产环境等效的一个关键因素是使用配置管理。通过配置管理,操作系统版本、关键驱动程序版本和应用程序版本等关键资源会被记录在基于文本的配置文件中。理想情况下,配置文件会通过版本控制进行管理,并带有标签,标明解决方案的版本及其在测试环境和生产环境中的应用。
因为为生产环境分配完全相同的资源可能会非常昂贵,所以重要的视角是,资源的确切版本,而不是资源的确切数量,是保持等效性的关键。
测试自动化
系统级测试可以涵盖多个层次,其中大部分可以实现自动化。在不同层次的测试中,哪些测试可以被自动化?
除了前面提到的测试金字塔,我们可能还需要考虑需要理解测试结果的人员。第二个考虑因素是,测试是验证解决方案是否符合要求,还是让开发人员看到他们的设计方法是否正确。
敏捷测试矩阵查看各种类型的测试,并根据这些考虑因素对其进行组织。下图展示了在 SAFe 文章中看到的敏捷测试矩阵,关于敏捷测试 (www.scaledagileframework.com/agile-testing/):
图 11.7 – 敏捷测试矩阵(© Scaled Agile, Inc.,保留所有权利)
从前面的图示可以看出,第一个考虑因素是从业务或技术的角度来看待的。开发人员从技术测试的角度,确保解决方案的正确功能和正常操作。最终用户从面向业务的测试角度,确保对解决方案的理解并验证其效益假设。
我们还可以看到第二个考虑因素:测试是否涉及完整的解决方案或实现。指导开发的测试有助于 TDD 和 BDD 方法,其中测试先于代码编写。批判产品的测试则关注解决方案是否符合用户需求。
在每个考虑因素的两个领域中,我们可以将测试分为以下四个象限:
-
Q1:这些包含单元测试和组件测试。这些测试可能作为 TDD 方法的一部分创建。
-
Q2:这些包含功能性测试以及故事和特性的测试。这些测试可以使用 BDD 方法创建,以实现自动化测试。否则,其中一些验证可能需要手动进行。
-
Q3:这些是整个解决方案的验收测试。这些可能是发布前的最终验证。这些测试通常由 alpha 和 beta 用户手动执行。
-
Q4:这些测试整体系统的质量,包括非功能性需求(NFRs)。这些测试验证生产环境中的系统。
我们将看到,第 3 象限的测试是在第十二章 持续部署到生产环境 中的 CD 阶段进行的。第 4 象限的测试是在第十三章 按需发布以实现价值 中提到的按需发布阶段进行的。
测试数据的管理
确保测试环境与生产环境之间相似的一个关键部分是用于测试解决方案的数据。使用在生产环境中可能找到的数据,可以提供更现实的测试结果,从而增加对解决方案的信心。
现实的测试数据可以来自合成测试数据或真实的生产数据。测试数据可能来自生产数据的备份,这些数据被恢复到测试环境中。测试数据应该删除任何被视为私密的信息。
合成测试数据是由数据生成工具(如 DATPROF Privacy 和 Gretel)创建的虚假数据。它的优点是无需进行匿名化步骤来删除私人信息。
无论数据是匿名化的生产数据还是合成数据,测试数据应该使用版本控制来维护,使用工件库软件来存储大规模的基于二进制的数据。
服务虚拟化
服务虚拟化使得即使测试环境缺少生产环境中可用的资源,测试环境也能像生产环境一样工作。生产环境可能依赖于一些关键组件,这些组件由于以下因素而无法复制:
-
该组件尚未完成
-
该组件由第三方供应商或合作伙伴开发
-
在测试环境中对组件的访问有限
-
该组件在测试环境中配置困难
-
需要访问该组件的多个团队具有不同的设置
-
该组件太昂贵,无法用于性能或负载测试
由组件组成的系统,如果它们通过公认的接口进行通信,可以利用服务虚拟化来模拟一个或多个组件的行为。如果虚拟化服务是一个数据库,它可以返回合成的测试数据。
在测试环境中模拟的组件称为虚拟资产。虚拟资产是通过以下方法由工具创建的,这些方法可以测量真实组件的行为:
-
记录一个组件在共享通道或总线上通信时的消息、响应和响应时间
-
检查组件的日志
-
查看服务接口规范
-
手动输入数据并测量行为
一旦虚拟资产创建完成,它就会在测试环境中占据一席之地。生产环境与测试环境之间使用虚拟资产的区别示例如下:
图 11.8 – 生产环境与测试环境
用于创建虚拟资产的流行工具包括 Smartbear 的 SoapUI 和 ReadyAPI、MockLab、Parasoft Virtualize 和 WireMock。
一个重要的区别需要考虑的是,尽管服务虚拟化看起来类似于模拟或桩化组件,但这两个概念并不相同。添加模拟组件或桩通常是在开发过程中进行的,当组件尚未准备好发布时。模拟对象的行为只返回一种类型的输出——成功信息——因此其他组件的开发不会受到阻碍。服务虚拟化允许在各种场景下提供正确的行为。
使用虚拟资产的环境应在配置管理工具中进行维护。虚拟资产的配置文件和接口定义文件应保存在版本控制中,紧密存放,并贴有标签以标识它们作为应用程序版本的测试资产。
测试非功能性需求
在进行端到端系统测试时,我们需要记住系统的约束条件,这些条件我们之前已经确定为非功能性需求(NFRs)。非功能性需求影响每个用户故事和功能,作为必须遵守的约束。诸如安全性、性能、可靠性和可扩展性等质量属性,应该通过测试进行检查,以验证这些约束没有被破坏。
非功能性需求的测试通常是自动化的,涉及专门的测试工具。ART 上的敏捷团队通常与系统团队合作,确保建立工具链,以便作为端到端测试的一部分执行非功能性需求的测试。
在对变更执行完所有测试组合后,我们可能还希望有一个机会来查看我们的变更是否准备好部署到生产环境。我们将变更放入阶段环境,这是生产环境的替代品,用于在将变更部署到生产之前进行最终检查。让我们来看看将变更部署到阶段环境的活动。
移动到阶段环境
我们可能希望验证能否将变更部署到类似生产的环境中,并验证我们的解决方案是否仍然有效。为了进行这最后的检查,我们采用了一些实践。
让我们深入了解这些实践。
阶段环境
阶段环境是生产环境的复制品,在 PI 过程中有多种用途。它是系统演示的地方,展示当前系统的状态。用户验收测试可以在这个环境中进行,它尽可能接近生产环境。
随着产品的变更开发,阶段环境展示了在部署到生产之前的变更状态。至少,每个迭代或冲刺期间,阶段环境都会进行变更。只要构建过程和端到端测试成功完成,更频繁的变更也是允许的。
阶段环境也可以作为生产环境的替代环境,采用蓝绿部署配置,这种配置可以在生产故障时轻松回滚。现在,让我们来看一下这种配置。
蓝绿部署
在蓝绿部署中,你有两个相同的环境。两个环境中,一个是生产环境并面对流量,另一个是空闲的,处于待命状态。
空闲环境接收最新的变更,并进行彻底的测试。适当时,变更将通过将空闲环境切换为上线状态,并使另一个环境处于空闲状态来发布。以下图示说明了这一过渡:
图 11.9 – 蓝绿部署发布新版本
如果发现问题,可以切换回滚变更。对于不追踪状态的系统来说,这种来回切换很容易。否则,蓝/绿部署必须精心设计,以确保能够存储状态的组件,如数据库,在过渡时不会被损坏。
系统演示
在每个 PI(程序增量)的每个冲刺或迭代结束时,在每个团队的迭代评审后,团队会聚集在一起整合他们的工作成果。与系统团队合作,他们展示目前在暂存环境中该 PI 中产品的当前状态。商业负责人、客户和 ART 的其他关键利益相关者会出席此演示活动,以查看进展并提供反馈。这个活动为 ART 目前的努力提供了快速反馈。
请注意,系统演示并不妨碍将变更部署到生产环境中。这可以继续作为 CD(我们将在下一章讨论)的一部分自动发生,但反馈可能会阻止变更发布给客户,直到基于反馈的变更进入生产并按需发布。
在暂存环境中的成功测试让我们有信心,变更具有正确的功能,并且在生产环境中足够稳定,但唯一真正证明这一点的方式是将我们的变更部署到实际的生产环境中。
总结
在本章中,我们继续探索持续交付管道,关注 CI(持续集成),它实现了在持续探索中创建的功能。功能被拆分成更易消化的故事。产品的开发不仅包括产品本身,还包括验证产品的测试。安全性和面向运维的设计也纳入了开发中。
构建阶段将自动化引入管道中。当版本控制发生提交时,单元测试会运行以确保功能的持续正确性。构建还会扫描代码错误并查找安全漏洞。如果一切正常,提交将被允许与版本控制仓库的主分支或干线合并。
成功的构建可以触发在类似生产环境的测试环境中进行进一步测试。在这里,会进行系统级的端到端测试,以防止任何生产故障。这里的测试尽可能自动化。准确的测试数据和服务虚拟化可能为生产环境提供合理的仿真进行测试。
当构建和测试完成后,变更可能会出现在一个暂存环境中,它是生产环境的副本,或者是蓝/绿部署的一部分。暂存环境也是在系统演示期间展示变更的地方,这是一个在每次冲刺或迭代结束时,ART(敏捷释放训练)团队获得系统开发反馈的活动。
在进入暂存环境后,我们必须将更改移入生产环境。这是在 CD 中发生的,我们将在下一章中探讨它。
问题
-
协同开发的两个例子是什么?
-
独立编程
-
配对编程
-
挑战编程
-
Mob 编程
-
跨团队编程
-
-
TDD 的第一步是什么?
-
编写测试
-
编写代码
-
重构测试
-
重构代码
-
-
在进行基于主干的开发时,成功的构建和测试将使提交的更改与哪个分支合并?
-
发布分支
-
修复分支
-
主分支
-
完整测试分支
-
-
根据测试金字塔,哪种类型的测试执行速度最快?
-
单元测试
-
安全测试
-
故事测试
-
用户验收测试
-
-
应该存储在版本控制中的基于文本的文档是什么?
-
代码
-
测试
-
配置文件
-
A 和 C
-
以上所有
-
-
可以用什么方法让测试环境与生产环境相似?
-
使用旧的生产服务器
-
清理后的生产数据备份
-
服务虚拟化
-
B 和 C
-
以上所有
-
-
与生产环境完全相同的暂存环境可以用来做什么?
-
用户验收测试
-
用于蓝绿部署的空闲环境
-
系统演示
-
以上所有
-
进一步阅读
-
Scaled Agile 指南,说明如何将功能分解为故事及良好故事的内容:
www.scaledagileframework.com/story/ -
一份常用模式的指南,说明如何将功能分解为故事或将大故事拆分成小故事:
www.humanizingwork.com/wp-content/uploads/2020/10/HW-Story-Splitting-Flowchart.pdf -
一篇好文章,详细介绍了配对编程的实践:
www.techtarget.com/searchsoftwarequality/definition/Pair-programming -
犹他大学进行的研究,详细描述了配对编程的好处:
collaboration.csc.ncsu.edu/laurie/Papers/XPSardinia.PDF -
Woody Zuill 的原文,详细描述了 mob 编程的工作原理及其好处:
www.agilealliance.org/resources/experience-reports/mob-programming-agile2014/ -
Scaled Agile 的一篇文章,关于“将测试向左移”和采用 TDD 和 BDD:
www.scaledagileframework.com/built-in-quality/ -
来自 开放 Web 应用程序安全项目 (OWASP) 的文章,详细描述了威胁建模:
owasp.org/www-community/Threat_Modeling -
这篇来自 OWASP 的文章详细介绍了用于威胁建模的流程,包括 ASP 和 STRIDE:
owasp.org/www-community/Threat_Modeling_Process -
一篇扩展了 Mike Cohn 测试金字塔的文章:
martinfowler.com/articles/practical-test-pyramid.html -
Scaled Agile 关于敏捷测试和敏捷测试矩阵的文章:
www.scaledagileframework.com/agile-testing/ -
Smartbear 公司(两款领先服务虚拟化工具的供应商)撰写的关于服务虚拟化的文章,内容包括什么是服务虚拟化,它的好处,以及它与存根的比较:
smartbear.com/learn/software-testing/what-is-service-virtualization/ -
Scaled Agile 关于系统演示的指导:
www.scaledagileframework.com/system-demo/
第十二章:持续部署到生产环境
在我们继续沿着持续交付管道前进时,我们设计了特性来测试在持续探索过程中获得的效益假设。这些特性的实现发生在持续集成阶段,我们在这一阶段创建了故事、开发了变更和测试,并将变更通过构建和测试过程。最终,我们的变更被放置在一个预发布环境中。
在持续部署中,我们完成了变更到生产环境的整个过程。然而,活动并不在部署到生产环境后就结束。
在本章中,我们将探讨使得在持续部署中能够实现以下操作的实践:
-
将变更部署到生产环境
-
验证变更在生产环境中的正常运行
-
监控生产环境
-
响应和从生产故障中恢复
需要记住的是,我们将部署与发布分开。我们在第十章,持续探索与发现新特性中看到了使得新变更能够自动部署到生产环境的架构问题。虽然我们持续将变更部署到生产环境,但直到我们发布这些变更,客户才会看到它们。本章将讨论如何只允许特定人员查看生产环境中的这些变更。我们将在下一章,第十三章,按需发布以实现价值中讨论按需发布。
让我们从第一项活动开始,探索持续部署:将变更部署到生产环境。
部署到生产环境
部署的目标是将我们的解决方案(无论是新产品还是对现有产品的增强功能)投入生产环境。在持续部署中,我们希望尽可能频繁地推动这一解决方案,同时将对生产环境的风险降到最低。
以下实践使我们能够更频繁地部署并降低生产环境中的故障风险:
-
设置暗启动
-
使用特性标志
-
自动化部署
-
基础设施即代码
-
选择性部署
-
自助部署
-
版本控制
-
蓝绿部署
我们在前面的章节中,特别是第十一章,解决方案开发的持续集成中已经讨论过版本控制。我们也在同一章中讨论了蓝绿部署。
让我们来看看其余的实践,它们是如何在降低风险的同时增加部署频率的。
增加部署频率
我们在第一章,介绍 SAFe®和 DevOps中看到了一组实践,这些实践使得 Flickr 能够在 Velocity 大会上宣布他们可以一天进行 10 次部署。他们通过创建脚本,确保在所有测试通过后进行自动部署。
当今的自动化和实践是 Flickr 最初成功的自动化部署的演变。为此,我们将研究今天正在使用哪些实践以及如何使用。
让我们从今天的部署自动化开始探索。
部署自动化
允许 Flickr 自动化其部署的脚本将从代码提交到部署的时间从天缩短到了小时。随着这一脚本的现代演变,CI/CD 管道进一步将部署时间从小时缩短到分钟甚至秒钟。让我们来看看它是如何做到的。
在整体的持续交付管道中,我们看到在持续集成过程中引入了自动化。自动化可以尽可能地在不需要人工干预的情况下完成构建、测试、合并和打包操作,如下图所示。
图 12.1 – CI 和 CD 自动化
我们继续在持续部署过程中使用自动化,如前面的图所示。在持续部署中,我们将应用程序包从持续集成的尾部提取并部署到测试环境。在测试环境中执行系统级测试后,应用程序包将被部署到生产环境。这种自动化可以通过将持续集成和持续部署结合在一起的工具来完成,如 Jenkins 以及 GitLab 和 Bitbucket 的管道。持续部署自动化也可以在像 ArgoCD 这样的工具中与持续集成分开进行。多个技术和实践方面的支持有助于在持续部署中实现有效的自动化。
第一个重要的部分是版本控制。我们已经看到版本控制对文本工件的重要性,它是 CI/CD 管道的触发器,并且能够将所有工件连接起来,以便理解特定部署或发布过程中涉及的一切。
工件库可以充当大规模二进制工件的版本控制工具,这些工件无法存储在基于文本的版本控制系统中。它们存储中间构建、代码库、虚拟机镜像和可能作为构建过程的一部分创建的 Docker 容器。如果某个组件不需要重建和测试,其工件可以直接从工件库中获取,从而节省时间和精力。
更改的大小是另一个可以减少自动化部署到生产环境所需时间的因素。我们在第四章,利用 精益流程保持工作持续推进中看到,批量大小是促进流程流动的一个重要因素。一个小的独立更改会比一个大型更改处理得更快,因为后者可能会启动大量的重建和测试流程,影响 CI/CD 管道的效率。
自动化尽可能多的步骤,包括部署推送,将显著减少部署的前置时间。允许自动化继续进行构建和测试的后续步骤,贯穿整个持续集成和持续部署阶段,能够保持持续的工作进度,避免由于需要手动操作才能进行下一步而导致的延误。这可能将部署时间缩短到秒级,而非分钟级。
基础设施即代码
部署自动化的关键部分是创建和配置生产环境中的资源。基础设施即代码(IaC)使我们能够通过基于文本的描述来定义所需的基础设施及其资源配置。这些配置文件与配置管理工具一起使用,用于创建新资源、更新资源配置,或者在需要时销毁资源。如第三章中提到的,提高效率与质量的自动化,流行的 IaC 工具包括 Hashicorp 的 Terraform 和适用于 Amazon Web Services 环境的 AWS CloudFormation。
版本控制在建立顺畅的基础设施即代码(IaC)流程中扮演着关键角色,确保配置文件的演变得到记录和维护。如果产品的更改需要对生产环境中的配置进行更改,则配置文件的更改会在预发布环境中创建并进行测试。版本控制中的标签将用于将所有与更改相关的工件连接起来,从源代码到测试,再到配置文件的更改。
构建和测试配置文件的过程与开发产品或其测试没有区别。这有助于确保在生产环境中创建的资源是可靠的,并与任何产品更改保持同步。
选择性部署
在某些组织中,生产环境可能会被划分为多个生产环境。这种划分可能基于以下一些因素:
-
基础设施/资源
-
地理
-
客户
选择性部署利用了环境隔离,通过仅在生产环境的某一个实例上进行部署来实现。以下示例展示了一个面向单个客户的环境的选择性部署。
图 12.2 – 向客户 A 的生产环境进行选择性部署
我们前面的例子允许在有限的生产能力中与客户 A 进行测试,而其他生产环境中的客户看不到变化。在多个环境中的部署允许灵活的发布策略,例如金丝雀发布,其中变化首先发布到特定区域或客户,然后才发布到整个客户群。我们将在第十三章中更详细地讨论金丝雀发布,按需发布以实现价值。
一个现实世界中选择性部署的例子发生在 Facebook。随着 Facebook 的流行增长,发布工程团队通过开发一个从主分支推送系统来跟上开发活动,这使得发布更频繁。正如在engineering.fb.com/2017/08/31/web/rapid-release-at-massive-scale/中详细介绍的那样,部署开始时针对 50%的 Facebook 员工,然后是 0.1%的 Facebook 生产流量,最终推广到 10%的 Facebook 生产流量。
自助部署
可能有正当理由,导致你的组织无法允许自动化部署到生产环境中。通常,这是为了遵守合规政策。
如果是这种情况,自助部署(通常称为一键部署)允许任何人,通常是开发人员,将通过持续集成的更改部署到生产环境中。这种方法仍然使用自动化来执行实际部署,因此开发人员没有对生产环境的无限制访问权限。
使用自动化的部署仍然会被记录和审计,以便追踪完整的活动。每次自动化部署的可追溯性可能会让业务合规部门对自动化部署的推进充满信心。
降低风险
Jez Humble 在《持续交付:通过构建、测试和部署自动化实现可靠的软件发布》一书中著名地说过以下关于部署的话:“如果它让你痛苦,就更频繁地做它,并把痛苦提前。”我们已经看到了一些更频繁进行部署的关键方法。现在我们将看看一些可能帮助我们应对部署痛苦的实践。
以下实践可以帮助我们降低在生产环境中引入故障的风险:
-
黑暗启动
-
功能标志
-
蓝绿部署
-
版本控制
蓝绿部署和版本控制在前几章中已有讨论。在本章中,让我们将重点放在其他的风险缓解措施上。
功能标志
功能标志(或功能切换)是实现黑暗启动和金丝雀发布的主要机制。通过选择功能的可见性,即是否启用或禁用标志,你可以有效地将新功能的部署与功能的发布分离,后者使功能对所有用户可用。
功能标志还允许在生产中出现问题时迅速回滚。只需在发现问题的第一时间禁用功能标志。
设置功能标志时,重要的是要测试功能标志在两个状态下的行为:测试功能标志启用时的效果,然后是禁用时的效果。这个测试应该在预生产环境中完成,远在部署到生产环境之前。
功能标志的存在确实增加了整体解决方案的复杂性,因为它增加了更多的行为测试组合。使用过多的功能标志,尤其是对于那些已经发布很久的过时功能标志,会增加测试的复杂性并产生技术债务。过时的功能标志应该在第一时间被移除。
暗推出
暗推出允许在生产环境中仅对开发人员、测试人员以及通常是 beta 或特定客户可见新功能,而不是对所有客户群体可见。为了实现暗推出,组织通常使用功能标志,根据需要可见性的用户群体来允许或禁止功能的可见性。
以下插图详细展示了开发人员和测试人员如何使用功能标志进行暗推出的示例。
图 12.3 – 使用功能标志进行暗推出的示例
在我们之前的示例中,新功能在生产环境中对开发人员和测试人员可见。这种可见性使他们可以在不影响客户的情况下对该功能进行实验,而客户并不会看到该功能。
开发人员和测试人员可以通过以下方式使用暗推出:
-
测试新的应用基础设施
-
动态控制哪些早期客户可以看到新功能
-
新功能的实验
暗推出通常与金丝雀发布同义。暗推出和金丝雀发布之间的主要区别在于,功能标志允许选择一部分客户查看新功能,以了解他们对金丝雀发布中新功能的反应。
我们现在需要确认这些变更不会对我们当前的生产环境产生不良影响,即使这些部署的变更没有正式发布。为此,我们需要进行测试。让我们来看看我们在生产环境中的测试过程。
验证功能的正常运行
产品的变更,以新功能的形式,已经进入生产环境,但这并不意味着工作已经完成。实际上,工作才刚刚开始。我们需要确保我们的功能按预期运行。这不仅从功能角度来看是对的,还涉及到与非功能性需求(NFR)相关的其他方面。
以下做法帮助我们验证生产环境中的正确行为:
-
生产环境测试
-
在生产环境中的测试自动化
-
测试数据管理
-
测试非功能性需求(NFR)
有些做法在前一章已经介绍过,但现在我们看到生产环境,我们可以更仔细地检查这些做法。让我们看看所有这些做法及其在生产中的应用。
生产测试
在功能开关的配合下进行暗发布,测试可以继续在生产环境的资源上进行。尽管在生产环境中的测试并不完全模拟生产环境的条件,但测试人员仍然应谨慎进行生产环境中的测试。生产测试有以下优势:
-
允许在实时、真实的场景中监控应用程序性能
-
监控应用程序在实时流量下的性能
-
进一步检测漏洞和恶意攻击
-
有助于维护应用程序的质量
在生产中运行的测试应该是测试金字塔顶部的测试,并结合前一阶段的持续集成中运行的部分测试作为基本的 sanity check。我们真正关注的是确认我们即将发布的功能行为是否符合预期。测试金字塔中的其他所有方面应该已经在测试环境和预发布环境中进行了测试。生产中的测试是对早期测试的补充,而不是替代。
成功的生产测试需要详细理解以下因素:
-
在生产环境中使用真实浏览器和设备。测试环境中可能使用了仿真器或模拟器,但它们可能无法展现与“真实设备”相同的行为。
-
允许生产环境中的真实流量来衡量在负载下的应用程序性能。毕竟,这才是应用程序将面对的流量。
-
使用功能开关让少部分开发者、测试人员和测试客户体验新功能。功能开关还允许在出现问题时快速禁用所有用户的该功能。
-
在进行生产测试时,必须持续监控生产环境。这可以在问题出现的第一时间快速关闭任何测试。此外,可能还需要恢复测试操作。
-
使用专用的测试用户账户,以便日志能够区分测试交易和真实交易。
在生产中执行的关键测试之一是 A/B 测试。在 A/B 测试中,功能开关可能会将测试中的新功能(选项“A”)分配给测试用户,以此评估该新选项在行为上是否与当前应用程序(选项“B”)有所不同。
生产环境中的自动化测试
在生产环境中进行测试时,功能开关管理非常重要。功能开关不仅决定功能是否可见,还决定该功能对哪些用户可见。
功能标志管理的一个关键用例发生在 Facebook。在 www.facebook.com/notes/10158791573022200 的博客文章中,Meta(Facebook 母公司)的一名工程师描述了他们如何使用 Gatekeeper 为每个 UI 变更建立 A/B 测试,测试对象为真实的 Facebook 用户。Gatekeeper 确保真实用户参与单一 UI 元素的测试,并确保 A/B 测试之间不会发生冲突。
因为 Facebook 在评估小规模变化时知道一些用户可能会有不理想的用户体验,但 Facebook 仍然致力于提供更好的整体产品。为此,如果足够多的用户不使用该 UI 元素变化,就会视为测试失败,并且不会向所有 Facebook 用户推广。
测试数据管理
虽然 A/B 测试可以用来确定特定功能是否会被最终用户使用,但其他测试可能需要在生产环境中进行,以查看该功能的预期流程和信息是否得以实现。
合成交易使用自动化测试脚本验证应用程序在生产环境中的端到端性能。脚本模拟用户完成交易时的操作。这些合成交易及应用程序作出的响应会被合成监控工具记录。允许合成监控和使用合成交易进行测试,能够让位于功能标志后的测试人员验证应用程序的以下特征:
-
功能性:应用程序是否按正确的路径运行?
-
可用性:应用程序在生产环境中的性能是否足够?
-
响应时间:这是衡量应用程序在生产环境中性能的另一个指标。
合成监控使你能够了解应用程序的关键流程以及它们的表现如何。这些内容还可以提供发布时用监控工具检查的重要事项。
测试 NFRs
将新功能部署到生产环境,并通过功能标志让少数用户可见,允许在发布之前评估关键的 NFRs。
合成交易和监控允许在生产环境中进行性能测试。接收生产环境中真实流量的样本能够进行漏洞测试。
在生产环境中对 NFRs 的测试是发布前功能验证的重要最后一步。这是一个关键步骤,不能忽视。合成交易和功能标志可以使 NFRs 的低风险测试成为可能,从而确保生产环境的稳健性。
当我们在生产环境中执行测试时,我们发现验证过程的关键部分是持续监控。接下来我们将探索进行持续监控所需的内容。
监控生产环境
监控生产环境让我们了解环境的 NFR(非功能需求)是否仍然得到保持,以及部署的新功能是否按照 NFR 中识别的约束条件正常工作并执行。
有一些实践对提供持续监控至关重要。让我们看看这些实践是什么,以及如何确保它们在我们的生产环境中得到建立。
全栈遥测
我们需要在不同层级上监控我们解决方案的重要指标,原因有很多。在较低层级,我们希望确保我们的生产环境稳定,并且没有失败的风险。当我们提升到更高层次来审视我们的系统时,我们希望确保我们拥有可以判断最初启动开发的商业假设是否成立的衡量指标。最终,在商业层面,我们所做的衡量可以判断开发是否与我们的战略保持一致,或者是否需要做出战略上的调整。
为了满足我们所需的各个层级的度量标准,这些度量被称为全栈遥测。以下表格详细说明了各个层级和示例度量标准。
| 测量层级 | 示例度量标准 |
|---|---|
| 商业 | 价值流关键绩效指标(Cycle Time, Lead Time)和解决方案关键绩效指标(收入、NPS、转化率)。 |
| IT 服务管理(ITSM) | 服务级别目标和其他服务 KPI(服务器正常运行时间和网络可用性)。 |
| 产品或解决方案 | 垃圾回收指标、响应时间、可用性和应用日志。 |
| 基础设施 | CPU 利用率、RAM 利用率、网络指标和事件日志。 |
表 12.1 – 解决方案层级的样本度量标准
所需的度量标准必须在持续交付管道的持续探索阶段设计,以确保它们能够在持续部署及之后的阶段轻松收集。计划中的度量标准应包括用于衡量利益假设的商业数据,以及能够告诉我们生产环境中系统状态的技术数据。
可视化显示
通过全栈遥测可以收集大量数据。使数据有用的是组织数据的方式,以便用户能够一目了然地了解环境状态,并及时识别何时需要采取快速行动。
仪表盘提供了一种可视化收集数据的关键方式。这种可视化有助于识别趋势,或理解某个重要指标是否已超出阈值,这可能表示生产中的故障。
以下是一个示例仪表盘。这是 Grafana 的云版本的公共仪表盘,Grafana 是一款用于创建仪表盘的产品。
图 12.4 – 来自 grafana.org 的示例仪表盘
仪表盘的重要性毋庸置疑,但同样重要的是这些仪表盘要对组织中的每个人都可见。透明度使得价值流中的每个人都能获取所有必要的信息,而无需等待批准或争论是否被允许查看单独的度量数据。
联邦监控
在复杂的组织中,显示数据可视化的透明度可能会很困难,尤其是当涉及多个业务线、业务单元和其他小组时。为了确保信息不被孤立,可能需要考虑如何确保信息是联邦化的,并且容易共享和交流。以下图是显示联邦信息的仪表盘示意图。
图 12.5 – 联邦仪表盘示例
在前面的图中,仪表盘显示了所选系统(系统 B)的测量数据。通过在控制面板中选择相应的系统,可以查看其他系统的信息。
在联邦结构中共享信息可以提供更多的透明度,同时鼓励各个业务单元的敏捷性。来自其他来源的数据应与本地业务单元的信息结合,提供对业务单元系统的更全面视图。仪表盘和其他信息展示机制可以显示系统数据,并允许深入查看数据及其来源。
通过仪表盘上共享和可见的各种数据,组织可以持续监控其生产环境。这可以为他们做好准备,应对在发布新功能时可能发生的生产故障。让我们来看看发生生产故障时他们可以采用的做法。
灾难发生时的响应和恢复
快速恢复的能力是 DevOps 方法的关键特性之一。DORA 的关键指标之一是恢复服务的时间,表现卓越的 DevOps 组织能够在几分钟内完成恢复。准备恢复是 CALMR 方法的一个重要部分。
为了促进恢复,我们需要了解以下做法:
-
主动检测
-
跨团队协作
-
混沌工程
-
会话回放
-
回滚并向前修复
-
不可变基础设施
在生产环境中,主动响应至关重要,因为这里是最终用户所在的环境。这里的问题是显而易见的,并且会影响我们的客户。没有及时处理的问题可能会影响到持续交付管道中其他部分的工作。
让我们来看看在生产环境中可以采取的主动做法。
主动检测
因为我们使用功能标志将部署与发布分离,所以可以主动测试并寻找问题,而不会干扰客户,或者更糟糕的是让客户发现问题。为测试人员启用功能标志,可以让他们在生产环境中检查新功能。
利用这个独特机会,在不干扰客户流量的前提下将新功能放入生产环境,测试人员可以进行额外的测试,执行“假设”场景,并最终计划灾难恢复程序,涉及到新功能的发布。
跨团队协作
对客户可见且初期信息较少的问题,可能会成为相互指责的温床。压力在一个非常显眼的问题上增加,伴随着愤怒客户的反馈。解决方案在早期可能并不明显。正是这种类型的压力,可能会考验跨团队协作的有效性,但它已被证明是解决此类问题最有效的方式。
拥有来自不同领域的开发和运维人员是我们在第一章,引入 SAFe®和 DevOps中最初讨论的 Flickr 成功的关键之一。跨部门的协作至今仍然是成功的关键。
要实现真正的协作,我们需要朝着我们在第二章,共同责任文化中识别的以任务为导向、心理安全的创造性文化迈进。随着这种文化的转变,集体拥有感就会产生,团队在不同领域之间协作,共同识别问题的根本原因,并迅速找到解决方案。这样,问题就会成为学习的机会。
混沌工程
在发布功能之前,你可以主动进行一个混沌工程练习,利用功能标志来确保影响不会被现有用户看到,这是一项值得做的练习。
最著名的混沌工程案例来自 Netflix。正如在netflixtechblog.com/the-netflix-simian-army-16e57fbab116的博客文章中所详细描述的那样,Netflix 运行了一套名为“Simian Army”的工具,模拟亚马逊 Web 服务云中的生产故障。其中最著名的工具是 Chaos Monkey,它模拟虚拟服务器宕机。实验通常在工作日进行,工程师们会实时监控并处理发现的问题。
你可以进行类似于 Chaos Monkey 执行的练习。通过模拟故障情况来测试新功能是否足够健壮。在实验结束后,通过复盘来确定下一步行动。
完整的方法详细介绍请参见第六章,从生产故障中恢复。如果在错误预算中有足够的时间,可以对已经发布的现有功能进行混沌工程练习。如果功能管理非常健全,可以对未发布的功能进行练习。
会话重放
一个有用的故障排除工具是会话回放。会话回放是记录单个用户交易并回放这些交易的能力。执行会话回放具有以下优点:
-
开发人员可以了解用户在网站的可用性方面可能遇到的问题,并且可以洞察用户如何真正使用某个功能。
-
开发人员可以查看用于在网站上执行欺诈性交易的操作,这有助于关闭潜在的漏洞。
-
对于生产故障,开发人员可以查看用户执行的具体操作序列,从而导致故障发生。
在客户端执行的会话回放展示了终端用户的操作视角。这些工具允许开发人员看到光标的位置、点击的内容以及输入的内容,像视频回放一样。Dynatrace 和 Datadog 是提供会话回放功能的工具示例。
基于服务器的会话回放捕获所有网站流量,包括键入内容和点击的内容,但不包括滚动和鼠标移动。
使用会话回放时,必须关注会话数据。此类数据通常包含私人信息,如密码,并且可能需要大量存储空间。
回滚和向前修复
当生产故障发生时,恢复稳定环境的两种快速方法包括回滚和向前修复。
回滚是将生产环境恢复到先前的版本,即不包含可能导致生产故障的最新更改的版本。正如我们在第六章《从生产故障中恢复》中看到的那样,回滚的两种常见方法是蓝绿部署和功能标志。
蓝绿部署是一种简便的方法,可以将生产环境回滚到空闲环境,并将原先空闲的环境恢复为活跃状态。在回滚过程中,必须特别注意表示状态的组件,如数据库或易变存储。这些组件在回滚时需要谨慎处理。
功能标志是一种简便的方法,用来在新功能发布导致生产环境故障时隐藏该功能的可见性。将功能标志切换回关闭状态不需要进行大量的代码或配置更改。
向前修复是解决生产环境稳定性的另一种方法。为了进行向前修复,你需要在持续交付流水线中开发并传播故障修复,以便将其部署并发布到生产环境。当执行向前修复时,建议你通过持续交付流水线使用标准部署流程,并且不要跳过任何测试。绕过测试进行“快速修复”可能会导致更大的技术负担。
不可变架构
自动化部署到测试、预发布环境,最终到生产环境的一个主要原因是为了使架构不可变。也就是说,环境中的任何变化都不能手动进行。
任何环境中的变化必须通过持续交付管道进行,并且每个变化所需的工件必须记录在版本控制中。与版本控制和持续交付管道的紧密耦合防止了配置漂移或不同环境之间的变化差异。
总结
在本章中,我们继续探索将持续交付管道引入生产环境的过程。在持续探索阶段完成设计后,我们的特性进入了持续集成阶段进行开发和测试,现在准备部署到生产环境。自动化在执行将变化引入生产环境的步骤中起着关键作用,可能使用基础设施即代码(IaC)来创建和配置新的生产资源。
即使在生产环境中引入了新变化,测试仍然会进行,以便在发布之前建立信心。功能标志允许工程师和选定的测试客户在生产环境中对新变化进行测试,同时对普通用户隐藏。以合成事务形式存在的测试数据允许进行功能测试和非功能性需求(NFRs)测试。
在生产环境中的监控让我们能够看到生产中测试的成功或失败。我们希望确保从系统资源到可能作为领先指标的那些度量数据都能反映出我们希望实现的收益假设。我们希望这些数据在仪表盘上可见,且对所有人透明。如果监控显示生产环境出现问题,我们将准备采取行动。整个价值流协同工作,找到根本原因。我们可以回滚到之前的版本,或修复问题,并通过持续交付管道传播修复。
我们的变化现在已经进入生产环境。接下来,我们等待最后一个事件:发布给我们的用户,以便他们能利用这些变化。为此,我们将在下一章中探讨我们的持续交付管道的最后阶段——按需发布。
问题
-
什么有助于减少部署到生产环境的交付时间?(选择 3 项)
-
单元测试
-
小批量变化
-
版本控制
-
行为驱动开发
-
自动化部署
-
-
哪种实践可以让你执行金丝雀发布?
-
基础设施即代码
-
蓝绿开发
-
选择性部署
-
自助部署
-
-
功能标志允许……(选择 3 项)
-
测试人员在生产环境中查看未发布的特性
-
让你更快地运行单元测试
-
开发人员开始部署到生产环境
-
在生产环境故障发生时回滚新特性
-
进行 A/B 测试的精选客户群体
-
CI/CD 管道的执行
-
-
在生产环境中运行合成事务可以帮助衡量……(选择 3 项)
-
周期时间
-
功能性
-
可扩展性
-
可用性
-
响应时间
-
-
全栈遥测应该衡量哪些操作级别?
-
IT 服务管理
-
商业
-
解决方案
-
基础设施
-
上述所有
-
-
服务器端会话重播中可以回放哪些信息?
-
向下滚动网页
-
网页表单上的输入字段
-
将鼠标光标从左向右移动
-
水平滚动到按钮
-
-
在不可变架构中如何进行生产环境的更改?
-
管理员更改生产环境中的文件。
-
管理员更改配置文件并执行 IaC 工具来创建更改。
-
管理员更改配置文件,将更改提交到版本控制,并执行 CI/CD 管道。
-
管理员重新启动生产服务器。
-
-
请列举两个有助于实现不可变架构的实践。
-
特性标志
-
版本控制
-
CI/CD 管道
-
蓝绿部署
-
行为驱动开发
-
进一步阅读
- 来自 Scaled Agile 特性指导的总结,关于持续交付管道中的持续部署:
www.scaledagileframework.com/continuous-deployment/
)
-
来自 Meta(Facebook 母公司)工程师的观点,描述了 Facebook 如何进行测试、部署和发布:
engineering.fb.com/2017/08/31/web/rapid-release-at-massive-scale/ -
持续交付:通过构建、测试和部署自动化实现可靠的软件发布,作者 Jez Humble 和 David Farley——关于创建 CI/CD 管道的权威指南,详细讲解了集成、部署和发布。
-
来自 LaunchDarkly 的博客文章,LaunchDarkly 是特性标志管理的供应商,描述了特性标志的使用和好处:
launchdarkly.com/blog/guide-to-dark-launching/ -
一篇文章描述了在生产环境中进行测试的优势:
www.softwaretestingmaterial.com/testing-in-production/ -
一篇详细的博客文章,描述了在生产环境中进行测试的用途和优势:
www.tothenew.com/blog/testing-in-production-environment-what-why-and-how/ -
一篇文章描述了 Facebook 如何使用 Gatekeeper 监控生产环境中的用户测试:
www.facebook.com/notes/10158791573022200/ -
一篇博客文章,描述了在测试新特性时使用合成事务:
www.netreo.com/blog/synthetic-transactions/ -
一篇来自 Netflix 工程师的博客文章,描述了他们如何使用一套称为“猴子军团”的工具进行混沌工程:
netflixtechblog.com/the-netflix-simian-army-16e57fbab116
第十三章:按需发布以实现价值
我们现在已经完成了持续交付管道的旅程。我们从一个为客户提供价值的假设开始,并将其转化为在持续探索中开发的功能。在持续集成中,我们逐个故事地开发功能,并将这些变更应用到版本控制中,利用持续交付管道的自动化构建和测试这些变更,直到它们准备好进入生产环境。在持续部署中,我们将变更传播到生产环境,但始终将其隐藏,直到我们准备好发布。
现在我们准备将变更发布给客户。按需发布我们的变更包括以下四个活动:
-
将这些价值发布给客户
-
在运营中稳定我们的解决方案
-
衡量价值
-
学习结果
让我们从查看发布过程开始。
向客户发布价值
到目前为止,我们已将变更放入生产环境,并测试它们以确保功能、安全性和可靠性。现在我们准备发布。我们希望将变更发布给客户,原因如下:
-
我们认为现在是客户可以利用的时机,并且组织认为市场需求较高时
-
我们有信心这些变更不会对生产环境产生负面影响
即便有这些原因,我们也许不希望一次性发布所有内容。1985 年 4 月 23 日,可口可乐公司宣布对其旗舰软饮配方进行首次重大更改。新可乐在超过 200,000 次盲测中,成功击败了可口可乐的主要竞争对手百事可乐。然而,发布后,反应迅速且负面。对新配方的强烈反对迫使可口可乐在仅 79 天后重新推出原始配方,命名为可口可乐经典。从那时起,许多公司在向整个市场发布之前,采取了逐步发布的策略。
如果我们希望采用逐步发布的方式,我们将使用以下实践:
-
功能开关
-
黑暗发布
-
通过组件架构解耦发布
-
金丝雀发布
在前面的章节中,我们已经讨论了功能开关和黑暗发布,参考第十二章,持续部署到生产环境。让我们来看一下通过组件架构解耦发布和金丝雀发布的其他实践。
通过组件架构解耦发布
在第十章,持续探索与发现新特性中,我们讨论了如何将架构设计作为开发新特性时的关键活动之一。其一部分是确保可发布性,以符合组织的商业优先事项。
实现这种可发布性的一种方法是将你的产品或解决方案架构成主要的解耦组件。这些组件可以有各自独立的发布节奏。
在第二章,共享责任文化一章中,我们首次介绍了运营和开发价值流的概念。我们讨论了开发价值流是如何设计、开发、测试、发布并维护一个产品或解决方案的,并且我们识别出几个开发价值流,它们的解决方案是我们视频流服务的运营价值流所依赖的。
回到这个例子,我们来检查一下其中一个开发价值流,即维护移动应用程序的价值流。这个价值流有多个组成部分,每个部分的发布节奏不同,如下图所示。
图 13.1 – 移动应用程序价值流的解耦发布计划
在我们的移动应用程序价值流示例中,我们会在漏洞出现后,随着它们通过持续交付管道的流动,发布安全更新。
其中一个组成部分是移动设备上看到的界面和逻辑,也就是我们所说的前端。这里的开发可以以较快的节奏发布,实际上是在每个冲刺的结束时发布。
另一个组成部分是处理视频流服务数据中心或云端的逻辑和处理,称为后端。在这个例子中,该组件的发布周期是每月一次。
金丝雀发布
“金丝雀发布”这一术语来源于矿业中的做法——带一只金丝雀进入煤矿。金丝雀会作为有毒气体存在的警告。由于其体积较小,如果它在煤矿中死亡,说明矿井中存在有毒气体,矿工应该立即撤离。
就现代产品开发而言,金丝雀发布是将产品或新特性发布给一个小范围的用户群体,以便在全体用户之前获取他们的反馈。
要设置金丝雀发布,再次使用功能标志来决定谁可以在生产环境中看到变更。这一功能标志配置如以下图所示。
图 13.2 – 使用功能标志的金丝雀发布配置
另一种执行金丝雀发布的方式是在分布式生产环境中。如果生产环境位于不同的地理区域,变更会首先在一个生产环境中发布,供一部分用户使用,而其他生产环境则保持其版本不变。如果一切顺利,最终其他区域的生产环境将会被升级。
金丝雀发布的优势在于,它们允许进行 A/B 测试,在该测试中,接受变更的A组可以与未变更的B组或对照组进行比较,以查看新的变更是否对用户行为产生了预期的影响。将金丝雀发布作为实验进行时,确实需要能够测量用户和系统行为的能力,这是全栈遥测的一部分。
可能会有一些情况不适合进行金丝雀发布,以下是一些原因:
-
如果解决方案是关键任务、医疗或安全系统的一部分,且对故障的容忍度较低
-
如果最终用户对被当作小白鼠或测试版测试人员做出负面反应
-
如果变更需要对后端配置进行修改,如数据库架构,而这些修改与当前生产版本不兼容
随着我们将发布从最初的金丝雀用户扩展到整个用户群体,我们希望能够确保我们的生产环境保持弹性。这可能需要我们稳定解决方案并确保其正常运行。在接下来的部分中,我们将探讨实现这一目标的步骤。
稳定并运营解决方案
我们的目标是确保生产环境保持稳定,能够承受新的变更,并持续提供可持续的价值交付。为了维持这一活动,我们希望应用以下实践:
-
网站可靠性工程
-
故障转移和灾难恢复
-
持续安全监控
-
为运营架构设计
-
监控非功能性需求(NFRs)
我们之前在第十二章中探讨了如何测试和监控 NFRs,持续部署到生产环境。让我们来看看剩余的实践。
网站可靠性工程
我们首次在第六章中了解了网站可靠性工程(SRE),从生产故障中恢复。在这一章中,我们看到网站可靠性工程师使用以下四种实践来维护生产环境,特别是当大规模系统需要高可用性时:
-
使用服务级指标(SLI)和服务级目标(SLO)制定错误预算
-
通过发布工程创建发布标准
-
与发布协调工程团队合作进行产品发布
-
通过混沌工程和事件管理程序进行恢复演练
在第六章中,我们看到,如果可用性 SLO 为四个九(99.99%的可用性或更高),那么每月允许的停机时间为 4 分钟 23 秒。为了保持这一可用性,SRE 会使用前述的实践来确保系统的可靠性,并且会定义和排练标准的事件管理政策,以最小化问题发生时的停机时间。
谷歌采纳的其他原则和实践能帮助我们更好地理解 SRE 学科及其如何推动 DevOps 方法。为了理解这些额外的原则和实践,可能需要了解 SRE 在谷歌的起源。
SRE(站点可靠性工程)始于 2004 年,由 Ben Treynor Sloss 在谷歌发起。他的初衷是重新思考系统管理的操作方式。他希望从软件开发的角度来解决运营中发现的问题。从这个角度出发,除了之前提到的实践之外,还出现了以下原则:
-
消除繁重工作,即找到重复性的任务并查看是否能够消除这些任务
-
增加自动化使用,作为一种有效消除繁重工作的方式
-
监控生产环境的各个方面,这有助于实现可观察性
Sloss 为其初始 SRE 团队招募的人员将一半时间用于开发,另一半时间则用于操作,跟踪他们从头到尾开发的变化。这使他们能够培养必要的操作技能,并保持开发专长。
自 2004 年以来,随着技术的进步,许多实践被引入 SRE 学科。然而,许多站点可靠性工程师仍然坚持之前提出的原则。在可靠性作为关键非功能性需求的情况下,采纳这些原则和实践可能会带来实际的好处。
容错和灾难恢复
穆菲定律(Murphy’s Law)著名地指出:“任何可能出错的事情,都会出错。”从这个意义上讲,问题不在于系统是否会遭遇灾难,而在于何时遭遇灾难。我们已经探索了防止灾难的方法,并使用混沌工程来模拟灾难,但是否还有其他准备灾难的方式?
灾难恢复专注于确保在自然或人为灾难发生时,确保对业务重要的技术方面尽快恢复。灾难恢复包括以下要素,以为最坏的情况做好准备:
-
灾难恢复团队:一群负责创建、实施和管理灾难恢复计划的人员。灾难恢复计划概述了团队在紧急情况下需要遵循的职责,包括与其他员工和客户的沟通。
-
风险评估:灾难恢复团队应识别可能发生的场景,并为每种情况制定相应的响应措施。例如,如果发生网络攻击,灾难恢复计划中的步骤应该是什么?
-
资产识别与评估:灾难恢复团队应识别所有系统、应用程序、数据及其他资源。识别过程中需要评估它们对业务连续性的重要性,以及恢复它们的相关指引。
-
资源备份:灾难恢复计划应确定需要备份的资源、备份频率、备份存储位置以及备份保存的时间。
-
演练:灾难恢复计划的所有部分应定期进行演练。应尝试恢复备份,以发现备份过程中的缺陷,并确定备份是否有效。在演练过程中发现的任何缺陷应进行修复,以改进灾难恢复计划。演练应检查不断变化的威胁,看看是否需要在灾难恢复计划中加入新的措施。
灾难恢复计划将根据以下两个度量目标来确定整体策略:
-
恢复点目标(RPO)是指数据的状态,通常从上次备份的时间开始计算,当资源恢复时恢复点的状态。
-
恢复时间目标(RTO)是指灾难发生后可接受的停机时间。
让我们通过以下图示的示例来解释这些目标。
图 13.3 – RPO 和 RTO 的示意图
在前面的图示中,我们每四小时备份一次资源。我们已经练习了对资源进行灾难恢复,并且能够在 30 分钟内可靠地恢复操作。当灾难发生时,如果是熟悉的情况并且已经经过演练,我们的服务恢复时间将与我们的 RTO 目标相匹配,为 30 分钟。
对于 RPO,我们需要查看上次备份的时间点。在我们的示例中,上次备份与灾难之间的时间差可能高达四小时。备份频率越高,RPO 就越低。
灾难恢复机制可以采取多种形式。组织可以选择使用以下方法之一或多种组合:
-
备份:备份是最简单的灾难恢复形式。请注意,这确保了数据的安全,但对于基础设施没有任何帮助。
-
冷站点:冗余的第二生产环境。这可以确保业务连续性,但无法恢复数据。蓝绿部署就是一个冷站点的例子。
-
热站点:一个冗余的第二生产环境,其数据与活动生产环境定期同步。
-
灾难恢复即服务(DRaaS):供应商将组织的处理能力从组织自身的基础设施转移到其自身的(通常是云基础设施)中。
-
备份即服务(BaaS):备份由第三方供应商执行,并存储在异地或云基础设施中。
-
数据中心灾难恢复:这些是组织场所上的设备,用于应对如火灾或停电等灾难。这些设备的例子包括备用发电机或灭火设备。
持续安全监控
在我们持续交付流水线的前期阶段,我们对安全的关注重点是预防。我们希望确保我们设计和开发的变更不会引入安全漏洞。因此,我们在流水线中执行的自动化安全测试检查了代码变更。
随着代码发布,我们的关注点从预防转向检测来自恶意行为者的威胁。我们寻找利用当前未知漏洞的攻击或入侵。
国家标准与技术研究院(NIST)将持续安全监控(CSM)视为信息安全持续监控。在 2011 年 9 月发布的白皮书中(nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-137.pdf),他们将信息安全持续监控定义如下:
信息安全持续监控(ISCM)被定义为保持对信息安全、漏洞和威胁的持续意识,以支持组织的风险 管理决策。
白皮书进一步定义了通过以下步骤实施 CSM 的过程:
-
通过查看风险容忍度来定义策略,包括资产的可见性、漏洞意识、当前威胁信息,以及对任务或业务的影响。
-
建立一个程序,包括指标的定义、状态监控频率和技术架构。
-
实施该程序并收集与安全相关的信息,用于度量、评估和报告。尽可能实现信息的收集、分析和报告自动化。
-
分析发现并报告。
-
响应发现的问题。
-
审查并更新监控程序。
需要监控的资产不仅包括由组织直接维护的资产,还可能扩展到第三方和供应商。监控工具可能会查看以下资产:
-
已知资产:属于组织资产清单的一部分
-
未知资产:被遗忘的资产,包括开发网站或旧的营销网站
-
恶意资产:由恶意行为者创建的资产,可能伪装成组织的域名
-
供应商资产:第三方供应商拥有的资产
一旦识别出资产,应检查其可能的威胁和漏洞。以下是一些常见的威胁和漏洞:
-
不必要的开放 TCP/UDP 端口:任何开放的端口如果相关服务配置错误或未修补,可能会成为问题,从而可能暴露出漏洞。
-
中间人攻击:这是一种网络攻击,攻击者介于两方之间,双方认为它们有直接连接,但攻击者可能监听甚至修改信息,然后再传输给另一方。
-
邮件安全差:这可能会让你的组织暴露在邮件欺骗攻击中。
-
域名劫持:攻击者在未获得域名所有者许可的情况下,改变了一个组织的域名注册。
-
跨站脚本攻击(XSS)漏洞:攻击者可以在网页上注入客户端脚本,从而绕过访问控制。
-
泄露的凭证:通过数据泄露事件发现,它们允许攻击者访问组织系统。
-
数据泄露:私人或敏感数据的暴露。
-
域名拼写欺骗:这是一种网络域名抢注形式,攻击者注册与已知组织域名相似的域名,期望有人错误输入网址并进入攻击者的网站。
识别这些攻击可能是自动化监控后进行的评估的一部分。缓解步骤和行动将明确谁在组织内执行修复步骤并协调响应。
针对运维的架构设计
在持续交付管道的这个阶段执行的支持活动将对系统架构产生深远的影响,甚至可能推动产品或解决方案未来的方向。这些可能是系统架构师在持续探索阶段考虑新功能时所做的架构决策的一部分。
在这一阶段做出的决定可能会被纳入持续探索阶段,具体项目包括以下内容:
-
由站点可靠性工程师创建的修复和新自动化工具
-
因灾难恢复计划中发现的缺陷而导致的更改,这些缺陷影响了测试、预发布或生产环境的配置。
-
CSM 发现的新漏洞,产品架构必须防止这些漏洞未来的发生。
因此,系统架构师成为了有意架构与突发设计的平衡点,监督着产品或解决方案的预期架构,同时也考虑环境等因素对架构变更的需求。
这个阶段的学习不仅限于架构方面。我们还必须从产品性能的角度评估我们的开发是否实现了收益假设。为此,我们需要衡量我们解决方案的价值。让我们在下一部分中探讨这个问题。
衡量价值
在持续交付管道的设计与开发过程中,我们已对我们的更改进行了一系列测试。现在我们将查看最终测试,以回答以下问题:我们的开发努力是否为客户带来了价值,达到了既能使客户受益,又能使组织受益的程度?
为了帮助我们回答这个问题,我们将查看以下活动:
-
创新会计
-
证明/反驳收益假设
我们将首先回顾创新会计及其来源:精益创业循环。基于这些知识,我们将看到领先指标和滞后指标如何验证或反驳我们在持续探索中创建的收益假设。
创新会计
我们首先在第五章中看到了创新会计,衡量过程和解决方案。在本章中,根据埃里克·里斯的《精益创业:当今企业家如何利用持续创新创造极为成功的企业》,我们了解到,衡量标准对于评估收益假设是否成立非常重要。
里斯在他后续的书《创业之道:现代公司如何利用企业家管理转变文化并推动长期增长》中进一步扩展了创新会计。在书中,他对创新会计给出了以下定义:
创新会计(IA)是一种评估进展的方法,当一个成熟公司通常使用的所有衡量标准(收入、客户、投资回报率、市场份额)都 几乎为零时,才适用此方法。*
他提出了三层创新会计,每一层都有不同的衡量标准。现在我们来看看这些层级。
第一层级:仪表盘衡量标准
这些衡量标准作为起点。里斯建议设置一个仪表盘。在这个初步的仪表盘上,显示的是开发团队认为重要的面向客户的衡量标准。这些衡量标准基于每位客户的投入。以下是用于学习的每位客户的衡量标准:
-
转化率(通常是指从免费版到付费版产品的客户百分比)
-
每位客户的收入
-
每位客户的生命周期价值
-
客户保持率
-
每位客户的成本
-
推荐率
-
渠道采用
像这样的衡量标准有助于强化开发可以在观察到其努力成果后影响这些标准的观点。这里可见的衡量标准有助于保持开发过程与反馈保持一致。
第二层级:商业案例衡量标准
在第二层级中,我们会使用一组不同的衡量标准深入探讨。在这里,我们尝试量化“信念飞跃假设”,正如里斯所说的那样。信念飞跃假设分为以下两类:
-
价值假设:这些描述了用户从产品或解决方案中获得的价值
-
增长假设:新用户如何找到产品?
这些类型的假设对于任何新开发都是必需的,否则就不会有新的开发。这些假设通过最小可行产品(MVP)及其他验证性实践得到检验。
以下衡量标准展示了假设和假设的分类:
-
客户保持率(价值假设)
-
推荐率(价值假设)
-
口碑推荐(增长假设)
价值假设关注客户行为。它们基于用户的积极行为来实现。增长假设则关注可持续增长。
第三层级:净现值
在这个层级,我们关注的是长时间段的表现。随着你获得新的数据,并重新评估或比较当前数据与预测数据的差异,变化会逐步显现。我们关注的是产品未来表现的长期驱动因素。
以下度量指标可能为长期提供指导:
-
网站用户数量
-
访客转化为用户的百分比
-
付费用户的百分比
-
用户支付的平均价格
这些度量指标通常涉及的不仅仅是开发团队。财务团队可能也会参与进来,目标是在此时将重点转向产品的财务表现。
证明/反驳收益假设
现在我们已经了解了创新会计中的步骤,接下来我们来看看它们如何与我们在持续探索中创建的收益假设对照。
在我们穿越持续交付管道的旅程中,我们在持续探索中创建了我们的收益假设。为了衡量假设的有效性,我们可能会在仪表板中加入第二级度量标准。我们的仪表板通过我们在测试、预发布和生产环境中设计的全栈遥测,自动获取这些度量数据。
我们可能会从持续部署阶段的测试中获得一些迹象,但真正的测量结果会来自按需发布,首先是在 A/B 测试或金丝雀发布中,随后是一般发布。我们希望看到表现与初始收益假设之间的所有关联。
我们现在在此步骤中收集和分析的数据,不仅仅是为了改进产品,也为了改进我们的价值流和开发流程。让我们探索下一个部分,看看这两者是如何实现的。
从结果中学习
根据我们的学习,我们现在需要找出最佳的下一步。无论是从产品角度,还是从价值流角度来看,这都是正确的。
对于我们的产品来说,关键在于确定最佳方向。这可能意味着是否该调整方向,改变我们的整体产品战略,或者坚持原有方向继续前进。
对于我们的价值流,这段时间用于反思如何改进。我们可以从中学到哪些经验,以便改进?
以下实践用于确定产品未来方向以及价值流的未来方向:
-
《精益创业》中的调整方向或坚持原有方向
-
不断改进
-
价值流映射会议
我们进行这种学习是为了能够在持续交付管道的起始阶段重新聚焦,设定执行的想法。我们通过改进价值流来提升持续交付管道的表现。
让我们来看一下这些可以帮助我们改进的实践。
调整方向或坚持原有方向
在 第十章 持续探索与寻找新功能 中,我们观察了 Eric Ries 的 Build-Measure-Learn 循环在 SAFe® 精益创业循环中的应用,在这里我们看到了 Epics 是如何通过效益假设来创建的。这些 Epics 通过最小可行产品(MVP)进行实施,MVP 作为实验来验证或反驳效益假设。MVP 通过创新会计和领先指标的追踪进行评估,这些指标将用于决定是转变方向还是坚持下去。
我们现在正处于作出这一决定的时刻。对于我们的 ART,MVP 可能是通过持续交付管道初期创建的一些功能。我们已经开发了这些功能,进行了测试,并通过管道中的持续集成和持续部署阶段将其部署到生产环境中。现在,在按需发布中,我们将 MVP 作为功能展示给用户群体,看看效益假设是否得以验证。根据我们通过完整堆栈遥测收集的创新会计指标,我们做出了以下两个决定:
-
转变方向:我们的功能未能达到预期效益假设。是时候朝着不同的方向前进了。这可能包括停止该产品方向的开发。
-
坚持下去:我们的效益假设已经得到验证。我们应该继续开发更多功能来增强我们的 MVP。
请注意,即使在我们为 MVP 作出坚持决策之后,我们的功能仍然会被评估,以确定它们是否证明是有价值的,并且产品方向仍然能与客户产生共鸣。
不懈改进
我们第一次看到不懈改进是在我们首次检查 SAFe 精益之屋时,在 第二章 共享责任文化 中提到。我们提到,在不懈改进中,我们寻求通过那种“潜在的危险感”来寻找变得更好的机会。
在整个开发过程中,团队和 ART 一直在寻找改进价值流动的机会。团队定期在每次迭代结束时举行回顾会议,以识别团队层面的问题,而 ART 在每个项目增量结束时举行检查与调整(I&A)活动,以便审视系统性问题。
其他改进可能会出现在持续交付管道本身。更新的工具、额外的测试以及持续的维护使 ART 能够保持或改进他们创建实验的方式,以验证效益假设。
额外的价值流映射会议
不懈改进的另一个重要部分来自于价值流管理和持续学习,这些理念最早在 第九章 通过持续学习走向未来 中进行了讨论。
我们最初在价值流映射中执行的一个活动,不仅是绘制当前的价值流图,还包括识别一个理想的未来状态价值流。改进行动可以通过向着理想价值流的小步迭代变化来实现。
另一个改进步骤是至少每年举行一次价值流映射会议,以评估当前迭代中的价值流。这使得 ART 能够查看目前阻碍价值流动的瓶颈。在这次价值流映射会议中,可以为新的改进确定一个新的未来状态价值流。
总结
在本章中,我们已达到持续交付管道的最后阶段:按需发布。在使用功能标志让测试人员查看开发环境中的新变化后,我们可以使用它们将这些变化逐步发布给少量用户进行金丝雀发布。我们可能还希望设置架构,使每个组件具有不同的发布节奏。发布后,我们希望确保这些变化不会破坏环境,并且我们的整体解决方案是稳定的。为此,我们遵循 SRE 的原则和主要实践,包括准备灾难恢复。
在稳定环境中发布变更后,是时候通过全栈遥测来衡量业务结果了。我们在持续探索过程中选择了我们的度量标准,依靠创新会计原则。通过查看每个人都可以看到的仪表板上的这些度量,我们可以尝试确定我们在持续探索中创建的利益假设是否有效。
基于利益假设是否有效,我们必须决定是转型、改变方向,还是坚持并继续在相同的产品方向上发展。在做出决定后,ART 通过回顾、I&A 以及定期绘制价值流图来查看其他改进机会。
这使我们接近第三部分的结尾。接下来,我们将在本书的最后一章中看看新兴趋势,以及在 DevOps 采纳过程中取得成功的一些技巧和窍门。
问题
-
以下哪些是 SRE 的关键实践或原则?(选择 3 个)
-
使用功能标志进行 A/B 测试
-
通过自动化减少无谓劳动
-
在生产环境中运行单元测试
-
通过错误预算了解自己能承受多少风险
-
混沌工程
-
在生产环境中测试
-
-
以下哪些应成为灾难恢复计划的一部分?(选择 3 个)
-
确定灾难恢复团队
-
资源识别
-
供应商联系信息
-
服务器原理图
-
备份计划
-
重要文件的纸质版本
-
-
数据库每两小时进行一次备份。如果数据库服务器崩溃,预期的 RPO 是多少?
-
2 小时
-
4 小时
-
8 小时
-
16 小时
-
-
CSM 可以检测哪些问题?(选择 2 个)
-
中间人攻击
-
许可证违规
-
跨站脚本(XSS)漏洞
-
弱密码
-
-
哪些做法不是持续改进的例子?(选择 2 项)
-
回顾会议
-
代码审查
-
检查与适应(I&A)
-
向持续交付管道添加测试
-
代码注释
-
进一步阅读
- 关于 New Coke 推出的描述:
www.coca-colacompany.com/company/history/the-story-of-one-of-the-most-memorable-marketing-blunders-ever
)
-
另一篇关于 New Coke 推出的描述,增加了竞争格局的视角:
www.vox.com/2015/4/23/8472539/new-coke-cola-wars -
blog.getambassador.io/cloud-native-patterns-canary-release-1cb8f82d371a– 介绍金丝雀发布并详细说明实现、好处和使用实例的博客文章 -
关于金丝雀发布的有趣参考资料:
martinfowler.com/bliki/CanaryRelease.html
)
- 来自 LaunchDarkly 的博客文章,LaunchDarkly 是一个功能标志管理解决方案的供应商,介绍了如何使用功能标志进行金丝雀发布:
launchdarkly.com/blog/what-is-a-canary-release/
)
- 来自 Google 的 YouTube 视频,详细介绍了站点可靠性工程的历史,包括 Ben Treynor Sloss 的视角:
www.youtube.com/watch?v=1NF6N2RwVoc&t=6s
)
- VMWare 关于不同类型灾难恢复的详细资料:
www.vmware.com/topics/glossary/content/disaster-recovery.html
)
-
来自 NIST 的白皮书,详细介绍了信息安全持续监控(Information Security Continuous Monitoring),这是在谈论 CSM 时常用的内容:
nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-137.pdf -
来自 Upgard 的博客文章,Upgard 是 CSM 工具的供应商,定义了主要的安全漏洞:
www.upguard.com/blog/continuous-security-monitoring -
The Startup Way: How Modern Companies Use Entrepreneurial Management to Transform Culture and Drive Long-Term Growth by Eric Ries – 精益创业的续集;进一步定义了如创新会计等概念
-
一篇博客文章,概述了关于创新会计的更多思考:
www.boldare.com/blog/lean-startup-innovation-accounting/
第十四章:避免陷阱并迈向未来
自 2009 年在 Velocity 大会上 Flickr 的演讲以来,DevOps 运动在许多方面发生了演变和变化。技术的最新进展,如容器和 Kubernetes,已经改变了许多核心实践。新方式的出现,如站点可靠性工程(SRE),也改变了人们扮演的角色。
在本章中,我们将讨论如何开始将全书讨论的原则和实践融入其中,从而成功地迈向 DevOps 转型或转向 SAFe®。
我们将探讨一些可能在 DevOps 演进中发挥重要作用的新兴趋势。我们将关注 XOps,它试图将更多组织部分融入 DevOps 和 DevSecOps 中所看到的协作方法中。我们还将看看与标准线性价值流不同的另一种视角。
我们还将探讨一些新兴技术,它们有望改变我们的工作方式。通过 IT 运维中的 AI,也称为 AIOps,我们将探讨人工智能(AI)和机器学习(ML)在预测问题和漏洞中日益增长的作用。我们还将考察版本控制与持续集成/持续部署(CI/CD)的融合,在此过程中我们将关注 GitOps。
最后,我们将看一些常见问题,并给出一些答案。
避免陷阱
在朝着 DevOps 方法前进的过程中,显然并非每个人都会走相同的路径。不同的组织处于不同的阶段,准备好接受所需的思维方式转变,以便实现成功的 DevOps 旅程。
话虽如此,我们将根据本书前几章所学,来看一组启动或重启 DevOps 方法的步骤。你会发现,从一个步骤到下一个步骤之间通常没有直接的路径。
让我们来看看 DevOps 旅程中的以下步骤:
-
了解系统
-
从小做起
-
开始自动化
-
衡量、学习并调整
现在让我们开始我们的旅程吧。
了解系统
无论我们是从头开始,还是在失败后重新开始,我们都需要从精益思维中的改进 Kata 步骤入手,评估我们当前的状况。这一评估应当是对现有流程、流程背后的人以及工具是否支持流程的全面审视。
观察所有这些方面的一种方式是进行价值流映射,正如在第七章中首次讨论的那样,映射你的价值流。正如我们在那一章中最初提到的,进行价值流映射工作坊可以帮助你发现以下几个方面:
-
从头到尾的工作流过程步骤
-
执行这些过程步骤的人
-
可能的改进领域
价值流映射工作坊还提供了一个从系统更广阔视角审视整个开发工作范围的视角。这个系统视角不仅仅是一个过程步骤和改进的系列,还包括工具在此过程中的作用,或者在尚未纳入时工具可以如何在过程里发挥作用。
价值流映射工作坊会生成两个价值流:当前价值流和一个包含增强和改进、降低周期时间和交付时间并提高完成度和准确度(%C&A)的理想价值流。记录这些增强项,以便价值流中的人员作为持续****学习(CL)的一部分来处理它们。
从小做起
在价值流映射工作坊后,查看来自理想价值流的改进和增强清单。从这些增强项中,价值流中的人员应选择他们认为最重要的改进来进行处理。
每次只允许一个改进的做法有助于集中精力。我们在第四章,利用 精益流动保持工作流动中看到,通过小批量工作避免了多任务处理可能带来的问题,从而防止了工作无法完成的情况。
一种可能的改进是通过提高流动性来减少开发产品的周期和交付时间。第四章中的实践——如小批量、监控队列和限制在制品——也能帮助实现这一目标。遵循这些实践可能会带来更高的敏捷性,随着 DevOps 方法的实施,这种敏捷性会不断提升。
价值流中的人员可以关注的另一个改进领域是工具的使用。需要考虑的第一个基础工具是版本控制。价值流中的团队应该评估是否将所有文件放入版本控制系统。如果他们已经在使用版本控制系统,他们应该确保使用的是统一的版本控制系统,并且每个人都拥有必要的访问权限。
除了选择版本控制系统外,价值流中的人员还应该选择一个分支模型,概述他们如何从主干分支并何时将变更合并回主分支或主干。
开始自动化
改善价值流的一个关键步骤是建立 CI/CD 管道。如果组织尚未建立 CI/CD 管道,可以建立一个,许多版本控制系统自带这样的管道。其他组织可能希望安装一个独立的 CI/CD 管道工具,以获得更多的灵活性。无论哪种方式都可以,因为最重要的是创建这样一个管道。
CI/CD 管道可以在版本控制中通过提交触发。当发生提交时,添加必要的后续操作,每次添加一个操作。这些操作可能从构建或编译提交中来的更改开始。完成的构建可以让合并进入更高级别的分支,并可能将构建产物保存到制品库中。
开始自动化测试
一旦定义了 CI/CD 管道的端点,你就可以用自动化测试填充管道中的其他中间步骤。你可以创建自动运行的测试,来发现功能和安全性方面的问题。
从创建以下类别的自动化测试开始,逐一进行:
-
单元测试
-
功能测试
-
系统测试
-
安全测试(静态应用安全测试(SAST)、动态应用安全测试(DAST)和其他扫描)
自动化测试的开发现在鼓励创建多个部署环境,例如测试环境、预发布环境和生产环境。单元测试通过后,可以为其他测试级别部署测试环境。
创建环境、部署和监控
测试的建立让我们能够建立不同的预生产环境,所有这些环境在实践允许的情况下都是等效的。
引入新的预生产环境还允许我们为这些预生产环境引入监控。监控可以先在测试环境上启动,直到我们对部署到预发布环境甚至最终生产环境的监控有足够的信心。
构建预生产环境让我们能够建立所需的工具进行构建。配置管理工具和基础设施即代码(IaC)可以被添加来定义和配置环境。建立标准配置允许像回滚这样的功能得以实现。
衡量、学习并调整方向
在每一步中,我们应该评估我们所增加的每个步骤是否有助于将我们带到理想的未来状态价值流。根据需要做出调整。这些微小的课程修正促使了 CL(持续学习)。
可能会有人质疑是否是时候进行调整。正当理由总是避免沉没成本谬误,在这种谬误中,人们会固守原有方案,尽管有压倒性的证据表明应该做出改变。
最后一点:有一个流传已久的故事称,约翰·F·肯尼迪曾指出,中文中的危机一词是由危险和机会这两个词组成的。虽然中文中危机一词的前半部分确实可以单独表示危险,但后半部分则单独翻译为变化的节点或转折点。
采用 SAFe 或采用 DevOps 很像观察组成危机的各个角色。观察危险和观察转折点能帮助我们远离危机。
在本书中,我们谈到了 DevOps 从 2009 年初期到今天的演变。现在,让我们来谈谈开始出现的趋势。
DevOps 中的新兴趋势
DevOps 运动成功的一个主题是组织内两个独立职能——开发和运维之间的协作,目的是频繁发布产品,同时保持生产环境的稳定。
随着运动的成长,它的成功鼓励了更多富有创意的协作努力,推动了除了增加部署频率和稳定性之外的其他方面的进展。我们将探讨的一些重新构想的努力包括以下内容:
-
XOps
-
革命模型
-
平台工程
让我们开始探索 DevOps 的潜在未来。
XOps
DevOps 运动的成功鼓励了组织其他部分(除了开发和运维)加入,以便除了开发频率和稳定性外,还能提升其他方面的速度和质量。值得注意的运动包括以下几个:
-
DevSecOps:在管道的各个阶段纳入安全性,以确保安全性不会被忽视。目前,许多人认为 DevSecOps 方法中执行的实践已经完全融入到 DevOps 运动中。
-
BizDevOps:被誉为 DevOps 2.0,这一运动增加了商业团队、开发人员和运维人员之间的协作,目的是最大化商业收入。
此外,其他工程学科也通过采用 DevOps 中首次提出的相同实践获得了成功。这些面向相邻学科的 DevOps 基础运动包括DataOps和ModelOps。
让我们看看 DevOps 方法在这些工程学科中的运作方式。
DataOps
DataOps 是将敏捷开发原则、DevOps 实践和精益思维融入数据分析和数据分析领域的过程。
数据分析遵循类似于产品开发的流程。以下步骤是数据分析中典型流程的一部分:
-
由指导分析的人或客户指定的数据需求
-
数据收集
-
使用统计软件或电子表格处理数据
-
数据清理以去除重复或错误
-
探索性数据分析(EDA)
-
数据建模以发现关系
-
通过使用数据产品应用程序创建输出
-
报告
随着数据量的指数增长,新的方法被投入使用,以便快速获取洞察。以下使用的方法类似于 DevOps 在产品开发中看到的步骤:
-
建立一个数据管道,使得数据能够通过数据分析过程处理成报告和分析结果
-
通过统计过程 控制(SPC)验证数据流经数据管道的情况
-
在数据清理、数据分析和数据建模阶段,加入自动化测试以确保数据的正确性
-
测量数据流经数据管道的情况
-
将数据分离为开发、测试和生产环境,以确保数据管道自动化功能的正确运行
-
数据科学家、分析师、数据工程师、IT 和质量保证/治理之间的协作
基于大量数据轻松发现关系为企业提供了竞争优势。使用 DataOps 实践和原则,能够使从数据中创造洞察的人员实现更高的可靠和无误数据分析的部署率。
ModelOps
当前技术领域中最大的趋势之一是 AI。这一趋势促使机器学习(ML)和决策模型的建立,利用大量数据不断提升性能。这些 ML 模型的开发可以为任何想要了解更多客户信息及其产品如何提供帮助的组织带来竞争优势。
现在开发有效的模型经历一个类似于软件开发生命周期(SDLC)的开发周期。2018 年 12 月,IBM Research AI 的 Waldemar Hummer 和 Vinod Muthusamy 提出了 ModelOps 的初步概念,将 AI 工作流通过 DevOps 方法中的技术,使其变得更加可重用、平台无关且可组合。
模型生命周期涵盖了如何为企业创建、训练、部署、监控 AI 模型,并根据数据反馈对模型进行再训练。以下图表展示了模型生命周期的路径:
图 14.1 – ModelOps 生命周期(作者 Jforgo1 – 自创作品,CC BY-SA 4.0,https://commons.wikimedia.org/w/index.php?curid=99598780)
由于模型生命周期和 SDLC 之间的相似性,快速部署变更、监控其对环境的影响,并学习以改进的期望行为,使得使用 ModelOps 开发的 AI 模型可以与使用 DevOps 创建的 AI 应用对齐,并且两者都依赖于使用 DataOps 开发的数据分析。
革新模型
软件开发中的价值流概念以传统的 SDLC 过程为模型。这个过程源自瀑布开发模式,假设开发是按照从一个活动到下一个活动的逐步线性运动进行的。随着产品的复杂度增加,DevOps 扩展了责任范围,线性的一次性活动进程是否还合理呢?
亚马逊 Web 服务(AWS)社区参与主管 Emily Freeman,也是《DevOps for Dummies》的作者,提出了一种不同的开发流程视角。她并未采用直线式的方法,而是提出了一个模型,在该模型中,优先级随着活动的进行而向前和向后移动,沿着活动的圆圈变化。她将这个模型称为革新。让我们更深入地了解一下。
Freeman 提出了以下五个软件开发角色,作为同心圆向外辐射:
-
运营
-
部署
-
自动化
-
开发
-
架构设计
这些圆圈的交集是工程师在每个活动中必须考虑的六个特性。这些特性,如下所示,作为同心圆的辐条被绘制出来:
-
可测试性
-
安全性
-
可靠性
-
可观察性
-
灵活性
-
可扩展性
在各个部分就位后,让我们展示以下模型图:
图 14.2 – 革新模型
为确保这六个特性得到充分满足,工程师或团队成员会从外向内跳跃不同角色(或圆圈),逐一进行处理。角色是由工程师临时承担的,直到不再需要为止。在 Freeman 在主题演讲中所描述的一个事件管理场景中(www.youtube.com/watch?v=rNBXfgWcy5Q),团队成员需要在运营、开发和部署之间切换,以调查是否具备足够的可靠性、可观察性、灵活性、可扩展性和可测试性。
平台工程
近年来,云原生环境中涉及的大量工具和技术得到了快速发展。为了设置和维护产品所在的测试、预生产和生产环境所需的知识水平,已经让负责其运营的人力捉襟见肘。
从历史上看,DevOps 最初是将运营融入到敏捷开发过程中,以便在保持稳定性的同时,也能维持开发速度。随着时间的推移,运营部门已经开始采用敏捷开发思维,结合 SRE(站点可靠性工程)来解决大型系统的可靠性问题。Honeycomb.io 的首席技术官 Charity Majors(这家公司在开发监控和可观察性平台方面处于领先地位)在一篇博客文章中(www.honeycomb.io/blog/future-ops-platform-engineering)写道,下一步是将运营所负责的环境视为可以通过敏捷开发思维来开发的产品本身。
平台工程(由 Humanitec 的 Luca Galante 定义,参考 platformengineering.org/blog/what-is-platform-engineering)设计工具链和工作流,以使用这种敏捷开发思维模式提供自服务能力。通过平台工程开发的产品是 内部开发平台(IDP),它是开发者用于构建产品和解决方案的操作环境中所用技术的抽象。
开发者将使用以下五个组件的 IDP 来建立其产品或解决方案所需的能力:
-
应用配置管理 (ACM):这包括自动创建清单文件,这些文件被配置管理工具用来部署应用程序更改。
-
基础设施编排:这建立了 CI 管道与部署环境之间的集成,包括可能的集群创建/更新、IAC 和镜像注册表。
-
环境管理:这将 IDP 的 ACM 与底层基础设施的环境集成,允许开发者根据需要创建完全配置好的环境。
-
部署管理:这设置了 CD 管道。
-
基于角色的访问控制(RBAC):这允许对环境及其资源进行细粒度的访问控制。
我们已经看到随着人们开始应用变化于流程中,趋势开始显现,但 DevOps 将继续随着技术的进步而变化。让我们来看一下由技术进步驱动的 DevOps 趋势。
DevOps 中的新技术
如今的 DevOps 已经超出了 2009 年最初设想的范围,这在一定程度上是由于技术的进步,推动了云原生环境中的部署。今天的进步承诺将增添前所未有的新能力。
我们将要讨论的 DevOps 技术变化,源自于部署到云原生环境和新兴技术应用的改进。我们将着眼于这些基于技术的 DevOps 趋势:AIOps 和 GitOps。
让我们从展望未来的 AIOps 开始。
AIOps
我们在上一节讨论了利用 AI 创建能够从大量数据中学习的应用程序的兴起。一个可以从基于大量数据的深入洞察中受益的领域可能是采用 DevOps 方法的产品开发,该方法通过全栈遥测收集数据。这与我们之前讨论的 DataOps 或 ModelOps 不同,因为这次我们将机器学习和数据可视化应用到实际的开发过程当中。
IT 运维中的人工智能(或 AIOps)旨在增强我们之前在 CI、CD 和按需发布阶段所识别的传统实践,加入基于机器学习(ML)的工具,以处理来自我们全栈遥测的数据。AIOps 工具的引入可以帮助理解 IT 环境中的以下领域:
-
系统:测试、预发布和生产环境可能是云原生和本地资源的复杂组合。云资源可能来自一个或多个供应商。资源可能是物理计算服务器(“裸金属”)的组合,或者使用虚拟化形式,如虚拟机(VMs)或容器。如此多样化的资源组合确保了环境的稳定性和可靠性。
-
数据:全栈遥测产生大量数据。其中一些数据可能对做出关键决策至关重要,而一些则不然。我们如何判断数据量是否庞大?
-
工具:为了获取全栈遥测,可能会使用各种工具来收集数据并管理系统。这些工具可能无法互相协作,或者功能受限,从而形成数据孤岛。
为了应对这一挑战,采用机器学习的工具可能会采用以下类型的 AI 算法:
-
数据选择:分析数据以去除冗余和无关信息
-
模式发现:分析数据以确定关系
-
推理:查看见解以识别根本原因
-
协作:使自动化通知团队发现的问题
-
自动化:旨在自动响应重复出现的问题
这些工具在识别安全漏洞、查找生产故障的根本原因,甚至识别可能预测生产环境中即将发生的问题方面都有应用。随着技术的进步,AIOps 成为 DevOps 和 IT 运维的标准组成部分的前景也在不断增加。
GitOps
随着 CI/CD 管道的接受度逐渐提高,许多人开始思考如何建立这些管道,以便将功能部署到云原生的测试、预发布和生产环境中。2017 年,Weaveworks 提出了 GitOps 这一术语,建议一种基于 Git 提交触发的 CI/CD 方法,Git 是一种流行的版本控制程序。
GitOps 从版本控制开始。应用程序和环境配置各自有独立的代码库。应用程序代码库将包含产品的代码,包括如何在 Dockerfile 中构建该产品作为容器。环境代码库将包含 CI/CD 管道工具的配置文件和脚本,以及环境的部署记录。
GitOps 中的部署可以是推送式或拉取式。推送式部署使用常规的 CI/CD 流水线工具,从 CI 推向 CD。拉取式部署则使用操作员监控环境仓库的变化。当发生这些变化时,操作员根据环境仓库的变化将其部署到环境中。
下图展示了从 Git 仓库到 CI 流水线,再到操作员和部署流水线的进展:
图 14.3 – GitOps 拉取式部署
GitOps 在那些希望使用 Kubernetes 设置部署的群体中受到了极大的关注。Kubernetes 是一种打包 Docker 容器以设置微服务集群的技术。随着 Kubernetes 的流行,GitOps 已成为一种成熟的实践,用于将 Kubernetes 集群持续部署到基于云的环境中。
常见问题解答
现在我们来看一些可能会出现的问题,即使是在阅读了本书的早期部分之后。
什么是 DevOps?
DevOps 是一个用于开发和维护产品的技术运动。它结合了精益思维和敏捷开发原则与实践,扩展了关注点,不仅仅局限于开发,还包括新产品及其功能的部署、发布和维护。DevOps 推广使用自动化和工具来允许频繁测试功能和安全性,并允许一致的部署和发布。当产品进入发布阶段时,DevOps 模型呈现出由开发人员和运维人员执行的操作实践,这些实践可以在生产环境出现问题时快速恢复,体现了一种任务导向的生成性文化。
什么是规模化敏捷框架(Scaled Agile Framework®)?
规模化敏捷框架(SAFe)是一套由 Scaled Agile, Inc. 开发的价值观、原则和实践。SAFe 主要被中型和大型组织采纳,帮助其为“团队中的团队”和企业的投资组合引入精益和敏捷的工作方式。正如 Scaled Agile, Inc. 所定义的:
SAFe for Lean Enterprises 是全球领先的业务敏捷框架。SAFe 将精益、敏捷和 DevOps 的力量整合成一个全面的操作系统,帮助企业在数字时代通过更快、更可预测且更高质量地交付创新产品和服务而蓬勃发展。——© Scaled Agile, Inc.
我是否需要采纳 SAFe 才能转向 DevOps?
不。我们在谈论 DevOps 时会提到 SAFe,因为在 SAFe 中工作的一个关键视角是专注于为其“团队中的团队”创建和组织价值流,这些团队被称为敏捷发布火车(ART)。SAFe 还通过其 CD 流水线专注于流程和自动化。这两者与成功的 DevOps 方法一致。
采用 SAFe 最适合当你的价值流可以通过一个由 5 到 12 个常规大小团队组成的团队来完成,并且这个团队中的团队正在共同开发一个单一的产品或解决方案时。这被称为Essential SAFe配置。
DevOps 仅适用于那些为云环境开发的公司吗?
尽管 DevOps 在最近的许多技术进步中是为了帮助开发、测试、部署、发布和维护云环境上的产品而产生的,但作为一项技术运动,DevOps 对产品所基于的任何技术都是中立的。
DevOps 的原则和实践在那些开发和维护云环境、嵌入式硬件、主机和物理服务器环境产品的组织中取得了成功。诸如采纳精益思维、价值流管理和 SRE 等实践,并不依赖于最终产品所使用的技术。
做 ___________ 最好的工具是什么?
一个常见的问题是询问在执行特定功能(如 CI/CD、自动化测试、配置管理或安全测试)时,最受欢迎的工具是什么。我总是避免选择单一的工具,原因有很多。
主要原因是每个行业和组织都有所不同。一个适用于某个行业或组织的工具,可能在另一个行业或组织中并不适用。
另一个原因是技术不断发展,发布了可能现在被认为是“最佳”的新工具。
DevSecOps 如何融入 DevOps?
在本章前面,我们看到 DevSecOps 是 XOps 的首个模型之一,最终发生的事情是将安全思维和实践融入到 DevOps 的更广泛定义中。通过 DevSecOps,我们在传统 DevOps 中,除了开发速度和操作稳定性外,增加了安全作为重点。在本书中,我们列出了几个地方,在这些地方包括安全实践将我们从 DevOps 带向 DevSecOps。
在第六章《从生产故障中恢复》中,我们看到混沌工程可以用来模拟灾难,如安全漏洞,并评估应对这些安全故障的潜在反应。
在第十章《持续探索与发现新特性》中,我们发现安全性是在为产品创建新特性时的主要考虑因素之一。这一考虑通常由系统架构师处理,常常与组织的安全团队进行咨询。
我们在第十一章《解决方案开发的持续集成》和第十二章《持续部署到生产》中进一步扩展了安全性,在这两章中,我们探讨了在不同形式的安全测试中加入,以检测潜在的漏洞。在 CI 过程中,我们进行了威胁建模,以识别任何潜在的攻击向量。
最后,在 第十三章,《按需发布以实现价值》中,我们探讨了在生产环境中进行持续安全监控和持续安全实践,以保持警觉,并在漏洞被利用时修复环境。
摘要
在本章的最后,我们展望了未来。首先,我们看到了 DevOps 在产品开发方面的新兴趋势。结合 AI 和数据工程的新进展为正在开发的产品添加了新的组成部分。像 AI 模型和数据管道这样的工件的开发表明,在 DataOps 和 ModelOps 等新领域中,采用 DevOps 方法可以带来很大的好处。我们还审视了可能影响 DevOps 和价值流管理的软件开发与维护的新视角。
技术的变化也改变了 DevOps。我们考察了如何将 AIOps 产品纳入其中,这些产品包括 AI 用于分析在测试和维护中收集的数据,以发现漏洞和潜在的故障。我们探索了将版本控制与 CD 结合起来的 GitOps 运动。
然后,我们从 DevOps 的未来转向将 DevOps 融入到您组织的未来中。我们探讨了如何采用 DevOps 实践,包括绘制您的价值流并在开发过程的不同领域中逐步应用自动化。最后,我们回答了一些可能遇到的问题及其解答。
我们已经探讨了 DevOps 的不同方面,从了解人们的动机到理解正在进行的过程,并考察了可以帮助实现更高绩效水平的工具。SAFe 采纳了这三个方面,使得多个团队能够作为一个价值流共同工作,开发、部署和维护为客户创造价值的产品。我们希望这次探索能为您继续进行 DevOps 之旅提供指导。
进一步阅读
欲了解更多信息,请参考以下资源:
-
一篇关于 XOps 及其各种组成部分的博客文章:
www.expressanalytics.com/blog/everything-you-need-to-know-about-xops/ -
关于 XOps 及其主要组成部分和受欢迎程度的描述:
datakitchen.io/gartner-top-trends-in-data-and-analytics-for-2021-xops/ -
来自 Scaled Agile, Inc. 的指导文章,详细介绍了如何在您的价值流中使用 DataOps:
www.scaledagileframework.com/an-agile-approach-to-big-data-in-safe/ -
来自 IBM Research AI 的 Waldemar Hummer 和 Vinod Muthusamy 撰写的初步白皮书,详细介绍了他们的 ModelOps 过程:
s3.us.cloud-object-storage.appdomain.cloud/res-files/3842-plday18-hummer.pdf -
ModelOp.com 制作的 ModelOps 基础指南:
www.modelop.com/wp-content/uploads/2020/05/ModelOps_Essential_Guide.pdf -
来自 Scaled Agile, Inc.的指导文章,关于如何在价值流中使用 ModelOps:
www.scaledagileframework.com/succeeding-with-ai-in-safe/ -
Emily Freeman 的《革命模型》官方文档:
github.com/revolution-model -
主题演讲,Emily Freeman 讨论《革命模型》:
www.youtube.com/watch?v=rNBXfgWcy5Q -
来自 honeycomb.io 的 CTO Charity Majors 的博客文章,介绍了平台工程:
www.honeycomb.io/blog/future-ops-platform-engineering -
来自 Humanitec 的 Luca Galante 的文章,描述了平台工程:
platformengineering.org/blog/what-is-platform-engineering -
IDP 及其组件的定义:
internaldeveloperplatform.org -
来自 Moogsoft 的博客文章,这是一家 DevOps 工具供应商,详细介绍了 AIOps 的应用:
www.moogsoft.com/resources/aiops/guide/everything-aiops/ -
GitOps 入门:
www.gitops.tech -
来自 Atlassian 的 Warren Marusiak 的博客文章,概述了采用 DevOps 的方法:
community.atlassian.com/t5/DevOps-articles/How-to-do-DevOps/ba-p/2137695 -
来自 Scaled Agile, Inc.的文章,定义了 Scaled Agile 框架:
www.scaledagileframework.com/safe-for-lean-enterprises/
评估答案
本节包含来自所有章节的问题答案。
第一章 – 介绍 SAFe®与 DevOps
-
C
-
C, D
-
B
-
B
-
C
第二章 – 共享责任文化
-
D
-
B
-
C
-
A, E
-
C
-
C
第三章 – 提高效率与质量的自动化
-
B, D
-
C
-
C
第四章 – 利用精益流动保持工作进展
-
A, D
-
B
-
A
-
C
-
B, E
-
B
-
C
第五章 – 测量过程与解决方案
-
C
-
A
-
B
-
B, D
-
A
第六章 – 从生产故障中恢复
-
B
-
C
-
C
-
A
-
C, D
-
B
第七章 – 绘制你的价值流
-
C
-
B
-
C
-
D
-
D
-
D
-
C
第八章 – 测量价值流表现
-
B
-
D
-
A
-
D, E
-
A
-
C
第九章 – 通过持续学习迈向未来
-
B
-
B, D
-
A
-
C
第十章 – 持续探索与发现新特性
-
C
-
B, C, E
-
B
-
D
-
A, C, E
第十一章 – 解决方案开发的持续集成
-
B, D
-
A
-
C
-
A
-
E
-
B, C
-
D
第十二章 – 持续部署到生产环境
-
B, C, E
-
B
-
A, D, E
-
B, D, E
-
E
-
B
-
C
-
B, C
第十三章 – 按需发布以实现价值
-
B, D, E
-
A, B, E
-
A
-
A, C
-
B, E
937

被折叠的 条评论
为什么被折叠?



