2022 年 7 月 4 日,【可观测,才可靠——云上自动化运维 CloudOps 系列沙龙_第一弹】正式推出,第三位分享的讲师是阿里云弹性计算技术专家秦隆,他带来的分享主题是《可靠性必备保障:云上如何进行混沌工程》,以下是他的演讲内容整理,供大家阅览:
01 混沌工程方法
传统的系统运维方式下,我们通常只关注系统主干流程、业务流程,而忽略旁路系统或底层架构。系统发生报警时很大可能性是由我们不关注的部分引起,从而导致运维人员无法很好地应对。发生较大规模故障时,可能需要拉齐各个业务域人员共同进行故障处理,但人员来自不同业务,负责和擅长方向也不同,无法很好地协同工作以及高效地处理故障。
业务系统的治理运维级别可根据不同业务系统层级分为四层:
① 业务系统:业务开发人员最擅长或最常涉及的系统,比如开发代码。
② 关联业务:指同公司或同部门开发的一些二方依赖。
③ 中间件及基础组件:一般开发人员不再关心此层。
④ 基础设施层:运维人员对其较为熟悉,开发人员几乎不参与此层的运维。
各个技术分层会面临不同的问题。
⚫ 业务系统最常见的问题为代码 bug 、突发流量以及发布中间态问题。
⚫ 关联业务层面对的问题是业务在遇到问题时会出现何种表现,比如关联业务宕机时,可能会出现关联业务依赖报错或 RT 突增;如果关联业务中出现代码 bug ,则为逻辑错误。
⚫ 中间件和基础组件遇到的问题大多为中间件不可用、 慢 SQL、RDS 故障或消息延迟等。
⚫ 物理基础设施层遇到问题大多为系统宕机或网络方面,包括网络不通、网络丢包、延时增加甚至整个机房不可用等问题。
为了解决以上不同技术层级所遇到的未知问题,我们引入了混沌工程,从四个方面进行验证:
① 容量:明确了系统容量,才能明确系统能够承受多少用户或多少调用。
② 系统复杂度:随着系统老化,系统会包含越来越多隐患。业务和技术的更新迭代也会导致技术欠债越来越多,链路越来越长,排查手段更欠缺。
③ 可用性:世界上没有 100% 可用的系统,任何系统都有可能出错。可用性即系统出错时会有什么样的表现。
④ 人和流程以及人员协作效率问题:是系统故障处理中最不稳定的因素。
混沌工程所有演练场景都来源于故障。总结出故障后,先在验证环境试水。随后,成熟的 case 可以转为线上环境演练。演练完成之后,进行复盘,总结系统需要解决的问题,这是混沌工程最终要达到的目标,即从演练中得到可以优化的点并进行优化。最后将所有稳定的 case 聚集起来,总结成混沌工程自动化 case 集。集合会稳定运行在线上系统,做线上系统性能和复杂度的回归,防止某些改动对系统稳定性或可用性造成影响。
混沌工程的实践分为经典四步:
第一步:定义和测量系统的稳态。要明确系统在什么样的条件下可以支撑什么样的请求,或系统在稳定运行时是什么样的表现。比如,系统在 1000QPS 时可以稳定提供服务。
第二步:创建假设。在系统稳定状态中找到有可能对系统稳定性造成影响的变量。比如,假设缓存不能正常服务,系统仍然可以在 1000 QPS 时提供服务。
第三步:将假设模拟成现实世界中可能发生的事件。比如针对缓存无法正常服务,在现实中生活中可能发生事件有:缓存服务器网络 down 或缓存系统强行淘汰。
第四步:证明或反驳假设。比如缓存无法正常服务后,造成系统不稳定,最大 QPS 是否还能达到 1000。若结果为系统 QPS 依然可以达到 1000,则说明系统稳定性至少在模型 case 里可以通过;若结果为 QPS 无法达到 1000,比如在 QPS 为 200 时系统已经不稳定,则可由此找到系统瓶颈点,进行治理。
混沌工程的实践有 5 个原则:
① 建立一个围绕稳定状态行为的假说:混沌工程要关注系统在发生不稳定事件时能否正常工作,而不是试图验证系统如何工作。
② 多样化真实世界的事件:首先,要对真实可能发生的事件进行实验,无需关心不可能发生的事件。其次,要尽可能多地枚举出系统中可能发生问题的点,发生概率高或已经发生过的事件优先级靠前。
③ 在生产环境中运行实验:弹性计算的初期也无法在生产环境中运行实验,原因为系统稳定性不高,且可观测性不佳,在线上注入故障时无法很好地观测影响范围。比如在代码隔离但数据不隔离的环境中实验时,完全无法测出系统真实的瓶颈点,因为任何微小的改变、任何与线上不同的点都会影响最终结果的准确性。所以我们提倡在生产环境中运行实验,能最大化验证发生问题时系统的表现。
④ 持续自动化运行实验:将性能作为回归的一部分,不仅需要功能的回归,还需要自动化的性能回归。
⑤ 最小化爆炸半径:当有足够强大的可观测性之后,要控制演练可能对系统造成的影响。演练的目的应该是验证系统薄弱点,而不是将系统彻底击溃。因此要控制演练范围,将影响降到最小,尽量不对线上用户造成过大影响。
02 弹性计算混沌工程实践
进行压测时我们为每个用户的每个 API 都设置了调用 QPS 上限,即流控。压测场景下所有用户的叠加较为稳定,但系统里依然有不稳定的点。第一,虽然对用户有流控,但流控未经验证,只有用户在阈值内调用才能保证功能可以完成,对系统没有太大压力;第二,单个接口或整个应用总容量未知;而单用户调用能保证系统稳定。
由于单一调用来源不同的用户调用峰值叠加,会导致系统后端压力过大,导致波峰系统出现问题。
上述流程总结起来可分为四步:
第一步:建立较为稳定的系统。
第二步:埋下问题——系统容量未知。
第三步:用户将现实环境中可能发生的问题触发,即同一平台不同用户的突发调用。
第四步:结论为系统无法承受压力,最终导致故障。
上述流程中存在四个需要解决的问题:系统容量未知导致严重后果、流量峰值下系统的表现未知、产生流量洪峰的原因未知、系统崩溃后的处理流程未知。而为了探索系统稳定性,需要将未知转变为已知,因此我们引入了压测,主要分为三个步骤。
第一步:基线。定义系统瓶颈以及压测停止条件。
第二步:实际压测。压测一般以 API 为入口,可能是外部 API 、内部以及内部调用,分为三种压测方式:
⚫ 简单暴力压测:主要针对一些非常简单的 API,单独的 API 调用即可对系统施加压力,并发调用接口,达到压测目。
⚫ 逻辑流程类压测:调用之前会经过一些资源准备,不能单独调用接口,也称为带上下文语义的接口,接口有状态。将接口和创建实例或查询实例进行编排,对每个实例编排出串行流,对串行流进行并行压测,最后组成逻辑流程类压测 case 。
⚫ 线上回放压测:用于针对更复杂的 case 或内部调用 case 。
第三步:自动化压测。将稳定 case 和对系统危害不大 case 统一成自动化 case 集,根据基线设置自动告警。当自动化压测回归发现某一接口不符合之前预测的基线时,会自动告警,做到系统性能回归,最终解决前文提到的四个问题:
⚫ 针对系统容量未知导致严重后果,设置了系统容量基线,通过将压力打到系统极限从而确定系统能力;
⚫ 针对产生流量洪峰的原因未知,测试时通过假设峰值、多用户模拟以及流控放开实现。在实际生产生产环境中,明确系统能力之后,可以通过用户流控计算来解决洪峰来源未知问题,将流控阈值设置到合理区间;
⚫ 针对流量峰值下系统的表现未知,在压测到系统瓶颈时,即可发现系统瓶颈时的表现;
⚫ 针对系统崩溃后的处理流程未知,会通过压测形式做突袭,检测业务人员是否能够针对大流量场景快速稳定地处理,减少故障时的发现-定位-恢复时长。
故障演练和可观测性密不可分,可观测性建设比较完善时,才能将故障演练注入到线上系统,才能控制系统爆炸面。
可观测性分为四层:
⚫ 业务层:包括结果 mock、JVM OOM、业务逻辑异常以及应用内 CPU 满。
⚫ 依赖业务层:针对依赖业务,有专门的业务接口监控,对自己以及内部依赖都会有一部分 SLA 协议。
⚫ 中间件和基础软件层:有针对中间件业务的监控,比如缓存命中率、慢 SQL 监控或网络状态监控。
⚫ 服务器层:有业务探活以及网络状态监测。
针对不同层有不同的故障演练方式。比如业务层的 mock 需要拉齐所有业务域人员,要在业务层监控,还需要关注 VM 的内部;对于依赖业务,比较注重 RT 升高、结果 mock 或结果报错等;中间件和基础软件层可能面对的问题有比如缓存变慢、击穿、慢 MySQL 、无法连接等;弹性计算作为基础设施提供商,更关注服务器层,弹性计算在每一个地域上线时,管控系统都需要经过多可用区、宕机、演练,验证管控系统的多活可用,因此服务器层有很丰富的演练经验。
故障演练的步骤如下:
第一步:故障演练的理念是尽量增加系统雪崩和不稳定事件,而这与开发人员日常的理念是冲突的。因此,首先要让大家接受故障演练,由专业的演练小组安排固定的演练时间以及清晰的演练安排,拉齐所有业务参加。
第二步:日常演练组织。日常演练组织中事件的选择原则为频发问题优先、风险由低到高。其次,先在低风险环境中试水,在隔离环境确认影响,在低风险环境中进行破坏性实验和大型故障模拟,比如影响完全不可控的故障需要在低风险环境中进行,较为稳定的 case 或可以确认影响的 case 方可进行线上环境演练。线上环境演练时,一般需遵循发现-定位-恢复流程。
第三步:突袭。突袭有红蓝军演练和一键演练。其中红蓝军演练较为保守,会在演练小组里抽取一部分对演练 case 比较熟悉的人员,作为红军参与故障演练,不定期在系统中注入问题;其他所有业务人员为蓝军,负责验证问题的发现-定位-恢复时间。一键演练是较为激进的方式,通常由业务领导角色直接注入故障,演练所有业务人员的故障处理流程。成熟度非常高的系统方可实现一键演练的目标。
第四步:总结和改进。总结和改进是混沌工程中故障演练和压测的最终目标。通过故障演练和压测确定系统极限,包括系统水位极限、运维响应极限、问题发现极限以及系统恢复极限,明确系统表现、问题处理流程;记录不可用节点以及性能瓶颈,最后将不可用节点抽取为改进目标项,责任到人做系统稳定性改进。
弹性计算系统作为超大规模的分布式系统,其混沌工程与简单的混沌工程有何区别?
① 多套环境部署。弹性计算有 20 套高可用部署以及多套环境规划,因此我们希望有自动化跟踪系统可以自动化进行 case 覆盖和 region 覆盖。
② 内聚和耦合节点多,需要规划的依赖非常多,需要拉的业务方也很多。解决方法为拉入更多业务域,根据优先级安排先做哪些演练。
③ 海量实时调用。演练时需要面对非常大的流量系统,流量无法短暂停止,因此演练时如果造成一部分系统不稳定,在线上将会放大为非常严重的故障,可以通过灰度演练、 SLA 以及熔断降级规避问题。
④ 接口功能多。希望通过自动化演练实现 case 覆盖,自动化回归 case 可以每天自动回归线上系统,回归系统性能变化。
03 系统评价和混沌工程工具
混沌工程系统成熟度从纵向可以分为 5 个等级。
第一级:多为起步系统,为单环境、单地域部署,只能在开发和测试环境中进行演练。
第二级:具备初步的多可用区部署,可以注入稍复杂的故障。
第三级:可以在生产环境和灰度环境中进行演练。
第四级:较为成熟的系统,在生产环境中可以运行实验,可以进行比较成熟的故障注入或关联业务故障注入。
第五级:在各种环境都可以注入系统故障和数据面故障,也是目标系统。
云上提供了很多配套工具。
在压测方面,有性能测试 PTS 工具可以配置场景,控制压测进度,通过全国部署的限定节点模拟用户请求,更接近用户行为。在压测时,可以通过云监控 ARMS 和 PTS 监控完成可观测性方面的工作,即可在压测的同时观测系统压力。
故障注入平台 AHAS 可以注入各种层面的问题,包括应用层、底层、物理机层。
有压测和演练,则必然要有防御。压测的主要工具有 PTS 、Jmeter 等。针对压测的防控工具有内部和外部的文档,比如 Sentinel、AHAS。系统出现问题时,可以通过 Hystrix、AHAS 做系统降级。演练方面有 AHAS、ChaosBlade、ChaosMonkey 等。针对演练场景,可以通过 AHAS 对故障场景做熔断。另外,云上还提供了一些可观测性组件,包括 ARMS、云监控等,云上云下都可以使用 Prometheus 做可观测。
Q&A 环节,观众提问
Q1 混沌工程是否只对复杂的分布式系统企业有用?对小企业是否有必要?有没有实际可落地的框架或工具?
答:首先要罗列自己系统中可能遇到的风险,比如网站应用可能遇到的风险较少,系统中关联业务较少或耦合度不深,中间件使用较少,且技术组件又有 ECS 或云服务厂商兜底,那么需要使用混沌工程的场景可能只有比如针对突发流量或代码 bug ,演练方面也较少。
混沌工程虽然对于代码层改动较少,但需要投入很多人力。而 AHAS 可以覆盖大部分使用场景,针对故障注入以及注入之后系统如何做流控、降级、熔断等,AHAS 提供了一套完整的解决方案。因此,投入方面无需担心。
小企业是否有必要做混沌工程,需要根据实际情况进行评估,如果系统可能存在这方面的隐患,则建议做混沌工程。同时,我们建议大部分云上公司都做混沌工程,以明确系统的薄弱点。
点击这里,观看嘉宾的演讲视频回放。
近期活动预告
【自动化,才高效——云上自动化运维 CloudOps 系列沙龙_第二弹】来袭,就在 7 月 25 日-27 日,敬请期待。
自动化即是通过运用工具或系统达到减少、甚至是完全取代人工的操作。在研发效能与运维工作中,自动化是降低成本、提升效率必不可少的方式,自动化还能减少人工带来的错误,提升团队满意度。因此,阿里云弹性计算云上自动化运维 CloudOps 系列沙龙,将以“自动化与智能化”作为第二弹的主题,分享相关思考与实践。免费报名通道已经开启!即刻扫描下方海报中的二维码,预约报名。
沙龙小 Tips:观看直播时在弹幕区提出自己的疑问,被讲师抽中回答问题的同学,还会获得加湿器等精美礼品哦!同时在直播结束时填写问卷,也有机会获得便携玻璃杯等多重好礼。