你遇到过这种诡异故障吗?所有服务健康检查都是绿的,但用户就是访问不了,流量凭空消失了。我合作过的一个团队就栽在这样一件事上:为了合规,他们把公网入口负载均衡器的 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(域名解析)、身份认证、路由、证书、配置、编排或第三方服务。团队实际上会观察到什么?对每个故障场景,定义能告诉你出问题的信号。绿色的应用仪表盘不算数,如果故障发生在它之前。

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

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

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

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

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

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