如何使用混沌工程有效地“搞破坏”

阅读数:2046 2019 年 9 月 24 日 08:00

如何使用混沌工程有效地“搞破坏”

本文要点:

  • 混沌工程的益处。该过程让漏洞测试更全面和有效,最终使客户受益。
  • 有坏处吗?没有,除非我们喜欢在系统于现实世界中运行时发现其弱点,不推荐这么做。
  • 混沌工程概述。简要分析混沌工程为何是加强系统的最佳方法及实现它的 4 个步骤。
  1. 定义一个可测量的稳定状态,该状态代表正常情况,用作基线。
  2. 提出一个假设,即这个状态将在控制和挑战组中继续存在。
  3. 把现实网络压力因素引入挑战组,如服务器崩溃、硬件故障和断开的连接。
  4. 在引入混沌后,试图通过发现控制组和挑战组之间的行为差异,来推翻这个假设。
  • 通过自动化重复该过程。像 Metasploit、Nmap 和 VPN 这样的自动化工具允许我们更改变量,并以指数级扩展测试。
  • 混沌工程最佳实践。了解何时使用人工测试、如何应用容器化的混沌测试,以及如何控制爆炸半径。
  • 测试工具和资源。随着混沌测试越来越流行,可以预期已经令人印象深刻的工具和资源的选择会增加。

更多的人连接到更多的服务器上,越来越依赖复杂的分布式网络,而开发中的应用程序的激增意味着增加了更多数据泄露和漏洞的机会。

现代的问题需要现代的解决方案,亚马逊经历了艰难的历程。Netflix 通过准备,用较小的不便解决了问题。

他们的做法有什么不同?

亚马逊基于云的平台 AWS 于 2015 年 9 月 20 日遇到了停电事故,造成了他们的服务器崩溃数小时,影响到很多供应商。Netflix 把这个问题看成小事一桩,因为他们在改变其服务交付模式时已经经历过了。这促使其工程团队为软件生产测试制定了独一无二的解决方案。

解决方案?混沌可以预防灾难。它基于把失败作为普遍现象而不是例外情况的想法,并促成了首个专用混沌工程工具的开发。它们被称为 Simian Army,Chaos Monkey、Chaos Kong,该家族最新的成员是混沌工程自动化平台(Chaos Automation Platform,简称 ChAP)

DevOps 中的混沌工程带来的益处有哪些?

只关注网络环境和相关的安全考虑(因为混沌工程的范围相当大),我们已经把它看作一种在已经很强大的网络安全市场中改善业务风险缓解、培养客户信心、为 IT 团队减少工作量的积极力量。如果我们是企业主,那么会有幸拥有更快乐的工程师,降低收入损失的风险和更低的维护成本。

无论是 B2B 还是 B2C,消费者将享受到更高的服务可用性,它们更可靠,更不容易受中断。技术团队将能够减少故障事件,获得对其应用程序工作原理更深入的见解。这将带来更好的设计、对 SEV 更快的平均响应时间、更少的重复事故。

有坏处吗?

评论家认为,混沌工程只是另一个行业流行语,或主要是为了给那些设计糟糕的应用程序打掩护。有些混沌工程的支持者认为,这是自我驱动心态的结果。如果我们对自己的能力和工作成果有信心,那么,对于测试它们的极限就没什么好担心的。

混沌工程旨在消除 8 个逻辑谬误,这 8 个谬误困扰着那些还是分布式网络新手的很多开发人员和软件工程师,同时,混沌工程为更精细的测试提供一个系统。

这些错误的假设是:

  1. 网络是可靠的
  2. 不存在延迟
  3. 带宽是无限的
  4. 网络是安全的
  5. 拓扑从不变化
  6. 每个系统只有一个管理员,并且,该管理员不会有变化
  7. 传递没有成本
  8. 网络是同质的

快速浏览一下世界各地的互联网使用统计数据,该数据表明,在所有软件开发阶段都需要关注创新的网络测试。为了实现这一点,就意味着要对 DevOps 采用非传统的方法

混沌工程及用例概述

基于云的分布式网络实现了以前看不到的扩展性。由于这些网络更复杂,并由于其功能的本质而具有内在的不确定性,因此,软件工程师必须使用经验方法来测试系统性和创新性的漏洞。

这可以通过控制的实验来实现,该实验制造混乱以确定任何给定的系统能够承担多少压力。目标是观察和识别系统性弱点。根据 principlesofchaos.org 的说法,该实验应该遵循如下过程,含有 4 个步骤:

定义一个可测量的状态,该状态代表正常情况,用作基线。

提出一个假设,即该状态将在控制组和挑战组中持续存在。

把实际网络压力因素引入挑战组,如服务器崩溃、硬件故障和服务中断。

在引入混沌后,试图通过发现控制组和挑战组之间的行为差异来推翻这个假设

这一过程背后的智慧表明,影响挑战组的稳定状态越难,开发人员能够对其应用程序的强度和完整性就越有信心。暴露的漏洞为部署前的改进提供了一个起点。

现在,让我们更加深入地探讨一下引入受控混沌如何改变软件的设计方法。

建立并定义我们的稳定状态和度量指标

我们的稳定状态是应用程序正常的、预期的行为,该应用程序没有明显的缺陷或漏洞。这取决于应用程序的目的和用例,因此,重要的是,在实验开始的时候,确定我们的稳定状态,定义用于评估性能的度量指标,并确定可接受的结果。

比如,在线购物者会被期望在装满购物车和结算的过程中不出现故障。用于评估结果的指标可能包含关键性能指标(Key Performance Indicators,简称 KPIs),如购物车被丢弃的比率(对零售商来说,通常非常高,令人不安)或延迟,以及服务水平协议(Service level agreement,简称 SLA)保证的正常运行时间百分比。我们可以通过评估指定时间段内收集的输出来收集这类数据,该段时间将代表稳定状态下的典型性能。

提出一个假设

我们应该利用数据集和其他信息,对预期输出做出一个有根据的猜测。这些数据应该支持我们的假设,并且应该依赖于可测量的输出而不是内部系统属性。这迫使软件工程师专注于验证系统是否工作,而不是深入研究系统是如何或为何工作的,这样做会错过重点。

以购物车为例,工程师可能使用来自结算过程的数据以最优水平工作,并假设应用程序会允许消费者从产品所在页面加载他们的购物车,进入结算页面,汇总订单,估计交付日期并生成发票,而没有发生故障、重定向或其他错误。

迫使混乱接踵而至

有很多变量可以模拟,或以其他方式引入流程。这些应该反映应用程序在使用过程中可能发生的实际问题,并根据发生的可能性进行优先排序。可引入的问题包括与硬件相关的问题,如故障或服务器崩溃,以及与突发的流量峰值或突然增长相关的过程错误。

例如,在整个线上购物的过程中,如果因季节性的促销造成大大超过预期的消费者反应,那么可能会发生什么事?我们还可以模拟服务器受到 DDoS 攻击的效果,这种攻击的目的是破坏网络。任何会破坏稳定状态的事件都是用于测试的候选项。

结果和假设的对比

把结果和最初的假设进行对比。系统是否按预期运行?或者比预计的好?还是产生了更糟的结果?这个评估不应该凭空进行,但是要包括来自团队成员和用来进行试验的服务的输入。收集所有相关数据,并花时间来找出这些数据的含义,系统正常运行的位置,是否有任何地方需要改进或一个完全的改革。

通过自动化重复该过程

同样,请记住,我们在本文中关注的是网络安全,任何特定的软件或工具都是从这个更狭隘的角度来讨论的。

有几种方法可以扩展该测试以增加我们的知识和找出潜在的解决方案。一旦我们解决了一个关注的地方,就要重新设置测试标准或参数,并用新的假设再次进行实验。我们还可以通过每次测试递增来扩大爆炸半径,把新的或更多强大的压力因素引入测试环境中,以便衡量系统的极限。

这个想法是,一次一个元素地,把尽可能多受控混沌引入到混合环境中,以便在系统完全崩溃前确定系统的最大极限。这可以在初始测试之后,通过引入自动化来进行。这样,我们可以轻松地用新的因素或预测进行其他测试,并扩展测试或重新定义参数。

对于网络漏洞测试,部署在这个环境中的两个最有效的自动化工具是 Metasploit 和 Nmap。

Metasploit 是个开源框架,允许白帽黑客通过坏人的眼睛和想法来探测漏洞。由于我们在使用的工具和技术是罪犯在用的,使用的界面要求我们去掉保护措施,如反病毒软件和防火墙,我们的 VPN 会允许我们自由地查找漏洞,而不会不必要地破坏数据的完整性,置系统的其他部分于危险的境地。

借助免费的开源网络映射器 Nmap ,在测试过程中,我们能够获得整个网络环境更壮观的视图。它不断地扫描我们的系统,记录 KPI,如正常运行时间和速度,但是,在混沌工程中,它有一个更重要的功能:远程主机检测。这样一来,测试人员就不会盲目地进入这种状况。

由于混沌工程的很大一部分涉及提出假设,然后证明或推翻它,获取尽可能多关于远程网络的信息(包括 OS 和软件),允许我们基于已知漏洞而不是猜测做出预测,并期望得到最好的结果。换句话说,它把测试团队从“已知 / 未知”带到“已知 / 已知”。

我们扫描单个网络,或通过改变命令查看整个子网络。

单个网络扫描:

复制代码
nmap target
# nmap target.com
# nmap 192.168.1.1

子网概览:

复制代码
nmap target/cdir
# nmap 192.168.1.1/24

扫描多个目标需要添加一个连接符以及最终目标编号,如下所示:

复制代码
nmap target-50
# nmap 192.168.1.1-50

这将对直到 50 的 IP 地址范围进行表面扫描。我们还可以简单地在命令行的第一行中写下 target target1 target2,每个 target 之间用空格隔开。

由于这两个工具都是开源的,因此,可以在任何 OS 或平台上使用。

上面提到的虚拟专用网络(virtual private network,简称 VPN)也可以方便地用来进行这类实验,而不仅仅是个简单的防守角色。尽管它把军用标准加密(AES-256)用于浏览器所有传入和传出的 web 流量,这通常是个很方便的事情,但是,很多面向消费者的VPN 服务的标准功能是允许我们改变源IP 地址和位置信息。后者是这里的重点部分。由于VPN 允许我们模拟来自其他国家或地区的用户,添加他们为变量,从而对去中心化的网络进行建模,这就像我们之前讨论的 DDoS,它常被用于网络攻击,因此,VPN 非常适合混沌实验。

混沌工程最佳实践

尽管混沌工程还没有取代更传统的质量保证(quality assurance,简称 QA)测试形式,但是,它已经存在了很长时间,足以发展一些程序和最佳实践。

我们需要关注的首要事情之一是尽量减小爆炸半径。在生产环境中进行测试时,这尤其必要,因为我们在这个过程中,可能会造成对实际消费者的伤害。选择可提供有意义结果的最小可能影响点,而不会增加过度的风险。如果对我们来说,收集所需的数据和见解是必要的,那么,我们可以用后续测试慢慢地扩展危险区域 。

如果这有助于减少我们的焦虑,那么,我们可以在模拟环境中使用手工测试来实施预演,分析结果,然后在实时生产环境中重复或扩展,以便获得更多相关的现实世界的结果。在我们需要回滚实验或删掉进程的情况下,制定一个备份计划也是个好主意。

我们应该为备份计划也可能失败的事实做好准备。我们的想法是引入受控的混沌,但我们永远无法确定一个复杂的系统会怎样表现,直到它完成了运行为止。

另一个越来越常见的实践是封装混沌测试。容器的协调环境允许我们在服务级别单独部署更多实验,而不会有很高的中断风险。我们可以一次销毁一个容器,以创建一点点混乱,并且,该技术将创建一个新的副本,以便在我们完成后替换它。

如果由于服务器崩溃或其他问题而造成现有容器消失,容器化的环境还使实际应用程序更轻松地快速创建和部署新容器。它允许我们信任调度程序并实施验证,在这种环境中势在必行。

对于容器化的实验,进一步是一个具有 4 个步骤的过程,它引导我们从测试那些我们知道的因素到那些我们不知道的,尽管,没有法律禁止根据个人喜好转换事物:

测试“已知 / 已知”或那些我们应该已经知道和了解的事物。比如,我们知道,当一个节点或副本容器关闭时,它将从节点集群中消失。新的副本会被创建并重新添加到集群中。

测试“已知 / 未知”或我们已经知道但缺乏理解的元素。这是我们了解上述内容的地方,但是,缺乏对在销毁一个克隆和创建一个新克隆之间需要的时间的知识。

检查“未知 / 已知”,这是我们理解但超出感知范围的事物。在这种情况下,我们不知道在特定日期或特定环境中创建新副本的平均时间,但是,我们的确知道有多少副本和会创建多少副本来替换它们。

“未知 / 未知”,它们是我们不知道或没有意识到的。例如,在整个系统关闭期间,我们不知道会发生什么事或虚拟区域故障转移是否有效,因为我们没有先前的试验或比较基础。

Kube Monkey 是 Netflix 团队的 Chaos Monkey 的一个版本,是特别为在容器化的环境中进行测试而开发的。

测试工具和资源

一旦我们知道如何有效地接受混乱,那么,就有很多部署的可行性。最好在生产环境中进行这些实验,但是,我们可以使用很多工具来模拟真实事件,而不危害实际的系统或用户。有很多自动化工具可用,它们在实时和模拟环境中都是有效和可靠的。

  • 如果我们在容器化的运行时环境中只运行几个服务器,那么,手工测试就很简单。我们可以从管理 UI 中暂停随机服务器,或把几个 SSH 注入到一些容器中并销毁它们。这也可以通过一个称为 Pumba 的仿真工具实现自动化。
  • Simian Army 中的所有工具现在都已开源,使用完全免费。我们可以在这里找到它们。
  • Git 社区有一个活跃的混沌工程社区、不断增长的知识库和额外的资源。
  • chaostoolkit 允许我们通过把策略定义为 JSON 文件,把异常注入多个平台中。

想找一些简单的实验试试?这里有两个简单的,可以帮助我们放轻松并习惯混沌工程的想法和感觉。

资源枯竭的实验

对于那些共享(通常便宜)托管平台,或是经历快速、出乎意料增长,导致资源紧张,挑战 CPU 或 RAM 极限的网站所有者来说,这是个常见的问题。

这个单实例测试,涉及对磁盘、CPU 和内存的攻击,随着系统的宕机,预期结果会产生良好的反应。但是,攻击会在所有层上成倍增加,导致系统进入掉电模式,或在重新路由流量前发出火警警报。

不可用 DNS 的实验

除了硬件可靠性,DNS 服务器对保持网络正常在线运行至关重要。模拟一个不可用的 DNS 服务器将允许我们拥有一个全面的恢复计划,以备网络可能出现这种罕见的事件。我们还可以更深入地了解应用程序在服务器丢失的情况下如何响应。

该攻击模拟 DNS 服务器黑洞的单次出现,以便测试入站流量的减少和启动可能无法初始化的假设。如果在现实中发生这样的事情,我们的团队会怎样处理?

最后的想法

生产测试(Testing in production,简称 TiP)是标准的软件工程实践。毫无疑问,DevOps 团队将在生产过程中的某些时间点上发现故障。传统方法和混沌工程的区别在于,这些故障是作为意外事件出现的,还是它们是故意引入的,以便衡量系统的优缺点。

混沌工程作为大规模分布式系统模型中特别针对和处理漏洞的方法应运而生。接受它可能需要一个文化转变:从不惜一切代价保护应用程序,到允许我们的生活中有点儿危险。

它不会真的破坏系统。

引入受控混乱可以让我们对它有更多的了解,这样,我们可以把它构建得更具弹性。
学习更多的知识,并通过申请加入谷歌混沌社区论坛成为一员参与讨论。

作者介绍:

Sam Bocetta 曾是一位安全分析师,作为网络工程师,为美国海军工作了很多年。现在,他处于半退休状态,并从事教育公众安全和隐私技术的工作。他的很多工作涉及突防试验弹道系统。他分析网络,寻找入口点,然后根据发现创建安全漏洞评估。此外,他帮助制定计划、管理和实施复杂的“道德”黑客演习,以识别漏洞,并降低美国海军(包括陆上和海上)所用的企业系统的风险状况。他的大部分工作集中在识别和防止应用程序和网络的威胁、降低攻击维度空间、消除漏洞和一般性报告。他能够识别弱点,制定新战略,以加强网络抵御一系列网络威胁。Sam 和架构师及开发人员紧密合作,以确定跨应用程序的漏洞识别的缓解控制,并实施安全评估,以模拟各种威胁的策略、技术和过程。

原文链接:

How to Use Chaos Engineering to Break Things Productively

评论

发布