瑞典马工

从头到尾复盘腾讯云故障

作为腾讯云的深度上云用户,我完整的经历了腾讯云故障的发现到恢复过程,并从中自己总结了下此次故障的根因。

本来打算等待腾讯云官方的公告,但 1 天过去了,貌似除了一个三无的公告和几个调皮的微博帖子之外,我大概拿不到任何的故障复盘了。

既然这样,我就把自己的故障复盘发出来,并讲一些自己在经历过此次故障之后的一些思考。

我的故障经历视角

4 月 8 日 15:15分,我的企业微信开始收到服务器报警,报警内容大概表述的信息为:

SCF(云函数)、COS(对象存储)、数据万象出现 API 请求问题,原因均为:[TencentCloudSDKException]message:An internal error has occurred. Retry your request, but if the problem persists, contact us.

一直到15:21分左右,所有依赖腾讯云 API 的服务正确率开始急速下降,另外服务器的状态拨测 API 也报同样的 TencentCloudSDKException 错误。

简单测试了一下,服务器、数据库、网络正常访问。我意识到这不是我自己的服务问题,大概率腾讯云 API 服务挂了,很自然的想到了去年阿里云双 11 故障。

那时候我还在入海关,过了海关通道后找个椅子开电脑检查起来。15:30:55秒登录进腾讯云控制台。

Image

登进去的当时还在想既然能登录进去,那就证明 API 服务还正常。紧接着迅速打脸,控制台全部爆红,红色的弹窗如潮水般涌来。

Image
腾讯云网络控制台故障截图
Image
腾讯云费用中心故障截图

重试了一下登录,无法成功。自己已经确认是腾讯云故障了,并且当时并没有做 API 这么底层的灾备方案,于是开启祈祷模式。16:32,我向群友发了腾讯云挂了的情报。

由于数据库、网络、服务器正常运行,所有控制台管控面失效,开发者自身服务使用的 SDK、API 出现相同的internal error。我合理判断出是 API 底层整个挂掉了,从 15 分到 31 分的这 15 分钟时间里,API 底层故障是蔓延的趋势,从一开始的小范围单地域影响,到全部地域整个 API 管控面全部完蛋。(原因我文章后面再大胆分析)

这和去年阿里云双 11 故障几乎是翻版,于是在群里给冯老板调侃说:可以直接把去年的文章改个名字再发一遍。

Image

15:45,腾讯云主站挂掉,开始报 502 和 500 错误,猜测是用户登录控制台大量重试造成 API 访问量激增,对恢复工作有影响,于是主站切断了访问。估计这个 35-45 时间段相关同学已经开始介入准备恢复了。

ImageImage

15:55 分左右的 10 分钟时间段,客户经理得到确切的回复口径,开始在客户群里回复。

16:05 分开始,故障开始逐步恢复;16:10 分控制台外壳管控面基本可用,但没有 100%恢复,仍然有报错。

16:20 分左右,API 在部分地域恢复见效,开始逐级消化响应,此时独立使用服务器、存储、网络底层的服务(比如服务器、NAT 网关控制面、数据库控制面)已经可用,成功率未达到 100%。

16:21 分,腾讯云官网发出恢复公告,告知控制台已经完全恢复,我觉得这里控制台三个字用的好,按照我的观测,确实是控制台外壳管控面已恢复,但这对于生产用户来说毫无意义。

Image
腾讯云官方公告

16:40 分左右,先期恢复的地域,管控面基本 100%恢复。重度依赖 API 的产品服务(比如数据万象、云函数)恢复见效,但成功率未达到 100%。

16:45 分左右,官方宣布部分地域已恢复,其他地域仍在恢复中。

Image
腾讯云官方微博发帖

16:55 分左右,观测到先期恢复的地域,重度依赖 API 的产品服务基本 100%恢复。

17:05 分左右,生产环境已经不出现报错,绝大部分地域正常,偶现 CDN 缓存失效问题,应该是故障时的脏请求留存。

17:16 分,官方微博宣布整体恢复,除了上海 API 服务之外其他的均以恢复。目测只是个别服务的 API 不可用。

以上就是我经历的整个故障过程,故障结束后我查看了日志和外部观测平台,确认了各个服务的故障时间段,为后面的复盘打个基础。

我是深度用云用户,除了服务器、数据库 RDS、NAT 网关、CLB 负载均衡之外,还用了对象存储 COS、内容分发网络 CDN、数据万象 CI、云函数 SCF、云开发 TCB、日志服务 CLS、凭据管理 SSM 等等,涉及地域有上海、南京、北京、广州、重庆。

在整个故障期间我的体感非常丰富,也让我掌握了比大部分用户更准确的故障时间节点。

接下来就开始一望而知的复盘了。

故障复盘

首先基本的服务器、网络、数据库 RDS 这些基础服务(只使用网络、CPU/内存、硬盘的服务)都能正常使用;而控制台和开发者生产环境 SDK 同时出现一致的内部错误,可以判定是 API 出现问题,除了它几乎不会有什么能导致全部地域全部接入都挂掉。

Image

从15:15 分开始,到15:31 分完全挂掉,故障是以蔓延的趋势发生的,从单个地域到多个地域,从重度 API 服务到管控面,这种趋势基本可以判断这是人为因素导致的。

人为因素有两个:

  1. 发布新版本,在灰度过程中出现不可知的问题,导致故障的迅速蔓延。

  2. 现行版本有隐藏 bug,在一个时间节点或者一定压力下会出现,进而因为调度导致影响面开始扩大,造成全部挂掉。

而从官方发布的公告来看,发布新版本的可能性最大。

如果有隐藏 bug,地域之间会有隔离(因为流量和接触面不同),不会短时间在全部地域内集中。最多会造成和去年 AWS 相似的单地域故障。

AWS 故障复盘:https://aws.amazon.com/cn/message/061323/

发布新版本这个,从 15:15 分-31 分的增量,和 16:05 到最后的减量,以及分地域的恢复,也很符合灰度发布和回滚的现象。另外从客户群里的口径回复中,也证实了这一点。

Image
其他大客户群里的回复,已打码

因此最终可以得出可信的复盘结论:

腾讯云 API 服务发布了有不可知问题缺陷的新版本,造成了此次故障。故障发生后,相关同学紧急对新版本做了回滚,并逐步切流量。

由于 API 是腾讯云的基石,整个控制台,开发者的生产 SDK 调用,甚至服务的内部团队都会依赖 API 来操作资源环境。在故障发生时,有很多中间状态,因此就会造成虽然 API 底层完全恢复了,但部分服务的恢复会有严重滞后性。

我们再来看看 API 挂掉的提示,简简单单的内部错误,几乎所有的控制台和二次包装的 SDK,以及依赖 API 的基础服务,都报了这个错误:

An internal error has occurred. Retry your request, but if the problem persists, contact us.

这个错误不属于任何服务,只是 API 的公共错误 InternalError,文档里说是内部错误。

这种模糊的描述,不属于任何一个确定的异常捕获,基本就是 try/catch 中捕获了一个代码运行问题,然后返回了这个公共的错误信息。

既然能接收请求,并能清楚的给调用者返回这个错误异常,就说明 API 服务所部署的资源(服务器、网络、硬盘)都没有问题,只可能是运行程序里的一个执行语句错误。(我猜的)

而具体到底是什么,我不是算命先生,也不是相关同学,既然腾讯云没有纰漏,我也只能复盘到这里了。

但猜测这种问题,无外乎 3 种情况:

  1. 代码写错了,或者环境变量配置指向出错(不可能吧,前期测试没发现?)

  2. 网络配置问题,如果 API 服务是微服务,那么内部的 RPC 调用出现问题也可能会造成错误,比如捕获失效,捕获代码缺少参数执行出错等。

  3. 部署问题,API 服务是一个很大的系统,这次更新可能只是更新了一小部分,但是部署出现问题,导致这部分完全启动不起来或者启动后运作失灵,会被外层函数捕获抛出。

以上是我预测的,因为信息缺少我也不是算命的。不过我还是希望腾讯云能够简单公告一下,内部错误到底是什么问题,好让开发者用户心里有个预期。

我从这个故障中得到什么?

我和马工一直是鼓吹 IAM 最佳实践的,但是阿里云、腾讯云接连两次深深的打了我们的脸。

IAM 最佳实践充分利用公有云提供的管控面和权限角色,深度使用公有云提供的专门服务(如对象存储、云函数、日志服务、CDN 等等),权限角色在公有云中做闭环控制,防止权限过大带来的团队安全问题。

这和直接使用虚拟机,然后在其中自建数据库和文件存储的方向截然相反,技术不太好的入门开发者会碰到各种问题并且很容易成为网络中被攻击的对象,而使用 IAM 最佳实践则会大大提升入门开发者部署更加安全可靠的生产环境(你只需要写代码,剩下的维护交给公有云)

但这里有个基础,就是公有云的 API 基石是稳固的,可靠的,才会使最佳实践发挥作用。但国内两大公有云先后在基石中发生故障,确实加深了我对其服务技术水平和操作合规的怀疑,也更加谨慎的再推荐用国内的云服务做最佳实践案例。

两次故障也为很多人带来了谈资笑料,公有云有很大的影响规模,一旦故障人所皆知,但如果我自己用虚拟机自建,出现故障或者服务不可靠,除了我自己不会有其他人知道。于是就会表现出,用公有云故障一堆,自建就一帆风顺了。

辩解归辩解,但事情已经发生了,我觉得我有必要认真考虑一下,如果以后再遇到基石出现故障,我应该怎么提前做好准备。

冯老板在去年阿里云双 11 故障的文章里,提了几条,我这里引用几条有价值的并重新加强一下。

1. 业务服务域名接入要独立控制

对外提供业务服务的域名解析尽量使用独立的服务商,最好跨云隔离,防止一个云的基石挂了,管控失灵,独立的服务商还能保证你能切换流量,而不是闭目等凉。

2. 在接入层尽量保留基础服务

从两次故障来看,基础底层的运行不会受到影响,因此可以在接入层中直接使用自建的网关服务,并通过这个网关服务做到故障感知和自动切换。

目前开源的网关服务配合多地或多可用区的部署,完全可以满足自己业务的接入层需求,没太大的必要直接使用公有云的 API 做请求接入。

在可靠性上,目前同个地域可用区全部故障发生的概率很微小,除非城市遭受了剧烈损害,网络全部断掉。如果你还需要更高的可靠性,可以考虑在多个地域建立 3 地 2 中心的接入配置或者主备配置。

3. 依赖 API 的服务需要在多云之间平替

依赖 API 的服务(你的业务代码使用了 SDK 来调用服务做生产,就算依赖了),有条件可以在其他云中建一个平替,一般这类服务都是按量计费的,能保证你的成本不会浪费太多。

当本云出现故障时,网关接入层立刻通过公网去联系备份云的服务,虽然可靠性降低,但能保证生产的基本稳定。

4. 考虑灾备链路

如果出现了集体性(包含基础服务)的团灭故障,可以考虑跨云,两个云的数据库做强同步。通过业务域名的 cname 解析流量管控,或者在前端应用中,设置主服务和备份服务域名。

写在后面

从故障的发生到现在,从用户角度观察到的公有云厂商的态度跟摆烂无疑。从官方公告到公关,再到用户安抚政策,严重迟缓,一副事不关己,高高挂起的样子。

在最基本的公告方面,不要求做到 AWS 这种翔实且有根因的复盘。

Image

阿里云这种最起码的时间点总要有吧?

Image

作为腾讯云的深度用户,在这次故障面前,自己感觉是光着屁股推磨——转着圈的丢人。所在的云平常鼓吹的可靠,专业,一切以用户为依归的承诺统统看不见,完全有失水准,大出洋相。

平常推销资源的时候说的很好的专属客户经理,在故障发生后全无踪影,要不是主动去问,根本不理。

另外我根据腾讯云各个服务公布的 SLA 来计算了一下,99.8%的可用性,我大概能得到 50 元代金券。

从上午发起工单开始,一直到晚上 8 点,才给我反馈 100 元半年无门槛代金券。而各个群里已经充斥着 30 秒到账 100 元,快去薅羊毛的经验了。

我还能说什么,只能摸摸的在工单里点了确认。作为小用户,还能奢求什么呢?人家理你就已经是不错了。

Image

本文的所有观点仅代表作为用户的自我观点,时间点和复盘内容也只是根据自身经验和技术水平的合理推断,不代表任何组织,如果现实雷同和不合理之处,还请见谅!