两次全球宕机之后,Cloudflare 用半年时间重建了什么
起因两次不该发生的故障2025年11月18日Cloudflare 发生了一次全球性故障。不到三周后2025年12月5日第二次全球故障接踵而至。两次事故的共同特点令人不安它们都不是由外部攻击引发的都不是硬件损坏而是内部配置变更推送到生产环境后代码在遇到非预期输入时直接崩溃没有任何兜底。一次是 Rust 服务调用了.unwrap()当数据不符合预期时直接 panic另一次是 Lua 代码访问了一个并不存在的对象。这两行代码最终导致了大量用户几乎同时失去访问 Cloudflare 服务的能力。事后Cloudflare 内部启动了一项代号为“Code Orange: Fail Small”的工程专项目标只有一个让这两次事故永远不会重演。历时约两个季度这项工作已于 2026 年初正式完成。这篇文章我们来拆解 Cloudflare 究竟做了什么以及这些改造背后的工程逻辑。根因不是某个人出了错在谈具体改造之前有必要先澄清一件事把两次故障归因于某段代码写得不好或者某次操作没审好是一种过于简单的归因。真正的问题是系统结构上的缺陷配置变更一旦发出就会瞬间推向整个网络没有中间状态可以观测服务在遇到错误输入时没有优雅降级的能力紧急情况下用于自救的工具链本身依赖于正在出故障的基础设施最佳实践存在于少数高级工程师的脑子里没有办法被系统性地执行。这不是一个代码审查能解决的问题而是一套系统性的工程改造。第一项改造配置变更不再全量即时生效在此之前Cloudflare 对配置变更的发布方式与软件发布有很大差异软件部署已经有了成熟的渐进式发布和健康监测流程但配置变更往往是一次性推送到整个网络。这个差距直接导致了两次事故的损害范围——错误配置刚一发出就已经覆盖了所有节点。Snapstone就是为了填补这个缺口而构建的内部工具。它的核心逻辑是把配置变更打包成一个可管理的单元然后像软件发布一样按波次渐进推送每一波都伴随实时的健康状态监测一旦发现异常立即自动回滚。Snapstone 的关键设计是灵活性。它不是针对某次具体故障的补丁而是一个通用框架任何团队都可以将自己负责的配置单元接入进来立刻获得渐进发布和自动回滚的能力。回溯两次故障的场景如果11月的机器学习分类器数据文件通过 Snapstone 发布系统会在早期波次就检测到读取失败自动回滚故障波及范围将仅限于极小比例的流量如果12月的全局配置标志位同样经过 Snapstone结果相同。这项改造改变的是变更发布的基础设施而不是要求工程师更小心一点。第二项改造出了问题尽量让影响范围更小光是让变更发布更安全还不够。Cloudflare 同时在推进另一项工作即使有什么东西出了问题也要让它倒得小一点。各产品团队对自己负责的关键流量路径做了全面审查核心目标是移除那些不必要的运行时依赖并为每一种可能的失败模式预先定义好行为。具体策略分为两种失效保守Fail Stale优先使用上一个已知的有效配置继续运行而不是因为读不到最新配置就停摆。失效放通 vs 失效关闭Fail Open vs Fail Close如果连旧配置也不可用则根据业务特性做选择——如果带着残缺功能继续提供服务好过完全不服务就失效放通反之则失效关闭。这个选择必须是预先审慎做出的而不是故障时临时决定的。以11月的故障为例Bot Management 的机器学习分类器读取了一个无法解析的数据文件导致服务崩溃。按照新的机制系统会优先使用旧的分类器数据继续运行如果旧数据也不可用则失效放通让流量照常通过仅仅是少了一层检测远比直接宕机要好。除了这些单服务层面的改造Cloudflare 还推进了流量分群隔离。Workers 运行时现在被切分成多个相互独立的服务实例分别处理不同用户群的流量其中一个实例专门处理免费用户的流量。新的变更从最低风险的用户群开始推送并且向低风险群推送的频率更快向高价值用户群推送的节奏更慢、更审慎。在一个七天的观测窗口里Workers 运行时的发布流程被触发超过 50 次每次都以波浪状逐步扩散前一次和后一次部署经常在时间上有所重叠。这在以前是无法想象的发布密度因为每次变更的影响范围已经被精确控制了。第三项改造打破自断手脚的困境这是两次故障中一个容易被忽视的细节Cloudflare 的内部运维工具跑在 Cloudflare 自己的网络上。这意味着当全网出现大规模故障时工程师用来排查、调试、推送修复的工具链可能跟用户看到的服务一起挂掉了。修路的铲车陷进了坑里。在 Code Orange 之前紧急的打破玻璃break glass恢复通道仅向极少数人开放工具访问能力有限并不适合大规模事故场景。改造的方向是为 18 个关键服务建立独立的备用授权和访问通道开发专用的紧急脚本和代理确保在主要工具失效时工程师仍然能够看到系统状态、执行必要的修复操作。工具建好之后Cloudflare 选择了一个重要的验证方式真实演练。在小范围团队演练之后2026年4月7日超过 200 名工程师参与了一次全工程部门的故障演练目的是让每个人在没有压力的环境下把紧急操作流程做成肌肉记忆而不是等真正的故障发生时才第一次摸到这些工具。第四项改造让最佳实践住进代码审查在两次故障之后Cloudflare 面对的一个现实问题是那些应该早就存在于代码库里的防御性写法为什么没有出现答案往往不是工程师不知道而是这些最佳实践只活在少数资深工程师的脑子里没有被系统性地执行。**工程守则Engineering Codex**就是为了解决这个问题。它是一套由领域专家通过 RFC 流程撰写和审议的工程规范文档然后被提炼成具体的、可执行的规则并接入到整个开发周期的 AI 代码审查系统中。两条具体规则可以直观说明它在做什么“不要在测试和 build.rs 以外的地方使用.unwrap()”——这条规则直接针对11月故障的根因。“服务在处理请求之前必须验证上游依赖处于预期状态”——这条规则针对更普遍的防御性编程原则。如果这两条规则在事故发生前就已经被执行相关代码会在合并请求阶段被自动标记要求额外审查而不是作为配置变更推送到生产环境引发全球故障。Codex 与 AI 审查代理深度集成覆盖从设计评审到部署的全生命周期。违规的代价从影响数百万请求的全球宕机缩小到一名开发者在合并代码前收到一条可操作的反馈。更重要的是Codex 本身是一个飞轮领域专家写 RFCRFC 提炼成规则规则进入 AI 审查故障暴露的新问题变成新的 RFC循环往复。它是有自我进化能力的制度记忆而不是一份写完就放进抽屉的文档。不只是工程问题沟通本身也是基础设施Cloudflare 在这次 Code Orange 计划中意识到故障期间的沟通能力同样需要被当作基础设施来建设。故障期间技术团队的注意力全部集中在排查和修复上对外的客户更新往往滞后、模糊有时甚至是把工程内部的技术术语直接发出去对客户没有实际帮助。改造之后Cloudflare 组建了一支专职的沟通团队在重大事故期间与技术响应团队并行工作负责将工程师的实时观察翻译成清晰的客户语言。对外更新的节奏被明确规定每 30 或 60 分钟发布一次进度即使当前没有新进展也照常发出。这个设计的目的是让客户可以根据可预期的信息节奏安排自己的工作而不是不停刷新状态页。在故障恢复之后Cloudflare 承诺提供详细的事后分析报告说明发生了什么、为什么发生、以及具体做了哪些结构性改变来防止它再次发生。这种承诺本身也是信任建立的一部分。韧性不是一个可以完成的项目Cloudflare 在博客中说了一句值得记住的话这项工作已经完成但对韧性的追求永远没有终点。这两次故障让 Cloudflare 做的事情放到任何一家运营大规模分布式系统的组织面前都有类似的参考价值配置变更与代码变更一样危险同样需要渐进式发布和健康监测。服务的每一种失败模式应该在设计阶段就被定义好行为而不是等到生产环境里第一次遇到再决定。紧急自救工具不应该依赖于正在出故障的系统而且要定期演练不能只是写在运营手册里。最佳实践需要被编码进工具和流程而不是依靠每个工程师自觉记忆。大规模故障往往不是某一个人的失误而是系统在某个假设上缺乏防御性思维的结果。Code Orange 计划做的是把假设输入永远有效这个危险的隐性假设从整个代码库里系统性地清除出去。原文来源Cloudflare Blog《Code Orange: Fail Small is complete. The result is a stronger Cloudflare network》2026 年 5 月 1 日。