2021.10.07 一行小错为何产生巨大破坏-Facebook史诗级故障大反思学习

释放双眼,带上耳机,听听看~!

Facebook大故障原因:一条写得很糟糕的命令、一款有缺陷的审核工具、一个阻碍成功恢复网络的DNS系统、以及严密的数据中心安全

Facebook故障是一系列不幸的事件酿成的!

2021.10.07 一行小错为何产生巨大破坏-Facebook史诗级故障大反思学习

一条写得很糟糕的命令、一款有缺陷的审核工具、一个阻碍成功恢复网络的DNS系统以及严密的数据中心安全,所有这些因素导致了Facebook长达 7 个小时的重大故障。

Facebook 表示,周一故障的根本原因是例行维护工作出了岔子,结果导致其DNS服务器不可使用,不过最先崩溃的是Facebook 的整个骨干网络。

雪上加霜的是,由于DNS无法使用,Facebook的工程师们无法远程访问他们所需的设备以便网络恢复正常,因此他们不得不进入数据中心手动重启系统。

这么一来速度慢了下来,但进一步阻碍恢复工作的是,数据中心实施了必要的保护措施,确保任何人都很难篡改。Facebook负责工程和基础设施的副总裁Santosh Janardhan在公司博客上写道:“数据中心很难进入;一旦你进入到里面,就算可以实际碰得到硬件和路由器,它们也被设计成很难改动。”

这要花时间,但是一旦系统恢复过来,网络就恢复正常。

恢复在其网络上运行的面向客户的服务是另一个漫长的过程,因为一次性开启全部服务可能会导致另一轮崩溃。Janardhan写道:“个别数据中心报告电力使用量下降了数十兆瓦,突然扭转电力使用量出现这种下降的情形可能会使电气系统到缓存的一切都面临风险。”

Facebook总共宕机了7小时5分钟。

例行维护搞砸了

触发故障的操作是,Facebook当时正将骨干网络的一部分断网进行维护。Janardhan写道:“在开展其中一项例行维护工作过程中,执行了一个命令,旨在评估全球骨干网容量的可用性,这无意中断开了我们骨干网络中的所有连接,实际上断开了Facebook全球数据中心的连接。”

这不是预定的计划,Facebook甚至部署了一款工具来理清可能导致这种灾难性故障的命令,但没有奏效。据Janardhan声称:“我们的系统旨在审核此类命令,以防止出现此类错误,但该审核工具的一个错误使其无法正确终止命令。”

一旦发生了这种情况,DNS注定要完蛋。

DNS是单一故障点

据监测互联网流量和故障的思科ThousandEyes的产品营销主管Angelique Medina表示,自动响应骨干网崩溃的机制似乎是导致DNS瘫痪的原因。

DNS(即目录名称服务)响应有关如何将Web名称转换成IP地址的查询,而 Facebook托管运行自己的DNS名称服务器。Medina说:“他们有一套架构,根据服务器的可用性来扩展或缩减DNS服务。当服务器的可用性因网络故障而降至零时,他们停用其所有的DNS服务器。”

这种停用是通过Facebook的DNS名称服务器向互联网边界网关协议(BGP) 路由器发送消息来完成的,这些路由器存储用来抵达特定IP地址的路由方面的信息。这些路由通常被公告给路由器,让路由器了解如何适当地引导流量。

Facebook的DNS服务器发送的BGP消息禁用了公告给自己的路由,因而无法将流量解析成Facebook骨干网络上的任何对应内容。Janardhan写道:“最终结果是,即使我们的DNS服务器仍在运行,也访问不了。这么一来,互联网的其余部分无法找到我们的服务器。”

即使DNS服务器仍然可以通过互联网来访问,Facebook的客户也会因他们试图访问的网络崩溃而丢失服务。对Facebook来说不幸的是,它自己的工程师也无法访问DNS服务器,而他们的远程管理平台访问已宕机的骨干系统少不了DNS服务器。

Medina说:“他们不仅仅将DNS服务用于面向客户的网站,还将其用于自己的内部工具和系统。通过完全关闭DNS服务,他们的网络操作员或工程师无法访问他们所需的系统以便解决问题。”

她表示,一套更稳健的架构将拥有双DNS服务,那样一个DNS服务可以支援另一个。据Medina声称,比如说,亚马逊(其AWS提供DNS服务)为其DNS使用两项外部服务:Dyn和UltraDNS。

汲取的教训

网络最佳实践认为,这起事件暴露了Facebook 架构存在的一个缺点。她说:“为什么他们的DNS在这里实际上是单一故障点?”如果本身出现DNS故障,又没有后备DNS,就可能会出现长时间的故障,“所以我认为一大经验教训就是要有冗余DNS。”

另一个共识是Medina针对其他服务提供商故障的看法。“通常就这些故障而言,他们的网络中存在错综复杂的依赖关系,以至于一旦整体服务架构中的一个部分出现了一个小小的问题,随后会出现这样的级联效应。”

“许多公司在充分利用大量的内部服务,这么做可能会带来不可预见的后果。这种情况在技术人员当中更为常见,但我确实认为值得指出。”

2021.10.07 一行小错为何产生巨大破坏-Facebook史诗级故障大反思学习

为何 Facebook 全球有 30 多亿用户,该次事件只影响到其中的 8000 多万的用户?

如上文所说,域名解析搬运工如 1.1.1.1、8.8.8.8,如果成功解析 facebook 网站的域名,通常会缓存一段时间,这样当下一个用户访问 facebook 网站时,可以立马将结果返回给用户,这样可以省却不少的时间,同时刷新缓存定时器。

这就意味着,如果一台域名搬运工一直有用户在解析 facebook 域名,一直在刷新缓存定时器,那么这个缓存一直不会被删除,一直可以被直接返回给用户。所以,即使在互联网无法访问 facebook 权威域名服务器,但是依靠分布在全球各地的域名解析搬运工的缓存机制,依然有很多用户可以访问 Facebook 网站。毕竟 Facebook 其他服务器是可路由的、是可以到达的!

当然如果有的域名搬运工,缓存的内容由于没有域名解析的刷新,超时最后被删除。当域名搬运工试图联系 facebook 权威服务器时,就出现问题了。

Facebook 负责变更 BGP 的工程师为何不在第一时间做回滚(Rollback)操作?

做变更的工程师通常都是远程 VPN 操作,而做路由变更操作是一种极度高风险的操作,因为一旦路由配置出错,工程师就无法再访问正在远程操作的路由器了。为了保险起见,为了不和路由器失去联系,工程师在 commit 变更代码时,会使用一个 confirm 选项,后面跟着一个数字,单位是分钟。比如

Commit confirm 2

这条代码的意思是,将当前的修改配置 commit, 两分钟之后自动回滚到修改前的版本。在这两分钟内,工程师发现远程 SSH 软件与路由器的远程 SSH 连接依然没有断,那么就认为当前的修改没有问题,于是再次使用 commit 命令确认当前修改,那么修改的配置就真正的生效了。

相反,如果工程师敲完命令立马自己的远程软件 SSH 断了,说明当前的修改让路由器与 Internet 失去了联系,路由出问题了。好在这种影响只会影响 2 分钟,2 分钟之后自动回滚到修改前的版本,工程师依然可以再次联系到路由器,检查自己的配置哪里出了问题。

很显然,在这两分钟内 facebook 工程师没有尝试去 Ping 一下 Facebook 内部权威域名服务器。否则他们一定不会 commit 这次变更操作。

为了简化操作,工程师在等待 confirm 的时间内,可以使用自动化的脚本,将公司内部最关键的服务器 Ping 一遍,其中包括域名服务器、域控制器、时间服务器等等,确保它们全部没有问题再 commit 配置版本。

从Cloudflare的博客中也能看到,问题的原因也确实出在了BGP指令方面,不过我们要问的是为什么这样一条小小的指令会造成如此之大的影响。

route-views>show ip bgp 185.89.218.0/23

% Network not in table

route-views>

2021.10.07 一行小错为何产生巨大破坏-Facebook史诗级故障大反思学习

上一次Facebook的全面中断事件还要追溯到7年的2014年6月当时Facebook在APP更新版本时出现了一些问题,随后就有一些用户开始无法登陆Facebook,不过Facebook方面很快就找到了问题所在并进行了修复,并在半小时之内就让服务100%恢复了正常。

这次史诗级故障也不是脆弱的BGP协议第一次出现问题,就在2020年1月23日,所有后缀为.net的域名也出现无法解析的情况,经DNS顶级根服务运营商ISC调查,发现.net域名缺失了关键的A记录和AAAA记录,所有.net后缀的互联网地址从ISC的F根服务器全部消失了,接下来美国宇航局(NASA)运营的E根服务器也遇到了类似的问题。

那次故障中ISC定位问题的时间也很快,在5分钟内就迅速将问题定位在他们与Cloudflare合作运营的节点上,后来Cloudflare很快查明原因是由于他们刚刚发布的变更代码所造成的问题。但最终问题的解决也花了近两个小时的时间,因为撤回导致该问题的BGP通告,出乎意料的长。

通过对比我们可以看到,本次Facebook的故障无论是从影响程度,还是故障时间上讲都堪称是负面教材的典型,而历史一再告诉我们,只要能从历史经验中总结一点教训就能避免悲剧的发生,因此复盘这次史诗级的故障,对于我们来说肯定也会是大有裨益。

BGP协议简介

2021.10.07 一行小错为何产生巨大破坏-Facebook史诗级故障大反思学习

BGP边界网关协议是EGP外部网关协议的一种, 顾名思义BGP处理外部网络区域的之间路由信息的协议,其主要功能是与其他网络自治区的BGP协议系统交换网络路由信息。我们看到EGP相对的IGP内部网关协议,拥有众多储如RIP、OSPF、IS-IS、IGRP、EIGRP的协议族实现不同。EGP家族当中几乎只有BGP这一根独苗是可用的,BGP几乎是唯一一个能够处理独立路由域间的多路连接的协议。

我们举个例子来说明一下这个BGP协议,比如互联网上有7个独立的网络自治区域AS (Autonomous System),他们分别是AS1-AS7,这7个AS之间相互的物理连接情况用橙色线段表示如下:

那么如果AS1区域内的设备想要与AS7区域内的设备产生连接,那么具体的路由路径应该选择AS1-AS4-AS5-AS6-AS7的蓝色路径,还是选择AS1-AS2-AS35-AS6-AS7的红色路径就是BGP协议要解决的核心问题,其实BGP之类的路由协议从宏观层面来看都有点像旅游规划,也就是可以把问题转化为从AS1到AS7的道路中哪条道路最快。BGP协议通过一系列的报文,Internet发布其前缀路由信息,并维护一个有限状态机,并以此来完成路由策略的收敛,但如果发布了错误的通告信息,那么就没有人能够知道如何连接这个错误区域了。当然本文不是要介绍BGP协议,这里各位读者对于BGP的有关概念性有所认识就可以了。

事件处理故障复盘
正如Facebook公告所说,事故的一开始,Facebook已经停他们DNS前缀路由的BGP通告也就是说Facebook的DNS无法访问,也就是说一条错误的指令让Facebook整体下线了。

route-views>show ip bgp 129.134.30.0/23

% Network not in table

route-views>

以下是完整的整个事件的前因后果:

Facebook 网络工程师,更新 BGP 路由配置时,将 185.89.218.0/23 和 129.134.30.0/23 这两条路由过滤掉了,这两条路由分别包含 512 个 IP 地址,一共 1024 个 IP 地址,其中:

185.89.218.0/23 代表 IP 地址从 185.89.218.0 开始到 185.89.219.255 结尾的 512 个地址。

129.134.30.0/23 代表 IP 地址从 129.134.30.0 开始到 129.134.31.255 结尾的 512 个地址。

意味着 Internet 上其他路由器将没有通往这 1024 个 IP 地址的路由,怎么办?

丢弃处理!

可是要命的是,这 1024 个 IP 地址恰恰包含 Facebook 公司权威 DNS 服务器的 IP 地址。这样就出大事了。要想透彻理解为何要出大事,首先要了解 DNS 是如何工作的?

当用户在浏览器里输入 Facebook.com 之后敲回车键,浏览器需要将 facebook.com 解析成 IP 地址之后才能建立 TCP 连接,然后 TLS 安全连接,然后是 http 交易。

通常用户的本地 DNS 服务器就是家庭网关 IP、或者公司网关、或者公司 DNS Server,比如 192.168.1.1 、10.0.0.1、172.16.1.1 之类的,也有的用户使用诸如 1.1.1.1 、8.8.8.8、114.114.114.114 的 DNS 服务器。但是这些这些 DNS 服务器,仅仅是域名解析的搬运工。当用户的解析 Facebook.com 请求到来时,它们先检查自己的缓存里是否有 facebook.com 与 IP 地址的条目,如果有,直接返回给用户。

在故障期间通过dig、nslookup等命令解析Facebook的DNS域名全部返回SERVFAIL,而且正如我们上文介绍,如果发布了错误的BGP通告,那么没有人能够再从互联网上找到你,这和人工破坏了Facebook数据中心的连向互联网的光纤线路,从结果上看没有任何本质区别。

根据CloudFlare的博客显示,Facebook的故障差点把整个互联网搞崩,因为Facebook用户太多了,用户在无法正常登陆APP时会疯狂的发起重试,而且由于Facebook域名解析缓存已经在各级DNS服务器上全部失效了,这就给根DNS也就是1.1.1.1造成了巨大的压力。据说这使1.1.1.1的DNS解析查询的速度比平时高出30倍,所幸1.1.1.1顶住了压力,Facebook故障期间绝大多数的DNS解析请求的返回速度都稳定在10毫秒左右,否则一旦根DNS也崩溃那么后果将不堪设想。

最终在7个小时之后,Facebook终端重新向互联网通告了他们的路由,至此服务才最终恢复。

通过本次事件我们能学到了什么
笔者相信以Facebook那些大牛人物的实力,从发现故障到定位故障原因的时间不会超过1分钟,甚至很有可能在刚刚指行完那条错误的BGP通告命令之后就发现问题了,但是故障依旧持续了长达7个小时。再结合Facebook内网全部中断的细节,那么我们可以推出隐藏在这背后的重要结论,那就是相关的错误命令把Facebook的VPN通道也全部影响了,我们知道Facebook目前在疫情的影响下,美国区的员工还处在远程办公的状态,也就是说在错误指令生效之后,远程运维工程师自身的VPN以及逃生通道也全部失效了,而数据中心现场值班的人员可能只会加电、重启等简单操作,甚至不排除现场人员连登陆到核心网络设备的权限都没有,一切都得指望远程运维的人员到现场解决了。

假设自己不出现低级失误,才是最大的低级错误:从上述分析中我们可以看出,Facebook的网络工程师对于自身的能力太过自信了,以至于他们可能就没有认真分析过回退方案的可行性,而故障发生之后才发现网络设备已经无法通过远程方式登陆了,回退方案执行的前提已经崩溃。因此在发布任何版本之前都要根据其造成的最大负面影响制订预案,假定自身不会出现低级失误的想法是绝对错误的。

逃生通道是最后生命线,必须严格保持独立:从故障的时间上看,远程登陆的逃生通道也一定是受到了影响,从这里我们能吸取到的教训就是一定要在平时做好逃生通道的可用性验证,并且要尽量保证逃生通道的独立性,不能把逃生和日常运营的通道混为一谈。

任何一起大事故都是一系列偶然因素的叠加,从BGP路由的变化来看,很有可能是在做流量工程的时候,将路由发布错了,极大概率又和BGP FlowSpec有关,但是一个值得反思的问题是过去几个小时静悄悄的没有任何路由器的更新发出,有传言称是

1
DNS

挂了导致门禁系统挂了,从而无法进入机房恢复数据。

关于故障的反思.1 BGP

关于BGP带来的重大事故已经不止一次发生了,BGP作为整个互联网的基石,其协议用了30年了,BGP协议源于1989年1月第12次IETF会议, 由Len Bosack, Kirk Lougheed 和Yakov Rekhter提出实现一种所谓的边界网关协议(Board Gateway Protocol”, 其后在三张餐巾纸上完成了BGP设计的草稿. 然后在会议结束后的不到一个月的时间, 他们提出了两个BGP的实现方案, 并在1989年6月发布了RFC1105.

协议设计之初的想法比较简单, 

1
第一个想法

在路由信息中包含相关的路径属性, 并且使用它来提供无环路的路由. 

1
第二个想法

是采用增量更新来尽量减少路由信息在两个路由器之间的交互. 

1
第三个想法

则是通过TCP来保证可靠传输. 

1
最后一个想法

则是使用TLV的方式来定义数据结构, 这样使得协议拥有了很好的扩展性.

但是30年后,其主要的问题是其通信和计算机制已经不能满足大量路由(接近1M前缀)的需求了。TCP带来的Head Of line Blocking导致了BGP通信过程中收敛缓慢。4Byte-ASN和IPv4地址交易带了路由前缀大量更新。数据中心内针对BGP-EVPN的扩展和使用BGP FlowSpec使得协议栈越来越复杂。互联网上各种魔改的开源BGP(FRR-OpenBGP/GoBGP)使得协议互通时出现Bug的几率急剧上升。当然最严重的问题是:

1
BGP状态机和TCP的耦合

2021.10.07 一行小错为何产生巨大破坏-Facebook史诗级故障大反思学习

其实早在10多年前我就看到了这个问题,简单的修复方式是使用MultiThread构建多个BGP Peering的会话来发送不同的Address-Family信息,另一种是针对路径上的一些问题,使用MultiHoming和MultiStreaming的方式,也就是使用BGP Over SCTP的处理方式,并且在10多年前就写了相应的RFC-Draft

2021.10.07 一行小错为何产生巨大破坏-Facebook史诗级故障大反思学习

但是最终因为当时BGP并未承载如此大的流量以及SCTP协议栈本身的失败,所以搁置了.

BGP另一个问题是其

1
低效的一致性收敛算法

。BGP协议设计时还是刚到486的年代,自然有一些自身的限制和容量的取舍,eBGP防环可以通过AS_PATH,而iBGP不同,因为出于防环的考虑,iBGP收到更新后不能将其传给其它iBGP对等体,因此必须要将AS内部的路由器进行iBGP Fullmesh连接。事实上, 对于一个大型的运营商其内部可能有数以百计的BGP路由器并需要全互联形成iBGP对等体. 这样的部署方式对于运营商来说是不切实际并不被接受的. 因此Tony Bates和Ravi Chandra在1996年6月提 出了RFC1966: Route Reflector 作为一种避免iBGP Fullmesh的备选方案。而提出BGP-RR的

1
Ravi Chandra

就是支持我搞ML在网计算的大佬:

2021.10.07 一行小错为何产生巨大破坏-Facebook史诗级故障大反思学习

现在说大爷的BGP-RR有问题,好像有点尴尬。但是事实如此,毕竟国内好多运营商还专门拿我们做的某款路由器来做整个骨干网的RR,所以里面大大小小的问题我都清楚,调TCP-Stack,优化QoS这些都干过…


1
结论

: 其实不光我说的,以前阿里的依群总也讲过BGP这样的协议发展了20、30年了也急需做一些变革了。而这些变革就在分布式一致性上,也就是我为什么建议在域内使用ETCD代替BGP路由并构建Ruta控制平面[3]的根本原因。2021.10.07 一行小错为何产生巨大破坏-Facebook史诗级故障大反思学习

在域内将iBGP的一致性转换为分布式K-V数据库同步的处理方式.

另一方面你们可以看到NSDI’21上Google发布的Orion[4]2021.10.07 一行小错为何产生巨大破坏-Facebook史诗级故障大反思学习Google便是使用其分布式数据库来保存路径信息和域内的一致性。而Ruta同样如此,采用ETCD来实现。

具体关于控制面协议设计,去看今年早些时候写的一文吧

包处理的艺术(2)-控制面协议设计

关于故障的反思.2 互联

当然BGP的失效有可能是中间某个运营商的错误配置导致的,虽然这次FB的故障是FB自身,但是下次有哪个运营商发布错了劫持了Facebook DNS地址呢?

2021.10.07 一行小错为何产生巨大破坏-Facebook史诗级故障大反思学习

然后由于公有云和很多传统运营商都有Peering,可以让本地网络可以尽快的接到云上,这样就规避了传统的Internet路由使用BGP跨越多个运营商的缺陷,在不改变Internet架构的同时,构建了一个Overlay将部分云节点构成了Transit-AS

关于故障的反思.3 DNS

DNS其实某种意义上来看也是一种基于域名的路由协议,这也是我前几个月要自己开发一个开源项目

1
ZaDNS

的原因,传统的主机只能选择一主一备两个DNS服务器,然后通常我们又因为很多场景需要基于不同的Domain查询不同的DNS服务器,因此有了基于DNS的Domain Based Routing的需求。另一方面针对CDN失效避免和CDN优化需要进行可达性探测,还有针对网络安全需要做ZTNA或者基于ML算法的DNS域名或者Bad Reputation Record的过滤,这些都一起实现好了开源出来了:

项目地址:

github.com/zartbot/zadns

关于故障的反思.4 监控

针对BGP的监控比较容易,有现成的BGP Monitor Protocol, 另一个比较有用的就是快速的TraceRoute,ThousandEye算是比较成功的一家了。当然TraceRoute和探针测量本来就很简单:

TraceRoute我自己开源了一个并行的快速探测软件:

github.com/zartbot/ztrace

而针对Internet的测量和统计,也有相应的最佳实践:

Internet 的性能测量

关于故障的反思.5 激励

基础架构团队主要是为整个业务提供算力、网络等各种资源,基础设施建设本来就是重资产支出的部门,简单的来说一个纯花钱的部门如何进行业绩评估和激励。从运营的角度不出事故永远看不到这群人的重要性,而6小时的故障损失也一定程度上衡量了这种部门的关键性。

其实我们从另一个角度来看, 银行揽储的部门是不是有额外的奖金?但是这些部门也是纯花钱的部门,毕竟揽储来的钱不得付利息啊?那么为啥都是花钱一个有激励,一个没有呢?关键就是针对计算弹性的资源提供方如何进行转移定价的问题。

内部资金转移定价(FTP)是指,商业银行内部资金中心与业务经营单位按照一定规则全额有偿转移资金,达到核算业务资金成本或收益等目的的一种内部经营管理模式。业务经营单位每笔负债业务所筹集的资金,均以该业务的FTP价格全额转移给资金中心;每笔资产业务所需要的资金,均以该业务的FTP价格全额向资金管理部门购买。对于资产业务,FTP价格代表其资金成本,需要支付FTP利息;对于负债业务,FTP代表其资金收益,可以从中获取FTP利息收入。

FTP能够科学评价绩效、优化配置资源、合理引导定价、集中管理市场风险等,具体而言:一是以合理的资金成本或资金收益为基础,逐步构建银行对产品、对客户、对个人的科学评价体系;二是以资金成本的准确计量为基础,逐步建立和完善银行资源配置机制、产品定价机制以及经风险调整后的绩效评估机制;三是通过科学的产品FTP定价,剥离经营单位的市场风险,建立由专业化团队集中管理市场风险的经营管理模式;四是通过FTP推广,逐步推进资金管理体制改革,以及扁平化、事业部方式的全行条线为主的组织架构改革。而对于数字化资产我们同样可以实施相应的FTP,为解决基础架构部门和业务及应用部门相互利益分配会有很大的好处,从而进一步从财务核算上激励双方进行技术创新

2021.10.07 一行小错为何产生巨大破坏-Facebook史诗级故障大反思学习

基于FTP的机制还有一个好处是在基础架构建设过程中,通过完整的端到端成本核算,能够有利于激发团队进行关键性的节点的创新和风险补偿机制。

给TA打赏
共{{data.count}}人
人已打赏
安全运维

安全运维之道:发现、解决问题的有效闭环

2024-4-14 20:59:36

安全运维

稳定性建设 – 架构优化的关键策略

2025-2-11 17:15:56

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索