

# REL12-BP04 使用混沌工程测试韧性
<a name="rel_testing_resiliency_failure_injection_resiliency"></a>

 在生产环境中或尽可能接近生产的环境中定期运行混沌试验，了解系统如何应对不利条件。

 **期望结果：**

 除了在事件期间验证已知预期工作负载行为的韧性测试之外，还可以通过以故障注入实验或注入意外负载的形式应用混沌工程，定期验证工作负载的韧性。将混沌工程和韧性测试结合起来，这可以让您提升信心，相信工作负载能够经受组件故障，并可从意外中断中恢复，而影响极小甚至没有影响。

 **常见反模式：**
+  进行韧性设计，但不验证故障发生时工作负载如何作为一个整体运行。
+  从不在真实环境和预期负载下进行试验。
+  不将实验视为代码，也不在整个开发周期中维护实验。
+  不将混沌实验作为 CI/CD 管道的一部分，也不在部署之外运行。
+  在确定要对哪些故障进行试验时，没有想到使用过去的事件后分析。

 **建立此最佳实践的好处：**注入故障来验证工作负载的韧性，这可以让您提升信心，相信韧性设计的恢复程序会在真正发生故障的情况下发挥作用。

 **在未建立这种最佳实践的情况下暴露的风险等级：**中 

## 实施指导
<a name="implementation-guidance"></a>

 利用混沌工程，您的团队能够在服务提供商、基础设施、工作负载和组件级别，以可控的方式不断注入真实世界的干扰（模拟），而对客户的影响极小甚至没有影响。其可让团队从故障中学习，观察、测量和提高工作负载的韧性，并验证在发生事件时，系统会发出警报并通知团队。

 当持续执行时，混沌工程可突出工作负载中的缺陷，这些缺陷若不加以解决，可能会对可用性和运营产生负面影响。

**注意**  
混沌工程是在系统上进行实验的学科，目的是建立对系统抵御生产环境中失控条件的能力以及信心。– [混沌工程原则](https://principlesofchaos.org/) 

 如果系统能够经受住这些干扰，则应将混沌实验作为自动回归测试来加以维护。这样一来，应将混沌实验作为系统开发生命周期（SDLC）的一部分，以及作为 CI/CD 管道的一部分来执行。

 为了确保工作负载能够经受住组件故障，请在实验中注入实际事件。例如，对 Amazon EC2 实例的丢失或主 Amazon RDS 数据库实例的失效转移进行试验，并验证工作负载没有受到影响（或影响极小）。使用组件故障的组合来模拟可能因可用区中断而引起的事件。

 对于应用程序级故障（如崩溃），您可以从内存和 CPU 耗尽等压力源开始。

 为了验证因间歇性网络中断而引发的外部依赖项的[回退或失效转移机制](https://aws.amazon.com/builders-library/avoiding-fallback-in-distributed-systems/)，组件应通过在指定时间段（从几秒到几小时不等）内阻止对第三方提供商的访问来模拟此类事件。

 其他降级模式可能会影响功能的使用并降低响应速度，这通常会导致服务中断。性能下降的常见原因是，关键服务的延迟增加以及网络通信不可靠（丢包）。对于这些故障（包括延迟、丢弃的消息和 DNS 故障等网络效应）的实验，可能包括无法解析名称、无法访问 DNS 服务或无法建立与依赖服务的连接。

 **混沌工程工具：**

 AWS Fault Injection Service（AWS FIS）是一项完全托管式服务，用于运行故障注入实验，而这些实验可用作 CD 管道的一部分，或在管道之外使用。AWS FIS 是在混沌工程 GameDay 活动期间使用的一个不错选择。该服务支持在不同类型的资源中同时引入故障，包括 Amazon EC2、Amazon Elastic Container Service（Amazon ECS）、Amazon Elastic Kubernetes Service（Amazon EKS）和 Amazon RDS 等资源。这些故障包括终止资源、强制失效转移、对 CPU 或内存施加压力、节流、延迟和数据包丢失。由于该服务已与 Amazon CloudWatch 警报集成，您可以设置停止条件作为防护机制，在实验导致意外影响时回滚。

![\[图中显示了 AWS Fault Injection Service 与 AWS 资源集成，让您能够为工作负载运行故障注入实验。\]](http://docs.aws.amazon.com/zh_cn/wellarchitected/latest/framework/images/fault-injection-simulator.png)


故障注入实验也有多种第三方选项。其中包括开源工具（例如 [Chaos Toolkit](https://chaostoolkit.org/)、[Chaos Mesh](https://chaos-mesh.org/) 和 [Litmus Chaos](https://litmuschaos.io/)），以及商用工具（例如 Gremlin）。为了扩大可在 AWS 上注入的故障范围，AWS FIS [与 Chaos Mesh 和 Litmus Chaos 集成](https://aws.amazon.com/about-aws/whats-new/2022/07/aws-fault-injection-simulator-supports-chaosmesh-litmus-experiments/)，让您能够在多个工具之间协调故障注入工作流程。例如，您可以使用 Chaos Mesh 或 Litmus 故障对容器组的 CPU 运行压力测试，同时使用 AWS FIS 故障操作终止随机选择的集群节点百分比。

## 实施步骤
<a name="implementation-steps"></a>

1.  确定哪些故障要用于实验。

    评测工作负载的设计是否具有韧性。这种设计使用 [Well-Architected Framework](https://docs.aws.amazon.com/wellarchitected/latest/framework/welcome.html) 的最佳实践创建，考虑到了基于关键依赖项、以往事件、已知问题以及合规性要求的风险。列出每个旨在保持韧性的设计元素及其旨在缓解的故障。有关创建此类列表的更多信息，请参阅《[Operational Readiness Review](https://docs.aws.amazon.com/wellarchitected/latest/operational-readiness-reviews/wa-operational-readiness-reviews.html)》白皮书，了解如何创建流程来防止以往事件再次发生。故障模式与影响分析（FMEA）流程提供了一个框架，可对故障及其对工作负载的影响执行组件级分析。Adrian Cockcroft 在《[Failure Modes and Continuous Resilience](https://adrianco.medium.com/failure-modes-and-continuous-resilience-6553078caad5)》中更详细地概述了 FMEA。

1.  为每个故障指定一个优先级。

    先进行粗略的分类，如高、中或低。要评测优先级，请考虑故障的频率和故障对整体工作负载的影响。

    考虑给定故障的频率时，请分析此工作负载的以往数据（如有）。如果没有以往数据，则使用在类似环境中运行的其他工作负载的数据。

    考虑给定故障的影响时，故障的范围越大，影响通常也越大。还要考虑工作负载设计和目的。例如，访问源数据存储的能力对于进行数据转换和分析的工作负载至关重要。在这种情况下，您要确定访问故障以及节流访问和延迟插入等实验的优先级。

    事件后分析是了解故障模式的频率和影响的良好数据来源。

    使用指定的优先级来确定首先对哪些故障进行实验，以及开发新的故障注入实验的顺序。

1.  对于执行的每项实验，请遵循下图中的混沌工程和持续韧性飞轮。  
![\[混沌工程和持续韧性飞轮图，显示了“改进”、“稳定状态”、“假设”、“进行实验”和“验证”阶段。\]](http://docs.aws.amazon.com/zh_cn/wellarchitected/latest/framework/images/chaos-engineering-flywheel.png)

    

   1.  将稳定状态定义为指示正常行为的工作负载的一些可测量输出。

       如果工作负载运行可靠且符合预期，则显示为稳定状态。因此，定义稳定状态之前，请验证工作负载是否运行状况良好。稳定状态并不一定意味着故障发生时对工作负载没有影响，因为一定百分比的故障可能在可接受的范围内。稳定状态是您将在实验期间观察到的基线，如果下一步中定义的假设结果不符合预期，则会突出显示异常。

       例如，可以将某个支付系统的稳定状态定义为处理 300 TPS，成功率为 99%，且往返时间为 500 毫秒。

   1.  形成一个关于工作负载如何应对故障的假设。

       一个好的假设是基于工作负载预计如何缓解故障来保持稳定状态。该假设指出，如果发生特定类型的故障，系统或工作负载将继续保持稳定状态，因为该工作负载在设计时就有特定缓解措施。应在假设中具体说明特定的故障类型和缓解措施。

       假设可以使用以下模板（但其他措辞也可以接受）：
**注意**  
 如果发生*具体故障*，则*工作负载名称*工作负载将*描述缓解控制措施*，以此维持*业务或技术指标影响*。

       例如：
      +  如果 Amazon EKS 节点组中 20% 的节点出现故障，则 Transaction Create API 将在不到 100 毫秒的时间内继续处理 99% 的请求（稳定状态）。Amazon EKS 节点将在五分钟内恢复，容器组将在实验开始后八分钟内得到调度并处理流量。警报将在三分钟内发出。
      +  如果单个 Amazon EC2 实例发生故障，订单系统的弹性负载均衡运行状况检查会让弹性负载均衡仅向剩余的运行状况良好的实例发送请求，而 Amazon EC2 Auto Scaling 将替换故障实例，从而保持服务器端（5xx）错误增长率低于 0.01%（稳定状态）。
      +  如果主 Amazon RDS 数据库实例发生故障，则供应链数据收集工作负载将失效转移并连接到备用 Amazon RDS 数据库实例，以保持不到 1 分钟的数据库读写错误（稳定状态）。

   1.  通过注入故障来进行实验。

       默认情况下，实验应具有故障保护机制，可承受工作负载。如果知道工作负载将发生故障，则不要进行实验。混沌工程应该用于寻找已知的不确定因素或未知的不确定因素。*已知的不确定因素*是您知道但不完全理解的东西，而*未知的不确定因素*是您既不知道也不完全理解的东西。对已知发生了故障的工作负载进行实验，并不会为带来新的见解。您应该仔细规划实验，明确影响范围，并提供一种可在出现意外动荡时应用的回滚机制。如果尽职调查表明工作负载应该能经受住实验，才继续这项实验。有几种注入故障的选项。对于 AWS 上的工作负载，[AWS FIS](https://docs.aws.amazon.com/fis/latest/userguide/what-is.html) 提供了许多称为[操作](https://docs.aws.amazon.com/fis/latest/userguide/actions.html)的预定义故障模拟。您还可以定义在 AWS FIS 中运行的自定义操作（使用 [AWS Systems Manager 文档](https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-ssm-docs.html)）。

       我们不鼓励使用自定义脚本进行混沌实验，除非这些脚本能够了解工作负载的当前状态，能够发出日志，并在可能的情况下提供回滚和停止条件的机制。

       支持混沌工程的有效框架或工具集应跟踪实验的当前状态，发出日志，并提供回滚机制以支持实验的受控执行。从 AWS FIS 这样的成熟服务开始，该服务支持您在明确定义的范围内和安全机制下进行实验，可在实验引入了意外动荡的情况下回滚实验。要了解更多使用 AWS FIS 的实验，另请参阅 [Resilient and Well-Architected Apps with Chaos Engineering 实验室](https://catalog.us-east-1.prod.workshops.aws/workshops/44e29d0c-6c38-4ef3-8ff3-6d95a51ce5ac/en-US)。此外，[AWS Resilience Hub](https://docs.aws.amazon.com/resilience-hub/latest/userguide/what-is.html) 将分析工作负载，并创建您可以选择在 AWS FIS 中实施和执行的实验。
**注意**  
 对于每项实验，要清楚地了解其范围及影响。建议首先在非生产环境中模拟故障，再在生产环境中运行。

       应使用实际负载，通过[金丝雀部署](https://medium.com/the-cloud-architect/chaos-engineering-q-a-how-to-safely-inject-failure-ced26e11b3db)在生产环境中进行实验，尽可能同时启动控制和实验系统部署。在非高峰时间进行实验是一种很好的做法，可以减小首次在生产环境中试验时的潜在影响。此外，如果使用实际的客户流量会带来太大的风险，您可以在生产基础设施上针对控制和实验部署使用合成流量进行实验。当不能使用生产环境时，在尽可能接近生产环境的预生产环境中进行实验。

       您必须建立和监控防护机制，确保实验对生产流量或其他系统的影响不会超过可接受的限度。建立停止条件，以便在实验达到您定义的防护机制指标的阈值时停止实验。这应该包括工作负载的稳定状态指标，以及针对您要注入故障的组件的指标。[综合监控](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries.html)（也称为用户金丝雀）是一个通常应作为用户代理包含的指标。[AWS FIS 的停止条件](https://docs.aws.amazon.com/fis/latest/userguide/stop-conditions.html)应纳入实验模板中，每个模板最多可以有五个停止条件。

       混沌的原则之一是尽量缩小实验范围并减小其影响：

       虽然必须考虑到一些短期负面影响，但混沌工程师有责任和义务确保实验产生的影响极小且可控。

       验证范围和潜在影响的一种方法是首先在非生产环境中进行实验，确认停止条件的阈值是否在实验期间按预期激活，以及是否具有可观测性来捕获异常，而不是直接在生产环境中进行实验。

       运行故障注入实验时，确保所有责任方均知情。与适当的团队（如运营团队、服务可靠性团队和客户支持团队）沟通，让他们知道实验将在何时运行以及预期会发生什么。为这些团队提供沟通工具，以便在他们看到任何不利影响时通知进行实验的人员。

       必须将工作负载及其底层系统恢复到最初的已知良好状态。通常，工作负载的韧性设计会自我修复。但一些故障设计或失败实验可能会让工作负载处于意外的失败状态。在实验结束时，您必须意识到这一点，并恢复工作负载和系统。使用 AWS FIS，您可以在操作参数中设置回滚配置（也称为后期操作）。后置操作可将目标返回到操作运行之前的状态。无论是自动执行（如使用 AWS FIS）还是手动执行，这些后期操作都应包含在描述如何检测和处理故障的行动手册中。

   1.  验证假设。

      [混沌工程原则](https://principlesofchaos.org/)为如何验证工作负载的稳定状态提供了以下指导：

      关注系统的可测量输出，而不是系统的内部属性。短时间内对该输出的测量构成了系统稳态的代理。整个系统的吞吐量、错误率和延迟百分比都可以是代表稳态行为的相关指标。通过关注实验过程中的系统行为模式，混沌工程验证系统确实在工作，而不是试图验证它如何工作。

       在之前的两个示例中，我们包括了服务器端（5xx）错误增长率低于 0.01% 和数据库读写错误持续时间不到 1 分钟的稳态指标。

       5xx 错误是一个很好的指标，因为此类错误是工作负载客户端会直接经历的故障模式的结果。数据库错误测量适合作为故障的直接结果，但是还应补充一个客户端影响测量，例如失败的客户请求或向客户端显示的错误。此外，在工作负载客户端直接访问的任何 API 或 URI 上包含一个综合监控（也称为用户金丝雀）。

   1.  改进工作负载设计，提高韧性。

       如果未保持稳定状态，则调查如何改进工作负载设计来缓解故障，并应用 [AWS Well-Architected 可靠性支柱](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/welcome.html)的最佳实践。可以在 [AWS Builder’s Library](https://aws.amazon.com/builders-library/) 中找到其他指导和资源，其中包含有关如何[改进运行状况检查](https://aws.amazon.com/builders-library/implementing-health-checks/)或[在应用程序代码中结合采用重试与回退](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/)的文章，等等。

       实施这些更改后，再次进行实验（如混沌工程飞轮中的虚线所示），确定更改的效果。如果验证步骤表明假设成立，则工作负载将处于稳定状态，循环将继续。

1.  定期进行实验。

    混沌实验是一个循环，作为混沌工程的一部分，应定期进行实验。在工作负载满足实验的假设后，实验应实现自动化，作为 CI/CD 管道的回归部分持续运行。要了解如何做到这一点，请参阅关于[如何使用 AWS CodePipeline 进行 AWS FIS 实验](https://aws.amazon.com/blogs/architecture/chaos-testing-with-aws-fault-injection-simulator-and-aws-codepipeline/)的博客。这个关于反复[在 CI/CD 管道中进行 AWS FIS 实验](https://chaos-engineering.workshop.aws/en/030_basic_content/080_cicd.html)的实验室让您能够动手实践。

    故障注入实验也是 GameDay 活动的一部分（请参阅 [REL12-BP05 定期进行 GameDay 活动](rel_testing_resiliency_game_days_resiliency.md)）。GameDay 活动会模拟故障或事件，以便验证系统、流程和团队的响应。其目的是实际执行团队在发生意外事件时会执行的操作。

1.  捕获和存储实验结果。

   必须捕获并持久保存故障注入实验的结果。包括所有必要的数据（如时间、工作负载和条件），以便以后能够分析实验结果和趋势。结果示例可能包括控制面板的屏幕截图、从指标数据库进行的 CSV 转储，或实验中事件和观察结果的手写记录。[使用 AWS FIS 进行实验记录](https://docs.aws.amazon.com/fis/latest/userguide/monitoring-logging.html)可作为这种数据捕获的一部分。

## 资源
<a name="resources"></a>

 **相关最佳实践：**
+  [REL08-BP03 将韧性测试作为部署的一部分进行集成](rel_tracking_change_management_resiliency_testing.md) 
+  [REL13-BP03 测试灾难恢复实施以验证实施效果](rel_planning_for_recovery_dr_tested.md) 

 **相关文档：**
+  [什么是 AWS Fault Injection Service？](https://docs.aws.amazon.com/fis/latest/userguide/what-is.html) 
+  [什么是 AWS Resilience Hub？](https://docs.aws.amazon.com/resilience-hub/latest/userguide/what-is.html) 
+  [混沌工程原则](https://principlesofchaos.org/) 
+  [Chaos Engineering: Planning your first experiment](https://medium.com/the-cloud-architect/chaos-engineering-part-2-b9c78a9f3dde) 
+  [Resilience Engineering: Learning to Embrace Failure](https://queue.acm.org/detail.cfm?id=2371297) 
+  [混沌工程案例](https://github.com/ldomb/ChaosEngineeringPublicStories) 
+  [避免在分布式系统中回退](https://aws.amazon.com/builders-library/avoiding-fallback-in-distributed-systems/) 
+  [用于混沌实验的金丝雀部署](https://medium.com/the-cloud-architect/chaos-engineering-q-a-how-to-safely-inject-failure-ced26e11b3db) 

 **相关视频：**
+ [AWS re:Invent 2020: Testing resiliency using chaos engineering (ARC316)](https://www.youtube.com/watch?v=OlobVYPkxgg) 
+  [AWS re:Invent 2019: Improving resiliency with chaos engineering (DOP309-R1)](https://youtu.be/ztiPjey2rfY) 
+  [AWS re:Invent 2019: Performing chaos engineering in a serverless world (CMY301)](https://www.youtube.com/watch?v=vbyjpMeYitA) 

 **相关工具：**
+  [AWS Fault Injection Service](https://aws.amazon.com/fis/) 
+ AWS Marketplace：[Gremlin 混沌工程平台](https://aws.amazon.com/marketplace/pp/prodview-tosyg6v5cyney) 
+  [Chaos Toolkit](https://chaostoolkit.org/) 
+  [Chaos Mesh](https://chaos-mesh.org/) 
+  [Litmus](https://litmuschaos.io/) 