专业书籍精读 · Chaos Engineering · 第 4 章
Chaos Engineering: System Resiliency in Practice · Ch 4 · Richard Crowley(Slack)· 2020
上一章把规矩立好了:别只做检查,要真去制造故障。最自然的下一个问题是——那我装个什么工具?
这一章的回答出人意料:第一步不是找工具,是写一份剧本、约一场排练、把人叫到一个房间里。讲这事的是 Slack 的工程师,他要摇的不是崭新的云原生系统,而是公司里那些年头久、当初压根没按「会坏」设计的关键部件。
假设一台剧要演一个吊威亚的动作。没有哪个剧组会在首演那天、满座的观众面前,第一次把人吊上去试试看。
正常做法是:先有剧本——谁在第几分钟做什么、出什么岔子算岔子;然后在空场里走一遍,把绳长、灯光、站位这些丢人的小错先摔完;正式那场,安全绳挂着、有人守在开关旁、全组对好一句「喊停」的词。
这一章讲的就是这套排练法,作者管它叫「灾难剧场」。
上一章提过那只「随机关机的猴子」:随手关掉几台机器,系统该自动绕开。这招好用,但有个藏起来的前提——这些机器本来就是按「随时会死」造的,死了自动有人接班。
可一家公司跑久了,最要紧的那几样往往不长这样。它们更像老房子:拆一堵墙整栋会歪,扶正还得有人爬上去。对老房子扔猴子,不叫演练,叫塌房。于是很多团队卡住:不敢碰,这部分永远是个没验过的黑箱;硬碰,第一次就真出一次事故,这件事在公司里的名声当场毁掉。
最实在的收获是:你终于敢碰那些最要紧、最老的部件,而且第一次碰不会把演练变成事故。还有一个反直觉的发现——最常撞到的不是「它没扛住」,而是「它扛住了,但没有一个人知道」:东西好好的,警报一声没出。诚实说一句代价:这种演法非常费人,一个季度排几场,不可能天天跑。
对当初没按「会坏」设计的老系统,做混沌工程的第一步不是装工具,而是写剧本、先空场排一遍、正式那场把人和「喊停」的开关都备齐——把一次潜在的事故,降格成一场有安全绳的排练。
想进到具体机制、量级和示意图? → 切到精读版
你以为落地混沌工程的第一步是选一个故障注入工具。Slack 的答案是:第一步是一份文档、一次评审、一场在非生产环境的预演,和一个被量过耗时的中止方案。因为 Chaos Monkey 那条路有个藏起来的前置条件——被摇的东西本来就是按「随时会死」设计的;而任何活了几年的公司,最关键的那几个系统恰恰不是。这一章给的不是工具,是一套让存量系统(legacy system)第一次被摇时,产出的是知识而不是一次事故的流程。
全书 21 章的第 4 章,Part II「原则落地」的开篇——Ch4 到 Ch8 是五家公司把上一章五条原则在各自约束下的变形,而这一章是第一种、也是门槛最低的那种变形:原则三(在生产跑)保留,原则四(自动化、持续跑)暂时让位于「人在回路」。往下 Ch5 是 Google 的 DiRT(同一种人在回路,但做到公司规模),Ch7 是 LinkedIn 对爆炸半径的伦理约束,Ch8 是 Capital One 在合规下的渐进路线,Ch16 才回到全自动。现实里它对着的,是有一堆多年前写的服务、平台不统一、却必须开始验韧性的团队——也就是绝大多数团队。
上一章的五条原则有个没说出口的假设:被实验的系统是为失败而设计的。Chaos Monkey 能随机终止实例,前提是实例无状态、被统一平台编排、死了之后流量会自动绕开。
但真实公司的基础设施是分层沉积的。本章在 Slack 内部划的分水岭很干脆:新系统按「故障是常态」设计——无本地状态、可随时重启、流量自动绕开;老系统按「基础设施可靠」设计——有本地状态、切换要人、甚至依赖某台具体机器的身份。不巧的是,老系统往往正是最关键的那一层:数据库、服务发现、消息路由、身份。给个量级感:Slack 当时日活在数百万量级,每个在线客户端维持一条长连接(WebSocket),连接层一抖是所有在线用户同时重连。
所以这章的问题是:怎么给一个压根没为失败设计过的系统做实验,而且不让实验本身变成那次事故?
不解决会怎样?一是不敢做:最关键那层永远是未验证的黑箱,你的信心全来自「它一直没出事」——上一章刚说过这不算证据。二是硬做:第一场演练炸成一次真事故,技术损失有限而政治损失致命,混沌工程在这家公司的信誉当场清零。本章的流程一半是技术设计,一半是在保护这件事的政治生命。
这是全章最可操作的一句判据,拿它去问手上每一个系统。「自动绕开」意味着后果有界且已知:实例死掉 → 健康检查摘除 → 剩下的分摊,最坏情况你算得出来,可以放手让机器随机去摇。「需要人」意味着后果不可预先界定:注入后系统进入一个没人见过的中间态,恢复时间取决于当时谁在、他多熟、文档准不准。对这类系统自动随机注入,不是实验,是开盲盒。
这也解释了 Chaos Monkey 为什么不通用——它硬要求你先有一个把应用管起来的平台(见 §6 实证):没有那个平台的系统不是「还没接入」,是架构上不满足前提。
本章主体就是这条流水线:看着很「重」,但每一环都在消掉一类特定的失败。
① 文档(最重要的一步)。主持人事先写一份不长的文档,必须回答:摇哪个系统、注入什么故障、敲哪几条命令、动哪几台实例;盯哪些看板、告警、日志;以及假设——预计会发生什么,包括哪些告警会响、用户有没有感觉。
文档里有一个设计得极妙的问题:「你有多确信非生产环境里的容错,能预测生产环境里的容错?」它把上一章原则三那个抽象争论变成主持人必须书面回答的具体问题,而且回答会改变设计:答「很有信心」,生产那场可以轻快;答「没什么信心」,就得更小的半径、更短的时长、更多人在场。
② 评审。文档在相关团队里传阅。这一步常被低估:很多问题在传阅阶段就被想出来,根本不用真的注入——这是整条流水线里最便宜的一次「实验」。
③ 非生产预演。先在 dev 演一遍。它不替代生产(否则就是偷偷放弃原则三),只负责把和假设无关的丢人错误先摔完:命令写错、权限不够、工具自己坏了、依赖起不来。这些错留到生产,会让你死在一个毫不相干的地方,白烧一个时间窗。
④ 生产演练。约定时间窗,把专家集中在一处一起看。为什么不靠告警把人叫来?因为告警本身也在被检验——不能用待验证的东西去保障验证过程。排在工作时间还有个好处:最熟的人是清醒的,不是凌晨三点被叫起来的值班同学。
⑤ 记录与跟进。写下实际发生了什么、与假设差在哪、开修复项。缺这步,前四步的产出会停在「大家当时都知道」,三个月后归零。
绝大多数团队的中止方案就一句「有问题就回滚」,等于没写。本章要求它具体到三件事:
影响范围 × (注入时长 + 中止耗时),后一项不量,前面压到 1% 也没意义。按价值排序,最有价值的那类最反直觉:
自动化注入有个前置条件:你已经知道这个故障的后果是有界的。第一次摇一个老系统你恰恰不知道——所以人在场不是保守,是在补那个缺失的前提。
这也给出了演进方向:人在场的边际价值在第一次最高、第 N 次最低。同一个实验演过几轮、后果摸清、判据能写成代码,就该交给机器天天跑(Ch16)。流程不是终点,是入口。
还有一个自动化永远产不出的副产品:教育。一场演练把五到十个工程师放在同一处、看同一组指标、在同一分钟里修正自己的猜测——这是把 Ch1 里各自残缺的局部心智模型强行拼一次。流水线产出的是一条绿灯,演练产出的是五个人更新过的理解。
第一张表是那条判据的落地:手上每个系统该用哪种做法。
| 系统形态 | 拿掉一台会怎样 | 能自动注入吗 | 该用的做法 | 代价 / 失效点 |
|---|---|---|---|---|
| 无状态 + 平台编排 | 健康检查摘除,剩下的分摊 | 能 | 随机自动注入,持续跑 | 前提是先有那个编排平台 |
| 有状态 + 自动故障切换 (共识集群 / 主从自动切) | 自动切换,但有秒级抖动与数据代价 | 半自动 | 先人在回路演几轮,确认切换真的发生、耗时可接受,再交机器 | 切换本身可能丢最后一小段写入 |
| 有状态 + 切换要人 | 进入没人见过的中间态 | 不能 | 灾难剧场:文档 → 评审 → 预演 → 人在回路演练 | 费人,频率上不去 |
| 真单点,无切换路径 | 直接不可用 | 不能 | 别做实验,先去建冗余 | 摇它只会确认你早就知道的事 |
判据只有一句:这台机器消失,是自动绕开还是需要人?它决定你能不能把判断权交给机器。
第二张表是「在哪演」的权衡,关键在认清每一档各自抓不到什么。
| 在哪演 | 抓得到 | 抓不到 | 什么时候用 |
|---|---|---|---|
| 非生产预演 | 命令写错、权限不足、工具自己坏、依赖缺失 | 一切和量级有关的:连接池打满、重试风暴、缓存塌陷 | 每一场生产演练之前,必做 |
| 生产 · 人在回路 (本章的做法) | 真实量级下的行为、告警到底响不响、恢复路径安不安全 | 罕见的故障组合——频率上不去,一季度几场 | 第一次摇某个存量系统 |
| 生产 · 自动持续 (Ch16 的做法) | 频率与覆盖面,以及回归(昨天的结论今天还成不成立) | 需要人现场判断的东西;它只验已编码进判据的那些 | 同一实验演过几轮、后果已有界之后 |
落到具体选择:
这一章给的是三句能直接改变评审结论的话。一:在问「先摇哪个系统」之前,先问「它消失时是自动绕开还是需要人」——答案决定方法,而不是反过来先选工具。二:演练首先验的不是系统扛不扛得住,而是你会不会知道。三:中止方案要报一个数——撤回生效需要多少秒。
面试被问「你们怎么在生产做故障验证」,答「我们用了 XX 工具」是工具层;答「关键系统不是为失败设计的,所以走文档 + 评审 + 预演 + 人在回路,中止耗时必须量过」是另一个层级——它显示你知道自动化的前置条件。
大厂实证
① 核心命题:落地混沌工程的第一步不是选工具,而是一套流程——因为最关键的系统往往压根没按「会坏」设计,对它自动注入不是实验,是制造事故。
② 分水岭判据:这台机器消失,是自动绕开还是需要人?需要人 → 后果不可预先界定 → 只能人在回路。这条判据也解释了 Chaos Monkey 为什么不通用(它硬要求一个编排平台)。
③ 流程五环:文档 → 评审 → 非生产预演 → 人在回路的生产演练 → 记录跟进;每环消掉一类失败,越早失败越便宜。
④ 文档里最妙的一问:「你有多确信 dev 的容错能预测 prod 的容错?」它把「预发不等价」从抽象争论变成必须书面回答、并据此改设计的具体问题。
⑤ 生产那场把专家集中在一处,因为「告警会不会响」本身就在被检验,不能用待验证的东西保障验证过程;排在工作时间,最熟的人是清醒的。
⑥ 中止方案要具体到三件事:撤回操作、撤回生效耗时、谁能喊停。真实爆炸半径 = 影响范围 × (注入时长 + 中止耗时)。
⑦ 三类典型发现,第一类最反直觉:扛住了但没人知道(告警哑);扛住故障却死在恢复上;故障根本注入不进去(心智模型错了)。
⑧ 人在回路不是落后,是在补「后果有界」这个自动化前提,并产出自动化产不出的东西——五到十个人同时更新的心智模型。但频率上不去,终点仍是 Ch16 的持续验证。
⑨ 演练一旦被用来追责就会退化成表演:没人愿意主持、没人愿意写悲观的假设。