可用区静态稳定性架构:如何提升云服务高可用性

SEO 摘要: 本文介绍如何使用可用区实现静态稳定性,并通过控制平面与数据平面分离、主动—主动架构、主动—备用架构、分区服务设计和故障前容量预置,提升云服务的高可用性与故障隔离能力。

可用区静态稳定性架构:如何提升云服务高可用性

简介

在海外某些大型科技公司,基础设施服务通常需要满足极高的可用性目标。这意味着,团队必须仔细分析系统中的各种依赖关系,并将系统设计得足够有弹性:即使某些依赖受损,系统也不会因此中断。

本文将介绍一种名为“静态稳定性”的高可用架构模式,并说明如何借助这一模式实现系统弹性。我们还将展示如何将这一概念应用于可用区。可用区是云基础设施中的关键构建块,也是许多服务构建高可用架构时所依赖的基础能力。

在静态稳定的设计中,即使某项依赖发生故障,整个系统仍然能够继续工作。系统可能无法获得该依赖本应提供的最新信息,例如新增内容、删除内容或修改内容。但是,在依赖故障之前已经完成并生效的工作,仍然会继续发挥作用。

本文将介绍某海外云服务商的弹性计算服务如何通过静态稳定性保持运行,并给出两个静态稳定的示例架构。这些架构对于在可用区之上构建高度可用的区域级系统非常有用。

最后,我们将进一步讨论这类弹性计算服务背后的一些设计理念,包括如何在软件层面提供可用区独立性。同时,我们也会讨论在采用这种架构构建服务时需要考虑的一些权衡。

在企业内部落地这类高可用架构时,架构方案往往需要贯穿目标制定、需求评审、开发、测试、发布上线和经验沉淀等多个环节。团队可以借助 PingCode 这类智能化研发管理工具,将架构决策、需求拆解、缺陷跟踪、发布验证和 Wiki 知识沉淀串联起来,让高可用能力建设从设计到交付都更加可追踪、数据化和可复盘。

可用区的作用:云高可用架构的基础

可用区是云区域中逻辑隔离的一部分。每个云区域都包含多个可用区,这些可用区能够相互独立地运行。可用区之间在物理上保持有意义的距离,以降低雷击、龙卷风、地震等潜在事件造成关联影响的风险。它们不共享电力或其他基础设施,但会通过高速、加密的专用光纤网络互联,使应用程序能够快速完成故障转移,而不会中断服务。

换言之,可用区为基础设施隔离提供了一层抽象。需要使用可用区的服务,可以让调用方告知云平台希望在某个区域内的哪个物理位置预置基础设施,从而受益于这种独立性。在海外某些大型云服务商中,许多区域级服务都会利用可用区之间的独立性来实现自身的高可用性目标。例如,托管 NoSQL 数据库服务、托管消息队列服务和对象存储服务,都是这类区域级服务的典型代表。

当调用方与在虚拟私有云中预置云基础设施的服务交互时,其中许多服务不仅要求指定区域,还要求指定可用区。可用区通常会通过必填的子网参数隐式指定。例如,在启动弹性计算实例、预置托管关系型数据库,或创建托管缓存集群时,调用方通常都需要提供子网。虽然一个可用区中可以存在多个子网,但单个子网只会完全位于一个可用区内。因此,提供子网参数时,调用方也就隐式指定了要使用的可用区。

静态稳定性:在故障发生前完成准备

在基于可用区构建系统的过程中,我们学到的一条重要经验是:必须在故障发生之前做好准备。

一种效果较差的方法,是把服务部署到多个可用区,并假设如果某个可用区发生故障,服务就可以扩展到其他可用区中,例如通过自动伸缩机制扩容,然后恢复到完全正常的运行状态。这种方法效果不佳,因为它依赖于故障发生之后的响应,而不是在故障发生之前就完成准备。换言之,它缺乏静态稳定性。

相比之下,具备静态稳定性的服务会更加可靠。它会提前超额预置基础设施,使系统即使在某个可用区受损时,也无需启动新的计算实例,就能够继续正常运行。

为了更好地说明静态稳定性的特征,我们先来看某海外云服务商的弹性计算服务。这类计算服务本身通常就是按照静态稳定性的原则设计的。

弹性计算服务通常由控制平面和数据平面组成。“控制平面”和“数据平面”原本是网络领域中的术语,但在云基础设施架构中也被广泛使用。控制平面负责对系统进行变更,例如添加资源、删除资源、修改资源,并将这些变更传播到需要生效的位置。相比之下,数据平面负责这些资源的日常运行,也就是资源正常工作所需的核心能力。

在弹性计算服务中,控制平面包含启动新实例时发生的一切。控制平面逻辑会执行多项任务,将新计算实例所需的所有内容组合起来。例如:

  • 在考虑置放策略和虚拟私有云租赁要求的同时,为计算任务查找物理服务器;
  • 从虚拟私有云子网中分配网络接口;
  • 准备块存储卷;
  • 生成身份与访问管理角色凭证;
  • 安装安全组规则;
  • 将结果存储在各种下游服务的数据存储中;
  • 根据需要,将必要配置传播到虚拟私有云中的服务器和网络边缘。

相比之下,弹性计算服务的数据平面负责让现有计算实例按预期持续运行,例如:

  • 根据虚拟私有云路由表转发数据包;
  • 从块存储卷读取数据,或向其中写入数据;
  • 执行其他与实例日常运行相关的工作。

与大多数系统中的数据平面和控制平面一样,弹性计算服务的数据平面比控制平面简单得多。正因为相对简单,数据平面的设计目标通常是提供比控制平面更高的可用性。

更重要的是,弹性计算服务的数据平面经过精心设计,即使控制平面发生可用性事件,例如启动新计算实例的能力受损,也能保持静态稳定。例如,为了避免网络连接中断,数据平面会被设计为:运行计算实例的物理服务器能够在本地访问将数据包路由到虚拟私有云内外所需的全部信息。

如果控制平面受损,事件期间物理服务器可能无法获得某些更新,例如虚拟私有云中新增的计算实例,或新增的安全组规则。但在事件发生之前已经能够正常发送和接收的流量,仍会继续工作。

控制平面、数据平面和静态稳定性的概念并不只适用于弹性计算服务,而是具有广泛适用性。将系统拆分为控制平面和数据平面,是设计高可用服务时非常有用的概念工具,原因包括:

  • 对使用服务的客户而言,数据平面的可用性通常比控制平面的可用性更重要。例如,对大多数云客户来说,计算实例启动后的持续可用性和正常运行,通常比启动新计算实例的能力更重要。
  • 数据平面的运行容量通常高于控制平面,很多时候甚至高出一个或多个数量级。因此,最好将两者分离,使它们能够按照各自相关的扩展维度进行扩展。
  • 多年来,工程团队发现系统的控制平面通常比数据平面包含更多活动部件。因此,仅从统计角度看,控制平面也更有可能因为复杂性而受损。

综合这些因素,较好的实践是沿着控制平面和数据平面的边界拆分系统。

为了在实践中实现这种拆分,团队会采用静态稳定性原则。数据平面通常依赖来自控制平面的数据。但是,为了实现更高的可用性目标,数据平面必须能够在控制平面受损时保持现有状态并继续工作。数据平面在故障期间可能无法获得更新,但在此之前一直正常工作的内容仍应继续工作。

前文提到过,一种应对可用区故障的方案是替换计算实例,但这种方案效果不佳。原因并不是系统无法启动新的计算实例,而是为了应对故障,系统必须立即依赖弹性计算服务控制平面的恢复路径,以及让新实例开始执行有用工作所需的所有应用层系统。

根据应用程序的不同,这些依赖可能包括下载运行时配置、向服务发现系统注册实例、获取凭证等步骤。控制平面系统天然比数据平面系统更复杂。当整个系统已经处于受损状态时,它们也更有可能出现异常行为。

静态稳定性架构模式

本节将介绍云架构中常见的两种高级模式。这两种模式都利用静态稳定性来设计高可用系统,并且都建立在可用区抽象之上。每种模式适用于不同的场景。

主动—主动模式:使用可用区构建负载均衡服务

许多云服务内部都由横向扩展的无状态计算实例组或容器组成。团队会将这些服务运行在跨三个或更多可用区的自动伸缩组中。此外,这些服务还会超额预置容量,以便即使整个可用区受损,其余可用区中的服务器也能承载全部负载。

例如,当使用三个可用区时,可以超额预置 50%。换言之,通过超额预置,使每个可用区只运行在其经过负载测试的承载能力的 66% 左右。

最常见的例子是经过负载均衡的 HTTPS 服务。典型架构中,一个面向公众提供 HTTPS 服务的应用负载均衡器,会将流量转发到一个跨三个可用区运行的自动伸缩组。这是使用可用区实现主动—主动高可用性的示例。

可用区静态稳定性架构:如何提升云服务高可用性

如果出现可用区故障,这类架构不需要采取任何额外操作。受损可用区中的计算实例无法通过运行状况检查后,应用负载均衡器会自动将流量从这些实例上转移出去。实际上,成熟的弹性负载均衡服务本身也会按照这一原则设计:预置足够的负载均衡容量,以便在可用区受损时,无需扩容即可继续运行。

即使不涉及负载均衡器或 HTTPS 服务,也可以使用这种模式。例如,处理托管消息队列消息的计算实例组,也可以遵循这一模式。这些实例部署在跨多个可用区的自动伸缩组中,并进行适当的超额预置。如果某个可用区受损,服务无需执行任何额外操作。受损实例停止工作,而其他实例会继续处理剩余任务。

主动—备用模式:使用可用区构建关系数据库高可用

一些服务是有状态的,需要一个主节点或领导节点来协调工作。一个典型例子是使用关系数据库的服务,例如使用 MySQL 或 PostgreSQL 数据库引擎的托管关系型数据库服务。

这类关系数据库的典型高可用设置包含一个主实例,所有写入操作都必须通过该实例完成,同时还包含一个备用候选实例。系统也可能有其他只读副本,不过下文示例中不展开讨论。使用这类有状态基础设施时,团队会在不同于主节点所在可用区的另一个可用区中放置热备用节点。

当使用托管关系型数据库预置数据库时,通常需要提供一个子网组。子网组是一组跨多个可用区的子网,数据库实例会被预置到这些可用区中。托管数据库服务会将备用候选实例放置在与主节点不同的可用区中。这是使用可用区实现主动—备用高可用性的示例。

与主动—主动的无状态示例类似,当包含主节点的可用区受损时,有状态服务不需要主动对基础设施执行额外操作。对于使用托管关系型数据库的服务,数据库服务会管理故障转移,并将访问入口重新指向工作可用区中的新主节点。

这种模式也适用于其他主动—备用设置,即使它们并不使用关系数据库。尤其是,对于包含领导节点的集群架构系统,也可以采用这种模式。团队会将这些集群部署到多个可用区中,并从备用候选节点中选出新的领导节点,而不是在故障发生时临时启动替换节点。

这两种模式的共同点在于:在可用区受损之前,系统已经预置好了所需容量。在这两种情况下,服务都不会为了应对可用区故障,而临时依赖控制平面操作,例如预置新的基础设施或修改现有基础设施。

幕后原理:弹性计算服务内部的静态稳定性

本文最后一节将更深入地介绍弹性的可用区架构,并说明某海外云服务商的弹性计算服务如何遵循可用区独立性原则。当团队构建的服务不仅自身需要高可用,还要为其他服务提供可用于构建高可用系统的基础设施时,理解这些概念会很有帮助。

作为底层云基础设施的提供方,弹性计算服务是应用程序实现高可用性的基础设施基础。有时,其他系统也可能希望采用类似策略。

在弹性计算服务中,团队会在部署实践中遵循可用区独立性原则。弹性计算服务的软件会被部署到多个组件上,包括托管计算实例的物理服务器、边缘设备、DNS 解析器、实例启动路径中的控制平面组件,以及计算实例依赖的许多其他组件。

这些部署遵循分区部署日历。也就是说,同一区域中的两个可用区不会在同一天接收同一个部署。成熟的云服务商通常会采用分阶段部署方法。例如,无论部署哪类服务,都可以遵循这样的最佳实践:先部署一小部分整体容量,再逐步部署服务器的 1/N,持续扩大范围。

但对于特定基础设施服务,部署会进一步与可用区边界对齐。这样,如果部署出现问题,影响范围会限制在一个可用区内,并可以在该可用区内完成回滚和修复。其他可用区不会受到影响,并会继续正常工作。

这类部署实践往往涉及架构评审、发布排期、跨团队沟通、故障演练和复盘跟进等协作工作。团队可以使用 Worktile 这类通用项目协作系统统一管理任务、文档、日历、甘特图和审批流程,让可用区感知部署、容量准备和应急演练等工作更加清晰可控。

在构建弹性计算服务时,团队采用可用区独立性原则的另一种方式,是将所有数据包流设计为留在可用区内部,而不是跨越可用区边界。第二点,也就是网络流量保持在可用区本地,值得进一步说明。

这是一个很有意思的例子,能够说明在两类场景中,团队会如何以不同方式思考高可用架构:一类是构建高可用区域系统,并使用可用区独立性作为基础;另一类是向其他系统提供可用区独立的基础设施,使它们能够在此之上构建高可用系统。

假设有一项高度可用的外部服务,它依赖另一项内部服务。一种简单设计,是将这两项服务都视为独立使用可用区的区域服务。每个服务都由应用负载均衡器作为入口,并且每个服务都有一组经过适当预置的后端主机,分布在三个可用区中。一个高可用的区域服务调用另一个高可用的区域服务。这是一种简单设计,也适用于许多服务。

但是,假设内部服务是一项基础服务。也就是说,它不仅自身要具备高可用性,还要作为提供可用区独立性的构建块。在这种情况下,团队可能会将其设计为三个可用区本地服务实例,并在此基础上遵循可用区感知的部署实践。这样就形成了一个高可用区域服务调用高可用分区服务的设计。

之所以将构建块服务设计为可用区独立,原因可以通过一个简单计算来说明。

假设某个可用区已经受损。对于黑白分明的故障,应用负载均衡器会自动从受影响节点上进行故障转移。然而,并非所有故障都如此明显。有些故障属于灰色故障,例如软件中的某类错误,负载均衡器可能无法通过运行状况检查发现,也无法彻底规避。

在“高可用区域服务调用另一个高可用区域服务”的示例中,如果请求经过系统中的两个区域服务,并做一些简单假设,那么请求避开受损可用区的概率为:

2/3 × 2/3 = 4/9

也就是说,这个请求成功避开故障的概率反而低于单个服务避开受损可用区的概率。

相比之下,如果将内部服务构建为分区服务,那么外部服务中的主机可以调用同一可用区中的内部服务端点。在这种架构下,请求避开受损可用区的概率为 2/3。

如果调用路径中包含 N 个服务,那么对于 N 个区域服务,成功避开故障的概率通常会变成:

(2/3)^N

而对于 N 个分区服务,只要调用始终保持在同一可用区内,概率仍然保持为常数:

2/3

因此,某些云网络能力会被设计为分区服务。例如,NAT 网关是一种允许私有子网中的实例访问出站 Internet 流量的能力。它不一定被设计成一个区域级、虚拟私有云范围内统一的网关,而可以作为分区资源,由客户按可用区分别创建。

NAT 网关位于虚拟私有云的 Internet 连接路径上,因此是其中所有计算实例数据平面的一部分。如果某个可用区存在连接问题,团队希望将问题限制在该可用区内,而不是传播到其他可用区。

最终,采用前文所述架构的客户应该能够依赖这样一个事实:如果他们在三个可用区中预置实例组,并确保任意两个可用区都拥有足够容量来承载全部负载,那么其他可用区将完全不受受损可用区中事件的影响。实现这一点的关键,是确保 NAT 网关等基础组件确实保持在可用区内部。

这种选择会带来额外复杂性。对于弹性计算服务团队而言,额外复杂性体现在需要管理分区服务环境,而不是单一的区域服务环境。对于 NAT 网关客户而言,额外复杂性体现在需要拥有多个 NAT 网关和路由表,以便在虚拟私有云的不同可用区中分别使用。

这种复杂性是合理的,因为 NAT 网关本身是一项基础服务,也是弹性计算服务数据平面的一部分,应当提供分区级可用性保证。

在构建可用区独立服务时,还需要考虑另一个因素:数据持久性。虽然前面介绍的每种分区架构都展示了包含在单个可用区中的完整堆栈,但为了实现灾难恢复,团队会将所有硬状态复制到多个可用区中。例如,团队通常会在对象存储中保存定期数据库备份,并跨可用区边界维护数据存储的只读副本。主可用区并不需要这些副本才能正常工作,但这些副本可以确保客户数据或业务关键数据被存储在多个位置。

在设计运行于云环境中的面向服务架构时,团队可以使用以下两种模式之一,或将两者组合使用。

更简单的模式:区域调用区域

这种模式通常是面向外部服务的最佳选择,也适用于大多数内部服务。例如,在云平台中构建更高层应用服务时,例如 API 网关类服务和无服务器类技术,可以使用这种模式提供高可用性,即使某个可用区受损也能继续工作。

更复杂的模式:区域调用分区,或分区调用分区

在弹性计算服务内部设计数据平面组件时,尤其是设计直接位于关键数据路径上的网络设备或其他基础设施时,团队会遵循可用区独立性模式,并使用隔离在单个可用区中的实例,使网络流量保持在同一可用区中。

这种模式不仅有助于将故障隔离在单个可用区内,在云环境中也通常具备更有利的网络流量成本特性。

结论:通过可用区与静态稳定性提升高可用能力

本文讨论了在云架构中使用的一些简单策略,用于成功管理对可用区的依赖。静态稳定性的关键,是在故障真正造成影响之前就提前预测并完成准备。

无论系统运行在主动—主动的水平扩展实例组上,还是采用有状态的主动—备用模式,都可以借助可用区实现高可用性。团队应提前部署系统,使故障发生时所需的全部容量都已经完成预置,并处于可用状态。

最后,我们进一步了解了底层弹性计算服务如何使用静态稳定性理念,使可用区之间保持相互独立。通过控制平面与数据平面的分离、可用区感知部署、分区级服务设计,以及在故障发生前预置足够容量,系统可以在依赖受损时继续保持稳定运行。

文章包含AI辅助创作:可用区静态稳定性架构:如何提升云服务高可用性,发布者:shang,转载请注明出处:https://worktile.com/kb/p/3974736

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
shang的头像shang

发表回复

登录后才能评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部