这就是领先科技公司采用更全面方法的原因:动态配置。
译自 Feature Flags Wouldn't Have Prevented the CrowdStrike Outage,作者 Sergey Passichenko。
7 月 19 日,世界变成了蓝色,至少有 850 万台运行 Microsoft Windows 操作系统的电脑变成了蓝色。这是由软件引起的 有史以来最大的全球性停机事件。关键业务和社会服务受到的影响最大:航空公司、银行、紧急服务和医院。
停机事件的起因是网络安全公司 CrowdStrike 进行的例行软件更新,该公司是终端安全领域的市场领导者——一种 高级防病毒软件,可以保护设备免受网络攻击。此类软件通常作为内核驱动程序运行以获得必要的访问权限。但是,当内核驱动程序崩溃时,整个操作系统也会崩溃,计算机必须重新启动。如果故障在重启后仍然存在,操作系统就无法启动,计算机将处于故障状态。这就是 CrowdStrike 更新发生的情况。
在本文中,我们将研究公开的 技术细节 并从配置管理最佳实践的角度进行分析。
- 配置更改导致停机事件: 上述配置文件被称为“通道文件”,是 Falcon 传感器使用的行为保护机制的一部分。
- 配置格式错误或无效,触发了未经测试的代码路径: 通道文件 291 包含问题内容,导致受影响的 Windows 系统因内存越界读取而崩溃。
- CrowdStrike 拥有全面的传感器更新发布流程: 对通道文件的更新是传感器正常运行的一部分,每天会发生多次,以应对 CrowdStrike 发现的新战术、技术和程序。传感器(在每台计算机上运行的软件),但它使用单独的交付方法来进行配置(通道文件):
- 配置更改一次性推送到所有地方: CrowdStrike 没有分享其配置部署流程的详细信息,但根据后续情况,它不是逐步进行的。
- 检测并回滚错误更新花费了 1 小时 18 分钟。
- 导致停机事件的配置被视为数据,而不是代码。此快速响应内容存储在一个专有的二进制文件中,其中包含配置数据。它不是代码或内核驱动程序。
配置是代码,更新频率更高,部署速度更快;你必须对它们 更加小心,而不是更少
让我们从一个显而易见但经常被遗忘的事实开始:配置不是内容;配置是代码。配置更改是代码更改;你应该在测试和发布它们时使用相同的原则。由于配置更新发生得更加频繁,并且可以快速部署到生产环境,因此你必须比代码更新更加小心地对待它们。
那么,我们如何保护自己免受错误的配置更新的影响呢?
我们的目标是在更改过程中(在本地测试或 CI 期间)检测到错误的更改。
- 配置应该有一个模式,任何更改都应该根据该模式进行验证。模式定义和序列化格式应该支持强制执行向后兼容的更改(例如,protobuf)。
- 任何更改都应该经过额外的验证,以确保配置中没有逻辑错误。例如,某些字段仅在特定规则类型下才需要,或者业务规则的数据大小限制应该小于 4MB。
- 代码应该使用所有(或至少所有重要的)配置不变式进行测试,以确保配置更改不会在代码中触发逻辑错误。属性测试和模糊测试可以用于此目的。
- 使用生产环境中部署的代码测试配置更改。
任何合理的测试量都无法捕获所有错误,因为生产环境总是比最好的测试环境更加不同和多样化。你需要做好准备,在生产环境中捕获问题,并尽可能地防止它们演变成重大事件。
- 拥有一个“狗粮”步骤:让内部/测试用户在一段时间内测试新版本。
- 使用 分阶段发布 方法部署配置变更,逐渐增加目标数量,直到更改在所有地方部署。
- 在阶段之间留出足够的“烘焙”时间,以便您的监控有机会检测到问题。
- 更多阶段意味着更慢的部署,但至少一个“金丝雀”步骤可以捕获大多数关键错误。
- 拥有一个记录良好且定期测试的回滚机制。撤销配置更改不应该花费数小时,这对于关键配置尤其重要。
即使您执行了上述操作,错误的配置更改仍然可能到达生产环境。对于大多数常见用例,快速(且大声地)失败是最佳选择:错误的推送将被检测到并恢复,一切将顺利恢复。但有时,系统无法自行恢复,也无法上线接收更新(例如 CrowdStrike 传感器软件!)。在这种情况下,关键组件必须更具弹性,并具有额外的隔离级别。
例如,CrowdStrike 传感器可以使用 eBPF来交付更新。
另一个选择是实现“配置隔离”:
- 除非组件在开始使用新版本配置后的一段时间内保持健康状态,否则该版本配置不被视为稳定。
- 如果配置在超时后不稳定,则将其标记为“拒绝”并停止使用它。
- 这增加了复杂性,但对于无法停机的关键组件来说,这可能是正确的权衡。
一旦明确罪魁祸首是配置更改,有人建议可以通过使用功能标志来防止停机。其理由是分阶段发布是一种解决方案,而使用功能标志是最常见的进行分阶段发布的方式。
功能标志是一种有价值的技术,可以将新功能的发布与代码部署分离,高级功能标志工具通常支持基于百分比的发布。例如,您可以在 X% 的目标上启用一项功能,以确保它在达到 100% 之前正常工作。
虽然功能标志确实有助于防止停机,但考虑到 CrowdStrike 事件的规模和复杂性,它们不足以解决三个原因。
首先,全面的分阶段发布不仅需要“在接下来的几天内逐渐启用此标志”:
- 必须与监控堆栈集成以执行健康检查,并在出现问题时停止发布。
- 必须有一种方法与 CD 管道集成,以重复使用要发布到的目标列表以及要跟踪的健康检查列表。
现有的功能标志解决方案需要大量工作和专业知识才能以任何合理的规模支持分阶段发布。
其次,CrowdStrike 的配置具有复杂的结构,需要“配置系统”和“内容解释器”。此类配置将受益于一流的模式支持和端到端类型安全(保证任何更改都与代码期望的模式兼容)。最好在错误进入生产环境之前捕获它们。
最后,这次停机事件突出了行业需要认识到的一点:配置不是外部系统,而是代码的组成部分,必须以相同的严格性和工程实践来对待。这就是领先的技术公司采用更全面方法的原因:动态配置。