8混沌工程:系统韧性实践

游戏日演练

组织级的混沌实践

Game Day演练策划无指责复盘DiRT

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第8章 游戏日演练

组织级的混沌实践

章节导读

前面几章讨论的混沌实验大多是「机器对系统」的:自动化平台注入故障、护栏监测指标、判定逻辑给出结论。但韧性有一个维度是自动化实验永远无法完整覆盖的——人的韧性。当真实故障在凌晨两点发生时,决定损失大小的不仅是系统的自动降级能力,还有:值班工程师能否在告警风暴中抓住关键信号?团队能否在信息不完整时做出正确的止血决策?跨团队的通信协作是否顺畅?管理层能否及时获得准确的态势通报?客服团队面对用户投诉时是否有统一口径?这些「组织级韧性」无法用 PromQL 度量,无法用 YAML 注入,只能通过一种方式验证与训练——游戏日(Game Day):组织级的协同混沌演练。

游戏日的定义:一个有计划、有剧本(或半开放剧本)、多团队协同参与的故障演练事件,在受控条件下模拟真实故障场景,同时验证系统韧性与组织响应能力。它与自动化混沌实验的关系是互补而非替代:自动化实验高频、小半径、机器判定,验证的是「系统属性」;游戏日低频(季度/半年)、大半径(AZ 级、区域级、全链路)、人工深度参与,验证的是「系统 + 组织」的复合属性。有些问题只有游戏日能回答:整个可用区失效时的流量转移是否真的无缝(大半径才能触发涌现行为)?值班团队面对二十条同时告警的优先级判断是否正确(需要人参与)?事故指挥体系(incident command)在压力下的运转是否顺畅(需要组织参与)?

游戏日的思想源头可以追溯到多个领域。军事领域的战争演习(实兵对抗、沙盘推演)验证的是部队在战场迷雾下的协同能力;航空业的飞行员模拟器训练让机组在零风险条件下经历引擎失效、液压故障、恶劣天气;核电与化工行业的应急演练是法规强制要求。软件领域最著名的先行者是 Google 的 DiRT(Disaster Recovery Testing):从 2008 年开始,Google 每年举行全公司级的灾难演练,模拟数据中心失效、核心服务宕机、甚至关键人员「被绑架」(模拟无法联系上)等场景,数千名工程师参与,演练发现的问题推动了 Google 基础设施韧性的系统性提升。DiRT 的核心洞察是:「未经演练的恢复计划只是假设」——写在文档里的灾备方案、从未跑过的切换流程、纸面上的值班制度,在真实故障面前的表现通常远差于预期,而演练是把「假设」变成「验证过的能力」的唯一途径。

Netflix 的游戏日实践同样深刻。除了自动化的 ChAP,Netflix 定期举行「区域级演练」:在受控条件下把整个 AWS 区域的流量切走(模拟区域完全失效),验证多区域活跃架构的真实性。这类演练的爆炸半径极大——理论上如果切换失败,全球用户都会受影响——因此演练的准备极其充分:预检查清单、实时作战室、多层回滚手段、高管层的明确授权。演练的价值也极大:它验证的不是某个服务的韧性,而是「Netflix 全球架构承诺」的兑现能力。很多公司宣称「多活架构」,但只有真正做过区域切换演练的公司才知道自己的多活是真是假——纸面多活与验证过的多活之间,隔着无数次演练发现的配置漂移、容量不足、数据同步延迟、DNS TTL 过长。

游戏日的双重目标需要展开。目标一:验证系统韧性——大半径故障下系统是否保持稳态?这本质上是第 3-5 章内容的规模化应用:稳态假设依然适用(甚至更重要,因为大半径下判定更复杂)、爆炸半径控制依然适用(游戏日不是「豁出去」,而是「有充分准备的大实验」)。目标二:验证组织响应——团队在模拟压力下的表现如何?这包括技术响应(诊断速度、止血手段的正确性、工具熟练度)与组织响应(指挥链是否清晰、通信是否有效、决策是否及时、记录是否完整)。游戏日的场景设计应当刻意制造「组织压力」:信息不完整(故障的表象与根因分离,需要真实诊断)、多故障并发(考验优先级判断)、意外注入(剧本外的突发事件,考验适应性——高级游戏日会安排「injects」:演练进行中由控制组临时注入计划外事件)、时间压力(模拟故障发生在业务高峰)。

游戏日的完整生命周期包含五个阶段:策划(场景设计、目标定义、参与者组织、安全预案)、准备(预检查、环境验证、通信演练、角色培训)、执行(故障注入、响应观察、时间线记录、意外处理)、复盘(无指责分析、发现分类、行动项生成)、跟进(行动项跟踪、复验计划、知识沉淀)。每个阶段都有丰富的实践细节:策划阶段的「剧本开放度」选择(完全剧本化——参与者知道会发生什么,适合首次演练与流程验证;半开放——参与者知道演练时间窗但不知道具体故障,适合响应能力训练;完全无预告——只有控制组知道,最接近真实但风险与成本最高);执行阶段的「控制组与响应组分离」(控制组掌握全部剧本与中止权限,响应组是真正的被试对象);复盘阶段的「无指责原则」(游戏日发现的组织问题——比如值班工程师不知道 runbook 在哪——是流程缺陷而非个人过失,指责文化会让下次演练变成表演)。

本章将系统展开游戏日的完整方法论:策划的场景设计技术(从事故历史取材、从架构弱点取材、难度分级)、角色体系(总指挥、控制组、响应组、观察员、记录员、安全官)、执行的时间线管理、复盘的结构化方法、行动项的闭环跟踪,以及游戏日与自动化混沌的协同(游戏日验证的场景成熟后沉淀为自动化实验,自动化实验发现的疑点升级为游戏日议题)。Google DiRT 的详细案例将提供大规模演练的参照系。学完本章,你应当能够策划并执行一场从半天的小型团队游戏日到两天的全组织演练的混沌活动,并让它成为组织韧性文化的年度锚点而非一次性事件。

核心概念

  • Game Day
  • 演练策划
  • 无指责复盘
  • DiRT

要点精析

游戏日与自动化混沌实验的能力分工:什么问题只有游戏日能回答。自动化实验的边界由三个约束决定:爆炸半径小(涌现行为需要规模才能触发)、判定自动化(组织行为无法用 PromQL 度量)、无人参与(人的响应不在回路里)。游戏日突破这三个约束,独占四类验证能力:(1)大半径系统行为——AZ 级失效时的流量转移、全局配置错误的传播、共享资源(DNS、配置中心、证书体系)失效的级联,这些场景的爆炸半径超出自动化实验的授权范围,且其风险形态(容量临界、重试风暴的规模效应)只有大半径才能真实呈现。(2)组织响应能力——诊断与止血的速度、指挥链的运转、跨团队协作、对外沟通(客服/公关/管理层通报),这些是「组织韧性」的核心,只能在有真人参与的演练中验证。(3)流程与工具的真实可用性——runbook 是否可执行(照着做能完成操作吗)、应急工具是否好用(凌晨三点手抖的工程师能操作吗)、权限体系是否阻碍响应(值班工程师有没有权限执行止血操作)——纸面流程与真实可用之间的差距只有演练能暴露。(4)跨系统复合场景——技术故障 + 业务高峰 + 人员缺位(模拟关键专家休假)的组合,自动化实验无法编排这种「组织状态」变量。反过来的分工同样清晰:高频回归、小半径定向验证、统计判定属于自动化——让游戏日去做「杀一个 Pod 验证冗余」是巨大的浪费。成熟体系的节奏:自动化实验每日运行守住已知韧性,游戏日每季度验证大场景与组织,游戏日发现的场景成熟后下沉为自动化套件。

场景设计是游戏日策划的核心,好的场景有五个特征。特征一:真实取材——场景来自真实事故历史(本组织的、同行业的、公开复盘的),而非凭空想象;「重演 2023 年 3 月那次数据库切换事故,但这次我们有准备」比「模拟某种网络故障」的参与感与价值都高一个量级。特征二:目标明确——每个场景对应具体的验证问题:「验证跨 AZ 流量切换在 5 分钟内完成且稳态保持」「验证值班团队能在 15 分钟内定位缓存雪崩的根因」;没有明确验证问题的场景是「看热闹」,演练后无法判定成功与否。特征三:难度分级——初级场景(单服务故障,响应路径清晰)建立信心与流程熟练度,中级场景(跨服务级联,需要多团队协作)训练诊断与协作,高级场景(复合故障 + 信息迷雾 + 意外注入)考验真实压力下的组织韧性;一次游戏日的场景组合应当有梯度,让不同经验水平的参与者都有成长。特征四:可中止——每个场景有明确的中止条件与回滚手段(第 5 章的全部内容在游戏日语境下依然适用,且更严格——大半径意味着中止预案要演练过而非纸面存在)。特征五:观测丰富——场景执行期间的系统指标、组织行为(谁在什么时间做了什么决策)、通信记录(作战室频道、电话桥)全部被记录,为复盘提供三维素材;只记录系统数据的游戏日复盘会漏掉最有价值的组织发现。场景库的运营:每次游戏日后场景入库并标注执行历史与发现,新事故复盘产出新场景,年度评审淘汰过时场景——游戏日场景库与第 4 章的变量库同构,只是粒度更大、组织维度更重。

角色体系:游戏日的组织结构决定演练质量。六个标准角色:(1)总指挥(Game Master / Exercise Director)——演练的最高权威,负责推进节奏、裁决争议、下达中止令;应当由工程负责人或资深 SRE 担任,其权威必须在演练前明确宣布(「今天所有操作决策以总指挥为准」),避免多头指挥。(2)控制组(Control Cell / White Cell)——掌握完整剧本,执行故障注入,监控演练安全边界,按计划投放「意外注入」(injects);控制组成员不参与响应,他们的视角是全局的——同时看着系统指标与响应组的行为。(3)响应组(Players / Blue Cell)——真正的被试对象:值班工程师、服务 owner、事故指挥官;他们被告知的信息量取决于剧本开放度(时间窗 vs 完整场景)。(4)观察员(Observers)——不参与操作,专注记录特定维度:有人盯系统指标形态,有人盯响应组的诊断路径(他们先查了什么、走了什么弯路),有人盯通信质量(信息是否及时同步、决策是否被清晰传达);观察员的笔记是复盘的核心素材。(5)记录员(Scribe)——维护权威时间线:每个事件、每个决策、每条关键通信的精确时间戳;真实事故复盘依赖时间线,游戏日的时间线记录本身就是对「事故记录规范」的训练。(6)安全官(Safety Officer)——独立于总指挥的中止权限持有者:当演练出现超出预期的真实风险(真实故障与演练叠加、参与者操作失误扩大影响)时,安全官可以不经讨论直接叫停——这个「一票否决」角色是游戏日安全体系的最后防线,通常由不参与演练内容的资深基础设施负责人担任。小团队可以合并角色(总指挥兼安全官、观察员兼记录员),但控制组与响应组的分离不可妥协——自己演练自己没有观测价值。

剧本开放度的三档选择与演进路径。第一档:完全剧本化(announced & scripted)——参与者提前知道演练时间、场景、预期动作;价值在于流程验证与培训:新值班工程师第一次执行数据库切换操作、跨团队第一次磨合通信协议、runbook 第一次被完整走一遍。适合首次游戏日与流程建设期。常见误区是把它做成「表演」——大家照着剧本念台词,一切「顺利」,什么都没验证;对策是即使剧本化,故障注入也真实执行、响应动作也真实操作,剧本只保证「大家知道会发生什么」而不保证「结果一定成功」。第二档:半开放(announced window, unscripted faults)——参与者知道演练窗口(如「本周四 14:00-18:00 有演练」)但不知道具体场景;响应是真实的诊断与决策,压力适中。适合流程成熟后的常规游戏日。设计要点:窗口内的场景序列由控制组掌握,第一个场景可以从简单开始建立节奏,后续场景逐步加压;「意外注入」在此档开始引入——响应组处理场景 A 时,控制组追加场景 B,训练多故障并发的优先级判断。第三档:无预告(unannounced)——只有控制组与高管层知道,响应组在完全无准备状态下被「真实」告警唤醒(当然在安全边界内);这是最接近真实故障的验证,暴露的问题最真实(值班电话没人接、runbook 找不到、权限不够),但组织成本与风险最高:需要成熟的安全体系(安全官全程盯守、中止手段秒级可用)、需要文化基础(无预告演练不被视为「整人」而是被视为「帮助」)。演进路径:多数组织从第一档起步,每 2-3 次演练升一档,无预告演练只在年演练体系运行两年以上、文化充分成熟后引入。Google DiRT 的演进正是这个路径:早期完全剧本化,成熟后包含大量 surprise 元素,甚至模拟「演练期间发生真实事故」的元场景。

游戏日的执行管理:时间线、通信与态势感知。执行日的标准结构:开场会(30 分钟)——总指挥宣布规则(角色、通信频道、中止口令、安全边界)、控制组确认就绪状态(预检查清单全绿)、响应组确认工具与权限可用;演练循环(每场景 60-90 分钟)——注入 → 响应 → 观察 → 场景小结(5 分钟热复盘:刚才哪里卡住了);中场休息(控制组调整、观察员整理笔记、参与者喘息——疲劳会显著降低响应质量与安全性);收尾会(30 分钟)——宣布演练结束、确认所有注入已清理、系统回归稳态(第 5 章的恢复验证脚本在此强制执行)、收集参与者的即时感受。通信纪律:专用频道分层——控制组频道(剧本与注入操作,响应组不可见)、作战室频道(响应组的诊断与决策,观察员静默旁听)、全员频道(演练状态公告、中止令发布);语音桥常开(关键决策口头确认,文字记录的延迟与歧义在高压下被放大);中止口令标准化(「HOLD HOLD HOLD」全频道广播,所有操作立即冻结,等待总指挥裁决——这个口令必须在开场会演练一次)。态势感知:控制组维护「演练状态板」(当前场景、注入状态、系统稳态、响应组进展、时间线),实时可见——大半径演练中控制组对全局的掌握是安全的前提,状态板失去更新(控制组忙不过来)本身就是中止信号。

复盘(debrief)是游戏日价值兑现的环节,结构化方法决定复盘质量。时间选择:演练结束后 48 小时内(记忆新鲜)+ 演练当日的热复盘(每场景 5 分钟即时记录)。参与者:全体(控制组、响应组、观察员、记录员)+ 相关团队代表;人数超过 15 人时分组复盘再合并。结构化的四段议程:(1)时间线回放(30 分钟)——记录员主导,按时间线走一遍关键事件:故障注入时刻、首个告警时刻、响应组开始诊断时刻、正确定位时刻、止血完成时刻、稳态恢复时刻;每个间隔都是度量(检测延迟、诊断时长、止血时长),与预期对比的偏差是讨论焦点。(2)三维发现收集(45 分钟)——系统维度(架构弱点、配置问题、容量不足)、组织维度(流程缺陷、技能缺口、协作摩擦)、工具维度(监控盲区、runbook 失效、权限障碍);用便利贴/在线白板匿名收集再聚类,确保心理安全(组织维度的发现最容易触发防御心理)。(3)亮点确认(15 分钟)——什么做得好也要显式记录:某个工程师的快速直觉、某个 runbook 的精准有效、某次跨团队的无缝接力;亮点是文化的种子,复盘只找问题会让演练变成批斗会。(4)行动项生成(30 分钟)——每个发现转化为具体行动项:负责人、截止日期、验收标准;行动项分三类——修复类(弱点修复)、流程类(runbook 更新、权限调整)、演练类(本次未验证完的场景进入下次计划)。无指责原则的执行细节:语言规范(「流程没有提供 X」而非「某人忘了 X」)、发现归属到系统而非个人、行动项的负责人是「修复的 owner」而非「问题的责任人」——这三个规范由总指挥在复盘开场时显式声明。

行动项的闭环跟踪:游戏日的价值半衰期取决于跟进纪律。常见失败模式:复盘会气氛热烈、行动项列了三十条、三个月后没人记得——下次演练重复发现同样的问题,组织对演练的信任逐渐流失(「演练就是走形式」)。闭环机制:(1)行动项入库——演练结束一周内,全部行动项录入工单系统,带统一标签(gameday-2024Q4),P0 项(安全相关、重大弱点)有明确 SLA(两周内修复)。(2)双周检查——演练负责人在团队例会上过一遍行动项状态,卡住的项升级讨论(资源不足?优先级冲突?技术障碍?)。(3)复验绑定——修复类行动项的关闭条件是「对应场景的复验通过」:修复了缓存雪崩问题,就要重跑缓存雪崩场景(可以缩小半径用自动化实验复验);没有复验的修复是声明而非事实。(4)下次演练开场回顾——每次游戏日的开场会第一项议程是「上次行动项完成情况」,公开透明——这个仪式感设计让「行动项会被检查」成为组织预期。(5)年度审计——一年一次全面审计:历次演练的行动项完成率、复验通过率、重复发现率(同一问题在多次演练中重复出现 = 闭环失效的强信号)。度量游戏日 ROI 的指标:行动项完成率(目标 >80%)、演练发现弱点数与其中 P0 占比、真实事故中「演练覆盖过的场景」的 MTTR 对比(演练过的场景响应显著更快是最有说服力的价值证据)、组织参与度(自愿参加人数与部门的扩展趋势)。

Google DiRT 的借鉴:大规模演练的组织技术。DiRT(Disaster Recovery Testing)从 2008 年开始,发展为 Google 的年度全公司演练,规模可达数千人参与、模拟全球基础设施灾难。可借鉴的机制:(1)演练的「合法性建设」——DiRT 由高层显式授权并参与(高管在演练中扮演角色,如模拟「CEO 要求每小时通报」),演练不是工程团队的自娱自乐而是公司级活动;这解决了大半径演练的授权难题。(2)场景的想象力边界——DiRT 模拟过:数据中心被洪水淹没、核心服务(如 Chubby/Borg)全球失效、关键工程师集体「失联」(模拟度假季 + 手机故障)、甚至「山景城总部物理损毁」;这些极端场景的价值不在发生概率而在压力测试组织的深层假设——「如果只有 30% 的资深工程师在线,我们的响应能力如何?」(3)「演练中发现真实问题」的常态——DiRT 历史上多次在演练期间暴露真实的严重缺陷(备份恢复流程实际耗时是文档声称的十倍、某「多活」服务切换后数据丢失),Google 的经验是演练发现的问题严重度随演练规模与真实度上升——小演练发现小问题,大演练发现大问题,这正是大半径演练不可替代的原因。(4)演练文化的沉淀——DiRT 的报告在 Google 内部广泛传播,「你参加过哪次 DiRT」成为工程师的共同记忆与谈资;演练从「任务」变成「传统」,这是组织韧性文化的最高形态。(5)安全体系的成熟度——数千人参与的演练零重大事故,靠的是分层授权、独立安全官、秒级中止、以及「演练期间真实事故优先」的全局规则(第 6 章调度器的真实事故让路机制在组织层面的对应物)。

游戏日的安全体系:大半径演练的风险管理比日常实验严格一个量级。安全设计的五层:(1)授权层——演练计划(场景、半径、时间窗、中止预案)获得工程高管的书面批准;批准的意义不仅是权限,更是「组织知情」:演练期间出现的用户影响(即使受控)不会引发「谁允许你们这么干」的事后追责。(2)预检层——演练前 48 小时与 1 小时各执行一次预检查清单:系统处于稳态基线、无进行中的真实事故、无冲突的重大变更(发布冻结生效)、备份新鲜度验证、中止手段逐项测试(回滚脚本真的跑一遍)、值守力量确认(演练窗口内关键角色在线);任何一项不满足,演练推迟——「推迟演练」的决定本身是安全文化的体现,应当被表扬而非视为失败。(3)执行层——安全官的独立中止权、HOLD 口令、控制组对注入状态的实时掌握、真实事故优先规则(演练期间监控系统检测到非演练引起的异常,立即暂停演练并转入真实响应——演练让位于现实的机制必须自动化程度足够高,不能依赖人工判断的及时性)。(4)半径层——即使是游戏日,爆炸半径依然渐进:AZ 级演练先在流量最小的 AZ 做、区域切换演练先切非核心服务、首次执行的场景半径减半。(5)复盘层——安全事件(演练中的意外、接近失控的时刻)在复盘中优先讨论,near miss 的分析价值高于成功场景——「差点出事」的时刻精确标定了安全体系的边界。真实教训的引用:业界发生过多起「演练引发真实事故」的案例(某公司演练中回滚脚本因权限变更失效、某公司演练流量转移触发未预料的容量瓶颈),共同根因几乎都是预检层的遗漏——中止与回滚手段「以为可用」而未实测。

游戏日的频率、规模与组织节奏设计。频率的权衡:太频繁(每月)——组织疲劳、准备成本压垮团队、场景库枯竭导致重复;太稀疏(每年)——技能与流程的生疏速度快于演练频率(人员流动、系统变化让半年前的演练经验部分失效)。经验值:全组织大演练每年 1-2 次,部门级中型演练每季度 1 次,团队级小型演练(半天、单场景)每月或每双月 1 次——三层节奏嵌套,大演练验证组织协同,小演练保持技能热度。规模设计:小型(5-10 人,半天,单团队场景)→ 中型(20-50 人,一天,跨团队场景)→ 大型(百人级,两天,全组织场景 + 高管参与 + 对外沟通模拟)。时间窗选择:避开业务高峰季(电商避开大促月)、避开周五与节假日前(响应力量薄弱)、选择真实工作时段(凌晨演练测不出白天的组织行为——但凌晨故障的真实响应可以在半开放演练中用「模拟凌晨」的角色设定部分覆盖)。演练日历的年度规划:Q1 小型(新财年团队磨合)→ Q2 中型(验证 Q1 行动项)→ Q3 大型(年度旗舰演练)→ Q4 小型(复盘与明年规划);每次演练的场景与上次行动项复验绑定,形成「演练-修复-复验-深化」的年度螺旋。新组织的冷启动路径:第一次游戏日选「低风险高教育价值」场景(单服务实例失效 + 完整响应流程演练),目标不是发现深层弱点而是建立流程肌肉记忆与文化基调——第一次演练的体验决定了组织对演练的长期态度。

游戏日与自动化混沌的协同演进:两个体系不是并列关系而是流水线关系。协同的四个机制:(1)场景下沉——游戏日验证过的场景,其系统韧性部分(不含组织维度)转化为自动化实验进入日常套件:游戏日演练了「Redis 集群主节点失效」,发现并修复了两个弱点,修复后该场景的自动化版本(小半径、每日运行)防止回归——游戏日是场景的「孵化器」,自动化是场景的「守护者」。(2)疑点上浮——自动化实验发现的「可疑但无法归因」的异常(统计上显著但机制不明、小半径下无法复现的临界行为)升级为游戏日议题:大半径与人工深度参与提供自动化缺失的观测与判断能力。(3)能力分工的动态调整——随着可观测性与自动化成熟度提升(第 7、9 章),越来越多原本需要游戏日人工判断的验证可以自动化,游戏日的重心持续向「组织韧性」与「大半径涌现行为」集中——这个迁移本身是混沌工程成熟度的标志。(4)人员与知识的流动——游戏日的控制组经验(场景设计、安全管理)反哺自动化实验的设计质量,自动化实验的数据分析能力(统计判定、归因工具)提升游戏日的复盘深度;参与过游戏日的工程师设计自动化实验时天然更有「真实故障」的画面感。组织上的协同:游戏日与自动化平台由同一团队(或紧密协作的两个团队)负责,共享场景库/变量库(第 4 章)与稳态假设体系(第 3 章)——两套体系的基础设施复用度越高,边际成本越低,演进越协同。

代码示例

/* 示例 1:游戏日策划文档模板——演练的「设计图纸」 */
/* gameday-2024q4-plan.md */
# 2024 Q4 全组织游戏日策划案

## 基本信息
- 日期窗口:2024-11-21(周四)09:00-17:00(预检 07:00 开始)
- 规模:中型(预计 35 人:控制组 5、响应组 18、观察员 8、记录 2、安全官 1、总指挥 1)
- 剧本开放度:第二档(响应组知晓窗口,不知晓场景)
- 授权状态:CTO 书面批准(链接);发布冻结 11-20 18:00 至 11-21 18:00

## 验证目标(每个目标对应至少一个场景)
1. 系统:AZ-B 完全失效时,核心交易链路在 10 分钟内恢复稳态
2. 系统:Redis 缓存集群雪崩时,数据库保护层(限流+熔断)有效
3. 组织:值班团队对 P0 事故的指挥链建立时间 < 10 分钟
4. 组织:跨团队(交易/基础设施/客服)通信协议在压力下可执行
5. 工具:runbook DB-FAILOVER-01 可被非数据库专家照做执行

## 场景序列
| 时间 | 场景 | 半径 | 注入方式 | 中止条件 |
|------|------|------|---------|---------|
| 09:30 | S1: 单服务实例失效(热身) | 单 Pod | Chaos Mesh PodChaos | 稳态偏离>2% 持续 1min |
| 11:00 | S2: Redis 主节点失效 + 缓存雪崩 | 缓存集群 | 手动 failover + 缓存清空 | DB 连接数>80% 或成功率<98% |
| 14:00 | S3: AZ-B 网络隔离 | 单 AZ | 网络策略注入 | 全局稳态偏离>1% |
| 15:30 | S4: 意外注入(控制组临场决定) | 视 S3 进展 | - | 继承 S3 |

## 角色名单与通信
- 总指挥:@王工(SRE 负责人);安全官:@李工(基础设施总监,独立中止权)
- 控制组频道 #gd-control(响应组不可见);作战室 #gd-warroom;语音桥链接
- 中止口令:HOLD HOLD HOLD(全频道广播,所有操作冻结)

## 预检查清单(T-48h 与 T-1h 各执行一次)
- [ ] 全系统稳态基线正常(仪表盘链接)
- [ ] 无进行中真实事故、无未完成的重大变更
- [ ] 回滚手段逐项实测:AZ 流量切回脚本、Redis 主从恢复、网络策略删除
- [ ] 备份新鲜度验证(最近一次全量备份可恢复性抽检)
- [ ] 值守确认:响应组全员、DBA、网络工程师窗口内在线
- [ ] 客服团队知情:演练窗口的用户咨询口径已同步
这份策划案展示了游戏日设计的完整要素,每个部分都有明确的方法论依据。验证目标的设计遵循「系统 + 组织 + 工具」三维覆盖——目标 3、4、5 是纯组织/工具维度,它们无法被自动化实验验证,正是游戏日存在的理由;每个目标可判定(「< 10 分钟」「可被非专家照做执行」),演练后能明确回答「达成与否」。场景序列的梯度设计:S1 热身(建立节奏与信心,验证基础流程)→ S2 中等复杂度(跨组件级联,多团队协作开始必要)→ S3 大半径(AZ 级,本次演练的核心验证)→ S4 意外注入(训练适应性,控制组根据 S3 的实际进展临场设计——如果响应组在 S3 表现从容,S4 加压;如果 S3 已经暴露大量问题,S4 简化)。中止条件逐场景定义且量化,S2 的「DB 连接数 >80%」是典型的「领先指标中止」——不等稳态击穿,在级联的早期信号出现时就中止。预检查清单中「回滚手段逐项实测」与「客服知情」两项最容易被省略也最不能省略:前者对应业界多起演练事故的根因(回滚手段失效),后者对应大半径演练的用户影响管理(即使受控,部分用户可能感知到抖动,客服无准备会放大事件)。
/* 示例 2:AZ 级网络隔离的注入与回滚——游戏日大场景的技术实现 */
/* 注入:用 Kubernetes NetworkPolicy 隔离 AZ-B 的所有 Pod(模拟 AZ 网络失效) */
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: gameday-az-b-isolation
  namespace: production
spec:
  podSelector:
    matchLabels:
      topology.kubernetes.io/zone: az-b
  policyTypes: [Ingress, Egress]
  /* 空的 ingress/egress 规则 = 默认拒绝所有跨 Pod 流量 */
  ingress: []
  egress: []
---
/* 回滚:删除 NetworkPolicy(预检时实测过删除耗时 < 5s,流量恢复 < 60s) */
/* kubectl delete networkpolicy gameday-az-b-isolation -n production */

/* 配套的安全护栏:隔离范围外的稳态监控 + 自动回滚触发器 */
/* az-isolation-guard.sh */
/* 每 15 秒检查全局稳态;偏离超过 1% 持续 1 分钟,自动删除隔离策略 */
/* 自动回滚独立于控制组人工操作——即使作战室混乱,护栏依然生效 */
这个 AZ 隔离方案展示了游戏日大半径场景的「受控实现」技术。选择 NetworkPolicy 而非真实网络层操作(交换机 ACL、云厂商路由变更)的理由:声明式(一个 YAML 定义完整隔离语义)、秒级生效与回滚(对比网络设备变更的分钟级与人工风险)、精确范围(按 zone 标签选择,不误伤其他 AZ)、可审计(资源在集群中可见,状态明确)。空的 ingress/egress 数组实现「默认全拒」——AZ-B 的 Pod 之间、与外部的一切网络通信中断,等效于 AZ 级网络分区;注意这与「AZ 断电」有差异(Pod 进程还在运行、kubelet 还在上报状态),如果要模拟更彻底的 AZ 失效,需要组合 Node 级操作(kubelet 停止、节点关机)——场景设计时要明确「模拟到什么真实度」,真实度越高价值越大风险也越大。配套护栏是安全体系的技术落地:自动回滚触发器独立运行(第 5 章三层防线思想),即使控制组在作战室的紧张中反应迟缓,全局稳态偏离 1% 持续 1 分钟就自动解除隔离——大半径场景的护栏阈值(1%)比日常实验(2%)更保守,因为 AZ 级故障的级联速度更快,留给人的反应窗口更短。预检清单中「实测删除耗时与流量恢复时间」的意义:回滚的「秒级」是实测数字而非文档声明,恢复期的流量回涌(AZ-B 重新可达时积压请求的冲击)是否引发二次问题,也在预检的小规模试跑中验证。
/* 示例 3:游戏日时间线记录模板——复盘的权威素材 */
/* gameday-timeline.md(记录员实时维护,节选 S2 场景) */

| 时间 | 事件类型 | 内容 | 来源 |
|------|---------|------|------|
| 11:00:00 | 注入 | 控制组执行 Redis 主节点 failover + 缓存清空 | 控制组频道 |
| 11:00:34 | 系统 | cache_hit_rate 从 94% 跌至 12%(Grafana 截图 #12) | 监控 |
| 11:01:10 | 告警 | RedisLatencyHigh 触发,送达 #alerts-trade | Alertmanager |
| 11:01:15 | 告警 | DBConnectionsSaturation 触发(领先指标,距中止阈值 80% 还有余量) | Alertmanager |
| 11:02:40 | 响应 | 值班工程师 A 在作战室确认告警,开始查看 Redis 面板 | 作战室频道 |
| 11:03:55 | 响应 | A 判断「Redis 有问题」,呼叫 DBA(电话,2 分钟无人接) | 作战室频道 |
| 11:05:20 | 系统 | DB 连接数达 71%(阈值 80%),order-service P99 从 200ms 升至 3.4s | 监控 |
| 11:06:02 | 决策 | A 决定执行 runbook CACHE-STORM-02(数据库限流),开始查找 runbook 位置 | 作战室频道 |
| 11:08:47 | 摩擦 | A 在 wiki 搜索 runbook 未果,询问控制组外的同事,最终在 Confluence 旧空间找到(耗时 2m45s) | 观察员笔记 |
| 11:09:30 | 响应 | 限流生效,DB 连接数开始回落 | 监控 |
| 11:11:15 | 恢复 | cache_hit_rate 回升至 60%,稳态指标回归阈值内 | 监控 |
| 11:12:00 | 控制 | 总指挥宣布 S2 止血完成,进入恢复观察期 | 语音桥 |

/* 关键间隔度量(自动从时间线计算):
   注入→首个告警: 70s | 告警→响应开始: 85s | 响应→正确决策: 4m50s
   决策→执行完成: 3m28s(其中 runbook 查找 2m45s = 79%)| 注入→稳态恢复: 11m15s */
这份时间线记录展示了游戏日复盘素材的黄金标准:多源、精确、结构化。三类事件源交叉记录——系统事件(监控指标的客观变化)、组织事件(响应组的动作与决策)、控制事件(注入与指挥),每条带精确时间戳与来源,复盘时任何争议(「当时到底过了多久才有人响应?」)都有权威答案。记录员的操作要点:实时记录而非事后补记(事后记忆的时间误差以分钟计,而演练的关键度量恰恰是分钟级间隔)、原始引用(作战室的原话、告警的原文,不做转述加工——转述会丢失「A 说 Redis 有问题」与「A 说缓存命中率跌了」之间的诊断质量差异)、截图归档(Grafana 面板在关键时刻的快照,指标形态是复盘机制分析的证据)。底部的关键间隔度量是时间线的直接价值:本例中「决策→执行完成 3m28s,其中 runbook 查找占 2m45s(79%)」这个分解精确指出了改进方向——不是工程师能力问题(决策只用了不到 5 分钟且正确),而是知识管理问题(runbook 放在没人找得到的旧空间);对应的行动项是「runbook 集中化 + 告警消息内嵌 runbook 链接」,可验证、可复测。这份时间线同时是「事故记录规范」的训练素材:真实事故的复盘质量同样取决于时间线质量,游戏日让团队在低压环境下养成记录肌肉记忆。
/* 示例 4:演练状态板——控制组的全局态势工具 */
/* exercise-status-board.py - 实时状态板(终端 UI 或 Web 页面) */
/* 状态板数据结构 */
STATUS_BOARD = {
  "exercise": "GD-2024Q4",
  "phase": "S2-执行中",              /* 当前场景与阶段 */
  "elapsed": "00:42:15",
  "injections_active": [
    {"id": "redis-failover", "since": "11:00:00", "rollback": "kubectl delete -f redis-failover.yaml", "rollback_tested": "11-19 预检通过"},
    {"id": "cache-flush", "since": "11:00:05", "rollback": "自动(TTL 重建)", "rollback_tested": "N/A-自愈型"}
  ],
  "system_steady_state": {
    "global": {"status": "VIOLATED", "detail": "成功率 97.2% (红线 98%)", "since": "11:04:50"},
    "guard_armed": True,               /* 自动护栏状态:armed = 偏离超阈值将自动回滚 */
    "guard_threshold": "成功率<98% 持续 60s → 自动执行全部 rollback"
  },
  "players_status": {
    "oncall_primary": "响应中(作战室活跃)",
    "dba": "已被呼叫,未接听(第 2 次呼叫中)",
    "incident_commander": "未指定 ← 观察员标记:指挥链未建立(目标 3 验证点)"
  },
  "injects_pending": ["S2-inject-1: 15 分钟后追加 DB 慢查询(若响应组已稳定)"],
  "safety_flags": []                   /* 安全官标记的风险项,非空时总指挥必须处理 */
}
/* 更新纪律:控制组每 5 分钟核对一次状态板与实际的一致性;
   状态板失去更新本身是中止评估信号(控制组过载 = 演练超出可控范围) */
这个状态板工具是控制组态势感知的核心,它回答大半径演练中控制组必须随时掌握的六个问题:现在在哪个阶段?哪些注入还活着、怎么回滚、回滚验证过吗?系统稳态如何、护栏是否武装?响应组的状态(谁在响应、谁失联、指挥链建立了没)?下一个计划注入是什么、触发条件满足了吗?安全官有没有标记风险?几个设计细节体现演练安全工程:injections_active 中每个注入都带 rollback 命令与 rollback_tested 状态——「回滚手段已实测」不是预检清单上的一次性勾选,而是持续可见的状态(预检后如果环境变化,测试状态可能过期);guard_armed 显式展示自动护栏的武装状态与触发条件,控制组任何时候都知道「如果人工反应不及,自动防线会在什么条件下接管」;players_status 里的「incident_commander: 未指定」由观察员标记——这既是演练目标 3(指挥链建立时间)的实时验证数据,也是控制组决策「是否投放下一个 inject」的输入(响应组还没建立指挥,追加压力可能超出训练价值变成纯粹压垮);safety_flags 的「非空必须处理」规则给安全官的独立中止权提供了结构化的表达通道。状态板可以用简单技术实现(共享文档、终端 UI、内部 Web 页),关键不在工具形态而在更新纪律——「状态板失去更新 = 控制组过载 = 中止评估信号」这条元规则把工具健康度纳入了安全体系。
/* 示例 5:复盘发现的结构化入库——从便利贴到可跟踪资产 */
/* debrief-findings.yaml - S2 场景复盘产出(节选) */
findings:
  - id: GD24Q4-S2-F01
    dimension: tooling            /* system | organization | tooling */
    severity: P1
    title: "runbook CACHE-STORM-02 存放位置不可发现,查找耗时 2m45s"
    evidence:
      timeline_ref: "11:06:02-11:08:47"
      observer_note: "响应者在 wiki 与 Confluence 间反复搜索,最终靠询问他人找到"
    impact_analysis: "真实事故中该延迟直接延长止血时间;本次演练中占决策-执行间隔的 79%"
    action:
      type: fix
      description: "runbook 集中到 ops-runbooks 仓库;Alertmanager 告警模板增加 runbook_url 注解"
      owner: "@张工(SRE 工具组)"
      due: "2024-12-05"
      verification: "重跑 S2 缩小版(自动化实验),测量告警到执行间隔 < 90s"
  - id: GD24Q4-S2-F02
    dimension: organization
    severity: P2
    title: "DBA 呼叫两次未接听,升级路径未自动触发"
    evidence:
      timeline_ref: "11:03:55"
    impact_analysis: "关键角色失联时响应组等待而非升级,指挥链建立延迟"
    action:
      type: process
      description: "PagerDuty 升级策略调整:DBA 2 分钟未响应自动升级至备份 DBA 与 SRE 经理"
      owner: "@王工(值班体系)"
      due: "2024-11-30"
      verification: "下次演练 S2 场景注入「DBA 失联」inject 验证升级自动触发"
  - id: GD24Q4-S2-F03
    dimension: system
    severity: P1
    title: "缓存清空后 DB 限流阈值(80%连接数)触发前,order-service P99 已劣化 17 倍"
    evidence:
      timeline_ref: "11:05:20"
      dashboard_snapshot: "#14"
    impact_analysis: "中止条件依赖的领先指标(连接数)滞后于用户体验劣化(P99)"
    action:
      type: fix
      description: "S2 中止条件增加 P99 维度(>1s 持续 30s);缓存层增加单飞(singleflight)防击穿"
      owner: "@刘工(交易架构)"
      due: "2024-12-20"
      verification: "自动化缓存雪崩实验(小半径)验证 P99 劣化 < 3 倍"
这份结构化复盘产出展示了游戏日发现如何转化为可跟踪、可验证的工程资产。三个 finding 恰好覆盖三个维度,各自体现该维度发现的典型形态。工具维度(F01):证据链完整(时间线引用 + 观察员笔记),影响分析量化(占决策-执行间隔 79%),行动项的 verification 字段定义了「修复有效」的可测量标准——重跑缩小版场景并测量间隔 < 90s,把「runbook 好找了」从主观感受变成可复验指标。组织维度(F02):语言严格遵守无指责规范——「升级路径未自动触发」而非「DBA 没接电话」(后者是个人归因,前者是体系归因;DBA 未接听在真实世界有无数正当理由,体系的职责是让单点失联不阻塞响应);verification 设计巧妙——下次演练主动注入「DBA 失联」验证升级机制,组织流程的修复同样用演练复验。系统维度(F03):这是只有大半径演练才能发现的深层问题——中止条件依赖的连接数指标滞后于用户体验劣化 17 倍,意味着按原中止条件,护栏触发时用户已经历了严重的体验灾难;行动项同时修护栏(P99 维度)与修系统(singleflight 防缓存击穿),verification 用自动化小半径实验复验——大演练发现、小实验守护的协同模式(keyPoints 中「场景下沉」的具体体现)。severity 分级驱动 SLA(P1 两周、P2 四周),owner 到人,due 到日——这份 YAML 直接导入工单系统生成带标签的行动项,双周检查会议消费同一份数据。
/* 示例 6:游戏日场景的自动化下沉——从演练到日常回归 */
/* S2 场景验证通过后,其系统韧性部分下沉为自动化实验 */
apiVersion: chaos-mesh.org/v1alpha1
kind: Schedule
metadata:
  name: cache-storm-regression
  namespace: chaos-automation
  labels:
    suite: trade-resilience
    origin: "GD-2024Q4-S2"        /* 溯源:来自哪次游戏日 */
    tier: P0
spec:
  schedule: "30 3 * * 2,5"        /* 每周二、五凌晨运行 */
  concurrencyPolicy: Forbid
  type: StressChaos
  stressChaos:
    duration: "120s"
    mode: one
    selector:
      labelSelectors: { app: redis, role: primary }
    stressors:
      cpu: { workers: 2, load: 80 }   /* 简化版:用 CPU 压力模拟 Redis 劣化而非完整 failover */
    statusCheck:
      http:
        url: "http://prometheus:9090/api/v1/query?query=(orders:success_rate:5m>0.99)and(experiment:target_latency:p99{service='order-service'}<1)"
        criteria: { statusCode: "200", response: '"result":[{' }
      failureThreshold: 3
      periodSeconds: 10
这个 Schedule 展示了「场景下沉」的完整实践:游戏日 S2(Redis 主节点失效 + 缓存雪崩)验证通过、弱点修复后,其系统韧性部分转化为每周两次的自动化回归实验。下沉过程中的三个工程决策值得学习。第一,场景简化:自动化版本用 CPU 压力模拟 Redis 劣化,而非完整的主从 failover + 缓存清空——完整场景的半径与恢复复杂度不适合无人值守运行(failover 涉及数据一致性风险,缓存清空对数据库的冲击在生产每日运行成本过高);简化的原则是「保留场景的核心压力机制(缓存层服务能力下降 → 数据库穿透压力),去除高风险与高成本的操作」,下沉不是复制而是提炼。第二,判定条件继承演练发现:statusCheck 同时检查成功率(>99%)与 order-service P99(<1s)——P99 维度正是 F03 发现「连接数指标滞后于体验劣化」后新增的,游戏日的教训直接编码进自动化判定,这是「知识沉淀」的具体形态。第三,元数据溯源:labels 中的 origin: GD-2024Q4-S2 让每个自动化实验可追溯到它的演练源头——半年后有人问「这个奇怪的 StressChaos 为什么存在」,label 直接给出答案与完整的历史语境(关联的复盘报告、发现的弱点、修复的工单)。每周二、五的频率选择:缓存雪崩是 P0 场景但简化版风险低,双频运行在回归防护的及时性与集群资源成本间平衡。下沉的完成标志:这个实验连续通过一个月后,下次游戏日的 S2 可以升级为更复杂的变体(演练体系与自动化体系螺旋深化)。

实验笔记

【演练目标】策划并执行一场半天的小型游戏日(5-8 人规模),完整走完「策划 → 预检 → 执行 → 时间线记录 → 复盘 → 行动项 → 场景下沉」的全生命周期。演练的价值不在规模而在完整性——一场流程完整的小演练,教育价值远超一场走过场的大演练。

【环境准备】Kubernetes 集群 + Online Boutique + 完整监控栈 + Chaos Mesh + 前几章的全部产出(稳态假设、变量库、护栏、作战面板、告警验证)。人员:至少 5 人——总指挥 1、控制组 1-2、响应组 2-3(真正的被试者,对场景不知情或半知情)、观察员/记录员 1(可兼任)。若人数不足,可与搭档轮流扮演角色,或用「延迟知情」模拟(响应者在场景注入时刻才被告知)。

【演练步骤】第一阶段·策划(90 分钟,演练前一周完成):按示例 1 模板撰写策划案——确定 2-3 个验证目标(至少一个组织维度目标,如「runbook 可发现性」或「指挥链建立时间」)、设计场景序列(热身场景 + 核心场景 + 可选的意外注入)、分配角色、定义每场景的中止条件、编写预检查清单。策划案交搭档(扮演总指挥/安全官)评审,重点挑战:中止条件可执行吗?回滚手段实测过吗?组织目标可度量吗?第二阶段·预检(30 分钟,演练当日开始前):逐项执行预检清单——系统稳态基线确认、回滚脚本实际运行一遍(在镜像环境)、通信频道建立并测试、HOLD 口令全员演练一次、状态板(示例 4 简化版,共享文档即可)初始化。第三阶段·执行(120 分钟):开场会(10 分钟,宣布规则与口令)→ S1 热身场景(30 分钟:单服务实例失效,响应组完整走一遍告警响应流程)→ 热复盘(5 分钟)→ S2 核心场景(45 分钟:建议选「缓存劣化 + 数据库压力」或「依赖服务慢响应级联」,控制组按剧本注入,响应组真实诊断与止血,观察员记录组织行为,记录员维护时间线)→ 意外注入(若 S2 进展顺利,控制组追加一个计划外故障)→ 恢复验证(15 分钟:运行第 5 章的恢复验证脚本,确认无注入残留、稳态回归)。第四阶段·复盘(60 分钟,当日或次日):按四段议程执行——时间线回放(对照示例 3 计算关键间隔度量)、三维发现收集(匿名便利贴 → 聚类)、亮点确认、行动项生成(按示例 5 格式结构化,每项有 owner/due/verification)。第五阶段·跟进(演练后一周内):行动项录入工单系统;选择 S2 场景的系统韧性部分,按示例 6 设计下沉的自动化实验并部署运行。

【预期结果】完整的游戏日档案:策划案(含评审记录)、预检清单(含实测证据)、时间线记录、复盘报告(三维发现 + 亮点 + 行动项)、行动项工单、下沉的自动化实验定义。典型发现预告:runbook 找不到或过期、告警文案无法指导行动、值班权限不足、指挥链建立迟缓、时间线记录中断(记录员被拉去帮忙——这本身是发现)、回滚脚本因环境差异失败(预检的价值证明)。

【进阶挑战】(1)难度升级:下次演练引入第三档(无预告)元素——响应组只知「本月有演练」不知具体时间,测量真实响应延迟;(2)组织压力注入:S2 进行中模拟「关键专家失联」(响应组一人的手机被控制组保管 15 分钟),验证升级路径;(3)对外沟通模拟:增加一个角色演练「向管理层通报」——每 15 分钟写一份三句话的态势通报,复盘时评估通报质量(准确吗?及时吗?非技术人员能懂吗?);(4)跨团队扩展:邀请另一个团队的服务纳入场景(级联跨团队边界),演练团队间的信息同步与协作决策;(5)年度规划:基于本次演练经验,写出未来四个季度的演练日历(频率、规模递进、场景深化路线、与自动化套件的协同计划)。

延伸阅读

  • 《Chaos Engineering: System Resiliency in Practice》第 11 章——本书关于游戏日的原始论述,包含 Alaska Airlines 与 Netflix 的演练案例细节:传统企业如何从零策划第一场游戏日、演练如何改变组织对故障的认知。
  • Google SRE Workbook 第 22 章 "Addressing Cascading Failures" 与 DiRT 相关章节,及论文/文章 "Disaster Recovery Testing (DiRT) at Google"——Google 大规模演练的权威记录:演练的演进史、极端场景设计(总部损毁、关键人员失联)、数千人规模的组织技术,是大半径演练的最高参照系。
  • 《The Phoenix Project》与《The Unicorn Project》(Gene Kim)——小说形式的 DevOps 叙事,其中对「组织如何在压力下学习」的描写与游戏日的文化目标深度共鸣;比方法论文件更能让管理层理解演练的组织价值。
  • PagerDuty 官方 "Failure Injection" 与 "Game Day" 指南(response.pagerduty.com)——事故响应框架下的演练操作手册:角色定义、通信协议、复盘模板与本章高度对齐,可直接作为演练日的流程底稿。
  • Netflix Tech Blog: "Project Waterbear: Netflix's Resiliency Testing Program"——Netflix 的区域级演练与韧性测试项目披露,包含大半径演练的授权机制、安全体系与高管参与模式。
  • Gremlin "Game Day Playbook"(免费电子书)——混沌工程商业公司整理的游戏日实操手册:策划清单、角色卡片、复盘引导问题集,模板化程度高,适合首次演练直接取用。
  • 《Team Topologies》(Matthew Skelton)第 5-7 章——团队认知负荷与协作模式理论,为游戏日的「组织维度发现」(跨团队摩擦、职责边界模糊)提供分析框架,让组织类行动项的设计更有理论依据。
  • SREcon 历年 "Game Day" 主题演讲合集(USENIX 视频库)——多家公司(Dropbox、Slack、Shopify)的演练实践分享,不同规模与文化背景下的变体设计,是场景库与流程设计的灵感来源。
8/12游戏日演
0%