混沌工程与Agent Harness故意引入故障以增强韧性引言痛点引入从“99.99%可用性承诺”的崩塌说起2023年12月22日全球最大的云服务商之一AWS发生了一次跨区域主要覆盖北美和欧洲的us-east-1、eu-west-1、eu-west-2的“严重服务中断”——这次持续近3小时的故障不仅导致Netflix、Spotify、Slack等数亿级用户量的应用集体瘫痪还影响了亚马逊自身的电商交易、AWS控制台操作、第三方支付甚至部分医疗预约系统。事后AWS公布的故障原因极其简单却极具讽刺性一位运维工程师在手动更新S3存储服务的全球区域配置时误删了一个“用于同步关键元数据到边缘节点的DNS记录触发器”——这个触发器本身只占用了代码仓库不到100行的空间但它的缺失直接切断了边缘S3节点与主元数据集群的连接进而引发了雪崩式的连锁故障边缘节点无法定位文件S3 API返回500 Internal Server Error依赖S3存储用户数据、前端资源、日志的Lambda、EC2、Route53、CloudWatch、CloudFront等20项AWS核心服务全部失效最终整个“以AWS为基础设施底座的互联网半壁江山”都陷入了黑暗。无独有偶2021年Facebook现Meta的全球6小时大断网、2019年阿里云香港区的近8小时S3-like OSS故障、2018年GitHub的近24小时“master分支保护机制误触发导致的代码仓库冻结”事件……这些都是近年发生的、造成了亿美元级经济损失、严重用户信任危机的重大生产事故。当我们复盘这些事故时会发现一个惊人的共性触发原因微小且意外手动误操作、硬件单一节点故障、软件配置文件的语法错误、甚至是“一个程序员在办公室里不小心碰掉了电源插座的电源线”这不是玩笑2015年谷歌就发生过类似的触发事件系统没有有效的冗余/隔离/降级机制或者有机制但要么“没有经过充分的验证就上线了”要么“在真实的故障场景下完全失效了”故障排查和恢复过程极其缓慢运维团队面对监控面板上成千上万条红色告警信息完全不知道“从哪里下手”故障定位花了几十分钟甚至几小时找到问题后又因为“没有预演过故障恢复流程”而手忙脚乱系统的“韧性Resilience”几乎为零所谓的“高可用性High Availability”只是基于“过去没有发生过重大故障”的虚假承诺完全无法应对“哪怕是最微小的、真实世界中一定会发生的意外”。为什么会出现这种情况难道我们这些软件工程师、运维工程师、架构师每天熬夜写代码、调监控、做备份都是白费力气吗当然不是——但问题在于我们的“传统可靠性保障手段”比如单元测试、集成测试、回归测试、负载测试、压力测试、蓝绿部署、灰度发布、异地多活只能验证“系统在已知的、正常的或可预期的异常场景下是否能正常运行”却完全无法验证“系统在未知的、不可预期的、真实的生产级故障场景下是否能保持可用、快速恢复”。那怎么办难道我们只能“祈祷系统永远不要出故障”吗答案当然是否定的——我们需要一种“主动出击”的可靠性保障手段而不是“被动防守”的祈祷。这种手段就是我们今天要讨论的混沌工程Chaos Engineering。解决方案概述混沌工程是什么Agent Harness又是什么混沌工程故意引入故障提前发现系统弱点混沌工程是一种通过在生产环境或高度仿真的预生产环境中主动、可控地引入真实的或模拟的故障比如服务器宕机、网络延迟、网络分区、磁盘满、CPU负载过高、数据库连接池耗尽、API调用超时、配置文件错误等来观察系统的行为发现系统的弱点验证系统的冗余/隔离/降级机制是否有效进而持续改进系统的韧性的方法论。混沌工程的核心思想可以用一句话来概括“与其让系统在真实的、不可控的、会造成巨大损失的生产故障中‘自然死亡’不如让它在我们主动、可控、可观测、可终止的‘混沌实验’中‘提前死亡’一次然后我们从中学习把它救活让它变得更强大”——这和“疫苗原理”几乎一模一样疫苗是主动、可控地向人体引入少量的、灭活的或减毒的病原体让人体产生抗体提前获得对真实病原体的免疫力混沌工程则是主动、可控地向系统引入少量的、可观测的、可终止的故障让系统产生“韧性抗体”提前获得对真实生产故障的免疫力。Agent Harness混沌工程实验的“基础设施底座”与“执行引擎”虽然混沌工程的思想非常美好但要真正在生产环境中落地却面临着巨大的技术挑战如何安全地引入故障我们不能真的让系统在混沌实验中完全崩溃必须要有“紧急停止按钮”即“实验终止机制”一旦发现实验失控就必须立即停止所有故障注入恢复系统到初始状态如何可控地引入故障我们不能“瞎搞”必须要有明确的实验目标、实验范围、实验时长、实验强度、实验终止条件并且要严格按照“预定义的实验计划”来执行如何可观测地引入故障我们不能“只知道引入了故障却不知道系统发生了什么”必须要有完善的监控、日志、追踪系统能够实时、全面地采集系统在实验前后的各项指标比如可用性、延迟、吞吐量、错误率、资源利用率等并且能够对这些指标进行分析和对比如何高效地引入故障我们不能每次做混沌实验都需要“手动登录到服务器上执行命令”必须要有自动化的工具或平台能够“一键式”或“按计划”地执行混沌实验如何在大规模分布式系统中引入故障现代的生产级系统几乎都是由成百上千个微服务、容器、虚拟机、物理服务器组成的大规模分布式系统我们不能只在单一节点上引入故障必须要有能力在“多个节点”、“多个服务”、“多个区域”、“多个可用区”上同时或按顺序引入故障并且要能够模拟“网络分区即CAP理论中的‘Partition Tolerance’触发场景”这样的分布式系统特有的故障。为了解决这些技术挑战业界出现了各种各样的混沌工程工具和平台比如Netflix开源的Chaos Monkey、Gremlin的商业混沌工程平台、阿里巴巴开源的ChaosBlade、字节跳动开源的Chaos Mesh、微软的Azure Chaos Studio、谷歌的Cloud Chaos Engineering等——而Agent Harness也称为Chaos Agent或Chaos Daemon就是这些混沌工程工具和平台的核心基础设施底座与执行引擎。简单来说Agent Harness是一个部署在目标系统的每个节点物理服务器、虚拟机、容器、Pod等上的轻量级后台进程或守护进程它的主要职责包括故障注入执行接收来自混沌工程平台或实验控制器的故障注入指令然后在目标节点上执行具体的故障注入操作比如杀死进程、断开网络连接、限制CPU/内存/磁盘IO、修改系统时间等实验状态监控实时监控实验的执行状态比如故障是否成功注入、是否已经触发终止条件、系统是否已经恢复等并将这些状态信息上报给混沌工程平台或实验控制器紧急终止机制内置“紧急停止按钮”一旦收到来自混沌工程平台或实验控制器的终止指令或者自身检测到实验失控比如目标服务的错误率超过了预定义的阈值、系统的资源利用率超过了预定义的阈值等就会立即停止所有故障注入操作并执行预定义的“系统恢复脚本”将目标节点恢复到实验前的初始状态节点信息采集采集目标节点的基本信息比如节点类型、操作系统版本、CPU型号、内存大小、磁盘容量、网络配置等并将这些信息上报给混沌工程平台或实验控制器方便平台或控制器选择合适的目标节点执行混沌实验权限管理内置完善的权限管理机制确保只有授权的混沌工程平台或实验控制器才能向其发送故障注入指令防止未经授权的人员或程序在目标节点上“瞎搞”安全通信与混沌工程平台或实验控制器之间采用加密的通信协议比如TLS 1.3确保故障注入指令和状态信息的传输安全防止被第三方窃取或篡改。可以说没有Agent Harness混沌工程就无法真正在大规模分布式系统中落地——Agent Harness就像是混沌工程平台的“眼睛、耳朵、手和脚”没有它平台就“看不到目标节点的情况、听不到目标节点的反馈、无法向目标节点发送指令、无法在目标节点上执行操作”。最终效果展示使用混沌工程与Agent Harness提升系统韧性的真实案例为了让大家更直观地感受到混沌工程与Agent Harness的威力我们先来看几个业界已经成功落地混沌工程并取得显著效果的真实案例案例1Netflix的Chaos Monkey与Chaos KongNetflix是混沌工程的开创者和最佳实践者——早在2011年Netflix就推出了全球第一个开源的混沌工程工具Chaos Monkey并开始在自己的生产环境中大规模使用。Chaos Monkey的功能非常简单它会在工作日的上午9点到下午3点也就是Netflix的工程师们都在办公室上班的时间方便他们及时处理实验中发现的问题随机选择一个AWS EC2实例也就是Netflix微服务的运行节点然后直接将其终止——是的你没有听错Netflix就是在自己的生产环境中每天随机杀死自己的服务器那Netflix为什么敢这么做因为Netflix的微服务架构是高度冗余、高度分布式、高度自动化的——每个微服务都有多个副本Replica部署在不同的AWS可用区AZ甚至不同的AWS区域Region而且Netflix有一个完善的自动化扩缩容系统Auto Scaling Group一旦某个EC2实例被Chaos Monkey终止Auto Scaling Group就会立即启动一个新的EC2实例来替代它整个过程完全不需要人工干预用户甚至根本感觉不到有服务器被杀死了。更重要的是Netflix通过Chaos Monkey的持续实验提前发现了无数个系统弱点——比如某个微服务没有配置多副本、某个微服务的副本都部署在同一个可用区、某个微服务的依赖服务没有配置降级机制、某个数据库连接池的大小设置不合理、某个自动化扩缩容系统的触发阈值设置过高等等——然后Netflix的工程师们会立即修复这些弱点让系统变得更强大。除了Chaos Monkey之外Netflix还推出了一系列的混沌工程工具统称为Simian Army猿猴军团Chaos Gorilla比Chaos Monkey更“暴力”它会随机终止一个AWS可用区的所有EC2实例用来验证系统的“跨可用区冗余机制”是否有效Chaos Kong比Chaos Gorilla更“疯狂”它会随机终止一个AWS区域的所有EC2实例用来验证系统的“跨区域异地多活机制”是否有效Latency Monkey在API调用之间引入随机的延迟用来验证系统的“超时重试机制”和“降级机制”是否有效Conformity Monkey检查所有EC2实例是否符合Netflix的配置规范比如是否安装了必要的安全补丁、是否配置了正确的监控指标、是否启用了自动化扩缩容等Doctor Monkey实时监控所有EC2实例的健康状态一旦发现某个EC2实例出现了异常比如CPU负载过高、内存使用率过高、磁盘满等就会提前将其终止防止它引发更大的故障Janitor Monkey清理AWS账户中不需要的资源比如未使用的EC2实例、未使用的EBS卷、未使用的S3桶等节省成本Security Monkey检查AWS账户的安全配置比如是否有开放的SSH端口、是否有未授权的IAM用户、是否有未加密的EBS卷或S3桶等防止安全漏洞。通过Simian Army的持续实验Netflix的系统韧性得到了质的飞跃——根据Netflix公布的数据在使用Simian Army之前Netflix每年会发生数十次持续时间超过10分钟的重大生产事故而在使用Simian Army之后Netflix每年发生的持续时间超过10分钟的重大生产事故不到5次而且每次事故的恢复时间都从原来的“几小时”缩短到了“几分钟甚至几秒钟”。案例2阿里巴巴的ChaosBlade与阿里云的AHAS阿里巴巴也是混沌工程的重要实践者和推动者——早在2017年阿里巴巴就开始在自己的电商平台淘宝、天猫、支付宝中大规模使用混沌工程用来验证系统在“双11”这种“全球最大的购物狂欢节”场景下的韧性2019年阿里巴巴开源了自己的混沌工程工具ChaosBlade并将其贡献给了CNCFCloud Native Computing Foundation云原生计算基金会成为了CNCF的沙箱项目2020年阿里云推出了基于ChaosBlade的商业混沌工程平台AHASApplication High Availability Service应用高可用服务帮助更多的企业用户落地混沌工程。ChaosBlade的功能比Netflix的Chaos Monkey更强大、更全面——它支持多种故障类型包括基础设施层、应用层、容器层、Kubernetes层等4大类共200种故障类型、多种部署环境包括物理服务器、虚拟机、Docker容器、Kubernetes集群、阿里云ECS/ACK/ASK等、多种实验模式包括手动实验、定时实验、流量染色实验、灰度实验等、多种终止条件包括手动终止、定时终止、指标阈值终止等而且它的Agent HarnessChaosblade-exec非常轻量级只占用不到10MB的内存和不到1%的CPU资源不会对目标系统的性能造成任何影响。阿里巴巴通过ChaosBlade的持续实验提前发现了无数个“双11”场景下的系统弱点——比如某个核心交易微服务的降级机制在“流量突增10倍”的场景下完全失效、某个分布式数据库的分库分表规则在“某个分片的EC2实例被终止”的场景下导致数据丢失、某个CDN的边缘节点在“网络延迟突增1000ms”的场景下无法回源到主站、某个支付系统的对账服务在“系统时间被修改”的场景下出现了错误等等——然后阿里巴巴的工程师们会立即修复这些弱点确保“双11”当天系统的稳定运行。根据阿里巴巴公布的数据在使用ChaosBlade之前阿里巴巴每年“双11”当天都会发生几次持续时间超过1分钟的核心服务故障而在使用ChaosBlade之后阿里巴巴从2018年到2024年的“双11”当天核心交易服务的可用性达到了100%而且每次“双11”的峰值流量都从原来的“每秒几十万笔交易”增长到了“每秒几百万笔甚至上千万笔交易”系统的韧性得到了前所未有的提升。除了阿里巴巴自己之外还有数万家企业用户包括美团、京东、拼多多、腾讯音乐、网易云音乐、小米、华为等在使用阿里云的AHAS平台落地混沌工程并且都取得了显著的效果——比如美团通过AHAS平台的混沌实验提前发现了某个外卖配送微服务的跨区域调用超时问题修复后该微服务的错误率降低了90%比如京东通过AHAS平台的混沌实验提前发现了某个电商库存微服务的分布式锁死锁问题修复后该微服务的可用性从99.9%提升到了99.999%。案例3字节跳动的Chaos Mesh与抖音的韧性提升字节跳动也是混沌工程的后起之秀和创新者——早在2019年字节跳动就开始在自己的短视频平台抖音、TikTok中大规模使用混沌工程用来验证系统在“全球数十亿级用户量”的场景下的韧性2020年字节跳动开源了自己的混沌工程工具Chaos Mesh并将其贡献给了CNCF成为了CNCF的孵化项目2023年已经晋升为毕业项目这是CNCF项目的最高级别意味着Chaos Mesh已经达到了“生产级、成熟、稳定、可靠”的标准。Chaos Mesh是一个专门为云原生环境特别是Kubernetes集群设计的混沌工程工具——它完全基于Kubernetes的CRDCustom Resource Definition自定义资源定义来实现也就是说你可以像管理Kubernetes的Pod、Deployment、Service一样来管理混沌工程实验它的Agent HarnessChaos Daemon也是完全基于Kubernetes的DaemonSet来部署的也就是说你只需要执行一条kubectl apply命令就可以将Chaos Daemon部署到Kubernetes集群的所有节点上它支持多种故障类型包括Pod层、容器层、网络层、存储层、内核层等5大类共100种故障类型、多种实验模式包括一次性实验、定时实验、周期性实验、流量驱动实验等、多种终止条件包括手动终止、定时终止、指标阈值终止、PromQL查询终止等、多种可视化功能包括实验拓扑图、实验执行进度图、指标对比图等而且它的安全性非常高——内置了RBACRole-Based Access Control基于角色的访问控制机制、实验白名单机制、安全沙箱机制等确保混沌实验的执行安全。字节跳动通过Chaos Mesh的持续实验提前发现了无数个“全球数十亿级用户量”场景下的系统弱点——比如某个抖音推荐微服务的Kubernetes HPAHorizontal Pod Autoscaler水平Pod自动扩缩容触发阈值设置过高导致在“流量突增100倍”的场景下无法及时扩缩容比如某个TikTok直播微服务的网络分区机制在“跨区域网络延迟突增500ms”的场景下完全失效导致直播中断比如某个抖音评论微服务的Redis缓存降级机制在“Redis集群主从切换”的场景下出现了数据不一致的问题比如某个TikTok支付微服务的数据库连接池大小设置不合理导致在“流量突增200倍”的场景下连接池耗尽服务完全不可用等等——然后字节跳动的工程师们会立即修复这些弱点确保抖音和TikTok在全球范围内的稳定运行。根据字节跳动公布的数据在使用Chaos Mesh之前字节跳动每月都会发生几十次持续时间超过5分钟的核心服务故障而在使用Chaos Mesh之后字节跳动每月发生的持续时间超过5分钟的核心服务故障不到5次而且每次事故的恢复时间都从原来的“几小时”缩短到了“几分钟甚至几秒钟”此外抖音和TikTok的全球可用性达到了99.99%以上完全满足了全球数十亿级用户的需求。准备工作环境/工具本文实验所需的开发环境、软件版本、依赖库为了让大家能够亲手实践混沌工程与Agent Harness我们将在本文的“核心步骤”部分带领大家搭建一个基于Kubernetes的云原生微服务系统然后使用字节跳动开源的Chaos Mesh它的Agent Harness是Chaos Daemon来进行一系列的混沌工程实验。以下是本文实验所需的开发环境、软件版本、依赖库软件/工具/依赖库版本要求功能说明下载/安装链接操作系统Windows 10/11需启用WSL 2、macOS 10.15、LinuxUbuntu 20.04/CentOS 7/Debian 10运行实验环境的基础操作系统本文将以Ubuntu 22.04 LTS为例进行演示Docker Engine20.10.0运行容器的基础运行时环境Docker官方安装指南kubectl1.21.0Kubernetes集群的命令行工具kubectl官方安装指南kindKubernetes IN Docker0.17.0在本地Docker中快速搭建一个单节点或多节点的Kubernetes集群kind官方安装指南Helm3.8.0Kubernetes的包管理工具用来快速安装Chaos Mesh和其他应用Helm官方安装指南Chaos Mesh2.6.0本文实验使用的混沌工程工具内置Agent HarnessChaos DaemonChaos Mesh官方安装指南Prometheus GrafanaPrometheus 2.40.0、Grafana 9.0.0监控系统用来采集、存储、可视化混沌实验前后的各项指标Prometheus官方安装指南、Grafana官方安装指南Spring Boot2.7.0本文实验使用的微服务开发框架Spring Boot官方网站Spring Cloud Netflix Eureka3.1.0本文实验使用的服务注册与发现组件Spring Cloud Netflix Eureka官方文档Spring Cloud OpenFeign3.1.0本文实验使用的声明式HTTP客户端组件Spring Cloud OpenFeign官方文档Resilience4j1.7.0本文实验使用的容错框架包括熔断器、限流器、重试器、降级器等Resilience4j官方网站MySQL8.0.0本文实验使用的关系型数据库MySQL官方安装指南Redis7.0.0本文实验使用的缓存数据库Redis官方安装指南基础知识本文实验所需的前置知识为了让大家能够更好地理解本文的内容我们假设大家已经具备了以下前置知识Linux基础操作包括常用的Linux命令比如ls、cd、pwd、mkdir、rm、cp、mv、vi、vim、cat、grep、awk、sed、ps、top、htop、netstat、ss、iptables、systemctl等、Linux文件系统的结构、Linux用户和权限管理、Linux进程管理等Docker基础操作包括常用的Docker命令比如docker run、docker ps、docker images、docker pull、docker push、docker build、docker exec、docker logs、docker stop、docker rm、docker rmi等、Docker镜像的构建、Docker容器的管理、Docker网络的配置、Docker卷的使用等Kubernetes基础操作包括常用的kubectl命令比如kubectl get、kubectl describe、kubectl create、kubectl apply、kubectl delete、kubectl exec、kubectl logs、kubectl port-forward等、Kubernetes的核心概念比如Pod、Deployment、Service、Ingress、ConfigMap、Secret、DaemonSet、StatefulSet、Job、CronJob、HPA、VPA、RBAC、CRD等、Kubernetes集群的部署和管理等微服务架构基础包括微服务架构的核心概念比如服务注册与发现、服务调用、负载均衡、容错、熔断、限流、降级、分布式事务、分布式锁、分布式追踪、分布式日志等、微服务架构的优缺点、微服务架构的最佳实践等Spring Boot与Spring Cloud基础包括Spring Boot的核心概念比如自动配置、起步依赖、嵌入式Web服务器等、Spring Boot项目的创建和运行、Spring Cloud的核心组件比如Eureka、Ribbon、OpenFeign、Hystrix、Resilience4j、Gateway、Config、Bus等、Spring Cloud微服务项目的创建和运行等Prometheus与Grafana基础包括Prometheus的核心概念比如数据模型、指标类型、PromQL、Exporter、Alertmanager等、Prometheus的部署和配置、Grafana的核心概念比如数据源、Dashboard、Panel、Query等、Grafana的部署和配置等混沌工程基础包括混沌工程的核心概念、混沌工程的起源、混沌工程的原则、混沌工程的流程、混沌工程的工具等这部分内容我们会在本文的“核心概念”部分进行详细讲解所以如果大家暂时不熟悉也没关系。如果大家还不具备以上前置知识建议大家先学习以下相关的学习资源Linux基础操作《鸟哥的Linux私房菜基础学习篇》、B站UP主“尚硅谷”的Linux教程Docker基础操作Docker官方文档、B站UP主“狂神说Java”的Docker教程Kubernetes基础操作Kubernetes官方文档、B站UP主“尚硅谷”的Kubernetes教程、《Kubernetes权威指南从Docker到Kubernetes实践全接触》微服务架构基础《微服务架构设计模式》、B站UP主“尚硅谷”的Spring Cloud微服务教程Prometheus与Grafana基础Prometheus官方文档、Grafana官方文档、B站UP主“尚硅谷”的Prometheus与Grafana教程混沌工程基础Netflix的《混沌工程原则》、《混沌工程Netflix系统稳定性之道》、Chaos Mesh官方文档。核心概念核心概念1混沌工程Chaos Engineering问题背景正如我们在本文的“引言”部分所说的现代的生产级系统几乎都是由成百上千个微服务、容器、虚拟机、物理服务器组成的大规模分布式系统而且这些系统的规模还在不断地扩大——根据Gartner公布的数据到2025年全球将有超过90%的企业采用微服务架构来构建自己的应用系统而且每个应用系统将由超过1000个微服务组成。大规模分布式系统的出现虽然给我们带来了很多好处比如高可扩展性、高可维护性、高灵活性、技术栈多样化等但也给我们带来了前所未有的可靠性保障挑战系统的复杂性呈指数级增长随着微服务数量的增加系统的组件数量、组件之间的依赖关系、组件之间的交互方式都呈指数级增长——根据“梅特卡夫定律Metcalfe’s Law”一个网络的价值与该网络中节点数量的平方成正比同样地一个大规模分布式系统的复杂性也与该系统中组件数量的平方成正比。这意味着我们根本无法完全理解系统的所有行为也根本无法预测系统在所有可能的场景下的表现系统的“正常运行”只是一种“虚假的稳定状态”现代的大规模分布式系统都是“自适应系统Adaptive System”——它们会根据环境的变化比如流量的变化、资源的变化、配置的变化等自动调整自己的行为比如自动扩缩容、自动负载均衡、自动故障转移等。这种“自适应能力”虽然给我们带来了很多好处但也意味着系统的“正常运行”只是一种“暂时的、脆弱的稳定状态”任何微小的、不可预期的环境变化都可能打破这种稳定状态引发雪崩式的连锁故障传统可靠性保障手段已经完全失效正如我们在本文的“引言”部分所说的传统可靠性保障手段比如单元测试、集成测试、回归测试、负载测试、压力测试、蓝绿部署、灰度发布、异地多活只能验证“系统在已知的、正常的或可预期的异常场景下是否能正常运行”却完全无法验证“系统在未知的、不可预期的、真实的生产级故障场景下是否能保持可用、快速恢复”——因为我们根本无法想象出所有可能的生产级故障场景更无法在测试环境中完全模拟出这些场景用户对系统的可用性要求越来越高随着互联网的普及用户对系统的可用性要求越来越高——根据Forrester公布的数据现代用户对系统的可用性要求已经从原来的“99.9%每年允许宕机8小时45分钟”提升到了“99.999%每年允许宕机5分钟15秒”甚至更高。如果系统的可用性达不到用户的要求用户就会立即流失——根据Gartner公布的数据每1分钟的核心服务故障都会给企业造成平均5600美元的经济损失对于电商平台来说每1分钟的核心交易服务故障都会给企业造成平均超过100万美元的经济损失。在这样的背景下传统可靠性保障手段已经完全无法满足现代企业的需求我们需要一种全新的、主动出击的可靠性保障手段——这种手段就是混沌工程。问题描述混沌工程要解决的核心问题是如何在不造成巨大损失的前提下提前发现大规模分布式系统的弱点验证系统的冗余/隔离/降级机制是否有效进而持续改进系统的韧性让系统能够在未知的、不可预期的、真实的生产级故障场景下保持可用、快速恢复混沌工程的定义关于混沌工程的定义目前业界最权威、最广泛认可的是**Netflix在2015年提出的《混沌工程原则》Principles of Chaos**中的定义混沌工程是一种通过在系统上进行受控的实验来建立对系统在生产环境中抵御动荡条件的能力的信心的学科。Chaos Engineering is the discipline of experimenting on a system in order to build confidence in the system’s capability to withstand turbulent conditions in production.除了Netflix的定义之外还有很多其他的组织和个人也对混沌工程提出了自己的定义——比如CNCFCloud Native Computing Foundation云原生计算基金会混沌工程是一种主动的、实验性的方法用于识别分布式系统中的弱点方法是在受控的环境中故意引入故障然后观察系统的行为Gremlin全球领先的商业混沌工程平台提供商混沌工程是一种通过在生产环境或高度仿真的预生产环境中主动引入故障来验证系统的韧性的实践《混沌工程Netflix系统稳定性之道》混沌工程是一种通过在系统中进行受控的故障注入实验来发现系统的弱点进而改进系统的韧性的方法论。虽然不同的组织和个人对混沌工程的定义略有不同但它们的核心思想都是一致的主动、可控、可观测、可终止地引入故障提前发现系统弱点持续改进系统韧性。混沌工程的起源混沌工程的起源可以追溯到2008年Netflix的一次重大生产事故2008年8月Netflix的主数据库发生了一次严重的故障导致Netflix的整个流媒体服务完全瘫痪持续时间超过3天这次事故给Netflix造成了巨大的经济损失和严重的用户信任危机——Netflix的股价在事故发生后的一周内下跌了超过20%而且有数百万用户取消了自己的订阅事故发生后Netflix的工程师们进行了深刻的复盘他们意识到传统的“单一主数据库读写分离”架构已经完全无法满足Netflix的需求他们必须将自己的系统迁移到“云原生微服务架构分布式数据库多区域异地多活”架构上但是迁移到新架构之后Netflix的工程师们又面临着一个新的问题他们如何验证新架构的韧性他们如何确保新架构在真实的生产级故障场景下不会再次完全瘫痪为了解决这个新问题Netflix的两位工程师——Casey Rosenthal和Nora Jones——提出了一个“疯狂”的想法与其让系统在真实的、不可控的、会造成巨大损失的生产故障中“自然死亡”不如让它在我们主动、可控、可观测、可终止的“实验”中“提前死亡”一次然后我们从中学习把它救活让它变得更强大。这个“疯狂”的想法就是混沌工程的雏形。2011年Netflix正式推出了全球第一个开源的混沌工程工具——Chaos Monkey——并开始在自己的生产环境中大规模使用2014年Netflix成立了专门的“混沌工程团队Chaos Engineering Team”2015年Netflix正式发布了《混沌工程原则》Principles of Chaos标志着混沌工程从“一种实践”发展成为了“一门学科”2016年Netflix出版了《混沌工程Netflix系统稳定性之道》Chaos Engineering: Building Confidence in System Behavior through Experiments这本书是全球第一本关于混沌工程的专著被誉为“混沌工程的圣经”2017年混沌工程开始在全球范围内流行起来越来越多的企业比如阿里巴巴、字节跳动、美团、京东、谷歌、微软、亚马逊等开始在自己的生产环境中大规模使用混沌工程2019年CNCF成立了专门的“混沌工程工作组Chaos Engineering Working Group”负责制定混沌工程的标准和最佳实践2020年字节跳动开源的Chaos Mesh和阿里巴巴开源的ChaosBlade先后贡献给了CNCF成为了CNCF的沙箱项目2023年Chaos Mesh晋升为CNCF的毕业项目标志着混沌工程已经完全成熟成为了云原生生态系统中不可或缺的一部分。混沌工程的原则Netflix在2015年发布的《混沌工程原则》Principles of Chaos中提出了混沌工程的5大核心原则——这5大核心原则是混沌工程的“灵魂”任何混沌工程实验都必须遵循这5大核心原则否则就不能称之为“真正的混沌工程实验”而只能称之为“瞎搞”。以下是混沌工程的5大核心原则的详细讲解原则1建立一个关于“系统在稳态下的行为”的假设原文Build a hypothesis around steady-state behavior.详细讲解混沌工程实验的第一步也是最重要的一步是建立一个关于“系统在稳态下的行为”的明确的、可测量的假设——这里的“稳态Steady State”指的是系统在“没有引入任何故障”的情况下的正常运行状态这里的“行为”指的是系统的可测量的业务指标比如可用性、延迟、吞吐量、错误率、转化率、留存率等而不是系统的技术指标比如CPU使用率、内存使用率、磁盘IO、网络IO等——因为技术指标的变化并不一定意味着业务指标的变化我们最终关心的是业务指标的变化而不是技术指标的变化。举个例子来说明假设我们要做一个关于“杀死某个微服务的Pod”的混沌工程实验那么我们的假设应该是假设杀死电商平台的“商品推荐微服务Product Recommendation Service”的任意一个Pod不会导致电商平台的“商品详情页的加载时间99分位延迟超过500ms”也不会导致电商平台的“商品推荐服务的错误率超过1%”更不会导致电商平台的“整体转化率下降超过0.5%”。而不是错误假设杀死商品推荐微服务的任意一个Pod不会导致该Pod所在节点的CPU使用率超过80%。为什么第二个假设是错误的因为即使该Pod所在节点的CPU使用率超过了80%也不一定意味着商品推荐服务的错误率会超过1%更不一定意味着电商平台的整体转化率会下降超过0.5%——我们最终关心的是业务指标的变化而不是技术指标的变化。原则2用反映真实世界的事件来多样化实验原文Vary real-world events.详细讲解混沌工程实验的第二步是选择反映真实世界中一定会发生的事件来作为故障注入的对象——这里的“真实世界的事件”指的是在真实的生产环境中已经发生过或者未来一定会发生的事件比如基础设施层事件服务器宕机、服务器重启、网络延迟、网络丢包、网络分区、网络中断、磁盘满、磁盘损坏、CPU负载过高、内存使用率过高、电源故障、机房断电、机房火灾等应用层事件进程崩溃、进程重启、线程死锁、内存泄漏、API调用超时、API调用错误、配置文件错误、依赖服务故障、数据库连接池耗尽、数据库查询慢、缓存失效、缓存雪崩、缓存击穿、缓存穿透等容器层事件容器崩溃、容器重启、容器被杀死、容器资源限制CPU限制、内存限制、磁盘IO限制、网络IO限制、容器网络隔离等Kubernetes层事件Pod被杀死、Pod重启、Pod驱逐、Deployment缩容、StatefulSet主从切换、Service故障、Ingress故障、ConfigMap更新、Secret更新、Node宕机、Node重启、Node驱逐、网络分区AZ分区、Region分区等人为操作事件手动误操作、手动删除资源、手动修改配置、手动重启服务、手动终止Pod等。为什么要选择“反映真实世界的事件”来作为故障注入的对象因为我们做混沌工程实验的目的是为了验证系统在真实的生产级故障场景下的韧性而不是为了验证系统在“我们自己编造的、真实世界中永远不会发生的场景”下的韧性——比如我们没有必要做一个关于“将系统的CPU使用率限制在1%”的混沌工程实验因为这种场景在真实世界中几乎永远不会发生但是我们非常有必要做一个关于“杀死某个微服务的任意一个Pod”的混沌工程实验因为这种场景在真实世界中一定会发生比如Kubernetes的Node驱逐、Pod的健康检查失败、自动化扩缩容系统的缩容等。此外我们还需要多样化实验——也就是说我们不能只做一种类型的混沌工程实验而应该做多种类型的混沌工程实验我们不能只在一个节点上做混沌工程实验而应该在多个节点上做混沌工程实验我们不能只在一个可用区上做混沌工程实验而应该在多个可用区上做混沌工程实验我们不能只在一个区域上做混沌工程实验而应该在多个区域上做混沌工程实验——因为真实世界中的故障场景是多种多样的我们只有通过多样化的实验才能提前发现系统的所有弱点。原则3在生产环境中运行实验原文Run experiments in production.详细讲解混沌工程实验的第三步也是最具争议的一步是在生产环境中运行实验——这一点可能会让很多人感到震惊和恐惧“什么在生产环境中运行实验万一实验失控了怎么办万一系统完全崩溃了怎么办万一造成了巨大的经济损失怎么办”是的在生产环境中运行实验确实存在一定的风险——但是如果我们不在生产环境中运行实验我们就永远无法真正验证系统在真实的生产级故障场景下的韧性——因为预生产环境比如测试环境、 staging环境与生产环境之间存在巨大的差异预生产环境的规模通常比生产环境小得多比如预生产环境可能只有几个Pod而生产环境可能有几千个甚至几万个Pod预生产环境的流量通常比生产环境小得多比如预生产环境可能只有几个测试人员的访问而生产环境可能有几百万甚至几千万个用户的访问预生产环境的配置通常与生产环境不同比如预生产环境可能没有配置多区域异地多活而生产环境配置了预生产环境可能没有配置自动化扩缩容而生产环境配置了预生产环境可能没有配置完善的监控、日志、追踪系统而生产环境配置了预生产环境的依赖服务通常与生产环境不同比如预生产环境可能使用的是模拟的依赖服务而生产环境使用的是真实的依赖服务预生产环境的数据通常与生产环境不同比如预生产环境可能使用的是少量的测试数据而生产环境使用的是大量的真实数据——这些差异意味着我们在预生产环境中运行实验得到的结果可能与在生产环境中运行实验得到的结果完全不同真实世界中的故障场景是无法在预生产环境中完全模拟的比如我们无法在预生产环境中完全模拟“真实的网络波动”、“真实的流量突增”、“真实的硬件故障”、“真实的人为误操作”等场景——这些场景只有在生产环境中才会真正发生我们在预生产环境中运行实验建立的“对系统韧性的信心”是虚假的因为我们知道预生产环境与生产环境之间存在巨大的差异所以即使我们在预生产环境中运行实验得到了“成功”的结果我们也不会真正相信系统在真实的生产级故障场景下的韧性——只有当我们在生产环境中运行实验得到了“成功”的结果我们才会真正建立起对系统韧性的信心。那如何降低在生产环境中运行实验的风险呢Netflix给出了以下几个建议先在预生产环境中运行实验在生产环境中运行实验之前我们可以先在预生产环境中运行实验验证实验的安全性和有效性——如果在预生产环境中运行实验得到了“失败