B 站轻量级容灾演练体系构建与业务实践

B 站轻量级容灾演练体系构建与业务实践
2024年11月15日 15:30 InfoQ

分享嘉宾 | 刘昊

编辑 | Kitty

策划 | QCon 全球软件开发大会

近两年,随着企业降本增效的持续深化,企业 IT 服务的稳定性受到了一定的冲击,这点从微博热搜上也能初见端倪。如何确保过往企业在服务高可用、业务多活和基础架构容灾等方面的投入是真实有效的,当保障故障和灾难来临时,业务连续性不受过重损失?这是当下诸多公司面临的一大挑战。

在 10 月 18-19 日举办的 QCon 全球软件开发大会上,哔哩哔哩基础架构部平台工程负责人刘昊分享了“B 站轻量级容灾演练体系构建与业务实践”,从 B 站的容灾演练体系构建入手,逐步拆解体系,带大家深入了解 B 站在容灾演练上的组织阵型搭建模式、运营机制设定方法以及容灾产品能力建设,最后通过结合业务实践为大家展示 B 站是如何通过容灾演练体系来支撑业务多活、大促保障和研发质量交付等多个环节的,希望能为大家带来一些稳定性保障的新思路。

内容亮点:

  • 了解 B 站如何轻量级在组织内部常态化实施容灾演练

  • 了解 B 站容灾演练的技术演进路线、组织搭建模式和运营机制流程,掌握体系化的解决方案

以下是演讲实录(经 InfoQ 进行不改变原意的编辑整理)。

大家下午好,今天我要讨论的议题是「B 站轻量级容灾演练体系的构建与业务实践」。这个议题的名字有点长,关键点主要在于“轻量级”,也就是如何以低成本进行容灾演练。过去两年,大家也知道整个行业都在开展降本增效工作,在此基础上更是提出了要确保业务质量不受损。而容灾演练是推动业务质量建设和有效性验证的最好手段,但这又会对我们的整体工作负载带来提升。在此基础之上,我们去探讨如何轻量级、低成本的开展容灾演练工作就非常有意义。

我简单介绍一下自己。我加入 B 站较早,见证了 B 站从一个“小破站”发展到现在拥有亿级用户量的演进过程。近几年,我主要负责稳定性相关的工作,包括应急响应、变更防控、红蓝攻防演练,以及围绕运维稳定性的元数据建设。

今天的分享分为四个部分。首先,我会介绍在当前新形势下,我们面临的稳定性挑战有哪些,以及这些挑战如何引导我们构建轻量级演练体系。接着,我会详细阐述这个体系是如何构建的,以及如何实施。然后,我们将讨论体系落地的效果,特别是在业务场景演练实践中我们是如何操作的。最后,我会做一个简单的总结和展望。

新形势下稳定性挑战

当下基础设施层故障频发、业务高可用手段失效的原因

在当前的新形势下,我们正面临前所未有的稳定性挑战。随着信息技术的快速进步,数字化转型不断深入各行各业。从数十年前单一的集中式服务架构,到今天广泛采用的分布式系统、微服务架构、云原生技术,以及行业形态的剧变——从最初的黄页导航到互联网、移动互联网,再到产业互联网——我们见证了软件系统复杂度的几何级增长以及多样性的不断提升。这一切变化使得软件系统在稳定性方面面临前所未有的挑战,逐渐成为事故频发的高风险区域。

过去,我们的关注点通常集中在单个硬件设备的故障上,但如今,硬件故障的影响范围已远超单一机器。基础设施层面的故障和隐患也日益增多,且其影响常常具有全局性和长期性。例如,近期新加坡一处数据中心发生火灾,尽管只有部分楼层受灾,但其对国内出海业务的波及效应极为显著,这一事件甚至成为热搜话题。再如,今年 7 月 2 日,常熟地区发生了光纤被剪事件。尽管光纤并未完全中断,但很不幸我们的链路正好在被剪断的那一部分中,对我们的业务服务造成了直接影响。这些事件深刻揭示了基础设施故障的潜在风险:不再是局限于单一设备的故障,而是可能导致整个数据中心或大范围区域服务中断的重大事件。

过去几年,行业内广泛强调了高可用性服务架构的建设,包括服务的同城双活和异地多活。然而,这些理论和设计在常规运行中未必经受过实际的考验。当外部挑战真正来临时,我们的抵抗故障能力如何?这不仅是对整个行业的一次全面挑战,更是对我们自身在稳定性建设方面的一次实战检验。

对于 B 站而言,我们面临的稳定性挑战主要体现在两个方面。首先,B 站的核心用户群体以年轻人为主,我们拥有一个活跃的热搜体质。每当发生系统故障时,问题往往会迅速被放大,登上社交平台的热搜,这对我们负责技术稳定性保障的团队而言,造成了巨大的压力。即便是一个较小的故障,也可能会引发巨大的流量冲击。

这里举几个过往案例,比如商业 CDN 故障可能引发回源链路的级联问题,从而影响整个图片服务的稳定性。这一事件暴露了我们全链路图片服务方案中的潜在薄弱环节。其次,网络专线的异常可能会导致上海办公区与机房之间的连接中断,类似于之前提到的光缆被剪断事件,这种情况可能导致整个可用区的脱网情况发生。此外,业务代码的变更也可能由于架构设计的不合理,导致数据库过载,进而影响整体服务的稳定性。

回顾过去,B 站曾经历过一次重大的服务中断事件,即广为人知的“713 事件”。自那时以来,我们开展了一系列的技术改进工作,重点围绕用户端、接入层、服务层、中间件层以及基础设施层,逐步推进多活架构建设和业务架构的优化。经过多年的持续改造,尽管团队成员在心里对改造效果抱有期望,但面对这些技术变革,我们依然缺乏对改造效果的明确评估。我们可能仅仅是基于内部的技术架构指导方针和方案进行了改造升级,但这些改造措施是否真实有效,仍需通过实际运行中的验证来进一步检验。

如何破局?主动出击,以演带练

为了验证我们的技术改造和功能更新的有效性,我们需要建立一个专门的故障演练和验收平台。该平台的创建源于我们在日常运营中频繁遇到故障,迫切需要通过技术改进来提升系统稳定性,并确保改进后的功能能够得到充分验证。具体来说,我们面临的挑战包括:强弱依赖故障、应用依赖的不合理性、可用区切换问题,以及技术改造后强弱依赖治理的效果验证。此外,还需要对降级策略和兜底策略的有效性进行全面检验。

在验证过程中,我们需要开展实战演练,模拟真实环境中的故障情景,尽可能激发研发团队的主动性和自驱力,因为保障团队人员有限,无法覆盖所有细节。我们希望这种验证活动能够常态化,而非一次性任务,从而持续推动系统的稳定性建设。常态化的验证不仅能够持续检测系统的可靠性,还能在降低成本的同时,优化资源配置,这就引出了轻量化的必要性。

B 站自早期便开始投入高可用性建设,经过从基础的高可用性架构到双活架构、异地多活的迭代,再到 2021 年引入混沌工程(Chaos Engineering)的相关实践。我们借助开源工具,如阿里巴巴和 PingCap 的开源产品,将其封装成一个简易平台用于故障注入和验证。然而,这也带来了一些挑战,包括重复建设、不同业务部门的个性化需求、以及技术团队缺乏产品化思维,导致平台的产品化能力不足。此外,研发人员因日常工作繁忙,往往忽视了工具本身的潜在风险,这可能在进行故障验证时引发实际的线上大规模故障。需要强调的是,混沌工程并非随意注入故障,它必须遵循一定的规则和逻辑。在 B 站内部,大的事业部具备足够的人力和资源来专门负责混沌演练,而较小的事业部和业务线则缺乏这方面的支持。

过往的故障演练多集中在特定时期进行,例如大型赛事或春晚等特殊场景的前置保障期间,但日常演练的关注度又不足,这导致了演练并未实现常态化。这是我们面临的一个重要问题,因此我们亟需一个能够常态化、轻量化的故障演练平台,以确保我们的技术改造和功能更新在实际运行中能够稳定有效。

在 2022 年,我们进行了一次重要的整合,由大事业部牵头,将多个故障演练平台统一合并为一个平台。我们的目标是增强故障演练的基础能力,去除冗余部分,并以行业中混沌工程的五大核心指导原则为目标,优化产品化设计,提升平台的使用体验和稳定性。

在去年,我们进一步推进了演练 3.0 的阶段建设,旨在实现演练的常态化并确保其真实有效性。为此,我们提出了从混沌演练到容灾演练的全覆盖方案,强调演练的全面性和常态化。这引出了轻量级演练的概念,我们计划从组织、流程、技术等多个维度进行持续优化。

在平台优化方面,我们不仅仅着眼于架构层面的改造,还特别关注如何以低成本实现广泛覆盖,如何在演练过程中自动计算输入参数、自动圈定演练链路等功能。这些措施旨在降低演练的复杂性和成本,同时提升演练效率和效果,确保系统在各种情况下都能保持高稳定性和可靠性。通过这些全面的优化,我们希望实现一个更加高效、轻量化的演练体系,确保技术改造与功能更新能够持续支撑 B 站的业务稳定。

目前,我们正处于演练 3.0 阶段,核心目标是实现轻量级演练。这一目标是我们过去一年多持续推进的重点。通过实现轻量化,我们希望将演练流程推广到全公司,涵盖更多部门和角色。然而,由于涉及的部门和团队繁多,如何让这些角色有效协作成为了一个挑战。若组织架构不明确,容易导致职责划分不清,最终可能需要频繁补位和调整。

为此,我们需要固化和标准化组织内的演练流程与章程,明确哪些大型演练是必要的,哪些部门应在何时参与。此外,技术流程也需要规范化,以确保演练过程的一致性和高效性。在技术支撑方面,我们要提升平台的产品化能力,减轻人员的心智负担,使演练能力能够完全交给最终用户。理想状态是,演练不再依赖 SRE 或专门的演练团队,用户可以自主发起和执行演练。

在演练执行过程中,我们还需增强观测指标的能力,拓展可注入的演练对象和范围,推动演练的自动化。随着自动化水平的提高,我们需要能够量化预期结果,自动收集和分析演练数据,并在出现异常时提供自动防护措施。这将确保演练不会引发真正的生产环境故障,最大化保障系统的稳定性。

在组织间的协同机制和内部对演练的认知方面,我们需要明确的是,演练并非无事生非,而是为了提升系统的可靠性和应对能力,具有实际收益,因此必须受到足够重视。同时,演练平台的用户需要理解其价值并掌握相关操作,这就需要通过培训降低学习成本。即便是最优秀的产品,用户仍然需要一定的学习和适应时间。

基于这些挑战,我们设定了几个关键目标。我们希望演练平台能够充当“演练专家”的角色,帮助用户大幅降低操作成本和学习成本。我们计划通过标准化的流程来规范演练行为,确保演练的每个环节都在可控、安全的范围内进行,从而保障演练的可靠性与可操作性。最终的目标是推动演练的常态化。如果我们未能实现这一目标,之前的所有努力都将失去意义。因此,常态化演练是我们必须实现的关键成果。

轻量级容灾演练体系

在整体背景已经明确的基础上,我们现在深入探讨轻量级容灾演练体系的具体架构。

演练体系的底层基础是我们构建的 原子故障库。该库包含一系列基础的故障模拟,如 CPU 异常、网络异常、延迟、丢包等。这些原子故障构成了演练的核心元素,为各类场景的创建和演练提供了基础保障。

在原子故障库的基础上,我们封装了两大类故障场景。一类是通用场景,如 CPU 高负载、容器异常、网络丢包等。这些场景旨在简化用户的使用流程,用户只需轻松填写参数或直接调用封装好的场景即可,免去故障设计的复杂性。另一类是特化场景,针对公司内部的特定业务形态,如双活、多活策略、自研中间件等,定向封装特定的故障模拟。此类场景帮助内部团队进行有针对性的演练,满足个性化的业务需求。

进一步向上,我们构建了 混沌实验层。这一层关注于实验的设计与分发,包括如何在不同的载体中注入故障,模拟和测试系统在真实故障场景中的表现。通过混沌实验,我们可以有效地验证系统的弹性和容灾能力。

演练过程中,故障的注入和恢复效果需要通过 观测能力 进行实时监控。我们不仅需要验证系统恢复的有效性,还要通过稳态指标来观察业务的稳定性,并能够及时发现异常情况。这一层次确保我们能够精准评估演练效果,并在发现问题时做出快速响应。

经验沉淀是我们体系的另一部分。在演练的过程中,我们会通过故障组合来模拟更复杂的业务场景。通过多次演练积累的经验,将形成 演练模板,这些模板将帮助服务团队快速创建演练。例如,针对网关、SLB、跨机房、跨服务等复杂场景的演练模板,团队只需选择合适的对象、定义范围和业务稳态指标,即可直接使用模板,而不需要从头设计故障场景。

在体系的最上层,我们有 产品层的演练管理。这一层涵盖了演练的编排、故障生成、结果分析和演练报告生成等功能。通过演练管理平台,用户可以方便地管理整个演练过程,并生成详细的报告,便于事后分析和持续优化。

我们的发展路线清晰且逐步推进,目标是从工具到平台,再到一站式服务,最终实现轻量化目标。这一演练体系的迭代与发展,不仅是对容灾演练进行平台工程化的方向,也是我们轻量化目标的具体实现路径。

构建轻量级容灾演练体系的核心在于技术支撑,但单纯完成技术搭建并不足以确保成功的落地实施。为了使这些技术有效地应用于实际场景,我们必须确保它们能够无缝集成到现有的流程和平台中,发挥最大价值。

在研发过程中,我们计划将故障注入能力深度整合到持续集成(CI)流程和回归测试流程中。特别是在强弱依赖演练方面,我们希望能够在制品库出包之前,甚至在发布准备阶段,自动模拟各种故障并进行问题检查。这不仅包括传统的混沌演练,还涵盖了系统故障、网络故障等常见问题,以及针对内部业务的特定故障场景。通过这一做法,我们能够在发布前及早发现潜在问题,确保发布后的稳定性与容灾能力。这一环节的目标是将演练从开发阶段向前推进,实现更早的故障检测与风险防控。

其次,大型容灾演练往往涉及跨机房级别的测试,包括多活演练和降级兜底方案演练。这些演练不仅要求技术架构具备高可用性,还需要模拟不同故障情境下,业务如何进行自动切换和恢复。技术落地的过程中,这些高复杂度的容灾演练将是关键组成部分。通过跨机房、多活架构的演练,我们可以验证容灾方案在真实环境中的有效性,确保在不同故障场景下,系统能够快速、准确地恢复服务,减少业务中断时间。

技术落地后,我们需要进一步去思考如何实现容灾演练能力的跨领域赋能,通过与周边平台的协同,拓展演练平台的应用范围。这不仅限于系统内部的演练,还可以向外部提供服务,形成生态化。例如,在应急响应方面,我们可以通过演练进行故障溯源和定位,帮助快速找到系统中的薄弱环节,并提升团队的应急响应能力。在攻防演练方面,通过模拟故障链路和随机故障场景,增强系统在面对外部攻击时的抗压能力,提升安全性。以及我们可以借助内部大模型团队的能力,对演练内容进行详细的复盘和梳理。基于在应急过程中发现的问题,识别系统的薄弱点,并针对性地调整演练计划,进一步强化系统的容灾能力。

组织阵型搭建

在支撑容灾演练体系的建设过程中,组织架构的构建和制度的完善至关重要。我们通常从技术、流程和组织三大维度进行探索与实践。然而,随着项目推进的深入,我们逐渐认识到,组织架构的清晰与合理性对容灾演练的成效具有决定性影响。若组织架构不明确,责任划分不清晰,后续工作将容易陷入混乱。因此,我们在项目初期便通过对组织架构的优化调整,以及虚拟项目协同的推动,确保能够高效实现演练的整体协同目标。

为此,我们组建了“安全生产委员会”,成员由一线核心领导组成。这些领导在公司内担任重要职能,负责高层稳定性决策、关键稳定性演练路径的规划,同时制定相关规则,设立基线和红线。此外,委员会还肩负提升公司整体应急协同能力的任务,包括推动公司文化和应急意识的不断提升。

在制度建设方面,我们已编制并发布了多部白皮书,旨在规范容灾架构设计,明确容灾演练章程和故障演练的操作规范。这些制度为演练活动的开展提供了坚实的理论和实践依据。

在文化宣导方面,我们通过“安全生产月”活动来强化安全文化的普及和员工的稳定性意识。活动期间,我们通过在各楼层布置易拉宝、举办专题分享等方式,让不同业务线的员工分享在系统稳定性方面的改进经验和最佳实践。同时,我们还建立了在线学习平台,定期发布培训视频,尤其针对新入职的校招同学,帮助他们快速了解并掌握容灾演练的相关知识与技能。

另外,我们推出了“孤岛行动”专项活动,这项工作正处于持续推进阶段,旨在通过在机房级别进行断网等真实场景的模拟演练,促使各业务线自发进行自我诊断与保障。这一行动紧密围绕目标驱动,推动演练效果的逐步落地。

在技术分享方面,我们每周通过 B 站的技术公众号发布最新的技术文章,分享团队在容灾演练中的技术实践与经验。同时,我们也会定期在内部平台发布各个技术部门的创新成果和实践案例,确保技术经验能够在公司内部广泛传播并加以应用。

运营机制流程

在流程支撑方面,我们将其划分为两个核心模块:演练执行流程和演练全生命周期流程。梳理这些流程的目的在于确保业务能够高效开展日常演练,同时为平台功能设计提供科学依据,避免凭直觉设计出的功能在实际应用中产生不良效果。

演练执行流程涵盖演练的前、中、后三个阶段。演练前,首先需要梳理业务场景,明确需要演练的场景类型,同时评估方案及其可能的影响。此阶段还包括对演练方案的评估,决定采用染色流量演练、线上不切流演练,还是先切流量后注入故障进行验证。

在演练阶段,我们需明确演练的范围与环境,划定集群及机器的边界,配置规则,模拟故障,并确定需要监控的关键指标。此外,还要设计保护机制,确保在出现问题时能迅速拦截并恢复故障,同时执行应急预案。在验证场景时,需设置合理的指标,并通过断言验证演练是否符合预期要求。此阶段主要支持自动化演练的执行。

演练执行阶段相对简洁,关键在于按照既定步骤注入故障并进行观测。演练恢复阶段同样重要,确保故障恢复后业务状态达到预期,因为在某些情况下,即便故障已撤除,业务仍可能处于异常状态。

演练后,需规划未来的常态化演练,确定哪些场景适合常态化并制定相应计划。此外,还需评估是否开展突袭演练,并根据演练过程中发现的问题制定待办事项,分配责任并推进落实。

演练的执行流程已经明确,接下来我们要讨论的是演练的全生命周期流程。执行流程主要针对单次演练,而我们的演练目标是根据五大原则,在真实环境中模拟真实场景。虽然演练通常是指生产环境中的操作,但我们不可能直接在生产环境中进行演练,因为这不仅风险高,而且也不符合实际操作的安全规范。因此,我们首先会在非生产环境中进行演练测试,模拟并验证演练流程。如果在非生产环境中发现存在重大的待办事项、故障或隐患尚未修复,我们就没有必要继续推进生产环境中的演练,因为这样只会加剧问题。此时,优先解决这些潜在风险,确保环境稳定后,才能在生产环境中实施演练。

非生产环境与生产环境演练的主要区别在于对流量的处理方式。在非生产环境中,通常无需进行流量染色,可以直接进行跨网络的全局演练,这样能够涵盖更多的场景。但在生产环境中,我们需要特别考虑流量染色的策略。具体来说,流量染色的范围是按实例级别还是请求级别进行,或者是否需要在演练前就提前切流量,减少对现有生产流量的影响。

在验证和恢复阶段,非生产环境中的演练通常不涉及应急响应,因为演练本身并不对生产环境产生实际影响。而在生产环境中,演练很可能触发真实的故障或服务中断,这时应急响应必须迅速启动,确保业务的连续性和系统的稳定性。因此,生产环境中的演练需要联动应急响应流程,一旦触发故障,相关的恢复措施和应急处理流程也必须同步执行。

为了确保演练的全面性和有效性,我们推动常态化的演练周期,并引入突袭演练机制。通过这种方式,我们可以模拟和应对多种突发情况,确保演练不仅仅局限于常规场景,还能在真实环境中进行充分验证。通过全生命周期管理的演练流程,我们能够保证演练的安全性、有效性,并持续提升系统的稳定性和应急响应能力。

容灾产品能力

在组织支撑和流程标准的基础上,引入技术手段的目的是确保组织协同和流程标准的有效落地,从而保障整体轻量化演练目标的实现,确保演练能够高效、有质量地开展。通过技术手段的支持,我们能够实现六化落地,进而促进组织协同和流程标准的全面实施,确保轻量化容灾演练在质量、进度和效果上的目标得以实现:

  1. 演练协议标准化

  2. 故障引擎自研化

  3. 实验参数精简化

  4. 演练覆盖全面化

  5. 演练过程可视化

  6. 演练流程自动化

演练协议标准化

为了确保组织协同和流程标准的有效落地,我们通过六个关键点确保演练目标的质量和效率,尤其在标准化方面,我们注重细节。最初,我们依赖阿里的 ChaoBlade 等开源工具,极大地帮助我们降低了资源成本,但随着多个团队开发了各自的工具,面临着如何整合内外部演练工具的问题。由于不同团队的技术设计理念差异,这些工具在命令行参数、接口协议等方面存在差异,导致需要通过模型抽象来实现统一。具体来说,我们从两个关键方面入手:标准化的演练描述模型和标准化的演练交互模型。

演练描述模型:这是对故障演练的整体定义。无论工具设计如何不同,我们都需要标准化演练对象、演练范围、载体类型(如 IP 和端口)和演练参数。以网络故障演练为例,我们需要明确参数的形式、演练模式以及预检要求等细节,确保所有演练的执行都符合统一标准。

演练交互模型:针对不同工具的交互方式,我们通过封装这些交互过程,抽象出通用的实验注入、注册、执行、恢复、审计和查询等功能。为实现这一目标,我们使用 Golang 中的接口(interface)进行行为抽象,从而确保在一套统一的系统中能够兼容原有的工具,并逐步过渡到新的工具。这种方式不仅提升了系统的灵活性,还保证了高效的工具集成和后期的平滑迁移。

故障引擎自研化

在完成标准化工作后,我们逐步面临了自研化的需求。在混沌实验的过程中,尽管我们前期依赖了多个开源工具,但实际应用中暴露出的一些关键问题促使我们重新审视并最终选择了自研解决方案。虽然我通常反对仅仅因为开源工具存在就进行自研,但当面临一系列明确的业务需求和技术挑战时,自研变得更加合理和必要。以下是我们选择自研的四个主要原因:

  1. 故障注入可靠性不足,影响演练成功率:在实践过程中,我们发现开源工具在故障注入的可靠性上未能达到我们的预期,并且这直接影响了演练的成功率。作为负责相关指标的团队,我们急需确保故障注入的稳定性和可靠性。在生产环境中,我们遇到了多个具体问题:DNS 干扰演练,开源工具通过修改 /etc/hosts 文件来覆盖域名,但现代 SDK 在解析域名时忽略了这些覆盖,导致故障注入逻辑失效。网络不可用故障注入:开源工具在执行大规模网络故障注入时,由于命令参数过长,超出了系统执行的限制,导致注入操作无法完成。CPU 负载注入:开源工具在 CPU 负载注入方面的实现无法达到预期效果,无法有效模拟出真实的系统压力。

  2. 演练编排流程过于简易,缺乏状态管理和控制:开源工具的设计通常聚焦于底层的故障注入原子能力,而对于复杂的演练编排和流程控制,则显得相对简单。例如,故障注入链路通常缺乏状态管理,一旦某个环节出现故障,整个链路便会中断,无法有效回溯故障发生的具体位置。这种简单的设计无法满足我们对演练过程中的可控性、可追溯性和健壮性的要求。我们需要一个更为复杂、灵活的系统来管理故障链路中的每一个环节,保证故障模拟的精确性和完整性。

  3. 缺乏服务 / 资源鉴权,增加了演练的安全风险:开源工具通常未能有效地处理资源鉴权的问题,而我们的内部系统需要更精细的权限管理。这使得开源工具在执行演练时可能带来潜在的安全隐患。例如,资源的访问控制和操作权限无法与我们的安全要求相匹配,容易导致误操作或安全漏洞的发生。为了满足内部的安全合规要求,我们需要对现有工具进行封装和增强,确保演练的每个环节都在授权和安全的范围内进行。这种高度的定制化需求使得自研成为了更为合适的选择。

  4. 缺乏有效的观测手段,问题难以排查:混沌实验强调对故障注入全过程的精确控制和观察,因此可观测性成为了我们非常重视的一个方面。开源工具在注入过程中的监控能力不足,缺乏从故障调度到容器调度的全链路监控,导致问题排查困难。为了确保演练的高效和准确,我们需要自研一个更为完善的观测平台,能够覆盖从外部用户请求到内部故障代理调度的整个链路,实时监控并反馈每个环节的状态,帮助我们在发生问题时迅速定位并解决。这一改造将是高侵入性的,但对于提高演练的成功率和效率至关重要。链路复杂性:在涉及到容器和 Kubernetes 调度的情况下,故障注入链路非常复杂,任何一个环节的问题都可能导致故障注入或恢复失败。尤其当演练量逐渐增加时,这些小问题会积累成更大影响。缺乏实时反馈:现有工具在发生故障时无法提供详细的日志和反馈,缺乏足够的监控手段来实时追踪注入过程中的状态,难以快速定位问题。

实验参数精简化以网络演练为例

在自研化之后,我们面临的另一个关键挑战是 如何实现系统的轻量化,特别是在减轻用户和运维人员的操作负担方面。这一挑战的核心在于简化实验参数的配置流程,以提高用户体验和操作效率。我们的理想状态是,用户在进行跨网故障演练时,只需勾选“跨网故障”选项,而无需进行任何复杂的额外配置。为了实现这一目标,我们着力于对内部参数进行精简和优化。

以网络故障演练为例,我们发现网络故障注入的配置参数通常复杂且冗长。例如,在使用 TC 命令进行网络故障注入时,需要编写大量的命令来指定不同的网络干扰类型和细节。为了解决这一问题,ChaoBlade 作为一个封装工具,简化了注入参数,主要包括影响 IP、豁免 IP、本地端口和远程端口等。然而,实践中我们发现,网络故障的服务描述通常是通过 IP 和端口组合来进行的,这种描述方式在实际应用中更为常见和直观。因此,我们对原有参数进行了重新整理,将过程式参数(即操作步骤和命令)转化为声明式参数(即目标和效果的描述)。在新的模型下,用户只需声明他们希望达到的故障效果,而无需关心如何实现这些效果的具体操作过程。

这一转变使得网络故障演练的配置变得更加直观和易于操作,极大地降低了用户的心智负担。用户无需深入理解底层命令和复杂的参数配置,只需选择他们所需的故障类型和目标效果,系统会自动完成相应的操作。这种简化不仅提升了用户的操作便捷性,也为后续的系统扩展和场景应用打下了良好的基础。

此外,这种简化方案也极大提高了开发效率。由于系统内部参数的标准化和声明式设计,新增或修改演练场景时,开发者不再需要处理繁琐的命令行细节,而是可以专注于扩展和优化更高层次的功能。这使得我们在迭代和创新时能够更加高效,从而更好地满足用户日益增长的需求。

实验参数精简化跨 AZ 断网容灾演练

在跨可用区(AZ)的断网容灾演练中,服务级别的测试通常需要遵循以下步骤:首先,流量需要切换到其他路径;其次,模拟在某个可用区的专线断网故障;最后,验证各项服务功能是否仍然正常。然而,模拟应用层面的断网并非易事,因为实际操作中我们无法直接在机房断开网络连接,这样的操作可能会影响到整个机房的稳定性和业务连续性。

在演练的准备阶段,需要详细识别和分析哪些服务可能会受到影响。这包括服务的 Pod IP 和主机 IP,以及确定哪些服务需要断开连接,哪些则不应中断。对于不进行断开连接的服务,可以分为两类:预期内不断开服务和预期外不断开服务

  • 预期内不断开服务:例如 MySQL 数据库等,这些服务本身在日常运营中就需要跨机房进行通信,且未进行单元化拆分,演练时不应断开此类服务。

  • 预期外不断开服务:这类服务可能因改造不完全或某些依赖尚未完成,因此仍需要保持在线,不能断开。

针对这些尚未完成改造的服务依赖,核心任务是通过打通内部平台,自动化梳理和识别服务间的网络依赖关系。借助这一自动化工具,系统能够自动列出服务所依赖的数据库、缓存、键值存储等组件,并精准判断哪些服务应当断开,哪些不应断开。这一机制显著简化了容灾演练的操作,使得用户在进行服务级别的断网演练时,几乎无需手动填写复杂的依赖信息,重点只需关注需要豁免的服务,并做出相应配置。

通过自动化流程的引入,跨服务、跨可用区的容灾演练工作得到了极大简化和优化。同时,容灾建设通常涵盖三个关键环节:容灾架构设计、容灾基础设施建设以及容灾演练。通过实现自动化的服务依赖梳理与豁免管理,我们能够更高效地推动容灾演练的实施,确保容灾能力的验证与完善,并最终实现一个闭环的容灾体系。

演练覆盖全面化

在进行大部门与小部门演练时,必须考虑到不同规模的服务架构,包括海外服务、CDN 节点等。与传统机房演练不同,这类演练涉及到更加复杂和广泛的系统架构。因此,我们采取了以下三项关键措施,以应对这一挑战:

  • 多样化的注入对象类型:无论服务部署在容器、虚拟机还是物理机上,我们将所有故障注入的载体抽象为两个核心类型:容器和服务器。这样,无论具体服务如何部署,我们只需要满足这两种载体的故障注入需求。为了便于选择和管理这些多样化的对象类型,我们依托配置管理数据库(CMDB),它集中收集了所有集群的元信息,使得我们能够高效地勾选特定集群或组件进行演练。

  • 大规模注入载体管理:在类似 Kubernetes(K8s)的大规模容器环境中,我们管理着数十万个容器分布于多个集群中,这无疑增加了接入和操作的复杂性。为了确保演练的安全性,我们实现了自动化打标与撤标机制,即故障注入组件仅在演练期间自动激活,演练结束后自动撤除。这一机制有效避免了因误操作导致的潜在风险。

  • 多样化的环境支持:我们的服务涵盖了国内外多个环境,包括机房内、机房外以及不同区域的服务部署。对于机房内的环境,由于存在专线连接,问题较为易于解决。而对于机房外的环境,我们通过公有云服务和 Proxy 管理,实现跨网络的指令调度。这一机制基于内部统一的应用信息映射,确保跨区域调度变得简单、高效。

演练过程可视化

演练过程的可视化与我们之前提到的标准模型密切相关。当需要演练的对象较为众多时,除了接入核心的可观测团队,并遵循 OpenTelemetry (OTel) 标准的服务外,其他未遵循这一标准的业务服务或小型事业部同样需要纳入监控体系。否则,在演练过程中,这些服务将无法提供任何监控数据。

为了确保全面的可观测性,我们制定了监控指标的标准。这一标准相较于模型抽象更为简化,因为它不涉及复杂的指标体系,而是关注基础的行为抽象:如何获取对象的数据,明确服务对象的定义,以及围绕该对象的关键指标,最后确定如何实时获取这些指标数据。在演练过程中,一旦选择了某个服务对象,系统将自动加载该对象的所有相关指标,用户可以根据需求进行勾选。一旦勾选完成,用户便能在演练过程中实时监控这些指标的变化情况。

我们的演练架构图仍在不断优化和迭代中。该架构图以演练对象为核心,能够展示基于 Trace 的动态调用链以及基于 CMDB 的静态拓扑结构。这样,一旦故障注入,我们能够直观地看到故障对目标对象的上下游服务以及其自身的影响。这种可视化能力对于理解演练过程中的复杂性至关重要,它能够帮助我们全面监控并分析演练效果,从而确保演练的可控性和有效性。

演练流程自动化

在实现演练流程自动化时,我们关注以下三个关键要点:

  1. 场景自动验证:能否自动验证演练场景的有效性?鉴于测试团队在这一领域的丰富经验,他们已开发了许多高效的平台功能,这些功能能够直接与我们的演练流程对接,复用其 UI 自动化测试 能力。测试团队的关注点主要在于场景本身和结果的验证,包括多场景和单应用的结果验证。因此,当我们进行某个业务场景的演练时,系统能够全自动地验证演练结果的正确性。

  2. 演练自动执行:演练的自动执行可以分为三个核心部分:定时调度器:这是一项相对基础的功能,大家普遍熟悉如何实现它,通过编写定时任务来定期触发演练。编排自动化:我们能够自动化推进演练流程,确保各个步骤按预定顺序无缝衔接,并在演练过程中自动执行。护栏机制:这一部分旨在确保演练过程中能够有效预防意外情况的发生。与可视化和可观测性紧密关联,通过实时获取可观测的指标数据,结合断言和规则逻辑引擎,可以在演练过程中实现预期的验证,确保演练不会偏离预期目标。

  3. 预期自动验证:这一部分与场景验证类似,但更侧重于基于指标的验证。我们需要判断演练后的场景是否符合预期结果,或者是否故意触发了反结果。在某些演练场景中,系统预期在演练结束后会出现异常情况。实际演练中,我们可能会发现有些链路未能按预期发生故障,这本身也是一种异常情况。因此,我们需要追踪并检查这些链路的补偿机制,确保演练的结果和准确性,以便改进和提升系统的容错能力。

业务场景演练实践

演练协同一体

我们的业务场景演练实践的核心目标是将传统的线下协同演练转变为线上协同演练。通过平台化的演练协同一体化,我们将原本需要在小会议室内进行的多方协作,转移到线上环境。这种转变使得演练人员、相关系统、业务服务以及演练过程中的关键数据能够通过一个集中的演练面板进行实时汇聚和管理。

整个演练过程从开始到结束,都在同一页面完成,具体包括以下几个阶段:

  1. 演练配置:在此阶段,我们定义演练对象、确定测试范围、编排演练流程,并配置各项原子实验。随后,我们设定观测指标和护栏机制,确保在演练过程中能够有效监控关键指标,并在异常情况下自动采取应对措施。

  2. 演练执行:在演练执行阶段,所有操作都集中在同一页面上进行,从而简化了流程并显著提升了执行效率。

  3. 演练恢复:在演练完成后,我们会对系统进行恢复,以确保环境和服务能够回到正常状态。

  4. 报告生成与验收:演练结束后,生成详细的演练报告,并进行验收,评估演练的效果和对业务的影响,从而为未来的演练和改进提供数据支持。

可用区级断网容灾演练

我们的可用区级别的断网演练并非通过平台进行专线故障的注入。这里将展示了我们内部在执行此类演练时的具体推进模式。在服务级别的跨网可用区演练完成后,我们会进一步开展公司级别的大规模可用区演练。此类演练通过在交换机上实施策略,切断机房之间的专线以及公网入口,以确保在可用区故障发生时,我们的业务和服务能够实现有效的逃生和容灾。

整体演练的节奏是,我们通常会在年度规划中设定一个宏观目标,并根据具体方案进行细分,明确关键节点,将任务分解并安排在年度内完成。随后,我们会组织相关团队,明确不同环节所需的角色,涉及的事业部,以及各方负责的事务与结果交付。最后,我们会进行现状评估,完成项目摸排,并排除白名单中的内容,最终开始执行演练,演练结束后进行复盘总结。

我们的整体思路分为三个主要阶段:

  1. 断开机房间专线:首先,我们会切断两个机房之间的专线连接,检查双活和多活架构的实施效果,确保在机房间不存在不合理的依赖关系。

  2. 南北向流量切断:完成第一阶段后,我们会开始切断南北向流量,即通过断开机房的公网入口流量来测试系统的承载能力。

  3. 完全脱网模拟:最后,我们会同时切断机房间专线和公网流量,模拟一个机房完全脱网的情况,测试系统在极端故障条件下的恢复能力。这一阶段是我们演练的大方案。

目前,我们已经制定了详细的演练计划。首先,我们从多活风险治理入手,进行公网流量切换,以验证流量能否顺利承载到另一侧。接着,我们会切断机房间的专线,保留 1% 的流量,随后切断专线并将剩余流量引导至另一侧。接下来,我们会模拟非主机房的公网断开情况,保留 1% 的流量,最后实现整个机房完全脱网,以观察全流程的影响和反应。以上步骤构成了我们目前的具体计划和演练节奏。

集成测试演练

集成测试演练是我们的核心场景之一,它将故障注入能力有效地移植到测试环境中,成为测试团队日常工作的重要组成部分。平台提供了 OpenAPI 能力,允许测试和质量保障(QA)团队编写测试用例,并将这些用例集成到持续集成(CI)构建流程中。在代码提交后,相关测试用例会自动触发执行,确保新提交的代码不会引入不合理的依赖或潜在的故障。

关键在于识别出适合快速验证的测试场景,这些场景应当能够高效地在流水线中运行。例如,断网演练不适宜在 CI 流水线中执行,因为它可能消耗大量时间和资源。此外,考虑到我们前面提到的 UI 自动化测试和多场景接口测试功能的多样性,我们需要充分利用这些现有功能,确保它们能够有效地进行系统验证。

S 赛演练

《英雄联盟》赛事是我们每年重点演练的场景之一。我们的核心流程首先基于分级规则对赛事进行等级划分,随后根据分级结果制定具体的赛事保障场景地图。通过这张地图,我们能够有效规划并应用前述能力进行全面的系统摸排。

这种专项摸排属于针对性的演练,旨在深入挖掘潜在问题,尤其是在代码层面上的强弱依赖关系以及降级方案的合理性问题。通过此次演练,我们发现了若干关键问题,这些发现对我们而言具有极大的价值,因为它们直接影响赛事期间的服务稳定性和用户体验,确保能够在高负载情况下保障赛事顺利进行。

总结展望

演练收效

通过一系列措施的实施,我们整体的提升效果非常显著。首先,我们的演练从规划到落地的周期已经从以周为单位缩短至以天为单位,这显著降低了演练的时间和资源成本。其次,之前仅有核心部门能够参与演练,现在所有部门都可以利用这套工具进行演练,确保了全面覆盖与跨部门协同的实现。

在业务应用和核心场景的演练频次方面,过去我们通常每季度进行一次演练,而现在我们已将频次提升至每周一次。对于业务团队而言,除非有较大负载变更,否则他们对演练的抵触情绪较少,从而能更积极地参与其中。

最后,在演练有效性验收的环节,以前需要人工介入,且成本较高,现在我们已实现了自动化验收,并能够复用测试中的多个场景,从而实现了技术建设的复利效应。这种自动化与复用机制不仅提升了工作效率,也大大减少了人为错误的发生。

实践反思

  • 明确演练目标:在开始演练之前,必须设定明确的目的和预期成果,否则演练结束后可能难以评估效果,进而影响后续决策和改进。

  • 量身定制推广方案:在进行大规模推广时,必须充分考虑各业务团队的特性,定制化解决方案,并主动推动实施,确保各部门在自身业务场景下能够有效执行并获得最大收益。

  • 高密度、高关注、高收益的演练类型:强弱依赖演练、应急预案演练和多活演练等,均具备高密度、高关注度以及高收益的特点。这些演练能够充分测试系统的脆弱性和容错能力,是保障系统稳定性和优化服务的重要环节。

  • 演练自动化的关键:演练自动化的核心在于保证过程护栏的有效性以及演练效果验证的自动化。只有确保演练过程全程受控并能自动验证效果,才能实现高效、精准的自动化演练管理。

  • 自动化用例的完善:应根据演练场景的需求,补充和完善自动化用例,确保所有关键场景和操作都能被自动化覆盖。这可能需要特别针对不同场景进行用例设计和补充。

  • 接口自动化用例的优化:对于接口类自动化测试,可以利用流量录制工具捕获实际业务流量,并将其转换为自动化测试用例,从而增强测试的现实性和覆盖面。

  • 分阶段实施混沌工程实验:不同系统处于不同的成熟度阶段,需要针对性地采用不同类型的混沌工程实验,以逐步提高系统的稳定性、抗压性和容错能力,确保每个阶段的工程目标能够有效推进。

嘉宾介绍:

刘昊,哔哩哔哩 SRE 平台工程团队负责人,专注于技术风险领域的工程化落地,在应急响应、变更防控、混沌工程、风险治理和运维数据资产等方面有丰富经验。

财经自媒体联盟更多自媒体作者

新浪首页 语音播报 相关新闻 返回顶部