当今社会互联网应用越来越广泛,用户量日益剧增。在人们对互联网服务的依赖性增大的同时,也对服务的可用性和体验感有了更高的要求。那么如何保障服务在运营过程中能一直给用户提供稳定的、不间断的、可靠可信的服务呢?
例如一个金融产品,如果出现过一次问题,那可能带来巨大的损失。大家都知道金融产品的系统架构和服务逻辑是相当复杂的,至此大家都会第一时间联想到测试工程师,他们会通过单元测试、集成测试、性能测试等来验证服务的稳定性。但尽管如此,也是远远不够的,因为错误可以在任何时间以任何形式发生,尤其是对分布式系统。所以这里就需要引入混沌工程(Chaos Engineering)。混沌工程是一套通过在系统基础设施上进行实验,主动找出系统中的脆弱环节的方法学,最早由Netflix及相关团队提出。它旨在将故障扼杀在襁褓之中,也就是在故障造成中断之前将它们识别出来。通过主动制造故障,测试系统在各种压力下的行为,识别并修复故障问题,避免造成严重后果。2012年,Netflix开源了Chaos Monkey。今天,许多公司(包括谷歌,亚马逊,IBM,耐克等)都采用某种形式的混沌工程来提高现代架构的可靠性。
混沌工程非常适合揭露生产系统中未知的弱点,但如果确定混沌工程实验会导致系统出现严重问题,那么运行该实验就没有任何意义。目前国内有相关使用的公司内的实践偏向于故障测试,即在一个具体场景下实施故障注入实验并验证预期是否得到满足。这种测试的风险相对可控,坏处是并没有通过故障注入实验探索更多的场景,暴露更多的潜在问题,测试结果比较依赖实施人的经验。当然这也是我们认为在混沌工程目标之路上必经的一个阶段。故障测试预期、验证与混沌工程定义的稳态状态行为是存在差异的,差异的根本原因还是组织形态的不同。2014年,Netflix团队创建了一种新的角色,叫作混沌工程师(Chaos Enigneer),并开始向工程社区推广。而国内大部分企业目前并没有一个专门的职位来实施混沌工程,项目目标、业务场景、人员结构、实施方式的不同导致了对于稳定状态行为的定义不太标准。当然我们目前也没有Chaos Enigneer。所以基于不同的定义标准、不同的组织型态和不同的阶段,我们在混沌工程实验的引入和使用也是更偏向故障测试。以下原则描述了应用混沌工程的理想方式,这些原则来实施实验过程。对这些原则的匹配程度能够增强我们在大规模分布式系统的信心。
专注于系统的可测量输出结果,而非系统的内部属性。在短时间内测量输出结果并将此作为系统稳态的代表。整体系统的数据吞吐量、错误率、延迟百分比等皆可作为稳态行为的关键性表示指标。通过关注实验中各系统行为模式,混沌工程能够验证系统是否正常工作——而无需尝试解析其工作原理。
混沌变量应直接反映各类现实世界事件。我们应该考虑各类或者相关联的故障,任何可能导致稳态中断的事件皆应被视为混沌实验当中的潜在变量。由于多元化的业务和高复杂的系统架构,可能会遇到非常多种类型的故障,这里已经有人优先分析P1和P2故障,按照IaaS、PaaS、SaaS层的角度绘制了故障画像,如下图
从功能性的故障测试角度来看,非生产环境去实施故障注入是可以满足预期的,所以最早的强弱依赖测试就是在日常环境中完成的。不过,因为系统行为会根据环境和流量模式有所不同,为了保证系统执行方式的真实性与当前部署系统的相关性,推荐的实施方式还是在生产环境,但是目前很多企业还是没有做到生产环境实验。
使用故障注入平台化代替手动实验,自动构建编排和分析。
混沌工程建议在线上环境进行实验,但是导致系统异常甚至异常放大的可能性是存在的。从实施角度看,最好是通过技术手段来有效的减少异常带来的影响,例如通过系统稳态指标来有效停止注入、限流、流量切换、数据隔离等方式都是减少业务影响的手段。提供多样化、可视化操作的故障注入自动化平台
作为各种演练和故障测试及验证的统一入口
积累沉淀多种实验方案,建立系统上线健壮性评估基线
帮助业务发现更多未知的影响业务稳定的问题
验证业务的告警有效性和完整性
验证业务的故障预案是否有效
目前业内模拟故障的工具比较多样化,支持的功能和场景也各有优劣。通过对比来看,chaosblade支持功能和场景比较丰富,同时社区也是比较活跃的。我们在充分验证了大部分注入功能后,选择了它作为底层注入的核心模块。
chaosblade 所支持的场景,可以参考文档:https://chaosblade-io.gitbook.io/chaosblade-help-zh-cn/
整个故障注入一共分为四个阶段:
平台构建的思路还是以四个主流程为核心来开展。分类来看平台模块如下图所示:目前平台的注入场景我们支持了系统层和网络层类型,主要包含了网络延迟、丢包、cpu满载、内存满载、磁盘IO满载场景。这些场景都是热插拔式集成到平台,方便平台场景灵活调整和扩展。
实操演练我们挑选了1个相对较稳定的业务A(业务A是一个多节点的任务调度和目标抓取的服务),对业务A的测试环境进行了实验,同时业务方很期待如此稳定的系统是否存在或者有更多的缺陷。
业务方任务系统在运行时,以下指标可以代表系统的稳态。假设某些节点在存在性能或者网络相关问题的时候,可能存在任务提交响应延迟,不影响稳态。假设存在节点宕机,不影响稳态(此处不做介绍)。
使用系统层+网络层随机注入场景模拟。
在平台选择我们提供的系统场景故障模板和注入目标(一个注入任务中,单个机器只能注入一种场景,场景和机器随机选择)
通过选择的注入模板和目标,生成一个注入计划,如下图:
执行注入,如下图,在注入过程中,操作者是可用随时结束和暂停注入任务的。
人为暂停指定目标,点击继续会继续注入
服务cps陡降
提交成功的任务,失败率大幅提升
用户任务提交出现不同程度延迟
关联服务进程异常退出
监控不细粒,能发现cps和失败率增加,但定位困难
发现整个服务的cps有陡降,意味着服务的处理能力下降严重。任务执行失败数量增加,意味着任务提交了,但是服务并没有按照预期来完成。用户提交延迟和超时增加
结束整个注入任务
假设:某些节点在存在性能或者网络相关问题的时候,可能存在任务提交响应延迟,不影响稳态。
证明:存在任务提交响应延迟,间接性意味cps的下降。
反驳:发现非预期的 任务执行失败增加和关联进程异常退出的问题,监控缺失和不细粒等问题。
平台目前涉及到多个维度的权限:用户在职状态,平台用户权限,用户和机器权限,平台和机器权限。2、当因为注入导致目标机器满载或者丢包严重,sre同学无法登陆机器,平台是如何能正常中止?答:系统在对目标机器注入时会开白名单,例如丢包或者网络中断的场景会导致其他用户无法登陆,但是我们的任务机是不受影响的。系统性能满载的注入,我们会控制满载程度,不会让机器直接满载到无法工作的情况。后面也有个性化参数配置,用户在设置方位内可调整。3、平台是否能自动判断停止注入?如果不能,人工中止忘记了注入会一直持续吗?
答:目前还无法自动判断是否需要停止注入。如果人工中止操作忘记了,用户在选择注入模板或者自己配置注入计划的时候,会有一个持续注入时间,超过这个时间,注入任务自动结束。逐步完善本文中提到的按照IaaS、PaaS、SaaS层的角度绘制的故障画像中的故障场景。
结合SLO、降级和流量调度,缩小爆炸半径,为线上注入实验做准备。