共计 5418 个字符,预计需要花费 14 分钟才能阅读完成。
本文首发于:火山引擎开发者社区;
作者:字节跳动基础架构团队零碎治理方向负责人邵育亮。
本文次要为大家介绍字节跳动在高可用建设上的一些思考和落地教训。先给大家简略介绍一下零碎治理团队是做什么的。零碎治理团队在基础架构团队外部,次要负责字节跳动研发的闭环生态:从服务开发,到大规模微服务架构下的联调、开发以及对应的公布,再到上线当前的微服务治理、对应的流量调度、容量剖析,以及到最初通过混沌工程的建设帮忙业务晋升高可用能力。接下来就进入正题。首先介绍一下字节跳动混沌工程建设的背景。大家晓得字节跳动有很多 APP,咱们有十分多的服务,这些服务大抵能够分成三个类型:
- 在线服务:大家能够了解成反对抖音、西瓜视频等的后端服务。这些服务的特点是它们跑在咱们自建的大规模 K8s 上的 PaaS 集群上,这是一套十分大的微服务架构。
- 离线服务:包含一些举荐模型的 training,大数据的 report 计算等等,都属于离线服务。它们依赖大规模的存储和计算的能力。
- 基础架构:承载了字节中国的所有业务线,向上提供一套 PaaS 化的能力,包含计算和存储等,撑持各种业务不同的应用场景。
不同的服务体系对高可用的关注度并不一样。咱们简略做一下剖析:
- 在线服务:自身是无状态服务,运行在 K8s 容器上,其存储都在内部的 MySQL、Redis。这些无状态服务很不便做扩容,在产生故障时能尽可能容错,当然也可能会做一些降级。
- 离线服务:有状态服务,很关注计算的状态。大数据的计算服务特点是运行工夫很长,Training、model 的工夫都特地长。它能容忍一些谬误(如果某次 job 挂了,能够进行 retry),其更多状态的一致性、数据的完整性是依赖底层存储系统的反对。所以咱们在离线服务的高可用建设,很大规模依赖于整个基础架构提供的高可用能力。
- 基础架构:基础架构自身是有状态的,它是进行大规模存储、计算的平台,可能会遇到一些网络故障、磁盘故障等灰天鹅事件,这其中咱们关注较多的是数据一致性。
应答不同的服务类型,零碎治理团队负责高可用的同学提出了不同的解决方案。在这里先给大家介绍咱们应答在线服务(无状态服务)时混沌工程的演进。
在线服务的混沌工程演进
混沌工程平台 1.0 架构咱们认为咱们的混沌工程平台 1.0 版本还不是一个混沌工程零碎,更多的是一个故障注入零碎。
上图是咱们这个平台 1.0 版本的架构。这个平台面向用户提供可视化界面,可进行故障注入和一些简略的配置。在底层物理机上咱们装了 Agent。Agent 运行在宿主机上,可实现容器间网络相干的故障注入。对于服务稳态,咱们在做混沌演练的时候,在平台上能够注入一些 metrics,用户能够写一个 bosun 语句去查问 metrics,咱们提供一个阈值,零碎就会轮询这个 metrics 来断定服务是否达到稳固的状态。如果超出边界,咱们就进行故障复原。如果没有超出边界,就持续演练,看是否能达到预期。为什么这个零碎不能称之为一个混沌工程的零碎?Netflix 的 Principle of Chaos 对混沌工程的定义(http://principlesofchaos.org/)有五大准则:
- 建设一个围绕稳固状态行为的假说
- 多样化真实世界的事件
- 在生产环境中运行试验
- 继续自动化运行试验
- 最小化爆炸半径管制
比照以上五个准则,咱们来看一下为什么说这个平台只是个故障注入零碎。
- 首先整体的稳态还绝对比拟简陋。
- 理论的微服务架构中会存在各种故障,这个平台中只做到了比较简单的故障注入,如故障提早、断网等。
- 在生产环境进行演练是过后能做到的事件。
- 因为稳态比拟简陋,所以很难真正评估这个零碎是不是稳固,零碎也无奈自动化运行试验。
- 整个零碎申明 scale 的 scope 做的不是特地好。另外过后技术实现的构造是在物理机的宿主机上做故障注入,自身有肯定的隐患,爆炸半径管制做得也不是特地好。
混沌工程平台 2.0 架构
在 2019 年的时候,咱们开始想把混沌工程平台 1.0 版本演进到下一代,心愿可能做一个真正合乎混沌工程规范的零碎,因而有了平台的 2.0 版本,咱们认为它是字节跳动真正意义上的第一个混沌工程零碎。
混沌工程平台 2.0 版本的一些降级:
- 架构降级:引入了一个故障核心层,解耦了业务逻辑和底层故障注入。
- 故障注入:随着 Service Mesh 更大规模的利用,网络调用相干的故障更多基于 sidecar 实现。
- 稳定性模型:这个阶段咱们也构建了一个稳态零碎,基于服务的要害指标和机器学习等算法实现稳态计算。咱们十分关注稳态零碎,认为真正的自动化演练是不须要人工干预的,所以须要一个零碎来辨认被演练的零碎是否稳固。如果零碎只看到一堆 metrics,它很难间接去认知零碎的稳定性。咱们心愿通过一些特定算法将这些 metrics 聚合成一个百分位指标,假如这个指标达到 90 分,咱们就认为它是稳固的。后文还会再介绍咱们怎么在这个稳态零碎外面做算法的投入。
故障核心架构
咱们的故障核心借鉴了 K8s 的架构。
混沌工程平台 1.0 零碎有一个问题:假如通过 Agent 在 K8s 里胜利注入了一个提早故障。但 K8s 自身有弹性调度能力,如果很可怜在演练过程中这个服务 crash 了,K8s 会主动在另外一个机器上把这个 Pod 启起来。这种状况下,你认为故障演练是胜利的,但其实没有胜利,而是从新起了新的服务。故障核心能够在容器产生漂移的时候持续注入故障。所以咱们是一套申明式的 API,申明的不是要注入什么故障,而是形容服务器的一种状态,例如 A 跟 B 之间的网络是断开的,那么在任何状态下故障核心要保障 A 和 B 是断开状态。其次,整个零碎借鉴 K8s 的架构,有丰盛的 controller 反对底层不同的故障注入能力。在对业务的疾速需要的反对过程中,咱们在 controller 里能很快接入 Chaos Mesh、Chaos Blade 等开源我的项目。咱们本人也原生做了一些 controller,比方 service mesh controller,agent controller,服务发现的 controller 等。
爆炸半径管制
后面提到故障核心是通过申明式 API 注入故障,咱们就须要定义故障注入 model。
如上图所示:
- Target:示意要注入故障的指标服务。
- Scope Filter:对于爆炸半径管制,很重要的一点是咱们心愿可能让业务去帮忙申明心愿演练的 scope,咱们称为 Scope Filter。通过 Scope Filter 能定义故障注入的指标,能够是一个机房,一个集群,一个可用区,甚至准确到实例级别乃至流量级别。
- Dependency:它是所有可能影响服务自身的异样起源,包含中间件,某上游服务,也包含所依赖的 CPU、磁盘、网络等。
- Action:故障事件,即产生了何种故障,比方上游服务返回回绝、产生丢包;又比方磁盘写异样、CPU 被抢占等。
所以在故障核心申明故障时,须要形容上述内容,表明业务心愿零碎中是怎么的故障状态。
稳态零碎
稳态零碎会波及一些算法的工作,这里次要介绍三个算法的场景:
- 时序序列的动态分析:咱们叫稳态算法,能够尝试剖析服务是否稳固。其中应用了阈值检测、3 Sigma 准则、稠密规定等算法。
- AB 比照稳态剖析:借鉴了 Netflix 在用的曼 - 惠特尼 U 测验,大家能够看一些相干 paper 和文章介绍。
- 检测机制:应用指标稳定一致性检测算法,用来剖析强弱依赖。
通过以上这些算法(还有其余算法),稳态零碎可能去很好地刻画零碎稳定性。
自动化演练
咱们将自动化演练定义为齐全不须要人工干预,由零碎进行故障注入,在注入过程、演变过程中剖析服务的稳定性,随时止损或拿到后果。咱们当初进行自动化演练有这样一些前提:
- 可能明确演练的理论场景的指标;
- 通过稳态零碎,对稳态假如具备自动化判断能力;
- 可能通过申明式 API、Scope Filter 管制混沌演练的影响范畴,试验过程生产损失极小。
自动化演练目前次要的利用场景是强弱依赖剖析,包含:
- 强弱依赖现状与业务标注是否统一;
- 弱依赖超时是否会拖垮整体链路。
总结
当初咱们再来回顾一下,为什么咱们认为混沌工程平台 2.0 版本是一个混沌工程零碎。还是比照前文提到的五个准则:
- 建设一个围绕稳固状态的假说:通过稳态零碎曾经开启了稳态假说的演进。
- 多样化真实世界的事件:当初故障分层上更加正当,补充了大量中间件故障和底层故障。
- 在生产环境中运行试验:这一点在 1.0 期间就实现了,2.0 中进行了扩大,可反对生产环境、预发环境、本地测试环境的各种故障演习。
- 继续自动化运行试验:提供 csv、sdk、api 等能力,让业务线在本人心愿的服务公布流程中继续跟性能做整合。咱们也提供了 API 能力,帮忙业务线在须要的环境做故障注入。
- 最小化爆炸半径:提供申明式 API 的能力,其中一个起因就是为了管制爆炸半径。
撑持底层零碎演练的基础设施混沌平台
后面提到了离线服务很大水平上依赖底层状态的一致性,所以如果把基础架构中存储、计算做好,就可能很好地撑持业务。咱们用一个新的基础设施混沌平台来做一些外部的实验性尝试。对于基础架构的混沌工程,咱们要突破一下混沌工程的一些规范准则。
- 首先针对基础架构的混沌工程不太适宜在生产环境演练,因为它依赖于底层的故障注入,影响面十分大,爆炸半径不好管制。
- 在自动化演练上,业务方须要更加灵便的能力,进一步跟他们的 CI/CD 买通,也须要更加简单的编排需要。
- 对于稳态模型,除了稳定性之外,咱们更关注一致性。
要反对离线环境的混沌工程,该基础设施混沌平台给了咱们一个平安的环境,让咱们可能在外面开展手脚做更多的故障注入,比方 CPU、Memory、File system 等系统资源故障;回绝、丢包等网络故障;以及包含时钟跳变、过程被杀、代码级异样、文件系统级办法 error hook 在内的其余故障。对于自动化演练的自动化编排,咱们心愿通过这个平台给用户更加灵便的编排能力,例如:
- 串并行任务执行
- 随时暂停 & 断点复原
- 基础设施主从节点辨认
咱们也提供了一些插件能力,让一些组件团队可能更灵便地注入故障。有的业务团队可能在本人的零碎里曾经埋点了一些 hook,他们心愿这个零碎可能更间接地帮忙注入故障,同时也心愿复用咱们的编排体系和平台体系。咱们通过 hook 的形式,业务团队只需实现对应的 hook,就可能注入特定的故障,而后持续应用咱们的整套编排体系和平台。
从混沌工程到零碎高可用建设
咱们最开始做 Chaos Engineering 的时候,对团队的使命定位是在字节跳动落地混沌工程。然而当咱们做出一些能力找业务线应用的时候,会发现业务线对此并没有什么需要。起初咱们致力思考之后调整了团队的使命:通过混沌工程或者其余一些伎俩帮忙业务推动高可用建设。调整之后咱们就从过来钻研 Chaos Engineering 的业界倒退,变成了要去贴着业务了解业务的高可用。咱们如何帮忙业务进行高可用建设呢?
什么是高可用
咱们用上面这个公式来进行了解高可用。
- MTTR(Mean Time To Repair):均匀修复工夫
- MTBF(Mean Time Between Failure):均匀生效间隔时间
- N:事变产生次数
- S:影响范畴
这个公式的值显著小于 1,算进去应该是所谓的三个九、五个九。要让 A 的值足够大,须要:
- MTTRNS 的值足够小。所以须要升高 MTTR,升高事变产生次数,放大故障范畴。
- MTBF 的值变大。即尽可能拉开两次故障之间的距离。
如何升高 MTTR、N、S 呢?
升高故障影响范畴(S)
当面向生产架构的故障产生的时候,要升高故障影响范畴,从架构侧能够采纳一些设计伎俩:
- 单元化设计:用户申请隔离
- 多机房部署:系统资源隔离
- 外围业务独立部署:业务性能隔离
- 异步化解决
在这里,混沌工程能够做的事件是帮忙 SRE 团队验证这些架构设计是否合乎预期。
缩小故障产生次数(N)
这里要从新定义一下故障。Failure 是不可避免的,咱们要尽可能在软件系统的架构层防止 Failure 转换成 Error。如何升高从 Failure 到 Error 的转换率?最重要的是增强零碎的容错性,包含:
- 部署:异地多活,流量灵便调度,服务兜底,预案治理;
- 服务治理:超时配置,熔断 fail fast。
这其中混沌工程起到的作用帮忙验证零碎容错能力。
升高均匀修复工夫(MTTR)
上图展现了 MTTR 波及的一些因素:Fail Notification、诊断、修复、测试、最终上线等所需的工夫。要升高 MTTR 能够对每个波及的因素退出一些设计伎俩:
- 充沛的监控告警笼罩。须要推动业务进行告警的治理。
- 在告警充沛笼罩的同时保障告警的准确性。
- 高效定位,加强排障能力。目前咱们跟外部的 AIOps 团队单干,做进一步的智能化阻碍剖析,升高诊断工夫。
- 疾速止损预案。从修复到测试再到最终上线,须要有一个预案零碎,依据诊断的故障特色备有预案库,做到点击按钮即可抉择精确的预案做复原。
这其中混沌工程可做的是进行应急响应演练。其实演练不只是针对零碎,也是演练组织里每个人的应急能力。当面临事变时,团队能够有一套规范的 workflow 去发现问题、定位问题、解决问题,这也混沌工程零碎心愿演练达到的成果。
后续布局
最初介绍一下咱们在高可用、混沌工程方面的后续布局,次要有三个方面:
- 故障精细化能力建设
- 面向不同体系故障分层建设
- 丰盛各层故障能力
- 丰盛混沌工程的应用场景
- 持续摸索自动化场景
- 升高用户接入和应用老本,打造轻量级平台
- 扩大混沌工程外延
- 回归可用性视角,继续摸索混沌工程与高可用的关系
- 建设故障估算机制,通过量化故障损失进行预测和剖析,从而帮助决策在混沌工程的投入