作者:赵钰莹
本文转载于 InfoQ。
_原文链接_:https://www.infoq.cn/article/EEKM947YbboGtD_zQuLw
作为混沌工程的重要推动者,Netflix 在混沌工程手册(https://www.infoq.cn/article/AsN34J2T9QDXB0s-t9JN)中谈到,在生产环境进行软件验证的想法通常会被嘲笑。过去,这句话基本都被翻译为“我们在发布之前不打算完善地验证这些代码”。在经典的测试链路中,寻找软件缺陷的普遍信条是离生产环境越远越好。例如,在单元测试中发现缺陷要比在集成测试中发现更好,这里的逻辑是:离生产环境越远,或者是离发布越远的时候,发现的缺陷就越容易被找到根本原因并彻底修复。
对于混沌工程而言,整个链路刚好反过来:在离生产环境越近的地方进行实验越好,理想的实践就是直接在生产环境中执行。对于软件工程师来说,最难的莫过于,系统用户永远不会如预期那样与系统进行交互,混沌工程是解决这一问题的理想方法,可以让开发者了解除代码之外,整个系统其他方面的情况,特别是状态、输入、以及第三方系统导致的难以预见的行为。
据了解,在 TiDB 的研发初期,PingCAP 就引入了混沌工程,以此保证 TiDB 在各种极端情况下的稳定性。在 ArchSummit 全球架构师峰会(深圳站)2019 大会期间,InfoQ 就混沌工程理念及实践这一话题采访了 PingCAP 首席架构师唐刘,以此了解 PingCAP 的实践历程。
唐刘,PingCAP 首席架构师,主要负责分布式 Key-Value 数据库 TiKV 的研发工作,也会折腾下 TiDB 整个产品的测试,工具开发等工作。
混沌工程与分布式系统
理解是实践的前提之一,唐刘在采访中坦言,混沌工程这个名字比较容易让人困惑,包括其英文“Chaos Engineering”,初次听到这个单词时确实不太好理解。唐刘表示:“最开始,我就是把它当成一种注入测试的方法,后来才发现这其实是一门工程学科,通过实验的方式发现问题并解决问题。”
其实,混沌工程的理念很早之前就存在,唐刘表示,过去使用的错误注入就可以理解为混沌工程的一种表现方式,只不过 Netflix 将其提炼出来变成了通用准则,只要照着相关方法就能实施混沌工程,而这一技术诞生之际就与分布式系统密切相关,在《Chaos Engineering》一书中是这样表述的:
混沌工程是在分布式系统上进行实验的学科 , 目的是建立对系统抵御生产环境中失控条件的能力以及信心 。 注:分布式系统就是,其中有台你根本不知道的机器故障了,有可能会让你自己的服务也故障。——Leslie Lamport
即使可预见所有在控制范围内系统的状态,也总是会出现意外情况,比如系统依靠的某些外部服务突发宕机,这在系统搬迁上云后尤为明显,云服务也并不总是稳定可靠的。采访中,唐刘解释道,混沌工程主要是解决常规测试不能覆盖的问题。对于分布式系统来说,因为其异常的复杂性,加上错误可能在任何时候、任何地点发生,众多常规测试方法并不能保证系统正确。
当然,在某些场景下,直接在生产环境中进行实践是非常困难且不可用的,比如将干扰直接注入到行驶中的自动驾驶汽车的传感器上,这是比较危险的,但大部分用户应该都不是在操作这类生死攸关的系统。
相比较而言,唐刘认为混沌工程比较适合对数据安全性要求较高的场景。 此外,如果业务对故障容错有所承诺,也需要通过混沌工程验证系统是否可以支持容错。量化到具体指标来看,如果开发人员确定系统会宕机并且清楚宕机之后会造成较大损失,可以通过“支持快速终止实验”和“最小化实验造成的‘爆炸半径’”等方式实施混沌工程。
当执行任何混沌工程实验前,应该先有一个用来立即终止实验的“红色按钮”,更好的方法则是自动化该功能,当其监测到对稳定状态有潜在危害时立即自动终止实验。第二个策略涉及在设计实验时,考虑从实验中获得有意义结论的同时,兼顾最小化实验可能造成的潜在危害。
无论是架构师、开发人员还是测试人员,唐刘都建议关注这一技术,这相当于从另一个视角审视系统,尤其是对开发者而言。唐刘补充道,开发一个优秀的系统并不只是写代码就足够了,测试不应该仅仅依靠测试人员,他一直相信:
优秀的开发者一定是优秀的测试人员。
PingCAP 混沌工程实践
如上文所言,在开始研发 TiDB 时,PingCAP 就决定引入混沌工程,应该算是国内吃螃蟹的团队之一。谈到当初的引入原因,唐刘表示,起初开发分布式数据库时,整个团队很自然就想到需要保证开发的数据库能够让用户放心使用,这就需要进行各种各样的测试。当时,Netflix 开发的 Chaos Monkey 已经非常知名,得益于 Netflix 成功的部署经验,PingCAP 团队想到利用该工具解决稳定性问题。
回顾整个实践历程,唐刘表示大概可以分为三个阶段,第一个阶段是 2017 年之前,那时并没有自动化的概念,所有实验全部需要手动完成,包括申请机器、手动部署等。虽然比较繁琐,但也在系统上线之前发现了不少问题。
第二个阶段是从 2017 年到 2019 年初,PingCAP 基于 K8s 搭建了一套自动化 chaos 框架,叫做 Schrodinger,这套系统极大提升了整体生产力,只需自定义要做的实验,Schrodinger 就能搞定。
第三个阶段则是 2019 年初至今,PingCAP 一直在做 Schrodinger Cloud,Schrodinger 主要是为测试 TiDB,也可用来测试 TiDB 的周边工具,甚至是合作伙伴的业务。面对这些需求,PingCAP 考虑基于 K8s 做一套更加通用的 Chaos 框架,采用 Operator 的方式,任何 Chaos 在 K8s 里面都是 CRD,用户只需要定义好自己的 CRD,Schrodinger 就可以自动完成后续事宜。
在开发混沌工程实验时,唐刘建议可遵循以下原则,将有助于实验设计:
建立稳定状态的假设;
多样化现实世界事件;
在生产环境运行实验;
持续自动化运行实验;
最小化“爆炸半径”。
具体来说,系统稳态可以通过一些指标,比如延迟和 QPS 数据等来定义,当系统指标在测试完成后,无法快速恢复稳态要求,可以认为这个系统是不稳定的;其次,引进多样化的现实变量,比如网卡、磁盘故障等;然后,最为重要的是在生产环境中进行验证,这样做是存在风险的,因此最好提前与协作部门同步;最后,自动化可以让整个过程的效率更高,最小化“爆炸半径”可以避免不必要的损失。
举例来说,对于一个三副本的系统而言,可以通过随机杀死 Leader 节点的方式来验证系统是否可以保持稳态。可预想的情况是系统在主节点被杀死后会出现一段抖动,随后恢复正常则证明系统是具备容错能力的,反之,则证明系统存在问题。
在这之中,主要有两个大方向:一是发现错误;二是注入错误。TiDB 主要通过 Metrics(Prometheus 项目)、Log 和 Tracing 三种方式分析系统状态。其中,TiDB 默认不开启 Tracing 方式,因为这会对性能产生一定影响,仅在必要时启动该方法。至于注入错误,应用、存储、网络、CPU 等存在多种故障方式,唐刘在分享中提到了如下部分,供开发者参考:
根据过往实践经验,唐刘建议希望使用混沌工程的开发者可以参考混沌工程主页(https://principlesofchaos.org/) 列出的步骤和原则。但是,要想真正实践,还需要做很多工作,包括更好地对系统进行错误注入,更好地发现系统问题,这些其实业界没有通用的解决方案,因此实践起来还是比较麻烦的。采访中,唐刘推荐可以阅读 Netflix 的《Chaos Engineering》一书(中文翻译版:https://www.infoq.cn/theme/13),GitHub 上有一个 awesome-chaos-engineering的 Repo(https://github.com/dastergon/awesome-chaos-engineering)也可以参考。此外,如果整个开发团队本来对测试就不太重视,认为这完全是测试团队的事情,那可能也很难推动混沌工程落地。
结束语
三年前,我很少听到有人谈论混沌工程,现在已经蛮多了。
采访最后,唐刘表示如今的混沌工程在国内已经比较出名,这个概念应该已经进入普及阶段。但据唐刘的了解,国内真正对其应用很好的,并没有特别多公司,大部分仍然处于理清概念,但不知道如何实施的阶段。在这种背景下,企业可能最需要关注的是如何建立起自己的一整套自动化测试平台,实现对系统的自动错误注入,并自动发现系统问题。在此基础上,企业可以根据业务情况考虑深入实践混沌工程。