导读:混沌工程属于一门新兴的技术学科,行业认知和实践积累比较少,大多数IT团队对它的理解还没有上升到一个领域概念,但它实际上是一种提高技术架构弹性能力的复杂技术手段。这篇文章旨在解释混沌工程是什么、它是如何使用的以及阿里开源ChaosBlade模型的定义及使用方法。
混沌工程是在分布式系统上进行实验的学科, 目的是建立对系统抵御生产环境中失控条件的能力以及信心,最早由Netflix及相关团队提出。
了解混沌工程
拥抱"混沌"
为了支持日益复杂的业务,Netflix一直都发力基础设施。现在Netflix拥有分布在190多个国家的1亿用户。早期公司的服务器运行在自己机房,但这会造成单点故障和其他问题。在2008年8月,数据库的问题导致了三天宕机,在此期间在Netflix无法看任何视频。Netflix工程师在2011年将服务迁移到Amazon Web Services。
这种由数百个微服务组成的新型分布式架构消除了单点故障。但它也引入了新的复杂性问题,需要更加可靠和容错性更强的系统。正是在这一点上,Netflix的工程团队学到了重要的教训:通过不断失败避免失败。
"混沌"新用法
为此,Netflix工程师创建了Chaos Monkey,使用该工具可以在整个系统中在随机位置引发故障。随着Chaos Monkey的出现,一门新学科诞生了:混沌工程,被描述为“在分布式系统上进行实验的学科,目的是建立对系统承受生产环境中湍流条件能力的信心。”。
2012年,Netflix开源了Chaos Monkey。今天,许多公司(包括谷歌,亚马逊,IBM,耐克等),都采用某种形式的混沌工程来提高现代架构的可靠性。Netflix甚至将其混沌工程工具集扩展到包括整个“Simian Army(中文可以译为猿军)”,用它攻击自己的系统。
混沌工程:不是那么混乱
将混沌工程视为实际混乱是一种误解。事实上,大量测试是非随机的。相反,混沌工程会在实施前进行深入思考,组织有计划和受控制的实验,旨在揭示系统在失败时的表现。
尽量减少雷区
Amalgam Insights的研究员Tom Petrocelli在接受采访时说,混沌工程最佳实践的关键是“尽量减少雷区。这意味着最大限度地减少对业务的影响。”
为了确保不会破坏业务,Petrocelli建议工程团队“精心策划”混乱工程。
不只是测试,也是生成知识的实验
Netflix混沌团队前工程经理Casey Rosenthal在DZone Q&A中明确指出,混沌工程不仅仅是测试系统的一种方法,它也是一种产生新知识的正确方法。Rosenthal在问答环节中表示,传统测试仍然至关重要,但混沌工程应该是传统测试的补充。
1.定义并测量系统的“稳定状态”。首先精确定义指标,在混沌工程中,业务指标通常比技术指标更有用,因为它们更适合衡量用户体验或运营。
2.创建假设。混沌工程应该包括真正的实验,涉及真正的未知数。
DevOps解决方案策略师、New Relic SRE Beth Long认为:“混沌工程不适用于那些可预测的、被运行手册覆盖的、你知道必须自动化但还没有开始的事件。”“你需要它来处理由复杂性本身产生的各种因素。因为不知道该怎么介入,所以每个人觉得老虎吃天,无从下爪。”
3.模拟现实世界中可能发生的事情。在《混沌工程:通过实验建立对系统行为的信心》一书中,Netflix架构师,Casey Rosenthal,Lorin Hochstein,Aaron Blohowiak,Nora Jones和Ali Basiri,提出了许多混沌工程实践方法:
模拟数据中心的故障
强制系统时钟不同步
在驱动程序代码中模拟I/O异常
模拟服务之间的延迟
随机引发函数抛异常
一定要优先考虑潜在的错误。系统越复杂,越重要,它就越有可能成为混沌工程的候选对象。”
4.证明或反驳你的假设。将稳态指标与干扰注入系统后收集的指标进行比较。如果您发现测量结果存在差异,那么您的混沌工程实验已经成功 - 您现在可以继续加固系统,以便现实世界中的类似事件不会导致大问题。或者,如果您发现稳定状态可以保持,那么你对该系统的稳定性大可放心。
上述内容来自高可用架构公众号。
阿里开源工具ChaosBlade
3月底,阿里把六年来在故障演练领域的创意和实践汇浓缩而成的工具进行开源,命名为 “ChaosBlade”。混沌工程工具 ChaosBlade 自开源以来,由于其操作简洁、无侵入、扩展性强的特点,不少开发者将它用来测试自身系统的容错能力和健壮性,还将它用来验证容器编排配置是否合理。
接下来,我们将从模型的定义和实现两个方面为大家介绍 ChaosBlade 混沌实验模型,遵循此模型,我们可以简单明了地执行一次混沌实验,不仅可以控制实验的最小爆炸半径,而且可以方便快捷地扩展新的实验场景或者增强现有场景。chaosblade 和 chaosblade-exec-jvm 工程都是根据此模型来实现。
chaosblade 工程链接:
https://github.com/chaosblade-io/chaosblade
chaosblade-exec-jvm 工程链接:
https://github.com/chaosblade-io/chaosblade-exec-jvm
模型定义
在给出模型之前,我们先明确实施一次混沌实验所涉及的一些问题:
对什么做混沌实验?
混沌实验实施的范围是什么?
具体实施什么实验?
实验生效的匹配条件有哪些?
举个例子:
一台 IP 是 10.0.0.1 机器上的应用,调用 [email protected] Dubbo 服务延迟 3s。根据上述的问题列表,先明确的是要对 Dubbo 组件做混沌实验,实施实验的范围是 10.0.0.1 单机,对调用 [email protected] 服务模拟 3s 延迟等等。明确以上内容,就可以精准的实施一次混沌实验。我们将这些步骤总结并抽象出以下模型:
Target:实验靶点,指实验发生的组件,例如容器、应用框架(Dubbo、Redis、Zookeeper)等。
Scope:实验实施的范围,指具体触发实验的机器或者集群等。
Matcher:实验规则匹配器,根据所配置的 Target,定义相关的实验匹配规则,可以配置多个。由于每个 Target 可能有各自特殊的匹配条件,比如 RPC 领域的 HSF、Dubbo,可以根据服务提供者提供的服务和服务消费者调用的服务进行匹配;缓存领域的 Redis,可以根据 set、get 操作进行匹配。
Action:指实验模拟的具体场景,Target 不同,实施的场景也不一样,比如磁盘,可以演练磁盘满、磁盘 IO 读写高、磁盘硬件故障等实验场景。如果是应用,可以抽象出延迟、异常、返回指定值(错误码、大对象等)、参数篡改、重复调用等实验场景。
回到上述的例子,我们可以将实验总结成一句话:对 Dubbo 组件(Target)进行故障演练,演练的是 10.0.0.1 主机(Scope)的应用,调用 [email protected] (Matcher)服务延迟 3s(Action)。
伪代码可以写成:
Toolkit.
// 实验靶点
dubbo.
// 范围,此处是主机
host("1.0.0.1").
// 组件匹配器,消费者还是服务提供者
consumer().
// 组件匹配器,服务接口
service("com.example.HelloService").
// 组件匹配器,1.0.0 接口版本
version("1.0.0").
// 实验场景,延迟 3s
delay(3000);
ChaosBlade 模型的实现
chaosblade cli 调用
针对上述例子,chaosblade 的调用命令是:
blade create dubbo delay --time 3000 --consumer --service com.example.HelloService --version 1.0.0
delay: 模型中的 action,执行延迟演练场景。
--time: 模型中 action 参数,指延迟时间。
--consumer、 --service、 --version:模型中的 matchers,实验规则匹配器。
注: 由于 chaosblade 是在单机执行的工具,所以混沌实验模型中的 scope 默认为本机,不再显示声明。
chaosblade 模型的定义
一个组件混沌实验模型的定义,包含组件名称和所支持的实验场景列表。
type ExpModelCommandSpec interface {
// 组件名称
Name() string
// 支持的场景列表
Actions() []ExpActionCommandSpec
// ... 略
}
一个实验场景 action 的定义,包含场景名称、场景所需参数和一些实验规则匹配器。
type ExpActionCommandSpec interface {
// 演练场景名称
Name() string
// 规则匹配器列表
Matchers() []ExpFlagSpec
// Action 参数列表
Flags() []ExpFlagSpec
// Action 执行器
Executor(channel Channel) Executor
// ... 略
}
一个实验匹配器的定义,包含参数名、参数描述等等。
type ExpFlagSpec interface {
// 参数名
FlagName() string
// 参数描述
FlagDesc() string
// 是否需要参数值
FlagNoArgs() bool
// 是否是必要参数
FlagRequired() bool
}
chaosblade 模型的具体实现
以 network 组件为例,network 作为混沌实验组件,目前包含网络延迟、网络屏蔽、网络丢包、DNS 篡改演练场景,则依据模型规范,具体实现为:
type NetworkCommandSpec struct {
}
func (*NetworkCommandSpec) Name() string {
return "network"
}
func (*NetworkCommandSpec) Actions() []exec.ExpActionCommandSpec {
return []exec.ExpActionCommandSpec{
&DelayActionSpec{},
&DropActionSpec{},
&DnsActionSpec{},
&LossActionSpec{},
}
}
network target 定义了 DelayActionSpec、 DropActionSpec、 DnsActionSpec、 LossActionSpec 四种混沌实验场景,其中 DelayActionSpec 定义如下:
type DelayActionSpec struct {
}
func (*DelayActionSpec) Name() string {
return "delay"
}
func (*DelayActionSpec) Matchers() []exec.ExpFlagSpec {
return []exec.ExpFlagSpec{
&exec.ExpFlag{
Name: "local-port",
Desc: "Port for external service",
},
&exec.ExpFlag{
Name: "remote-port",
Desc: "Port for invoking",
},
&exec.ExpFlag{
Name: "exclude-port",
Desc: "Exclude one local port, for example 22 port. This flag is invalid when --local-port or remote-port is specified",
},
&exec.ExpFlag{
Name: "device",
Desc: "Network device",
Required: true,
},
}
}
func (*DelayActionSpec) Flags() []exec.ExpFlagSpec {
return []exec.ExpFlagSpec{
&exec.ExpFlag{
Name: "time",
Desc: "Delay time, ms",
Required: true,
},
&exec.ExpFlag{
Name: "offset",
Desc: "Delay offset time, ms",
},
}
}
func (*DelayActionSpec) Executor(channel exec.Channel) exec.Executor {
return &NetworkDelayExecutor{channel}
}
DelayActionSpec 包含 2 个场景参数和 4 个规则匹配器。
上述ChaosBlade的相关内容来自阿里巴巴中间件公众号,作者肖长军(花名:穹谷),GitHub ID @xcaspar,阿里巴巴高级开发工程师,多年应用性能监控和混沌工程领域工作经验,阿里云产品 AHAS 核心开发,ChaosBlade 开源项目负责人。
第五届深圳GIAC(6月21-23日)精心策划了“混沌工程”的专题,特邀肖长军作为此专场讲师,分享《分布式服务下的混沌工程实践》的话题。
此外,组委会从互联网架构最热门的AI、大中台、混沌工程、软件工程、中间件、Java专场等领域甄选最前沿的技术创新实践案例,识别图中二维码看详情,大会7.5折购票即将截止,席位有限,速速来抢购吧!