字节跳动混沌工程之云原生场景实践

时间:2021-12-05 00:37:57

本文将整体介绍字节跳动混沌工程在云原生场景下的实践,主要包括混沌工程背景介绍和发展历程,以及应用韧性增强服务(Application Resilience Enhancement Service,ARES)产品和未来展望。其中将从技术架构、演练流程、核心功能介绍等多个维度,重点展开介绍混沌工程应用韧性增强服务。

混沌工程介绍

1. 混沌工程诞生

字节跳动混沌工程之云原生场景实践

微服务拓扑图

随着公有云市场的高速增长和云原生技术的发展,企业用户逐步向云原生架构迁移,系统内的微服务进一步朝着分布式的架构演进,微服务数量呈爆炸式增长,各服务间相互调用关系也变得更为繁杂,这对软件的可靠性提出了更高的要求,而传统的质量工程和软件测试已无法检测出生产环境中的意外故障和性能问题。为了应对愈发复杂的实际生产问题,混沌工程应运而生,它可以帮助用户提前检测出生产环境中可能潜在的故障和性能问题。

2.混沌工程是什么

字节跳动混沌工程之云原生场景实践

混沌工程是一套通过在系统基础设施上进行实验,主动找出系统中脆弱环节的方法学。通过实验性的方法,发现系统中潜在的、可以导致灾难性故障、或让用户受损的薄弱环节,并推动研发自主地进行问题修复、代码优化,最终建设成为真正意义上的韧性架构,增加用户抵御突发事件的能力与信心。

混沌工程最早由 Netflix 在 2008 年开始实践,通过实践,Netflix 总结出来混沌工程五大基本原则:

  • 建立服务的稳定状态假设
  • 多样化真实世界的事件
  • 生产环境进行实验
  • 持续自动化运行试验
  • 最小化“爆炸半径”

混沌工程与传统测试

传统的测试或者 QA 通常包括以下环节:

  • 单元测试:验证代码片段的工作是否符合预期。
  • 集成测试:验证代码片段和系统中的其他模块是否能够一起正常工作。
  • 系统测试:验证整个系统和设计的行为是否一致。

然而这些传统的测试只能覆盖一些应用层面的内容,并不能解决异常场景下更为复杂的问题,如:网络发生延迟时,服务是否能够正常工作;服务器宕机时,系统是否能够切换到备份等。面对上述问题,混沌工程提供系统应对故障、从故障中恢复的能力,帮助我们预先发现潜在风险。

混沌工程与故障注入

混沌工程通常通过注入故障来模拟实验场景,虽然混沌工程、故障注入和故障测试在侧重点和工具集的使用上有一些重叠,但是混沌工程和故障注入本质上是不同的思维方式。

  • 故障注入: 故障注入是基于一个特定的条件、变量的验证方法。首先要知道会发生什么故障,然后一个一个地注入。然而在复杂分布式系统中,无法穷举所有可能的故障。
  • 混沌工程:混沌工程的思维方式是主动找故障,是探索性的,我们不知道摘掉一个节点、关掉一个服务会发生什么故障,虽然按计划做好了降级预案,但是关闭节点时却引发了上游服务异常,进而引发雪崩,这不是靠故障注入或预先计划能发现的,它是发现新故障信息的实践过程。

混沌工程云原生场景的诞生

字节跳动混沌工程之云原生场景实践

混沌工程在字节跳动的实践主要包括三个阶段:

  • 容灾演练平台:从 2016 年开始,字节跳动就已经开始建设内部容灾演练平台,该平台的主要目标是解决故障注入问题,同时提供基于阈值的简单指标分析与自动停止。当时容灾演练使用的大多是通过网络干扰模拟下游依赖故障,帮助头条、抖音等业务方实现了生产环境的容灾演练。
  • 混沌工程平台:2019 年字节跳动的混沌工程平台演进到了 2.0 版本。在架构上使得故障注入更加简单可控,在模型抽象上使得故障注入的扩展性更强,同时结合自动化指标分析能力,尝试进行强弱依赖分析、超时配置合理性验证等新的实践活动。更多字节的业务进行了混沌工程实践,包括抖音,飞书,西瓜视频等等。
  • 云原生产品:在内部实践中,我们发现很多用户场景是云原生场景,因此,服务内部业务的同时,输出了 ToB 高可用产品应用韧性增强服务(ARES)

混沌工程应用韧性增强服务

上面讲了字节跳动混沌工程发展的三个阶段,三个阶段实现能力总结如下:

  • 在第一阶段的容灾演练平台中,主要聚焦于基本故障注入能力的建设,如网络延迟,拒绝,丢包这些故障注入能力。
  • 在第二阶段的混沌工程平台中,主要在故障注入的基础上进一步扩展到混沌工程的理念,尝试了强弱依赖分析,故障指标分析的功能,结合字节的业务进行了更多的实践。
  • 在第三阶段的建设当中,随着越来越多的应用向着云原生的架构演进,平台从原来相对单一的微服务场景和单机场景进一步扩展到云原生场景。在面向云原生的场景中,对系统架构进行了更加灵活的扩展和升级,比如,把更多平台能力通过云原生的 controller、DaemonSet 组件来实现,故障定义也以 CRD(Custom Recource Definition)的形式来完成。除此以外,进一步把平台定位推向更加贴近混沌工程原生的理念当中,在平台的实验编排、故障观测、故障验证、稳态假说等功能上进行迭代增强,期望给用户提供更加完整的混沌工程体验。基于此需求和背景,我们研发了混沌工程应用韧性增强服务产品。

应用韧性增强服务( Application Resilience Enhancement Service,简称 ARES)是一款遵循混沌工程实验原理并融合了内部多年业务实践的产品。应用韧性增强服务提供丰富故障场景,能够帮助分布式系统提升容错性和可恢复性,增强系统和应用的韧性,满足用户对系统和应用的高可用需求。

字节跳动混沌工程之云原生场景实践

下面将主要介绍 ARES 如何进行落地和实现,以及相关的技术突破。

演练流程

演练流程可以总结为准备实验、实验编排、开始实验、执行实验、故障结果分析、优化系统六大步骤,下面具体介绍下每个步骤:

  • 准备演练:准备演练方案、演练目标、演练场景、演练影响面等
  • 演练编排:编排要演练的服务、任务串并行、类型、执行情况、实验时间、频率等
  • 开始演练:可根据实验编排,自动开始实验
  • 执行任务:根据演练任务,对目标进行故障注入,并开启演练指标采集
  • 结果分析:根据演练的前、中、后三个阶段,展示和分析演练对象等相关的指标,自动分析演练结果的有效性
  • 优化系统:根据实验结果,不断优化优化,最终建设成为韧性系统

字节跳动混沌工程之云原生场景实践

核心功能介绍

上图主要列了产品的主要功能,支持实验配置、实验流程编排、故障观测、实验报告与风险统计、演练活动、高可用演练方案、个人工作台等几大功能。

1. 多集群演练

字节跳动混沌工程之云原生场景实践

随着服务规越来越大,单个 Kubernetes 集群支撑的节点数有限,并且用户通常会将控制面和数据面进行分离等,把服务部署在多个集群上。因此,混沌工程云原生产品支持了多集群同时演练的能力,还支持异地多活演练。并支持多集群统一管理,可以动态增删多个指定 Kubernetes 集群,如下图所示。

字节跳动混沌工程之云原生场景实践

2. 多场景需求

分布式服务和场景越来越复杂,有些用户服务已通过完成云原生容器化部署和编排,而有些用户只有部分通过实现云原生改造,部分服务还在虚拟机上。由于服务的特殊性和改造成本,有一大部分用户仍通过物理机或者虚拟机运行服务。针对用户的复杂使用场景和需求,产品支持了多场景的演练。

字节跳动混沌工程之云原生场景实践

如上图所示,ARES 既支持应用服务的演练,也支持基础设施自身的高可用演练,适用于以下多种场景:

  • 应用服务维度:同时支持通过 Kubernetes 编排的微服务和单机(物理机/虚拟机)部署服务的服务演练
  • 基础设施:支持 Kubernetes 自身组件(Pod/Service/Node)的演练和单机(物理机/虚拟机)机器的演练

通过故障场景的细分,我们可以精准地控制故障的爆炸半径,同时我们也支持在数量、比例上进行精确的配置,能够按照全部、随机指定个数、指定数量、一定百分比四种模式进行目标选择。

3. WebShell运维管理

字节跳动混沌工程之云原生场景实践

上图是 WebShell 管理的部分截图,通常用户注入故障后,故障的有效性和指标,或者产生的日志,需要登录机器查看和操作。平台支持通过 WebShell 管理集群服务的 Pod、Node 节点,并查看对应的日志信息。可以快速验证故障是否生效,方便定位问题。

4. 支持故障类型

当前支持的故障能力类型如上图所示,主要支持网络、Pod、系统、主机、DNS、Kubernetes、进程、接口、Java、Python、Golang、中间件、自定义故障等几大故障类型,并且故障类型会持续不断地丰富。

5. 灵活的用户演练范围

在网络服务演练中,根据用户不同需求和不同场景,用户可以选择在服务的上游或者下游方向进行注入。

字节跳动混沌工程之云原生场景实践

6. 流程编排

通过演练流程探索系统的稳定性和缺陷,在提供了核心的故障模拟能力与指标分析能力之后,可以通过演练流程将故障、指标分析、串行或并行执行。

演练流程具备相对固定的步骤:演练开始阶段通过系统指令或对硬件设备进行人为干预注入干扰;演练进行中,观察并收集各类指标的实时变化;演练结束后,分析对比收集的各类指标,评估系统的状态变化。

7. 故障观测

故障管控

字节跳动混沌工程之云原生场景实践

上图主要展示故障验证的监护流程图,对故障的管控主要分为两个部分:

  • 故障生命周期管控:通过平台的管控页面,可以实时看到每一个故障所在的宿主机和 Pod 信息,以及它的运行状态、开始结束时间等等。通过可视化界面,用户可以用大盘的视角看到每一个故障实验的运行状态正常与否,更加安全、放心地进行混沌实验。
  • 故障验证:故障注入时,监控指标往往会发生变化,用户常常通过看监控来检验故障是否生效,然而在我们过去的实践当中,常常出现“故障成功注入,但是监控指标却没有变化”的情况,原因有很多:比如用户自身的系统做了容灾措施,当故障发生时,相关的业务指标依旧正常。为了在此类情况下我们依然可以验证故障,我们对于每一种故障都会采集相应的验证指标,此类指标是故障的最直观反映的指标,基本不会受其他因素干扰,在故障实验进行时,在页面上同步展示指标,辅助故障观测,快速验证故障的有效性。

故障生效分析

向系统中注入故障后,我们采用AI算法,观测分析故障是否生效。理论上,我们可以通过对同一个环境注入故障和不注入故障之间的系统差异来观测故障注入的效果。但事实上,我们不能同时既注入故障,又不注入故障,所以我们无法真实的观测到这个差异。因此,我们引入因果推断算法,通过构造贝叶斯结构化时间序列模型,预测反事实条件下(没有故障注入)的时间序列,并与注入故障后实际观测到的时间序列比较,计算注入故障对系统的累计因果效应,从而判断故障是否生效。

字节跳动混沌工程之云原生场景实践

上图中竖直的黑色虚线表示故障注入的时刻,紫色的阴影部分表示蓝色虚线的置信区间

上图从上到下分别展示为:

  • 上半部分 - 黑色实线:指标的真实观测时间序列,蓝色虚线:模型的拟合值
  • 中间部分 - 蓝色虚线:真实值与拟合值之间的差异
  • 下半部分 - 蓝色虚线:故障发生后,真实值和拟合值差异的累积和,即累积因果效应

实验可观测性

字节跳动混沌工程之云原生场景实践

如上图为注入内存故障后,内存使用的数据。在 观测 页面查看当前实验场景的运行结果。目标 Pod 的 Memory 负载在故障注入的一分钟时间内,到达了预设故障参数值 70% 。实验结束后可以恢复到正常状态。

8. 多监控接入

在混沌工程的实验里面,可观测能力是非常重要的一环,而监控指标的获取和接入是可观测能力里面比较基础的功能。

混沌工程的系统本身不会做过多的监控能力,但为了获取到混沌实验观测中所需要的指标,需要有一个适配层来接入用户的监控系统,以及获取监控系统的监控指标。而用户所使用的监控系统是多样的,因此适配层会适配多种主流的监控系统,并转化成混沌平台上的指标语义。

在 ARES 产品中,用户可以在平台上提前配置好想要观测的指标,提供指标的类型,名称,所属的监控系统类型(如prometheus,zabbix,skywalking等),指标 URL 等。配置完成过后,该指标可以在平台的稳态观测,指标分析等能力中进行使用。而由于不同监控系统的指标语义有所差异,ARES也会将不同语义的指标进行转换,统一为平台侧的语义,方便进一步的处理和展示。

字节跳动混沌工程之云原生场景实践

9. 稳态假设

“围绕稳态行为进行假设” ,是混沌工程的重要原则之一,也是混沌工程实验和普通的故障注入,故障演练的重要区别。

稳态观测的功能是 ARES 里面对混沌工程原则进行产品化落地的重要实践,通过对实验的稳态观测,使用户的每一次混沌演练都有比较明确的,可以量化的实验结果。

关于稳态假设的一些概念,我们这样定义:

  • 稳态:可以量化观测的对象,比如 QPS ,CPU 使用率,Http 返回码,Http Reponse 数据;
  • 稳态探测:获取稳态数据的过程,比如发起 http 请求获取返回码,获取 response 数据;向监控系统发起请求获取监控数据;通过调用自定义指令获取指令结果。
  • 假设:对系统行为的“预期”或者“猜测”,更具体的就是对稳态的猜测,比如“QPS会下降”,“CPU使用率会升高”,“Http返回码从200变成404”等等
  • 稳态算子:对稳态进行的计算操作,简单的比如“=”算子,用来判断 http 返回码是否是200;复杂的比如平均值计算等等

通过稳态假设的能力,我们把传统的故障注入和故障演练的场景进一步提升,向着混沌工程的理念更进一步,使得故障演练能得到更加直观的实验结果。

10. 权限管理

权限管理是 ARES 作为云产品的基本能力之一。同一个主账户下,不同子账户可能是不同的业务部门,不同部门的服务可能会运行在不同集群,也可能同集群下相同的 namespace。为了防止各业务账户故障注入互相影响,我们设计了一套权限管理体系,抽象出 role,permission,resource 等概念,进行权限管理。

  • resource:指资源,ARES 里面的各种抽象的对象都可作为资源,例如主机管理中的主机,实验模块下的场景,实验等等。
  • permission:权限单元,指对某资源是否有操作权利的表达,“对实验A有操作权限”则是一个permission。
  • role:指角色,一个账户可以拥有多个角色,一个角色可以拥有多个权限单元。

基于以上设定,我们提供了权限配置,权限继承等能力,使得管理员可以方便地对不同账户,不同资源进行管理。

11. 故障插件

故障插件为用户提供了更加高级,灵活的能力。顾名思义,在故障注入的前,中,后三个阶段,我们提供了钩子,用户可以在这三个阶段执行自定义的脚本,使故障实验更加丰富。

字节跳动混沌工程之云原生场景实践

12. 工作台大盘

工作台大盘以数据可视化大盘的形式,为用户提供了高频实验故障,高频实验集群,实验场景执行统计等实验执行的数据分析和统计的功能。通过大盘,用户可以直观,快速的了解到工作空间内的实验执行情况。

字节跳动混沌工程之云原生场景实践

未来展望

混沌工程是个漫长的探索之旅,故障的模拟和注入只是其中的一部分,我们的最终目标是要通过故障注入实验,提前发现系统的薄弱环节,降低事故影响,提升系统韧性。基于目前发现的问题和不足之处,我们从多个方面讨论未来的期望:

  • 演练可观测:当前平台已经具备了演练的能力,然而在演练的过程中,难以及时地对故障和演练进行观察,包括故障的生命周期,相关的服务状态,主机状态,爆炸半径等。未来平台将进一步优化演练的可观测能力,融入AI能力,能实现对服务拓扑的感知,让用户在演练的时候实时的看到整个服务集群的调用拓扑,以及故障注入前后的拓扑变化。

  • 韧性智能分析当前平台主要半自动对故障结果和效果进行分析。未来通过不同维度和不同程度的实验,对实验的结果进行数据分析,结合AI智能判断,评估出系统的韧性度等级和脆弱点,智能生成演练场景,并梳理出系统优化方案,推荐用户进行下次演练,形成演练闭环,增强用户抵御线上真实突发故障的信心。

  • 更好的安全性和故障能力:如 eBPF 内核技术等新的技术能力,给故障实现带来更多的可能性,能给我们带来更加精细化,更加安全,性能更好的故障注入能力。

未来我们将探索更多的故障能力,探索内核,硬件级别的故障。当前业界混沌工程还处在不断持续探索阶段,混沌工程的核心理念尚未体现,因此不断探索、完善混沌工程,任重而道远,欢迎大家和我们交流,一起努力共建。

字节跳动混沌工程之云原生场景实践