希望探究复杂系统如何应对异常时,对系统中的服务注入通信故障、超时、错误等,这是一个故障注入的典型场景。 希望探究更多其他的非故障类的场景,流量激增、资源竞争条件、拜占庭故障、非计划中的或非正常组合的消息处理等等。

和故障注入类似,故障测试方法通过对预先设想到的可以破坏系统的点进行测试,但是并没能去探究上述这类更广阔领域里的、不可预知的、但很可能发生的事情。

在测试中,要进行断言:即给定一个特定的条件,系统会输出一个特定的结果。 测试一般来说只会产生二元的结果,验证一个结果是真还是假,从而判定测试是否通过。 严格意义上来说,这个实践过程并不能发掘出系统未知的或尚不明确的认知,它仅仅是对已知的系统属性可能的取值进行测验。 而实验可以产生新的认知,而且通常还能开辟出一个更广袤的对复杂系统的认知空间。

故障注入则是对一个特定的条件、变量的验证方法。 混沌工程是发现新信息的实践过程。

一些混沌工程实验的输入样例:

  • 模拟整个云服务区域或整个数据中心故障
  • 在驱动程序中执行模拟 I/O 错误的程序
  • 强制系统节点间的时间不同步
  • 让某个 Elasticsearch 集群 CPU 超负荷
  • 跨多实例删除部分 Kafka topic 来重现生产环境中发生过的问题
  • 挑选一个时间段,和针对一部分流量,对其涉及的服务间调用注入一些特定的延时
  • 方法级别的混乱,让方法随机抛出各种异常
  • 在代码中插入一些指令可以允许在这些指令之前运行故障注入

混沌工程的前提条件是监控系统。 如果没有对系统行为的可见能力,就无法从实验中得出有效的结论。

软件工程师通常会对这三个方面进行优化:性能、可用性、容错能力。

原则

  • 建立稳定状态的假设
  • 多样化现实世界事件
  • 在生产环境运行实验
  • 持续自动化运行实验
  • 最小化爆炸半径
如何描述稳定状态

期望通过一个模型,基于所期望的业务指标,来描述系统的稳定状态,不只是数值范围。

建立假设

每当进行混沌工程实验的时候,应该首先在心里对实验结果有一个假设。 没有一个预先的假设,就不清楚应该从数据里找什么,最终也难以得出有效结论。

思考一下当向系统注入不同类型的事件时,稳定状态行为会发生什么变化。

故障
  • 硬件故障
  • 网络延迟或隔离
  • 上行或下行输入的大幅波动以及重试风暴
  • 资源耗尽
  • 状态转换异常
  • 服务之间的不正常的或者预料之外的组合调用
  • 下游依赖故障
  • 功能缺陷
  • 拜占庭故障
  • 资源竞争条件

不需要穷举所有可能对系统造成改变的事件,只需要注入那些频繁发生且影响重大的事件,同时要足够理解会被影响的故障域。

注入的事件一定是认为系统能处理的。 同时,注入的事件应该是所有可能的真实世界的事件,而不仅仅是故障或延迟。

让这些薄弱环节曝光出来而不会意外造成更大规模的故障。

确定故障的边界,逐渐加大故障范围。

爆炸半径

某一部署单元、某一机房,某一集群,甚至精确到实例级别乃至流量级别。

流程

  • 选定假设
  • 设定实验的范围
  • 识别出要监控的指标
  • 执行实验
  • 分析实验结果
  • 扩大实验范围
  • 自动化实验

阶段

  • 实验结果只反映系统指标,而不是业务指标;只对实验对象注入一些简单事件,如"关闭节点"
  • 用复制的生产流量来运行实验;实验结果反映聚合的业务指标;对实验对象注入较高级的事件,如网络延迟
  • 实验框架和持续发布工具集成;持续收集实验结果;在实验组和控制组之间比较业务指标差异;对实验组引入如服务级别的影响和组合式的故障事件

对比

image

Chaos Toolkit/Chaos Toolkit Extensions for Kubernetes

https://docs.chaostoolkit.org/drivers/kubernetes/

image

可扩展性,旨在成为创建自定义混沌工具和实验的框架。

“开放混沌计划”,旨在通过开放 API 规范,使混沌实验标准化。

Litmus

image

image

  • ChaosEngine 关联一个 Kubernetes 的应用或是 Kubernetes 节点。Litmus 的 Chaos-Operator 会 watch 这个对象并触发 ChaosExperiment。
  • ChaosExperiment 包含了一组混沌事件的配置。当 ChaoseEngine 触发混沌事件的时候,Chaos-Operator 就会创建 ChaoseExpeiment。
  • ChaosResult 混沌事件的结果。Chaos-exporter 读取结果并暴露 metrics 写到 Prometheus 中。
chaos-mesh

image

image

https://grafana.com/grafana/plugins/yeya24-chaosmesh-datasource

kube-monkey

每天早上,都会生成一个全天应该执行的 Pod 的计划。

允许指定每个 Pod 的故障之间的平均时间。

允许单个应用程序以自己独特的方式选择加入。 应用程序 a 可以要求每周一天杀死一个 Pod。 应用程序 b 可以要求杀死 50% 的 Pod。

chaoskube

每隔 10 分钟,随机杀 Pod。

kubethanos

会随机杀死一半的 Pod。