从 AWS 故障报告 (COE) 中学习分布式系统的教训 - 历次大规模故障如何改变了设计原则

从 AWS 公开的 Correction of Errors (COE) 和故障报告中,解析 S3 故障、us-east-1 DNS 故障、Kinesis 故障等历次大规模事件的根本原因,以及它们如何改变了 AWS 的设计原则。

AWS 公开故障的文化背景

AWS 在发生大规模故障时会公开 Post-Event Summary(故障后总结)。在内部被称为 Correction of Errors(COE)的这份文档,详细记述了故障的时间线、根本原因、影响范围和防止再发措施。在许多企业将故障信息公开控制在最低限度的情况下,AWS 之所以公开详细的故障报告,是基于 Amazon 领导力准则之一的「Customer Obsession」(客户至上)。隐瞒故障原因短期内可以保护企业形象,但长期会损害客户信任。AWS 认为故障透明性对建立信任不可或缺,这一态度影响了整个行业的故障报告文化。Google SRE 团队公开的事后分析和 Cloudflare 的详细故障报告,也在一定程度上受到了 AWS 透明性的启发。

2017 年 S3 故障 - 一个输入错误让半个互联网瘫痪的那天

2017 年 2 月 28 日,us-east-1 区域的 S3 发生了持续约 4 小时的大规模故障。原因是在 S3 计费系统的调试工作中,操作员执行了停止超出预期数量服务器的命令。具体来说,本意是停止少量服务器,但由于输入错误,S3 的索引子系统(管理对象元数据的系统)和放置子系统(管理数据物理位置的系统)的大部分被停止。S3 是 us-east-1 中使用最广泛的服务之一,依赖 S3 的无数服务和网站受到连锁影响。讽刺的是,AWS 的 Service Health Dashboard 本身也依赖 S3,因此连故障状态的显示都无法正常工作。从这次故障中 AWS 获得了多项教训。第一,对大规模变更操作设置速率限制(限制一次可停止的服务器数量上限)。第二,将 Service Health Dashboard 改为不依赖 S3 的架构。第三,优化索引子系统的重启流程以缩短恢复时间。这些改进已反映在此后的 S3 运维中。

2020 年 Kinesis 故障 - 前端服务器扩容引发的连锁故障

2020 年 11 月 25 日,us-east-1 发生了 Kinesis Data Streams 故障,波及 CloudWatchLambdaCognitoAPI Gateway 等众多服务。根本原因是 Kinesis 前端服务器的扩容。Kinesis 的前端服务器设计为每台服务器与所有其他前端服务器之间维持线程。服务器数量增加时,每台服务器维持的线程数呈二次方增长。当天定期容量扩充添加前端服务器时,线程数达到 OS 的线程上限,无法接受新连接。这次故障之所以大范围波及,是因为 CloudWatch 内部使用了 Kinesis。CloudWatch 失效后,其他服务的指标收集和告警停止,导致故障检测和响应延迟的二次损害。从这次故障获得的教训是服务间依赖关系管理的重要性,以及控制平面故障不应波及数据平面的设计重要性。此后 AWS 将 Kinesis 的前端架构从线程模型改为事件驱动模型。

2021 年 us-east-1 网络故障 - 内部网络拥塞的教训

2021 年 12 月 7 日,us-east-1 发生了持续约 5 小时的网络故障。AWS 内部网络设备的自动扩缩系统存在潜在 Bug,当超出正常水平的流量涌入内部网络时,网络设备陷入过载状态。这次故障的特点是 AWS 控制台本身也难以访问。由于 AWS 管理控制台托管在 us-east-1,通过控制台进行资源管理和故障状况确认都无法进行。通过 CLI 或 SDK 的 API 调用也因内部网络拥塞而出现延迟和超时。这次故障再次证明了「控制平面与数据平面分离」设计原则的重要性。数据平面(实际数据的读写)比控制平面(资源的创建、变更、删除)需要更高的可用性。AWS 在此次故障后加强了内部网络隔离,防止控制平面故障波及数据平面。用户侧的教训包括多区域设计的重要性,以及不依赖 AWS 控制台的运维流程(预先准备 CLI 脚本)的必要性。

从故障中提炼的 AWS 设计原则

AWS 从历次故障中体系化的设计原则反映在 AWS Well-Architected Framework 的可靠性支柱中。第一是「Blast Radius 最小化」。为限制故障影响范围,将服务分割为称为 Cell 的独立单元,使一个 Cell 的故障不波及其他 Cell。DynamoDB 的每个分区作为独立 Cell 运作,一个分区的故障不影响整个表。第二是「Static Stability」(静态稳定性)。即使依赖的服务发生故障,现有操作仍能继续的设计。例如,即使 Auto Scaling 发生故障,已启动的实例不受影响。第三是「Shuffle Sharding」。通过将客户随机分配到分片,最小化一个客户的异常流量影响其他客户的概率。这些原则是从 AWS 自身的故障经验中提炼出来的,也是用户设计自身系统时可应用的普遍知识。如需系统学习分布式系统设计原则,专业书籍 (Amazon) 可作为参考。