你遇到过这种诡异故障吗?所有服务健康检查都是绿的,但用户就是访问不了,流量凭空消失了。我合作过的一个团队就栽在这样一件事上:为了合规,他们把公网入口负载均衡器的 TLS 协议从 1.2 升到了 1.3(TLS 是加密网络流量的协议,版本越高越安全)。升级过程毫无异常,握手完成、服务健康、指标平稳,没有任何告警。但问题是,AWS 的 Route 53 健康检查(用来探测服务器是否存活的机制)当时只支持 TLS 1.2,一旦你禁用了 1.2 只保留 1.3,健康检查请求就无法完成握手,直接把该区域标记为不健康。CDN 看到区域不健康,就停止往这个区域分发流量了。区域内部一切正常,服务在跑、负载均衡器健康、应用照常响应请求、仪表盘没有任何异样,唯一的症状就是流量不再进来。用户被透明地路由到数千公里外的另一个区域,延迟飙升,那个区域被迫在没准备好的情况下扩容。合成监控(模拟用户访问的探测工具)最终暴露了问题,但定位真相花了约四十分钟。故障根本不在应用数据平面(实际处理用户请求的部分),而是在控制平面(决定流量往哪走的决策层)。

这个故事把高可用(High Availability)和韧性(Resilience)的差别血淋淋地撕开了。大多数团队把这两个词混着用,但它们根本是不同的问题。高可用关注在预期故障下保持服务不中断,比如一个实例崩溃、一个可用区(AZ,一个数据中心集群)挂掉、依赖超时——这些场景架构早就考虑到了。而韧性关注的是应对系统从未被显式设计过的意外状况。高可用可以用百分比衡量:正常运行时间、切换时长、复制延迟。韧性却很难量化,很多故障模式只有在真实压力下才会冒出来,而有意去复现这些故障往往太贵、太危险。

作者从那次事故中总结出三个让高可用和韧性脱节的模式。第一是冗余之间的相关故障(Correlated Failures)。传统 HA 会考虑整个可用区同时挂掉的场景,却容易忽略软件层面的相关故障:一个坏配置同步推到了所有副本、一个毒缓存记录被每个读副本同时读到、一次依赖升级悄悄破坏了整个系统依赖的某个接口。当独立性在软件层断裂,冗余就不再是保险。第二是优雅降级(Graceful Degradation)只是假设。多数系统都认为自己能在压力下降级得优雅,但几乎没有在真实负载下被验证过。当读副本在压力下落后时,缓存层是在吸收压力还是把压力放大到主库上?在真正演练之前,“优雅降级”只是一个假设,不是保证。第三是恢复路径会腐烂(Recovery Paths That Have Rotted)。系统跑了两年,重建手册写在当前一半依赖出现之前;IAM 权限(身份和访问管理)漂移了,部署工具也换了。恢复路径和其他代码路径一样,从不执行的代码路径会慢慢失效。

比架构更隐蔽的是组织问题。作者反复观察到,很多组织对可用性的所有权很清晰——谁负责 on-call(值班响应)、SLO(服务级别目标)是什么、升级渠道有哪些,但几乎没有对恢复(Recovery)的明确负责人。没有指定的恢复拥有者,没有定期的故障演练节奏,也没有随着基础设施演进持续更新手册的流程。这个空白不是故意造成的,而是没人认领时的默认状态。而真正去补这个空白很贵:测试真正重要的场景需要专门的工程时间和运营风险,还要为了可能永远不会发生的故障维护一堆专用基础设施。于是组织很容易滑向“表演式韧性”:架构图画得漂亮,备用区域存在,手册存在,但实际恢复能力是被“假定”存在,而不是被“证明”存在。这不是工程师粗心,而是严格证明它要花真金白银、承担真实风险,价值却只在最糟糕的时刻才显现。

现实中,重大事故的头三十分钟往往浪费在“依赖考古”上:大家发现权限漂移了、手册引用的工具一年前就退役了、没人清楚谁还懂备用环境。这些都不稀奇,就是普通的运维腐蚀。恢复路径因为很少被练习而逐渐退化。

解决办法并不酷,就是明确的恢复所有权,并且要和 on-call 分开。On-call 管响应,恢复所有权管准备:准备过程、工具,以及保持两者最新的责任。把它们混为一谈,你会有很棒的应急指挥官,但手册十八个月都没人打开过。恢复得好的团队把故障演练当常规工程承诺:先小范围试,一个服务、一个可用区切换。每次演练总能发现点问题——某个权限被撤销、手册过时、告警静默。这些问题只能通过实际跑流程才能找到。核心转变是:把恢复当作你需要去维护的东西,而不是架构图暗示它天然存在。

你不需要重新设计整个架构才能开始测试韧性。先问五个问题:什么会最先挂?找出你的恢复路径依赖的控制平面组件——DNS(域名解析)、身份认证、路由、证书、配置、编排或第三方服务。团队实际上会观察到什么?对每个故障场景,定义能告诉你出问题的信号。绿色的应用仪表盘不算数,如果故障发生在它之前。

Accelerating Performance by Incrementally Integrating Rust into Existing Codebas
Accelerating Performance by Incrementally Integrating Rust into Existing Codebas

讲到那次 TLS 事故,健康检查在控制平面失效,应用数据平面一切正常

Five Ways To Use AI Coding Agents to Improve Your Software Architecture
Five Ways To Use AI Coding Agents to Improve Your Software Architecture

。标准的多可用区架构应对孤立故障很有效

From Consumers to Builders: Turning 200 of our Team into Agent Creators in 2 Wee
From Consumers to Builders: Turning 200 of our Team into Agent Creators in 2 Wee

,但优雅降级往往没被实战检验过

Keeping the Mainline Green Across Diverse Language Monorepos
Keeping the Mainline Green Across Diverse Language Monorepos

。组织问题常在事故之前就暴露

Beyond Observability: Evolving Production Operations in the Age of AI
Beyond Observability: Evolving Production Operations in the Age of AI

,恢复路径需要反复演练才不会腐烂

。

这篇内容给我们的直接启发是:如果你的系统有跨区域容灾,别只盯着应用层指标,去验证 DNS、证书、IAM、路由这些控制平面依赖的健壮性。建立一个独立的恢复演练日历,哪怕每月只挑一个小场景。把恢复手册当成生产代码对待,每次基础设施变更都同步更新。韧性在复杂分布式系统里本质是概率性的,你没法保证成功,只能通过反复测试恢复路径、暴露隐藏依赖来积累信心。下次有人说“我们系统高可用”,你可以追问一句:“上次实际演练完整恢复流程是什么时候?”

阅读原文 → 返回 AI 技术文档

内容与图片版权归原作者所有 · 原文: https://www.infoq.com/articles/high-availability-not-resilience-cloud/?utm_campaign=infoq_content&utm_source=infoq&utm_medium=feed&utm_term=global