

# REL12-BP05 使用混沌工程测试弹性
<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 是在混沌工程实际试用期间使用的一个不错选择。它支持在不同类型的资源中同时引入故障，包括 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/2022-03-31/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 故障对容器组（pod）的 CPU 运行压力测试，同时使用 AWS FIS 故障操作终止随机选择的集群节点百分比。 

## 实施步骤
<a name="implementation-steps"></a>
+  确定哪些故障要用于实验。 

   评估工作负载的设计是否具有弹性。这种设计（使用 [Well-Architected Framework](https://docs.aws.amazon.com/wellarchitected/latest/framework/welcome.html)的最佳实践创建）考虑到了基于关键依赖关系、过去的事件、已知问题和合规性要求的风险。列出每个旨在保持弹性的设计元素及其旨在缓解的故障。有关创建此类列表的更多信息，请参阅 [《运营准备就绪情况审核》白皮书](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。
+  为每个故障指定一个优先级。 

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

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

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

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

   使用指定的优先级来确定首先用哪些故障进行实验，以及开发新的故障注入实验的顺序。 
+  对于您执行的每项实验，请遵循混沌工程和连续弹性飞轮。   
![\[混沌工程和连续弹性飞轮图，显示了“改进”、“稳态”、“假设”、“进行实验”和“验证”阶段。\]](http://docs.aws.amazon.com/zh_cn/wellarchitected/2022-03-31/framework/images/chaos-engineering-flywheel.png)
  +  将稳态定义为指示正常行为的工作负载的一些可测量输出。 

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

     例如，可以将某个支付系统的稳态定义为处理 300TPS，成功率为 99%，且往返时间为 500ms。 
  +  形成一个关于工作负载如何应对故障的假设。 

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

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

     例如： 
    +  如果 Amazon EKS 节点组中 20% 的节点出现故障，则 Transaction Create API 将在不到 100ms 的时间内继续处理 99% 的请求（稳态）。Amazon EKS 节点将在五分钟内恢复，容器组（pod）将在实验开始后八分钟内得到调度并处理流量。警报将在三分钟内将发出。 
    +  如果发生单个 Amazon EC2 实例故障，订单系统的 Elastic Load Balancing 运行状况检查将导致 Elastic Load Balancing 仅向剩余的运行状况良好的实例发送请求，而 Amazon EC2 Auto Scaling 将替换故障实例，从而保持服务器端（5xx）错误增长率低于 0.01%（稳态）。 
    +  如果主 Amazon RDS 数据库实例发生故障，则供应链数据收集工作负载将失效转移并连接到备用 Amazon RDS 数据库实例，以保持不到 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 的实验，另请参阅 [“通过混沌工程构建弹性且架构完善的应用程序”实验室](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) 在生产环境中进行实验，尽可能同时启动控制和实验系统部署。在非高峰时间进行实验是一种很好的做法，可以减小首次在生产环境中试验时的潜在影响。此外，如果使用实际的客户流量会带来太大的风险，您可以在生产基础设施上针对控制和实验部署使用合成流量进行实验。当不能使用生产环境时，在尽可能接近生产环境的预生产环境中进行实验。 

     您必须建立和监控防护机制，确保实验对生产流量或其他系统的影响不会超过可接受的限度。建立停止条件，以便在实验达到您定义的防护机制指标的阈值时停止实验。这应该包括工作负载的稳态指标，以及针对您要注入故障的组件的指标。A [合成监控器](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）还是手动执行，这些后期操作都应包含在描述如何检测和处理故障的行动手册中。 
  +  验证假设。 

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

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

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

     5xx 错误是一个很好的指标，因为它们是工作负载客户端将直接经历的故障模式的结果。数据库错误测量适合作为故障的直接结果，但是还应补充一个客户端影响测量，例如失败的客户请求或向客户端显示的错误。此外，在工作负载客户端直接访问的任何 API 或 URI 上包括一个合成监控器（也称为用户金丝雀）。 
  +  改进工作负载设计，以提高弹性。 

     如果未保持稳态，则调查如何改进工作负载设计以缓解故障，应用 [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/)的文章，等等。

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

   混沌实验是一个循环，作为混沌工程的一部分，应定期进行实验。在工作负载满足实验的假设后，实验应实现自动化，作为 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) 的实验室使您能够动手实践。

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

  必须捕获并持久保存故障注入实验的结果。包括所有必要的数据（如时间、工作负载和条件），以便以后能够分析实验结果和趋势。结果示例可能包括控制面板的屏幕截图、从指标数据库进行的 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/) 
+  [混沌工程：规划您的首次实验](https://medium.com/the-cloud-architect/chaos-engineering-part-2-b9c78a9f3dde) 
+  [弹性工程：学会接受故障](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：使用混沌工程测试弹性（ARC316）](https://www.youtube.com/watch?v=OlobVYPkxgg) 
+  [AWS re:Invent 2019：通过混沌工程提高弹性（DOP309-R1）](https://youtu.be/ztiPjey2rfY) 
+  [AWS re:Invent 2019：在无服务器世界中执行混沌工程（CMY301）](https://www.youtube.com/watch?v=vbyjpMeYitA) 

 **相关示例：** 
+  [Well-Architected 实验室：第 300 级：测试 Amazon EC2、Amazon RDS 和 Amazon S3 的弹性](https://wellarchitectedlabs.com/reliability/300_labs/300_testing_for_resiliency_of_ec2_rds_and_s3/) 
+  [“混沌工程在 AWS 上的应用”实验室](https://chaos-engineering.workshop.aws/en/) 
+  [“通过混沌工程构建弹性且架构完善的应用程序”实验室](https://catalog.us-east-1.prod.workshops.aws/workshops/44e29d0c-6c38-4ef3-8ff3-6d95a51ce5ac/en-US) 
+  [“无服务器混沌”实验室](https://catalog.us-east-1.prod.workshops.aws/workshops/3015a19d-0e07-4493-9781-6c02a7626c65/en-US/serverless) 
+  [“使用 AWS Resilience Hub 测量和提高应用程序弹性”实验室](https://catalog.us-east-1.prod.workshops.aws/workshops/2a54eaaf-51ee-4373-a3da-2bf4e8bb6dd3/en-US/200-labs/1wordpressapplab) 

 ** 相关工具： ** 
+  [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/) 