系统学习 学习路径总入口:先选领域,再建立模型,最后用故障演练验证

一次节后流量高峰击穿了 AWS Transit Gateway,Slack 的自动扩缩容又在错误方向上放大了故障。 本文是公开报告的摘要与解读,事实以原始报告为准

本文是公开报告的摘要与解读,事实以原始报告为准。

事件概要

2021 年 1 月 4 日是新年第一个工作日。Slack 当天发生大面积可用性事件:消息发送失败或变慢,随后整体不可用,恢复后仍有一段时间处于降级状态。Slack 工程博客于 2021 年 2 月 1 日发布复盘,作者为 Senior Staff Engineer Laura Nolan,2 月 3 日更新。

报告给出的根因不是当天发布:一个 AWS Transit Gateway(TGW)在每包速率突增时没有及时扩容,开始丢包;当天发布过的变更被回滚并排除。另一个独立问题是监控:Dashboard 和告警服务与它们的数据库位于不同 VPC,同样依赖 TGW,因此在事故中一起失效。报告没有给出精确的受影响用户数,也没有给出一个正式的“总故障时长”数字;按报告时间线,服务在 7:00 左右不可用,10:40 恢复正常。

时间线

以下时间均为 1 月 4 日 PST。

时间 事件
亚太白天、欧洲上午 服务正常
美洲上午 外部监控因错误率上升呼叫值班;随后 Dashboard 和告警失效,监控团队被呼叫
6:57 99% 的消息仍能成功发送,正常水平是高于 99.999%;网络已出现异常
7:00 整点/半点的定时流量高峰叠加网络降级,Web 层被打满,丢包和后端延迟上升,Slack 不可用
7:01–7:15 尝试扩容 1,200 台 Web 服务器,provision-service 失败
约 8:15 provision-service 恢复,健康实例开始进入服务
约 9:15 可用主机足够,服务从“完全不可用”转为“降级”
10:40 AWS 手动提升 TGW 容量并覆盖所有可用区,网络、错误率和延迟恢复正常

影响面

报告描述的用户体验是消息发送失败或变慢,Slack 不可用,之后一段时间仍降级。Slack 官方状态页把登录/SSO、连接、消息、文件、通知、Huddles、搜索、应用/集成/API、工作区管理列为受影响范围;核心访问在 10:40 左右恢复,日历集成、邮件通知和桌面客户端的一个独立问题在此后继续处理。

事故还直接影响了响应者:自动缩容移除了生产实例,许多工程师的 SSH 会话被中断;监控系统自身不可用,团队在“看不见”的状态下排障。报告没有提到数据丢失或数据损坏。

根因

第一层是网络。一个 AWS TGW 被打满并丢包。TGW 由 AWS 管理,设计目标是透明扩容,但这个 TGW 没有跟上每包速率的突增。报告给出的背景是:假期后第一个周一,客户端缓存为空,重新连接需要下载更多数据,流量从低活跃状态突然上升。AWS 手动增加了 TGW 容量,并表示正在审视 TGW 对大规模每包速率增长的扩容算法。

第二层是自动扩缩容。Web 层按 CPU 和 Apache worker 线程利用率扩缩。网络等待降低了 CPU,触发了最初的缩容;缩容移除实例,也移除了工程师的 SSH 会话。之后线程压力上升,触发一次 1,200 台服务器的大规模扩容。这个方向本身没有错,但扩容执行失败。

第三层是 provision-service 的瓶颈。它负责配置和测试新实例,同样依赖降级的网络。1,200 台的突发请求撞上两个资源上限:Linux 打开文件数限制(报告称这是更大的问题)和一项 AWS 配额。大量实例只完成部分配置,无法提供服务;这些坏实例又撞上自动扩缩组的上限。provision-service 过载还导致新的 Dashboard 主机无法创建。报告明确排除了当天部署:相关变更被回滚并排除。

处置与恢复

团队先把它当作网络问题升级给 AWS,同时尝试扩容。发现缩容在破坏实例和 SSH 会话后,团队关闭了缩容。7:01–7:15 的 1,200 台扩容失败后,重点转向恢复 provision-service;约 8:15 它恢复工作,健康实例开始进入服务。报告说还需要约一小时才能配置出足够实例,把错误率压到较低水平。

在实例不足期间,负载均衡器的“panic mode”、重试和熔断机制帮助恢复了部分服务,尽管健康检查大量失败。由于网络仍在降级,团队需要比平时更多的实例,配置也更慢。10:40 AWS 的 TGW 扩容覆盖所有可用区后,网络、错误率和延迟才恢复正常。

后续改进包括:把 Dashboard 实例迁到与其数据库相同的 VPC;定期对 provision-service 做负载测试;重新评估健康检查和自动扩缩策略,避免扩容本身压垮 provision-service;在下一次假期结束时提前请求 TGW 扩容,并为此设置了提醒。AWS 则表示正在审视 TGW 的扩容算法。

教训

第一,托管服务的“透明扩容”不等于无限容量。TGW、NAT、负载均衡器和云配额都有每包速率、连接数或 API 上限,关键依赖要知道上限、监控水位和升级路径。

第二,监控必须与被监控系统解耦。Dashboard 和告警放在不同 VPC,却依赖同一个 TGW,导致事故中“监控和告警一起下线”;监控应跨可用区、跨账号或走独立路径。

第三,自动扩缩容要考虑供给链。只盯着服务实例的 CPU 和线程不够,还要确认 provision-service、镜像仓库、配额和 OS 限制能承受扩容峰值;否则扩容会变成自我 DoS。

第四,缩容在事故中可能是危险动作。它会移除实例、切断调试会话,甚至删掉正在提供服务的容量;事故期间应关闭缩容或设置容量下限。

第五,健康检查和实例替换要避免“大规模同时发生”。不健康的实例被集中替换,会进一步压垮配置系统;需要速率限制和退避。

第六,日历效应要进入容量计划。节后第一个工作日、整点定时任务、客户端冷缓存,都是可以提前预演的流量模式。

对本站读者的检查清单

恢复手册与同类复盘

相关命令

参考链接

读完自测

合上页面,先回答,再展开对照。

  1. 报告如何排除“当天发布导致故障”?
  2. 为什么自动扩缩容在本次事故中反而放大了影响?
  3. 监控和告警为什么在事故中失效?应该怎样改造?
答案
  1. 当天变更被回滚并排除;根因指向 AWS TGW 在每包速率突增时未及时扩容,AWS 手动扩容后网络和延迟才恢复。
  2. 网络等待降低 CPU 触发缩容,移除实例并切断 SSH;随后线程压力触发 1,200 台扩容,但 provision-service 受打开文件数和 AWS 配额限制,产生大量半配置实例并撞上 ASG 上限,扩容失败且加剧了供给紧张。
  3. Dashboard 和告警与数据库位于不同 VPC,依赖同一个 TGW;TGW 故障时监控一起失效。应把监控迁到与数据库相同的 VPC,或建立跨账号、独立网络的监控与告警路径,并定期演练。
微信小程序码:扫码打开命令速查小程序

小程序版

微信扫码,随时查命令