一、弹性的概念
对于大多数用户而言,弹性服务的首要解决难题在于成本控制。特别是当用户的业务面临明显的流量波动时,如果云资源能够实时匹配这种流量波动,做动态的扩缩容。并结合云资源按秒计费和多种付费方式的能力,就能显著降低在云上的资源成本。第二个关键问题是自动化。自动化无疑是弹性服务的必然需求,因为在动态伸缩的过程中,我们需要初始化实例环境,并与其他云产品进行联动,确保网络畅通,以及安全的自动配置等,这些都需要自动化技术的支持。第三个问题是灵活性。在动态扩展与收缩的过程中,如果我们需要进行一些自定义操作,或者希望实施自定义策略,再或者我们想要采用多种付费方式、多种可用区以及多种实例规格的组合使用,这些都对弹性服务提出了高度的灵活性要求。
从分层的角度来看,弹性可以分为应用层弹性、平台层弹性和资源层弹性。应用层弹性通常是指直接承接用户工作负载的弹性能力。比如在K8S场景下,包括Pod的水平伸缩、垂直伸缩,以及其他用户进程级别的弹性功能。平台层弹性则主要聚焦于云上的弹性产品,如弹性伸缩服务以及ECS原生的API能力。基于平台层提供的弹性产品,用户可以在应用层构建更加灵活、更加丰富的弹性应用。底层则需要利用资源层的弹性能力,包括虚拟化的原子能力以及弹性控制系统、弹性调度系统,以及智能资源规划。而在session的第二部分,我的同事会针对资源增弹性做一个全景的介绍,包括我们最近一年在全链路优化方面的最新成果。而我的介绍将侧重于平台层弹性,重点讲解弹性伸缩服务的最佳实践及其一些高级应用方法。
二、为何需要弹性以及弹性的使用
接下来,以一个创业公司在云上经历的弹性扩展故事为时间轴,来探讨为何需要弹性以及如何使用弹性。这家创业公司起初的业务架构相对简单,在云上部署了3台包年包月的ECS实例、数据库以及负载均衡器,一切运行得十分顺畅,看起来很美好。直到有一天业务流量突然陡增,急需进行紧急扩容。此时,我们推荐使用快速交付大规模算力的利器弹性供应组。它支持通过目标容量的方式来描述自己对容量的需求,这个目标容量可以是ECS实例的个数,也可以是CPU、内存等其他的维度的资源。
此外,它还支持设置不同付费方式实例的比例,包括按量和抢占式实例,同时还支持多种不同的交付策略,例如均衡可持续分布的策略,以及成本优化的策略和优先级策略等。同时还支持多种不同的交付方式,包括一次性的异步交付、一次性的同步交付和持续交付。在一次性同步交付模式下,系统会在请求响应中实时返回所创建资源的列表。若遇到问题,系统会立即反馈异常原因。而持续交付则在供应组启动时持续监控资源创建情况,以确保达到目标容量,若资源有缺失,则会继续创建目标容量。在这种紧急扩容的场景下,我们推荐使用按量付费的付费方式,并使用均衡可用区的交付策略,同时选择一次性同步交付。这样能够快速满足用户的容量需求,同时在多个可用区中均衡创建所需资源,确保服务的高可用性,使业务能够迅速恢复正常运行。
随着客户业务的不断发展,他们观察到一种现象:晚上和周末的流量较高,而平日白天的流量则相对较少。那么如果可以做定时的扩缩容,就可以节省很多的云上成本。同时,每次在扩容新实例的时候,都需要进行实例的环境初始化、应用的部署,以及跟其他云产品的网络的配置、安全的配置等。偶尔进行一两次这样的操作尚可接受,但在频繁的动态扩缩场景下,这些操作会带来极高的运维成本。
弹性伸缩产品支持通过定时任务或报警任务来触发扩缩容操作,并且提供了灵活的伸缩策略和规则。此外,它还支持通过生命周期挂钩的方式,将弹性伸缩服务无缝集成到自身的业务程序中。然而,这一产品也面临着一些问题和挑战。首先是成功率的问题,从客户的视角来看,也可以叫确定性,只有足够高的成功率和确定性,用户才有信心使用弹性的服务。其次是效率的问题,在很多的场景下,对于扩容的速度要求是很高的。然后是规模,在成功率和效率都有很高要求的前提下,实现大规模的弹性伸缩本身就是一项极具挑战性的任务。
弹性伸缩支持不同的伸缩模式。在定时任务模式中,就可以很好的解决故事中的创业公司所面临的流量具有明显规律波动的场景。如果客户的业务流量存在波动但不规律,那么同样可以通过设置报警任务来应对。报警任务能够利用阿里云云监控提供的丰富系统监控指标,并且支持用户自定义业务监控指标,以实现基于事件触发的动态扩缩容。此外,通过目标追踪的方式,弹性伸缩服务能够自动计算伸缩组需要创建或释放的实例数量,以保持组内某个监控指标接近目标值。该指标同样支持阿里云云监控的广泛系统监控指标。近期,我们还推出了多指标计算功能,例如,在消息队列的场景中,可以根据消息队列的总消息量和伸缩组内实例数这两个指标进行计算,从而维持单实例处理的消息量在一个目标值,从而确保服务的稳定性。
用户在弹性伸缩过程中,会遇到许多运维方面的挑战。弹性伸缩服务本身支持与其他云产品的自动关联,包括但不限于负载均衡服务、数据库以及Redis等产品的自动关联能力。当关联了这些云产品之后,每次伸缩组内创建的新实例都会自动加入到负载均衡的监听列表中,以接收流量。同时,新实例还会自动与关联的数据库和Redis等产品建立网络连接,并进行安全白名单的配置,从而实现自动化的弹性伸缩过程。
至此,这家创业公司的基本弹性需求已得到了满足。然而,随着其业务的不断发展,他们将会遇到更多复杂多变的弹性场景。同样,在实际应用中,我们的客户也会面临许多更具挑战性和复杂性的弹性需求。
三、从“使用弹性”迈向“善用弹性”
接下来通过更多的最佳实践,继续探索如何从“使用弹性”迈向“善用弹性”。
首先,我们来全面了解一下弹性伸缩服务的整体功能。除了支持之前提到的定时任务、报警任务以及目标追踪规则外,它还支持手动触发。更重要的是,通过Open API的方式,用户可以将弹性伸缩功能完全集成到自己的业务程序中,实现自主控制。这意味着用户想什么时候谈,以及谈多少,也可以基于预测伸缩。比如用户的流量业务波动具有一定的规律性,其可以通过预测伸缩,利用阿里云算法和机器学习的能力来预测将来需要的容量,并进行相应的容量储备和自动扩缩容,同时,还提供了健康检查功能。这是一种针对实例本身的健康检查机制。例如,当实例出现IO异常或云监控的心跳丢失等情况时,系统可以自动替换掉这些异常的实例。此外,它也支持基于负载均衡的端口级应用监听,对出现异常的实例进行自动替换。
在执行伸缩活动之前,我们还需要对伸缩组进行一些预配置。包括预定一些伸缩规则,这规则可以是一些非常简单的规则,比如扩容几台、缩容几台,都可以是基于某些监控指标的区间梯度的步进规则。另外,我们还需要做一些伸缩配置,伸缩配置决定了伸缩组能弹出什么样的实例,包括实例的付费方式、规格、存储类型、网络类型以及所在的可用区等。这些配置项非常丰富,能够满足不同的需求。
在这些丰富的配置项中,我们应该优先创建什么样的实例呢?这取决于我们选择的伸缩策略。例如,如果我们对成本有严格要求,可以配置成本优先的策略,这样系统会优先创建抢占式实例或低价规格的实例。同时,我们也可以配置均衡可用区的策略,以满足对高可用性的高要求。此外,系统还支持生命周期挂钩和事件通知功能,这为用户提供了更便捷的方式,以便将自定义功能与自身业务进行集成。同时,如右侧部分所示,还具备与其他云产品联动的能力,这些能力在之前已经介绍过。
在弹性伸缩的能力评估中,我们刚才强调了成功率这一关键指标。为了实现高效的弹性伸缩,我们对镜像实例规格、存储类型、网络类型进行了自动匹配,并对虚拟化库存等方面进行了优化。目前,我们的成功率已经达到了99.99%的保证水平。在效率方面,目前单次扩容1000个ECS实例,我们可以在30秒内迅速完成。而在一些小批量的单次扩容场景中,最快甚至可以在10秒内实现交付。我们近期还将上线镜像加速等功能,以进一步帮助用户更快地启动实例。在规模方面,目前单伸缩组支持3000个实例的管理,并且单次扩容最多支持2000个实例,同时支持关联50个负载均衡以及十个生命周期挂钩。
伸缩配置决定了我们能创建出什么样的实例。这一点刚才已经介绍过,它包括实例的镜像、实例规格、存储类型、网络类型以及高级配置等多个方面。在实例规格方面,我们目前支持两种配置方式。一种是指定实例属性。如果用户对于阿里云的某些实例规格不是特别熟悉,那么可以通过描述自身对于实例需求的方式来进行选择。比如,用户可以指定所需的CPU和内存的范围、CPU架构、实例能挂载的网卡数量以及GPU型号等。
通过这种方式,用户可以明确地确定一批符合自己需求的实例规格。
如果用户对于某些具体规格有明确的需求,那么也可以通过指定实例规格的方式来配置。此外,还有一些非常实用的配置选项,比如user data。通过user data,用户可以配置一些实际环境初始化或应用部署的脚本,这些脚本可以通过cloud-init工具来执行,这也是我们在云上推荐的一种进行实例环境初始化的方式。另外,伸缩配置还支持设置有序且有规律的主机名称,以及设置登录密码、密钥等功能,为用户提供更加灵活和便捷的配置选项。
如果用户在扩松容过程中需要进行一些自定义操作,比如在自身环境中执行服务器注册或初始化等动作,那么可以通过生命周期挂钩功能来实现。以图中的例子为例,首先,在扩容流程中创建出新实例后,系统会利用之前介绍的关联数据库的方式,自动进行网络连通性和IP白名单的配置。这个扩容流程在实际启动后,会首先进入一个挂起状态,并会触发一个事件通知给用户。这个事件通知可以通过MS消息队列供用户消费,或者用户可以提前通过OS模板配置一些运维编排的动作来响应。
无论是通过OMS发送通知给用户的程序,还是通过OS执行来完成相关的自定义操作后,用户都需要回调弹性伸缩服务,以决定扩容流程是继续进行还是回滚。如果选择继续前进,新扩容的实例将被添加到负载均衡中,开始接收流量。如果选择回滚,则新扩容的实例将被释放。若用户在规定时间内未进行回调操作,系统将根据之前配置的默认行为,自动决定是继续前进还是回滚。缩容流程与此类似,通过这种方式,用户可以很方便地将自定义操作与弹性伸缩流程进行集成。并且我们的弹性伸缩服务已经能够很好地实现成本优化,特别是当它能与业务波动紧密匹配时。
但在此基础上,我们是否还能进一步降低成本呢?众所周知,抢占式实例的价格会波动,在价格最低时,我们可以享受到按量付费的一折优惠。因此,如果能有效利用抢占式实例,我们就能更进一步地降低云上成本。而弹性伸缩服务支持设置伸缩组内按量实例与抢占式实例的比例。例如,如果我们的业务对容量波动具有一定的容忍性,可以通过设置一定比例的按量付费实例来确保基础稳定性,而将弹性部分通过配置强抢占式实例来实现。相反,如果业务对容量波动有很高的容忍度,那么可以采用全抢占式配置,以最大化利用抢占式实例的成本优势,这种配置特别适用于一些离线业务场景。
在这里,有些用户可能会提出疑问:他们既希望系统稳定,又想最大化利用抢占式实例。针对这一需求,我们推荐以下两个最佳实践。首先,建议使用多种不同规格的抢占式实例,这样可以避免资源被整体释放的风险。第二个是弹性伸缩,它支持抢占式实例释放前的自动补偿机制。具体而言,当抢占式实例即将在五分钟内被释放时,系统会发送一个通知消息。弹性伸缩服务在接收到这一消息后,会自动进行补偿操作,尝试创建新的抢占式实例。如果无法成功创建,则会选择创建按量实例,以确保整体容量的稳定,从而避免产生断崖式的异常波动。
今年我们还推出了实例刷新功能,这一功能主要解决以下场景中的问题。例如,当用户伸缩组内有一批实例,并希望将这些实例替换为性能更佳、价格更低或者需要更新镜像、系统环境等配置的规格时,可以通过实例刷新功能,有计划、分批次地将组内实例替换为所需的新规格和配置。并且它在刷新的过程中相当灵活。若业务对稳定性有极高要求,可以先进行扩容,再逐步替换实例。在此过程中,还能控制正常服务中实例的容量占比,确保服务稳定,同时避免同一可用区的实例被同时替换。若对成本有较高要求,则可以选择先缩容再创建新实例的方式。同时,通过控制刷新过程中新创建实例的最大数量,可以确保整体扩容成本的可控性。此外,该过程非常灵活,不会阻碍正常的扩缩容操作。此流程支持暂停、回滚,并附有质检通知功能。
另一种相似的方式是滚动升级。它与实例刷新不同,无需替换伸缩组内的实例。并且它的滚动升级可以通过原地升级的方式,即更新镜像或使用云助手执行脚本来完成日常的应用发布或部署等需求。
以图中示例为例,我们将伸缩组内的实例进行分批处理。首先,第一批实例进入备用模式。若进入备用模式的实例关联了负载均衡,则会暂时从负载均衡中摘除,停止接收流量,以便进行镜像更新和执行脚本等操作。实例在执行完之后,退出备用模式,重新接入负载均衡并开始接收流量。若过程中出现问题,可以进行回滚或重试,这样就完成了一批实例的日常发布。通过这样有节奏的分批处理,我们就能顺利完成日常的应用部署需求。
在客户业务发展的过程中,有时会遇到性能突发的需求。之前介绍的很多例子都聚焦于资源数量的弹性伸缩。那么,性能是否也能实现弹性呢?答案是肯定的。在存储方面,我们的ESSD auto PL云盘支持性能预配置,能够将容量和性能进行解耦,支持高达100万IOPS的性能突发。同时,我们还提供了支持性能突发的实例规格T系列。将这两种方式组合使用,可以很好地解决性能突发的问题。比如,当我们的客户业务发展AI业务时,需要使用GPU资源。然而,我们知道在云上GPU资源有时会比较紧张。那么,如何解决这种紧张资源的弹性确定性问题呢?ECS的容量预定服务和弹性保障服务可以很好地解决弹性的确定性。同时,结合节省计划Saving Plan,可以在有效控制成本的前提下,进一步提升弹性的确定性。随着技术的发展,比如故事中的客户可能会采用云原生或容器技术。在K8s环境中,我们已知在Pod层面具备水平伸缩HPA、垂直伸缩VPA以及ACK提供的ground HPA等自动伸缩能力,以及定时伸缩功能。那么,在节点弹性,即更侧重于资源层的弹性场景下,我们有哪些有效的解决方案呢?
开源社区的Cluster Autoscaler是解决节点弹性的一个常用方案。它能够监听集群中是否存在处于Pending状态的Pod。如果发现有喷溅状的pod,他会模拟创建一个新的节点,看其能否满足Pod的运行,如果可以,那么决策就要扩容一个新节点,从而会触发云厂商的API来完成一个新节点的扩容。而cloud provider API对于各个云厂商来讲都是auto scaling的API。并且ACK在节点伸缩方面目前提供了两种方案。ACK(阿里云容器服务Kubernetes版)在节点伸缩方面目前提供了两种方案。第一种方案是基于Cluster Autoscaler的,其工作原理是通过轮询方式进行周期性检查,最快可以在50秒内完成一轮判断并决定是否扩容。然而,这种周期性轮询的机制在面对大规模节点伸缩场景时,可能会出现性能衰减。为了应对这一挑战,ACK现在推出了自研的节点即时弹性组件。该组件基于事件驱动,因此更适合处理大规模节点伸缩的场景,且不会出现性能衰减的问题。
同时,他们针对库存校验方面进行了优化,显著提升了弹性的确定性。这两种方案底层都依赖于弹性伸缩服务,包括我之前重点介绍过的弹性功能,如停机回收模式。在缩容时,停机回收模式不会释放实例,而是将实例置于停机不收费的状态。这样,在下次扩容时,可以非常迅速地启动这些实例,从而提升节点扩容的效率。
四、弹性应用的总结
我今天介绍的内容主要围绕弹性伸缩服务展开。结合阿里云提供的众多其他弹性能力,如抢占式实例、弹性供应组、ESSD auto PL云盘以及弹性确定性等能力,在平台层提供非常丰富的弹性能力给到用户。并且用户可以利用这些能力在应用层构建出既灵活又丰富的弹性应用。实际上,这些平台功能的升级都依赖于底层强大的资源弹性。关于这部分内容,我的同事稍后将为大家更详尽地展开介绍,包括我们在过去一年中针对多项能力进行的优化和最新进展。
接下来,我将介绍两个客户案例。首先是汇量科技,作为我们非常重要的弹性客户,汇量科技在弹性应用方面有着出色的实践。他们巧妙地结合了多种按量和抢占式实例的组合,并选用了多种不同的实例规格。同时,通过利用弹性伸缩的自动补偿机制,他们成功地将在线业务的成本降低了30%到40%。
第二个客户案例是Auto MQ,它也是我们非常重要的客户和合作伙伴。通常,我们的弹性业务用户主要面向无状态应用。但在消息队列这种有状态场景下,如何实现弹性伸缩呢?Auto MQ基于云对Kafka进行了重新设计,它将存储与计算分离,采用了分布式对象存储。并且,通过利用秒级分区迁移和流量重平衡机制,Auto MQ成功实现了消息队列这种有状态场景下的弹性伸缩。
五、ECS损失弹性能力的系统性建设
本次展示过去几年我们在ECS弹性能力方面所取得的建设和优化成果。或许有人会问,你所说的弹性能力具体指的是什么?实际上,弹性是一个涵盖广泛的概念,它包括长期的供给弹性、运行时的性能弹性,以及大家所熟知的瞬时交互弹性。而我今天的重点介绍,就是我们的瞬时弹性能力,更具体地说,是我们每分钟能够交付多少台ECS实例的能力。
今天,我将从四个方面为大家介绍弹性能力的建设情况。首先,是ECS弹性能力的演进历程;其次,是提升弹性能力所面临的挑战及我们的解决思路;第三,我会详细介绍我们在全链路体系化建设方面的举措;最后,我将分享我们在弹性能力建设上的未来规划与展望。
1.ECS弹性能力的演进历程
首先,我将从客户使用视角和我们的系统能力两个维度,为大家概述弹性能力的演进历程,以便大家有更直观的感受。通过观察这张趋势图,我们可以清晰地看到,在云的初期阶段,我们的弹性能力是完全没有办法和现在相提并论的。大约在2000年代,我们每小时仅能交付几百台ECS实例。然而,随着云的普及,越来越多的客户选择迁移到云端,涌现出了许多典型的弹性需求场景,如抢票活动、社会热点事件等。这些场景促使许多客户向我们提出了更高的弹性需求。因此,我们在2010年左右便开始了弹性能力的建设工作,当时已经能够实现每分钟交付几百台ECS实例的能力。
最近几年,随着客户对云理解的加深以及对集成方式的改进,按量和容器化场景逐渐成为客户使用的主流趋势。大家可以看到,近年来我们的ECS创建量每年都在成倍增长。为了应对这一变化趋势及满足客户的需求,我们不断提升弹性交付能力,这涉及到资源供给、系统架构以及资源调度等多个维度。当前的弹性能力,在新发布的产品规格上,能够在单规格单可用区内实现一分钟内交付1万台ECS实例。为了达成这一成果,我们为自己设定了极为严苛的目标,整个技术团队也为此付出了巨大的努力,并且整个过程也充满了挑战与艰辛。
2.弹性能力的难点以及用什么样的思路解决
首先,这是一个极为庞大的系统工程。如对ECS产品有所了解,就会知道我们为客户提供了丰富多样的产品矩阵,从实例产品到售卖产品,再到集成工具,在我前面的同事已从产品视角介绍了包括弹性伸缩和抢占实例等在内的产品能力,旨在最大限度地让客户能够利用云上的弹性能力。然而,客户所能感知到的这些产品能力,只是我们这个庞大系统工程中的冰山一角。在冰山之下,从计算到存储再到网络,涉及我们极为庞大的基础产品能力、系统能力以及资源能力。每一层都需要进行深入的优化和改造,才能共同释放出更为强大的弹性能力。
比如在资源层,需要应对极其庞大的用户资源创建场景,并针对每个场景制定精确的资源准备策略。而在服务层,面对海量的用户创建需求,需要协调全链路,确保所有场景下的稳定性和性能。因此,这确实是一个极其复杂且庞大的系统性工程。
3.弹性能力优化的架构
在最底层是资源层,其主要任务是在确保满足客户弹性需求的同时,尽可能地降低成本。中间层是系统层,其目标是在保证稳定性和成功率的基础上,提升性能和吞吐量。最上层则是产品层,致力于提供足够灵活且丰富的产品形态,以及更加高效的集成方案。在这样的架构框架下,我们启动了全链路的能力建设,并最终构建了我们的弹性能力产品层。刚才已经对这一层进行了深入的介绍。接下来,我将从资源层和系统层两个角度,向大家详细介绍我们的优化工作。
(1)资源层的优化
资源层,如之前所述,需要确保在各种场景下都能满足客户的弹性需求,同时还要保证低成本,这是一项极具挑战性的任务。我们在产品上提供了多样化的资源形态,包括计算资源、存储资源和网络资源等,这些资源组合起来可达数百种之多。在公有云和多租户的场景下,确保每个场景都能获得弹性资源,并保持其确定性,是极为困难的。另一方面,如果资源准备过多,就会导致资源浪费。因此,资源层需要制定非常精准的资源准备策略,以确保在满足弹性需求的同时,也能实现低成本。
在资源层,为了实现上述目标,我们从资源供给、统筹和高效使用这三个角度出发,分别建立了系统化的建设方案。在资源供给侧,我们通过对历史数据的持续深入分析,引入了包括季节性大客户、弹性需求数量、业务场景等多个维度的考量因素,并结合了楼宇机架、网络设备、服务器等不同资源的供给周期差异。最终,通过算法优化,建立了可持续的供应链流程,从而确保了更加精细化的资源供给策略。
其次,在资源统筹方面,引入了统一资源抽象层,对CPU、内存、端口、带宽等标量资源以及非标量资源进行了精细化的管理。并且结合统一算力型产品的定义,屏蔽了底层机型的差异,最终向上层提供了标准化的ECS和ECI交互形态,最大限度地实现了资源的统一。例如,大家可能了解到我们近两年发布的U系列实例,它就是基于统一资源层,通过底层神龙物理机的VCPU调度,向上层提供了算力一致的产品。
最后,在资源利用方面,我们依托智能规划引擎,将自动化部署流程、调度策略、资源规划、需求管理、碎片整理等多个不同的系统和流程串联起来,实现了资源的统一管理和运维,从而最大限度地提升了资源利用率。大家可能知道,每年双十一期间,集团都会提前准备大量的物理资源以应对流量高峰。然而,这些资源在双十一流量洪峰过后往往会面临闲置的问题。我们的智能规划引擎正是为了解决这一问题而设计的。
(2)系统层的体系化建设
系统层需要重点解决的问题是,在确保稳定性的基础上,如何实现控制平面的高可用,以及如何保持系统能力的持续更新与优化。正如前文所述,弹性能力的提升是一个庞大且复杂的系统性工程,而系统层也不例外。一个ECS实例的创建会涉及对上百个系统或服务的调用,其中任何一个微小的环节都可能成为影响稳定性、性能以及吞吐量的瓶颈。因此,为了进行全链路的优化,我们需要有非常精细且科学的数据作为依据和支撑。
在过去几年里,我们在全链路的各个系统和调度调用环节上,进行了全面而深入的数据采集与监测。在此基础上,我们根据客户使用的场景,对数据进行了细致的分类与聚合,从而能够精确分析瓶颈所在,并准确定位问题的根源。这进一步促进了我们在全链路的各个环节上更有效地开展问题定位与优化工作。
在数据驱动之上,首先从底层开始,对存储、虚拟化网络等原子能力进行了优化和提升。在存储侧中,我们通过全新的创盘索引设计,优化了开盘开销、分级流控、动态参数配置等。而这样的动作也大幅提升了创盘规模化的能力,同时,通过全链路设计,我们实现了并行挂载和异步开盘机制,从而大幅提高了磁盘开盘的速度。最终实现了在单个可用区内创建1万块云盘,并在30秒内完成的目标。
在虚拟化方面,我们通过精简虚拟化控制链路的交互流程,提升了实地启停设备及并发挂卸载的能力。同时,通过优化资源开销,确保了并发场景下控制面的算力是可预测的。最终,我们实现了在同一物理机上快速拉起60台虚拟机,并且整个过程仅需30秒。在网络侧,我们通过波塞冬平台提供了高性能网络配置演算和分发能力,借助乐神网络技术,我们大幅缩短了管控交互链路的长度,并在终端上实现了多层次的缓存加速。最终,我们达到了在同VPC下快速创建一万张网卡,并且整个过程仅需40秒的效果。
而在我们的底层原子能力之上,是调度系统,它负责为ECS分配物理资源。一方面,调度系统要确保底层物理资源能够被合理分配和高效利用;另一方面,它还需要保证分配动作的速度和吞吐量。过去几年,调度系统进行了大幅优化,以解决这些问题。在最上层,我们引入了资源规划器,它能够对来自ECS、Fleet、ACK等产品的大量批量请求进行多可用区、多产品之间的资源预调度规划。在中间层,我们通过单机内存视图和调度协调器等组件,优化了资源数据的复用,降低了调度过程中的长尾耗时以及资源碰撞的概率。在最下层,我们提供了统一资源池策略,建立了精细的资源模型定义,屏蔽了底层机型的差异,最终提供了归一化的资源视图。
刚才分别讲到了存储、网络、虚拟化等原子能力的提升以及调度能力的增强。在这些基础之上,是弹性控制系统ECS实例的创建过程。这一过程中,需要精心协调所有子模块,明确每个模块的任务时序、相互之间的依赖关系以及处理顺序。当任一模块出现异常时,我们需要有相应的策略来确保ECS实例能够顺利生成。同时,我们还需要保障各个模块的稳定性,确保全局数据和资源的一致性,以及最终的性能和吞吐量达到要求。
而控制系统就是这样的一个角色,它非常像一个集成电路,精密而复杂。为什么说他是复杂的呢?因为我们支撑的是一个服务于百万级别客户的多租户平台。在场景上,大家如果了解我们的实例生产的open API接口,以及在wrong instance上的150多个参数。就会知道每一个参数的背后都是一个独立的功能。这150个参数相互组合,所能覆盖的场景极为庞大。在流量方面,我们随时可能面临海量客户并发的资源创建请求。在形态上,我们不仅支持传统的迅捷VM实例的创建,还支持容器实例的生成。
那么为什么要进行精密的控制呢?原因在于,我们的全链路需要集成上百个这样的异构系统,从分布式的微服务到终端上各式各样的脚本。此外,我们的底层资源是瞬息万变的。在资源充沛时,我们需要增大任务调度的并发量,以获得更佳的性能和吞吐量。然而,在资源紧缺时,我们则要降低并发,以确保全链路以及资源的稳定性。在这样的复杂度之下,我们既要提升系统的弹性,又要确保整体的稳定性,这主要分为几个方面。首先,是我们系统的稳定性,必须确保全链路各模块在高压下不受影响,同时也要防止局部异常扩散至全局。其次,我们要保证资源和数据的一致性。
在分布式系统中,实现数据一致性所需付出的代价是极高的。而ECS场景不仅要确保分布式下的数据一致性,还要确保物理资源的一致性。任何底层物理资源的不一致都必须及时得到修正,否则我们交付的实例将会是损坏的,甚至可能导致公有云资源池大面积浪费,这是极其危险且无法接受的。第三方面是成功率,ECS作为一项服务,其最重要的特性在于确定性。如果我们无法持续提供99.99%甚至99.999%的成功率,那么客户将难以基于我们的服务去构建他们的业务。介绍到这里,相信大家已经能够理解,为何我们的控制系统会像一个集成电路一样复杂。它一方面要应对极度复杂的业务场景,另一方面又需要通过精密的控制来确保整个系统和业务的稳定性。因此,在这个基础上提升弹性无疑是一项艰巨的任务。
4.夯实稳定性,并提升弹性
在稳定性层面,我们随时可能面临海量的并发资源创建请求,同时底层资源也在不断变化。因此,实施精细化的任务调度流量控制显得尤为重要。这种流量控制与传统分布式系统中的限速概念有所不同。一方面,我们需要充分利用系统和资源的瞬时容积,确保任务能够最大化地得到执行;另一方面,我们要保护全链路,一旦发现任何模块出现异常,就必须迅速进行流量控制。而当异常解除时,我们也要能够迅速恢复任务调度的正常运行。
为了实现上述两点,我们在底层的流程编排工作流引擎中引入了队列机制,将原先上游推送的模式转变为下游拉取的模式。在此基础上,我们构建了一个非常精细的流量控制体系,能够根据产品、地域、可用区、客户等多个维度进行流量隔离。同时,我们实时与底层资源进行联动,确保这些能力能够让我们的任务持续在最佳的并发值上得到调度。此外,我们还引入了被压机制,时刻监控底层所有可能存在的细微风险指标,并建立了自动熔断、自动探测以及自动恢复的机制。综上所述,通过队列机制,我们的任务能够得到最大化的自适应调度,从而确保整个链路不被冲垮,同时让任务能够得到充分的执行。
在性能层面,ECS的控制系统扮演着编排与集成的关键角色。为了提升速度,我们既要提升原子操作的能力,又要确保整个流程编排的合理性。这要求我们的研发人员具备深厚的系统架构设计功底,同时对云服务以及虚拟化的知识有一个非常好的储备。在过去几年里,我们通过大量的研究,成功地将原本串行的任务调度优化为并行处理,并大幅减少了无效等待时间,从而显著提升了整体性能。
在存储层面,要提升吞吐能力,最关键的有两点。首先,我们需要在整个链路中消除瓶颈,并确保控制系统能够释放更多资源来处理更多并发请求。过去,这两方面问题最为突出的是资源管理方式过于简单粗暴,采用了串行锁定策略,并且过度依赖简单的使用同步模式。通过大量的分析和技术创新,我们将全链路上资源的访问从串行锁定改造成可以被并发的访问和控制。同时,我们也利用EDA的架构将原有的同步请求优化为异步任务调度。综上所述,我们在底层引入了队列机制,工作流支持并发处理,并结合EDA架构,使得上层全链路能够实现异步化、并发化、自适应化的改造。而最终的效果是,在我们的所有编排流程中,系统空闲时间被有效消除,系统负载得以减轻,从而实现了更高的效率和吞吐能力。
接下来向大家介绍几个可以量化的指标。通过过去几年的优化,ECS实例的单实例创建速度已从过去的10秒提升至现在的4秒。在存储方面,我们成功将单可用区内单规格交付1万台ECS实例的时间从之前的5分钟缩短至现在仅需1分钟。同时,在面临线上多租户大规模并发等复杂场景时,我们依然能够保证任务成功率高达99.999%,并确保任务时刻都能被自适应且充分地调度。
5.控制系统如何从运维层面保证整个服务的稳定性
如果大家还记得2022年香港发生的故障,我相信大家都会有所感触。当时,我们的表现并不尽如人意,特别是未能迅速恢复Open API服务。为此,我们深入进行了故障复盘,并采取了大量的改进措施。
共分为几个层面。第一个层面,我们进行了全链路的全面梳理,力求将服务进行细粒度化拆分,以确保在发生故障时,故障影响范围能够尽可能缩小。同时,我们也合理地对服务进行了分层,比如将客户的数据进行了缓存,并与资源控制层进行分离,从而减缓对他的访问压力。第二个层面,我们为所有控制平面的服务实施了计算存储多可用区容灾方案,并具备了随负载变化秒级横向扩容的能力。第三个层面,我们持续分析线上客户流量,建立了客户画像和智能流量预测算法,并通过持续的压测和故障注入测试,不断的摸索系统水位的能力,从而实现更为精细化的容量管理。
最后我们通过自适应的流量控制,能够精细地进行自动限流、降级、熔断等操作,从而使控制平面具备在故障下的自我恢复能力。我刚才所讲述的都是我们一系列优化工作的成果。然而,优化工作最怕的就是随着时间推移和功能迭代而被迅速削弱,因此保持这些能力的新鲜度和有效性至关重要。为此,我们在全链路部署了大量的性能监控系统,一旦出现耗时超出预期的情况,就会立即向相应的研发模块负责人发出预警,性能问题将被视为与故障问题同等重要来处理。此外,我们还会持续基于客户的使用场景进行压测和改进,以确保我们的弹性能力在各种场景下都能得到充分的覆盖。最后,在发布环节,我们引入了严格的卡控机制,任何未通过性能测试的发布都不得上线。
6.在弹性能力建设上的未来规划和展望
首先,弹性能力是弹性计算的核心本质,按量按需使用也是云上客户的一大使用趋势。因此,在持续提升弹性能力的道路上,我们不会停歇,会持续进行全链路联动优化。目前,我们已在众多场景下实现了每分钟一万台的交付能力,但这一覆盖度仍有待提升。我们将持续运用数据驱动的方法论,逐步扩展和优化客户实际使用中尚未覆盖的场景。此外,针对一些特殊场景,我们也会进行专项的垂直化优化。例如,在容器场景方面,我们将进行更轻量化的改造,并加强多个客户和产品之间流量的隔离。最后,我们会坚持不懈地进行技术创新。
刚才我所讲的都是关于水平弹性能力的内容,目前我们还在自主研发垂直弹性的产品,相信不久之后,大家就能见到并使用它。最后,我们也会在控制面持续探索新的架构,以便我们能够探索下一个数量级的瞬时弹性能力。