本文翻译自 https://blog.cloudflare.com/post-mortem-on-cloudflare-control-plane-and-analytics-outage/
原标题 Post Mortem on Cloudflare Control Plane and Analytics Outage
英语原文版权归 Cloudflare 所有
本文中的 “我们” 全部指 Cloudflare, Inc. “我” 全部指英语原文作者 Matthew Prince
注: Control Plane 和 Data Plane 被翻译为 “控制平面” 和 “数据平面” 是正确的, 详情参考此链接
Disclaimer:
All rights to the original English text are reserved by Cloudflare, Inc.
This is a translation provided for technical discussion purposes only and does not involve any commercial use. If you believe this infringes on your copyright and wish for it to be removed, please contact [email protected].
从世界标准时间 (UTC) 2023 年 11 月 2 日星期四 11:43 开始,Cloudflare 的控制平面和分析服务出现中断。 Cloudflare 的控制平面主要由我们所有服务的面向客户的界面组成,包括我们的网站和 API。我们的分析服务包括日志记录和分析报告。
该事件从 11 月 2 日 11:44 UTC 持续到 11 月 4 日 04:25 UTC。截至 UTC 时间 11 月 2 日 17:57,我们已能够在灾备设施 (disaster recovery facility) 中恢复大部分控制平面。灾备设施上线后,许多客户不会再遇到我们大多数产品的问题。然而,其他服务需要更长的时间才能恢复,并且在我们完全解决事件之前,使用这些服务的客户可能会遇到问题。在事件解决前,大多数客户无法使用我们的原始日志服务 (raw log services)。
现在已经为所有客户恢复了服务。在这次事件中,Cloudflare的网络和安全服务继续按预期工作。虽然客户在某些时段无法对这些服务进行更改,但我们的网络流量没有受到影响。
这篇文章概述了导致此事件发生的事件、我们已经采用的体系架构以防止类似问题的发生、发生了什么故障、什么有效以及原因,以及我们根据过去36小时的经验所做的更改。
首先,这本来不应该发生。我们认为我们已经建立了高可用性的系统,即使我们的核心数据中心提供商之一发生了灾难性故障,也应该能阻止这种宕机。尽管许多系统确实如设计的那样在线,但一些关键系统存在非明显的依赖关系,使它们无法使用。对于这次事件和给我们的客户和团队带来的痛苦,我感到非常抱歉和尴尬。
预期设计
Cloudflare的控制平面和分析系统主要在俄勒冈州希尔斯伯勒周围的三个数据中心的服务器上运行。这三个数据中心彼此独立,各自拥有多个公共电源供应,以及多个冗余和独立的网络连接。
这些设施特意选择了相隔一定距离的地方,以尽量减小自然灾害影响到所有三个设施的可能性,同时又足够接近,以便它们都可以运行主动-主动冗余数据集群。这意味着它们在这三个设施之间持续同步数据。按设计,如果其中一个设施下线,那么剩下的设施仍然可以继续运行。
这是我们四年前开始实施的系统设计。尽管我们的大多数关键控制平面系统已迁移到高可用性集群,但一些服务,特别是一些较新的产品,尚未添加到高可用性集群中。
此外,我们的日志记录系统有意的未被纳入高可用性集群。这一决策的逻辑是,日志记录已经是一个分布式模式的服务,日志会在我们网络的边缘排队,然后发送回俄勒冈州的核心设施(或者对于使用区域服务进行日志记录的客户,发送到其他区域设施)。如果我们的日志记录设施脱机,那么分析日志将在我们网络的边缘排队,直到设施恢复在线。我们认为分析日志的延迟是可以接受的。
Flexential 数据中心电源故障
俄勒冈州的三个设施中最大的一个由Flexential公司经营。我们称这个设施为“PDX-04”。Cloudflare租用了PDX-04的空间,其中包括我们最大的分析集群以及高可用性集群中超过三分之一的机器。它也是尚未迁移到高可用性集群的服务的默认位置。我们是该设施的相对大型客户,占用了其总容量的约10%。
在协调世界时 (UTC) 2023 年 11 月 2 日 08:50,服务 PDX-04 的公用事业公司 Portland General Electric,即 (PGE),发生了一次非计划维护事件,影响了他们向该建筑供电的一个独立电源线。这一事件导致 PDX-04 的一个电源线停机。数据中心具有多个电源线,其中一些具有一定程度的独立性,可以为设施提供电力。然而,Flexential 启动了他们的发电机,有效地补充了失效的电源线。
不同于最佳实践,Flexential 没有通知 Cloudflare 他们已切换到发电机供电。我们的可观测性工具没有能够检测到电源来源的变化。如果他们通知了我们,我们本可以组建一个团队来密切监控该设施,并在它受损时将依赖于该设施的控制平面服务迁移出去。
对接下来发生的事情的有根据的猜测
从这一决策开始,我们目前还没有从 Flexential 获得关于根本原因、他们做出的一些决策或事件的明确情况。随着我们从 Flexential 和 PGE 获取更多信息,我们将更新这篇文章。以下的一些内容是基于最有可能发生的事件序列以及一些 Flexential 员工非正式地与我们分享的内容,作为知情推测。
他们可能让公用事业线保持运行的一个可能原因是,Flexential 参与了与 PGE 名为 DSG 的计划。DSG 允许当地公用事业公司运行数据中心的发电机,以帮助为电网提供额外的电力。作为交换,电力公司帮助维护发电机并提供燃料。我们未能找到任何 Flexential 通知我们关于 DSG 计划的记录。我们已经询问 DSG 是否在当时处于活动状态,但没有得到答复。我们不知道它是否对 Flexential 做出的决策有所贡献,但这可能解释了为什么在发电机启动后,公用事业线继续保持在线。
大约在协调世界时11:40,PDX-04 发生了 PGE 变压器的接地故障。我们认为是这样——但无法得到 Flexential 或 PGE 的确认,这是从电网中提供电力的第二电源线进入数据中心时,被用来降压电力的变压器。尽管我们无法与 Flexential 或 PGE 确认,但似乎接地故障是由 PGE 执行的影响了第一电源线的非计划维护所引起的。或者这只是一个非常不幸的巧合。
高电压(12,470伏特)电源线的接地故障非常严重。电气系统被设计成在出现这种情况时迅速关闭,以防止损坏。不幸的是,在这种情况下,保护措施也关闭了PDX-04的所有发电机。这意味着该设施的两个电力发生源——冗余的公用事业线和10台发电机——都脱机。
幸运的是,除了发电机,PDX-04还包含一组UPS电池。据说这些电池足以为该设施提供大约10分钟的电力。这段时间足够弥合电力中断和发电机自动启动之间的差距。如果Flexential可以在10分钟内使发电机或公用事业线恢复正常,那么就不会出现中断。实际上,根据我们观察到的设备故障情况,电池在仅4分钟后就开始失效。而Flexential花了远远超过10分钟才恢复发电机。
尝试恢复供电
尽管我们尚未获得官方确认,但员工告诉我们,有三个因素妨碍了恢复发电机在线的工作。首先,由于接地故障触发了电路,需要物理访问和手动重新启动发电机。其次,Flexential 的访问控制系统没有由电池备份供电,因此它脱机了。第三,夜班人员没有包括经验丰富的运维或电力专家——夜班由保安和一名独立的技术人员组成,他只上班了一个星期。
在 11:44 UTC 到 12:01 UTC 之间,由于发电机没有完全重新启动,UPS 电池的电量耗尽,数据中心的所有客户都失去了电力。在此期间,Flexential 从未通知 Cloudflare 设施出现问题。我们首次得知数据中心出现问题是在 11:44 UTC 时,连接该设施与世界其他地方的两台路由器脱机。当我们无法直接或通过带外管理联系到路由器时,我们试图联系Flexential并派遣我们的本地团队前往设施。Flexential首次通知我们他们遇到问题的消息是在 12:28
我们目前在 [PDX-04] 遇到电力问题,问题始于太平洋时间上午 05:00 [协调世界时 12:00] 左右。工程师正在积极努力解决问题并恢复服务。我们将每30分钟或在有更多关于预计恢复时间的信息时与您通报进展情况。感谢您的耐心和理解。
针对数据中心级故障的设计
虽然在 PDX-04 的设计在建设之前被认证为 Tier III,并且预计提供高可用性 SLA,但我们考虑到了它可能会离线的可能性。即使是运营良好的设施也可能会有遇到困难的时候,我们有对此的应对计划。在这种情况下,我们预期的情况是我们的分析服务将脱机,日志将在边缘排队并延迟送达核心服务器,某些没有集成到我们高可用性集群的较低优先级的服务将临时脱机,直到它们可以在其他设施恢复。
该地区的另外两个数据中心将接管高可用性集群的职责,保持关键服务在线。总的来说,这个计划运作正常。不幸的是,我们发现一部分本应该在高可用性集群中的服务具有依赖关系,这些服务本应只在 PDX-04 中运行。
特别是,两个处理日志并支持我们分析服务的关键服务 — Kafka 和 ClickHouse — 仅在 PDX-04 中可用,但依赖于它们的服务在高可用性集群中运行。这些依赖关系不应该如此紧密,应该更具弹性,我们应该能够发现它们。
我们曾对我们的高可用性集群进行了测试,将另外两个数据中心设施完全脱机,甚至测试了将 PDX-04 的高可用性部分脱机。然而,我们从未测试过将整个 PDX-04 设施完全脱机。因此,我们忽视了一些关于数据平面的重要依赖关系。
此外,我们在要求新产品及其相关数据库与高可用性集群集成方面过于宽松。Cloudflare允许多个团队快速创新。因此,产品通常会走不同的路径达到它们的初步Alpha版本。尽管随着时间的推移,我们的做法是将这些服务的后端迁移到我们的最佳实践,但我们并没有在产品宣布为普遍可用 (GA) 之前正式要求这一点。这是一个错误,因为这意味着我们所拥有的冗余保护措施在不同的产品中的运作是不一致的。
此外,我们的许多服务过于依赖核心设施的可用性。虽然这是许多软件服务创建的方式,但这并不符合 Cloudflare 的优势。我们擅长分布式系统。在整个事件中,我们的全球网络一直按预期运行。虽然我们的一些产品和功能是可配置和可通过我们网络边缘进行维护而无需核心,但今天太多的服务如果核心不可用就会失败。我们需要使用我们为所有客户提供的分布式系统产品,以使所有我们的服务在核心设备发生故障时也可以继续大致正常运行。
灾难恢复
在12:48 UTC,Flexential能够重新启动发电机。电源返回了设施的部分。为了不压倒系统,当电源恢复到数据中心时,通常一次通过一次在一个电路上供电来逐渐完成。像住宅中的断路器一样,每个客户都会由冗余断路器服务。当Flexential试图重新启动Cloudflare的电路时,发现断路器出现了故障。我们不知道断路器是由于事件而导致的地面断层或其他一些激增,或者以前是否有些浪涌失败,并且只有在电源电源后才发现。
Flexential 开始更换故障的断路器。这需要他们采购新的断路器,因为坏掉数量高于数据中心内的库存。因为比我们预期的要多的服务处于脱机状态,而且 Flexential 无法告诉我们服务恢复的时间,所以我们在 13:40 UTC 时决定切换到 Cloudflare 的灾备站点 (位于欧洲)。幸运的是,我们只需要将 Cloudflare 整体控制面的一小部分切换到灾备站点。大多数我们的服务继续运行在我们的高可用性系统上,跨越两个活跃的核心数据中心。
我们在 13:43 UTC 时启动了灾备站点上的第一个服务。Cloudflare 的灾备站点在灾难事件发生时提供关键的控制面服务。虽然灾备站点不支持一些我们的日志处理服务,但它是为了支持我们控制面的其他部分而设计的。
当服务在那里 (位于欧洲的灾备) 启动时,我们遇到了一个“惊群问题
”,之前失败的API调用压倒性地涌入我们的服务。我们实施了速率限制来控制请求量。在这个时期,大多数产品的客户在通过我们的仪表板或API进行修改时可能会看到间歇性错误。到了17:57UTC,已成功迁移到灾备站点的服务稳定下来,大多数客户不再直接受到影响。但是,一些系统仍然需要手动配置(例如 Magic WAN),还有一些其他服务,主要涉及日志处理和一些定制API,直到我们能够恢复 PDX-04 之前仍然不可用。
译者注: 惊群问题是指当某个事件发生时,大量正在等待的进程或线程被唤醒,但只有一个进程能够处理该事件。当进程醒来时,它们将各自尝试处理该事件,但只有一个会获胜。所有进程都会争夺资源,可能会造成计算机资源被占用满直至宕机,直到进程再次平静下来。
https://en.wikipedia.org/wiki/Thundering_herd_problem
部分产品和功能被延迟重启
其中一小部分产品没有正确在我们的灾备站点上启动。这些通常是一些较新的产品,我们尚未完全实施和测试灾备程序。其中包括我们的上传新视频的 Stream 服务和一些其他服务。我们的团队同时进行了两个轨道的工作,以恢复这些服务:1)在我们的灾备站点上重新实现它们;2)将它们迁移到我们的高可用性集群。
Flexential 更换了我们故障的断路器,恢复了两个公用事业供电,并在 22:48 UTC 确认电力正常。我们的团队整天都全力以赴,紧急处理了问题,因此我决定大多数人应该休息一下,然后在早上开始迁回 PDX-04。这个决定延迟了我们的完全恢复,但我认为这样做减少了我们在这种情况下犯更多错误的可能性。
从 11 月 3 日一大早开始,我们的团队开始恢复 PDX-04 中的服务。这始于物理引导我们的网络设备,然后启动数千台服务器并恢复它们的服务。由于我们认为在事件中可能发生了多次重启,因此我们对数据中心内服务的状态一无所知。我们唯一安全的恢复过程是执行对整个设施的完全引导。
这涉及到手动启动我们的配置管理服务器,以开始恢复设施。重建这些服务器花了 3 小时的时间。从那里,我们的团队能够引导重建支持我们服务的其他服务器。每台服务器的重建时间在 10 分钟到 2 小时之间不等。虽然我们能够在多台服务器之间并行运行这个过程,但服务之间存在内在的依赖关系,需要按顺序逐个恢复。
截至 11 月 4 日 04:25 UTC 时,服务已完全恢复。对于大多数客户,由于我们在边缘排队分析数据的方式,您不应该在分析中看到数据丢失。我们预计,随着分析数据逐步被核心服务接收,目前出现的任何空白都将被填补。对于使用我们的日志推送功能的客户,您的日志在大部分事件中不会被处理,因此您未收到的任何内容将无法恢复。但是,我们的分析仪表板中的记录仍然是准确的。
教训和补救措施
我们有许多问题需要从 Flexential 那里得到答案。但我们也必须预期整个数据中心可能会发生故障。Google 有一个流程,当发生重大事件或危机时,他们可以发出 Code Yellow 或 Code Red 的警报。在这些情况下,大多数或所有工程资源都会转向解决当时的问题。
过去我们没有这样的流程,但今天显然我们需要实施一个类似的流程:Code Orange。我们将把所有非关键的工程职能都转向确保我们控制面的高可靠性。作为这个过程的一部分,我们预计将进行以下更改:
- 消除对核心数据中心的控制平面配置的依赖,将所有服务尽可能地首先迁移到由我们分布式网络驱动的设备上
- 确保网络上运行的控制平面在所有核心数据中心脱机时仍然能够正常运行
- 要求所有指定为“普遍可用”的产品和功能必须依赖于高可用性集群 (如果它们依赖于我们的任何核心数据中心),而不对特定设施有任何软件依赖
- 要求所有指定为“普遍可用”的产品和功能都具有经过测试的可靠灾备计划
- 测试系统故障的影响范围并最大程度地减少受故障影响的服务数量
- 对所有数据中心功能实施更严格的混沌测试,包括完全移除我们的每个核心数据中心设施
- 对所有核心数据中心进行彻底审核并制定重新审核计划以确保它们符合我们的标准
- 日志记录和分析灾备计划,确保即使在我们所有核心设施发生故障的情况下也不会丢失日志
正如我之前所说,对于这次事件和它给我们的客户和团队带来的困扰,我感到非常抱歉和尴尬。我们拥有适当的系统和流程,可以承受甚至像我们在数据中心提供商那里看到的级联故障串一样的故障,但我们需要更加严格地执行这些流程,并测试未知依赖关系。这将成为我和我们团队的焦点,将持续到今年底。过去几天的困扰将使我们变得更好。
—— https://blog.cloudflare.com/post-mortem-on-cloudflare-control-plane-and-analytics-outage/