GitHub 8·17 事故复盘:容量失败与重试风暴的连锁反应
工程笔记——记录一次由容量问题引发的链式故障,以及我们从中能直接抄走的运维规则。
事故摘要
- 发生时间:2026 年 8 月 17 日
- 持续时间:7 小时 47 分钟
- 影响范围:github.com、身份认证(SAML/OIDC)、Actions、API、PR、Issues、Copilot
- 峰值错误率:
- web/API:约 20%
- archive 与 raw 下载:约 50%
- 背景:这是 8 月内第二次重大故障(8 月 6 日已发生过一次 Actions 故障)
事故概况
8 月 17 日,GitHub 核心服务大面积不可用,从 Web 页面到 API、从认证链路到 Copilot 无一幸免。特别是 archive 和 raw 下载的错误率飙到 50%,说明这次已经不是"某个接口慢"的程度,而是基础设施层面的容量耗尽。
官方复盘将根因定性为 「容量失败」,而不是代码或配置变更引发的逻辑错误。这一点很重要——很多团队在追故障时习惯性先找变更,但这次问题出在增长曲线与容量规划脱节。
根因拆解
1. 流量翻倍,容量没跟上
官方给出的关键数字是:
- 月提交量在 4 个月内从 14 亿 翻倍到 29 亿
- Central US 数据中心的关键基础设施组件没能随流量同步扩展
这不是突发的热点流量,而是持续了四个月的陡峭增长。容量规划没有跟上,基础设施就变成了系统的隐性瓶颈。等到压力超过临界点,故障就集中爆发了。
2. 具体技术根因:Istio sidecar 成为瓶颈
故障链路的起点是 Istio sidecar pod 达到并发上限。
问题不在服务本身,而在于自动扩容策略。当前的扩缩容机制监控的是 主服务的容量指标,没有盯 sidecar 自身的并发状态。主服务看起来还扛得住,但 sidecar 已经是在超负荷硬撑。等到压力扩散,系统已经来不及加实例了。
3. 压力扩散:HAProxy 节点流限制耗尽
sidecar 被打满后,压力向外扩散。4 个 HAProxy 节点率先耗尽流限制(flow limit),导致网关认证链路大面积出现延迟和失败。
整个故障链路是:
流量增长 → Istio sidecar 并发打满 → 自动扩容没反应
→ 压力外溢 → HAProxy 流限制耗尽 → 网关认证大面积失败
恢复期的坑:客户端无限重试
故障恢复过程中,一个关键问题差点让恢复动作白做:
Copilot 报错后,客户端触发无限重试,形成了二次流量风暴。团队必须先专门压制客户端的重试行为,才能安全地逐步恢复服务。
这是一个典型的"故障引发故障"的场景。服务端已经处于脆弱状态,客户端的自动重试行为直接往伤口上撒盐。以后再遇到类似情况,恢复服务的第一步应该是先想清楚"客户端会不会自动重试",而不是闷头加机器。
官方对策
官方给出的后续动作有三条:
- 加容量:补齐 Central US 数据中心的容量缺口
- 继续迁移到 Azure:Azure 负载占比从 5 月的 12% 已升至 58%,迁移继续推进(原文未提供迁移完成时间表)
- 统一重试治理:为服务间调用统一设置重试预算、重试上限、可变超时
教训:最小可落地的重试规则
重试风暴是分布式系统的通用 hazard,不是 GitHub 独有。把这套规则抄下来,直接用在你的系统里:
最小规则
- 单请求必须有超时上限——不允许无限等
- 调用方必须设重试次数上限——重试 1~3 次足够,不允许无限重试
- 服务/租户维度设置重试配额——防止单个调用方把下游打爆
什么错误值得重试?
- 值得重试:临时性错误(超时、5xx、网络抖动)
- 不重试:4xx 业务拒绝、权限错误等确定性失败
重试一个注定失败的请求,除了放大流量没有任何意义。
退避策略:必须加随机抖动
固定退避时间会让所有客户端在同一时刻踩点重试,形成"重试尖峰"。在退避时间上叠加随机抖动,让重试请求在时间轴上散开。
最后一点:监控不要只看总可用率
官方复盘里没有直接展开说这一点(原文未提供具体监控面板细节),但事故本身已经说明问题:
入口层要按维度分层统计成功率,而不是用一个总可用率掩盖局部退化。
如果只盯着"总可用率 99.9%",你可能根本看不到某个具体服务已经退化到错误率 50%。这次事故中,archive 和 raw 下载的错误率高达 50%,如果只按平均值看,很容易错过真正的重灾区。
相关链接:原文来自 GitHub 官方事故复盘,原文未提供完整链接。
笔记完。核心一句话:容量规划的滞后是慢性的,重试风暴是急性的,两者叠加就是一场 8 小时的灾难。