精准故障注入方法探索
来源:华为云确定性运维专刊(第四期)
在传统的软件工程领域,测试技术是最常用的在软件开发阶段分析源码找出软件缺陷的方法。但是,随着软件规模增加、复杂程度提升、应用场景多样化,特别是当前云原生系统的出现及大量应用,传统的软件测试技术已经无法准确覆盖软件缺陷场景,导致大量的缺陷遗留到软件部署和运行阶段。现代软件系统已经成为支撑信息、金融、工业和服务业等众多产业的新型基础设施,其性能和可靠性对产业的影响力巨大。各种类型的故障时有发生,而且造成的损失居高不下,比如视频网站故障、通话系统故障、订票业务系统故障等。有报告指出,全球每年信息系统的宕机平均成本高达每分钟9000美元, 而且这一成本还在不断增加。因此,及时检测和解决故障,保障软件系统的可靠性至关重要。
当前主要采用反应式的方案解决系统中发生的故障,即当故障发生时检测、诊断故障、恢复系统,主要的过程包括:故障检测、故障诊断、故障隔离和故障恢复等,如图1所示。但是,每个故障处理过程都需要一定时间,造成系统宕机不可用。因此,为解决该问题,前摄式的故障解决方案逐渐开始流行,即提前预测故障,在故障发生之前解决故障,减少由于故障宕机的时间,故障注入应运而生。故障注入也称为混沌工程(Chaos Engineering),是一门测试分布式软件或系统的技术,通过主动注入故障,允许工程师研究系统行为并对系统进行增强、从而,在使用软件和系统时避免故障,保障软件的确定性运行状态,故障注入逐渐成为可靠性工程师SRE的重要工具。
图 反应式故障处理过程
故障注入虽然并不是新的话题,但是在现代软件系统具有新的应用价值,具有明显的降本增效的收益。首先,受到软件自身复杂性以及外部运行环境的动态性的影响,云原生系统具有更大的不确定性,故障场景更加复杂。故障注入能够帮助SRE掌握系统的韧性边界,提前针对不同类型的故障制定可靠性增强方案,避免故障发生。其次,现代云原生软件系统具有庞大的规模以及系统复杂性,动辄上百上千的依赖组件,难以通过规则或者经验准确掌握故障的传播路径。故障注入通过主动引入故障可以观察故障的传播路径以及传播规律,帮助SRE更准确了解系统;最后,当前智能运维逐渐兴起并被广泛采用,但是仅仅依靠系统既有的少量的真实故障难以准确、全面评价运维算法的效果。因此,故障注入可以提供大量的准生产环境故障案例验证智能运维算法的效果,促进智能运维产业的发展。鉴于上述多种收益,故障注入已经成为众多信息产业特别是云计算产业的关键技术服务。
故障注入现状分析
故障注入在2010年被Netflix首先系统化应用到云计算环境中,自此经过十几年的发展,出现了大量的工具,比如Chaos Monkey[1]、Gremlin[2]、 ChaosBlade[3]、ChaosMesh[4]、AWS FIS[5]等,越来越多的企业开始应用故障注入或者加入故障注入业务的商业竞争,并且开始向垂直化领域发展如面向数据库的故障注入等。但是,现有的故障注入系统主要在节点、虚拟机、进程等粒度上注入故障,存在故障爆破范围不可控的问题,难以与故障注入的原则完全对齐[6]。这种局面导致无法精确量化系统的韧性以及智能运维算法的有效性。因此,产业界急需能够在API、请求、函数以及指令等细粒度故障范围可控的精确故障注入。
为实现这一目标,学术界开展了丰富的研究,并产生一定的学术成果。 UC Santa Cruz的Peter Alvaro[7]教授提出了基于路径驱动的故障注入方法(LDFI),并且在Netflix进行了实践。这种方法能够通过业务的以来路径找到精确的故障注入点。论文[8]提出用于系统调用错误的新型故障注入框架,称为PHOEBE。PHOEBE的独特之处在于:首先,PHOEBE使开发人员能够充分观察系统调用;其次,PHOEBE生成的错误模型是真实的,因为它们模拟了生产中自然发生的错误;第三,PHOEBE能够自动进行实验,系统地评估应用程序在生产中的系统调用调用错误的可靠性。Sieve[9]提出第一个用于集群管理控制器的自动可靠性测试工具。通过系统地、广泛地干扰控制器对当前集群状态的视图,然后比较有扰动和无扰动时集群状态的演变,以检测安全性和可靠性问题。论文[10]构建了一个名为Rainmaker的“按钮式”可靠性测试工具,作为任何云支持应用程序的基本SDK应用。Rainmaker帮助开发人员预测基于云的故障模型下的多种故障,而无需编写新的策略、预言或测试用例。Rainmaker直接使用现有的测试套件,是用于现有测试环境的即插即用工具。Rainmaker在应用程序和云服务之间的交互中注入错误。它在REST层这样做,因此对测试中的应用程序是透明的。更重要的是,它对自动故障注入策略进行了编码,以涵盖各种分类的错误模式,以及包含现有内部软件测试的自动预言。Acto[11]实现了第一个针对云系统运营商的自动端到端测试技术。Acto使用以状态为中心的方法将控制器与托管系统一起进行测试。Acto不断指示控制器将系统调整为不同的状态,并检查系统是否成功达到这些期望的状态。Acto将操作建模为状态转换,并系统地实现状态转换序列,以在不同场景中执行支持的操作。Gremlin[12]和3milebeach[13]允许注入故障来影响特定的请求,但使用这些工具需要对源代码进行插桩。由于服务通常以不同的编程语言实现,用户在没有任何先验知识的情况下无法适当地向源代码添加额外的代码,这阻碍了这些工具的广泛采用。
虽然工业界和学术界提出了多种方法,已实现故障爆破范围的精确控制。但是,目前仍然无法实现在用户无感的情况下的精确故障注入,需要进一步探索技术方案。
精准故障注入必要性
图3展示 三个服 务实例(Frontend、Checkout、Product)以及三种请求API的调用链。服务实例通过代理与其他实例通信,代理为不同的API调用配备了转发规则。从图中可以观察到,Product服务的API级故障会影响向另外两个API函数(即search product和checkout)发出的请求。为进一步比较不同故障注入的差异,图4展示了服务实例级别、API级别以及请求级别注入的故障对业务的影响。从图中可以看出,服务实例级别的故障影响的业务种类最多,其次是API级别的故障,请求级别的故障能够精确控制故障的爆炸范围,只影响到目标请求。这些充分说明精确故障注入的重要性。
图 服务实例故障造成的不同请求同时失效样例
图 不同粒度故障注入对业务的影响
精准故障技术路线
既然精确的故障注入具有重要意义,那么如何控制故障的爆炸范围?这里提出一种解决方案,解决方案的主要框架如图5所示。该解决方案包括了6个模块。其中路径驱动的故障点场景计算模块用于获得精确而全面的故障注入点;故障场景优先级排序模块利用PageRank等重要性排序算法对候选的故障注入点进行排序;故障注入系统利用eBPF、strace、ChaosBlade等具体的技术实现不同场景的故障注入;多层次故障注入模块实现从基础设施到API层面的多层次多粒度故障注入;面向不同编程语言的故障注入模块实现Java、Python、C++等程序的无侵入故障注入,实现函数级和指令级的故障注入;抗故障韧性能能力评估模块根据系统在不同故障中的表现对系统的韧性进行定量评估。
图 精准故障注入框架
以下针对四种具体的不同粒度的精准故障注入进行说明。
1)程序语句级故障注入:该粒度的精准故障注入与编程语言有关,需要利用编程语言的特性进行故障注入。利用字节码动态插装技术实现对运行时 Java 程序进行语句级别故障,图6展示了故障注入的流程。常见的故障包括返回值修改、抛出异常、增加请求时延、CPU资源耗尽以及内存耗尽等。在程序运行过程中,通过在目标语句中注入Sleep函数实现请求、函数的延时,效果如图7所示。Python语言与Java语言类似,都有虚拟机,可以通过反射的方式动态修改字节码。这里利用Hypno[14]将Python故障代码注入到运行时的Python进程中,然后利用Bytehoo[15]在指定位置触发故障注入的字节码,并在故障注入后移除故障逻辑。与Java和Python不同,Golang/C++等语言没有虚拟机,需要在源代码中插桩,程序编译时重写语法树,通过环境变量控制故障开启,参加ChaosMesh针对Golang的故障注入。
图 应用程序中运行时注入sleep后请求时延增加
图 应用程序中运行时注入sleep后请求时延增加
2)系统调用级故障注入:针对特定的系统调用注入故障如增加系统调用的时延或者修改返回值等。Strace作为Linux中常用的性能追踪工具可以用来实现系统调用的故障注入,具体的指令格式为:strace -e inject=syscall_set[:error=errno|:retval=value][:signal=sig][:syscall=syscall][:delay_enter=delay][:delay_exit=delay][:when=expr],至少指定error、retval、delay_enter、delay_exit中的一个,error和retval不能同时指定。例如:利用Strace针对mysql进行故障 注 入,首先找到mysql在宿主机上的pid,直接利用strace对该mysql进程的accept系统调用进行故障注入。由于无法连接mysql服务,因此业务请求无法被处理,所以在故障发生期间,没有出现请求,如图8所示。
图 Strace对Mysql的accept系统调用注入故障后的效果
此外,还可以利用eBPF[16]提供的bpf_override_return()帮助函数实现系统调用故障注入。
3)请求级故障注入:基于eBPF实现请求故障注入方法,包括:监测客户端与服务端建立套接字的过程; 捕获套接字并获取所述套接字的端口信息;依据套接字的端口信息判断所述套接字是否为需要被监听及故障注入的对象;依据判断结果将所述套接字作为值更新至SOCKHASH中,并以对应的端口信息作为键值建立索引;当所述SOCKHASH中的套接字调用sendfile()函数或sendmsg()函数时,根据预先指定的故障注入模式在套接字层面进行故障注入。这种方法能够精准注入故障以模拟现实故障,且故障注入的实现不影响其他服务性能,实现影响面可控,进而保障系统的可靠性。
4)SQL级故障注入: 提出的故障注入工具即GDB-FI的运行流程如图9所示,总体包括:系统初始化、故障点选择、故障前置条件生成、故障策略生成和故障恢复五个部分。其中,系统初始化部分主要是解析用户的输入,提取目标连接信息、故障类型、语句匹配模板等信息,并通过GDB附着到GaussDB进程中完成初始化设置。故障点选择主要负责找到特定连接的工作线程并在其关键路径上设置断点。故障前置条件生成主要负责根据用户输入的SQL语句匹配模板生成故障注入的前置条件,并在符合条件时进行故障注入。故障策略生成主要负责将用户输入的故障类型和相关参数等信息转化为对于的故障策略并进行注入。故障恢复即完成故障的注入之后恢复系统的正常运行。
图 SQL级别故障注入框架
精准故障注入实现
融合上述多层次多粒度故障注入方案,设计与实现了CloudWrecker故障注入系统。该系统可以覆盖超过30种的故障场景,用户可以通过交互式界面进行故障场景选择和配置,并提供故障调度以及可视化能力,帮助用户实现面向云原生系统的一站式故障注入,后续会将系统开源。
图 CloudWrecker的运行界面
总结与展望
精准故障注入对云原生系统的可靠性至关重要。结合现有技术如字节码插桩、eBPF等可以在不侵入用户代码的情况,实现精准的故障注入。精准的故障注入不仅有助于发现系统的可靠性漏洞,还可以验证现有智能算法的效果,值得学术界和工业界进行更加深入的研究。随着大模型的广泛应用,面向大模型基础设施的精准故障注入技术将会是下一个研究热点。
[1] Chaos Monkey, https://netflix.github.io/chaosmonkey/;
[2] Gremlin, https://www.gremlin.com/;
[3] ChaosBlade,https://github.com/chaosblade-io/chaosblade;
[4] ChaosMesh, https://chaos-mesh.org/;
[5] AWS FIS, https://aws.amazon.com/cn/fis/;
[6] Principles of Chaos engineering, https://principlesofchaos.org/;
[7] P. Alvaro, J. Rosen, and J. M. Hellerstein, “Lineage-driven fault injection,” in Proceedings of the 2015 ACM SIGMOD International Conference on Management of Data, ser. SIGMOD ’15. New York, NY, USA: Association for Computing Machinery, 2015, p. 331–346.
[8] L. Zhang, B. Morin, B. Baudry and M. Monperrus, "Maximizing Error Injection Realism for Chaos Engineering With System Calls," in IEEE Transactions on Dependable and Secure Computing, vol. 19, no. 4, pp. 2695-2708, 1 July-Aug. 2022, doi: 10.1109/TDSC.2021.3069715.
[9] Xudong Sun, Wenqing Luo, Jiawei Tyler Gu, Aishwarya Ganesan, Ramnatthan Alagappan, Michael Gasch, Lalith Suresh, and Tianyin Xu, Automatic Reliability Testing for Cluster Management Controllers, In Proceedings of the 16th USENIX Symposium on Operating Systems Design and Implementation (OSDI'22), Carlsbad, CA, USA, Jul. 2022.
[10] Yinfang Chen, Xudong Sun, Suman Nath, Ze Yang, Tianyin Xu, Push-Button Reliability Testing for Cloud-Backed Applications with Rainmaker,20th USENIX Symposium on Networked Systems Design and Implementation (NSDI 23);
[11] Jiawei Tyler Gu, Xudong Sun, Wentao Zhang, Yuxuan Jiang, Chen Wang, Mandana Vaziri, Owolabi Legunsen, and Tianyin Xu. 2023. Acto: Automatic End-to-End Testing for Operation Correctness of Cloud System Management. In Proceedings of the 29th Symposium on Operating Systems Principles (SOSP '23). Association for Computing Machinery, New York, NY, USA, 96–112. https://doi.org/10.1145/3600006.3613161
[12] V. Heorhiadi, S. Rajagopalan, H. Jamjoom, M. K. Reiter, and V. Sekar, “Gremlin: Systematic resilience testing of microservices,” in 2016 IEEE 36th International Conference on Distributed Computing Systems (ICDCS), 2016, pp. 57–66.
[13] J. Zhang, R. Ferydouni, A. Montana, D. Bittman, and P. Alvaro, “3milebeach: A tracer with teeth,” in Proceedings of the ACM Symposium on Cloud Computing, ser. SoCC ’21. New York, NY, USA: Association for Computing Machinery, 2021, p. 458–472.
[14] Hypno, https://github.com/kmaork/hypno;
[15] Bytehook, https://github.com/tzickel/bytehook;
[16] eBPF, https://ebpf.io/;
- 点赞
- 收藏
- 关注作者
评论(0)