TT Lab
开始
学习 学习路径 课程

由我来搞坏 — 先写假设的混沌实验室

假设、测量、结论各写在各自的时刻

在 TT Lab 中继续学习

一句话总结

实验的产出不是故障,而是笔记。只有假设、测量、结论三者相互吻合,这份笔记才有价值。

为什么需要它

注入故障本身并不难,一行命令就够了。难的是做出下周仍然留得下来的东西。实验结束后,人们的记忆会以惊人的速度变得模糊,甚至连方向都会变。成功率明明是 76%,却被记成“几乎全失败了”;反过来,明明确实失败了的实验,却被记成“当时好像也扛住了”。所以实验要把三部分在不同的时间点分别写下来。

工作原理

第一,假设要在破坏之前写下。事后再写的话,它就不是假设,而是对结果的总结。人一旦看到了结果,就分不清“我早就知道会这样”的感觉和真正的预测。因此顺序本身就是方法的一部分。假设里不仅要写会发生什么,还要同时写为什么这样预期以及何时停止。

第二,测量要在实验窗口内进行。如果先制造故障再单独去测,测到的就是恢复已经开始之后的数字。必须先施加负载,在这个窗口内制造故障,窗口关闭后再读取结果。

第三,结论是把假设与测量对照之后的结果。这里有一条最重要的规则:被证伪的假设不是失败。恰恰相反,与预期不符的结果,才是这个实验能带来的最昂贵的信息。如果写的是“把副本增加到三个,就不会有任何请求失败”,而实际上有几个请求失败了,那么当天学到的就是“仅靠副本数是不够的”。结论里只写着 confirmed 的实验笔记,通常意味着假设是事后才补写的。

실험 한 건의 최소 구성
  가설      availability: ok / latency: slower        + 왜 + 중단 조건
  측정      성공률 0.993 · p95 291ms (기준선 33ms)
  결론      관측 ok / slower → 가설과 같음 → confirmed + 무엇을 바꿀 것인가

把这三部分分别存成不同的文件,也是方法的一部分。如果一直在同一个文件里不断追加,假设是什么时候写的、哪个数字属于哪次实验,很快就会变得模糊。假设文件在实验开始后不再改动,测量文件由工具连同当时的集群状态整体写入,结论文件最后单独创建。以后有人读这份笔记时,能按文件回答“这句话是什么时候写的”,这就是可信度的主要来源。

给数字命名的规则也要事先定好。成功率 0.993 算“没问题”还是算“变差了”,每个人的理解都不同。本课程的实验把成功率 0.98 以上称为 ok,0.5 以上称为 degraded,更低的称为 down;延迟达到基线 p95 的 2 倍以上称为 slower。规则先于结论存在,结论就不会变成争吵。

在现场相遇的样子

实验笔记里也必须写明局限。本实验中观测文件由工具生成,但它终究是 VM 中可以编辑的文本。因此评分不只看数字,还会一并检查集群中实际留下的痕迹——每次部署都会新生成的 ReplicaSet,以及当前存活的 Pod。数字可以编造,但没做过的部署不会留下 ReplicaSet,这一点编造不出来。生产现场也是一样。报告中的数字,始终应当附上可以再次确认的路径。

笔记的最后一栏是“那么要改变什么”。这一栏如果是空的,实验就只是看了场热闹。要改的可能是代码,也可能是配置,但很多时候是运维流程,比如“针对延迟再增加一条告警标准”。尤其是那种成功率完全正常、只有延迟变差的事件,现有告警根本捕捉不到,所以如果实验中确认了这一点,当场再新增一条告警就是正确的后续措施。理想情况是五次实验得出五个不同的决定;如果五栏里写着同一句话,通常说明其实只做了一个实验。

另外,实验结束后必须恢复原状,或者恢复成吸收了所学经验的更好的设计。没有恢复的实验,会被当作故障直接移交给下一个人。熟悉查看正在运行的 Pod 的方法,也能让恢复后的确认更快。

笔记积累起来之后,下一步就是自动化。把手动做过的实验在固定时间运行,并在偏离稳态时让它自行停止,而起点始终是手动做过一次的那个实验。必须先有人能读懂的笔记,机器才能重写这份笔记。

下一项实验要做什么

在真正的 k3s 上进行五次实验。先测出正常基线,一次性写下五个实验的假设,然后杀掉 Pod、限制 CPU、耗尽内存。最后根据所学改进设计,并再次承受同样的攻击。