通用集群管理:弹性扩缩容在eBay的实现和落地

文摘   2024-03-15 10:59   上海  



据Gartner预计,2024年,接近90%的全球性企业会将业务迁移到容器云服务,相关开支将达到6790亿美元。然而,由于种种挑战,多数企业的云资源利用率仅有10%至15%,这导致了大量的资源浪费。


新冠疫情的爆发使全球经济形势更加严峻,促使许多公司开始寻求变革。这些企业不得不重新评估预算,并采取措施来削减成本以及提升运营效率。在这样的大环境下,更加精细化的云资源管理变得至关重要,它是企业降本增效的关键所在。作为电商领域的巨头之一,eBay同样积极响应这一趋势。


eBay内部管理了10万多服务器的私有云,分为三大部分:Cassini(搜索)集群、Hadoop大数据集群和通用集群,分布情况如图1.1所示。


由于Cassini和Hadoop由专门团队管理,且专注于运行单一类型应用,它们已经实现了相对较高的资源利用率,像Hadoop集群达到了40%。相比之下,通用集群因需要运行不同类型的在线与离线应用,面临更复杂的资源管理挑战,导致其节点平均利用率低于20%。因此,eBay Resource Management团队决定首先着手提升通用集群的利用率。


谷歌在2019年发表的论文“Borg-the Next Generation”透露其2011年数据中心核心集群(1.2万台服务器)的平均CPU利用率在30%左右,而到2019年,其数据中心核心集群(9.6万台服务器)的平均CPU利用率超过了50%,8年时间内提升了约20%。


受此启发,eBay Resource Management团队设定了一个目标,即在不牺牲应用稳定性的前提下,将节点的平均利用率从20%逐步提升至50%+。为了达成这一目标,业界已有多种手段,包括节点资源超卖、资源弹性、混部等。eBay Resource Management团队希望采用FinOps的理念,围绕成本洞察、成本优化以及成本运营三个方面构建一个完整的闭环,并通过深入分析应用特性和节点资源的状态来更有效地进行资源优化

  • 调整应用规格及大小来提高应用级别资源利用率

  • 通过自定义调度器提高节点级别装箱率

  • 平衡各集群之间的资源分配

  • 通过在离线混部填补因“潮汐效应“导致的低利用率时段


本文将着重讨论弹性扩缩容(自动调整应用大小)在eBay的实现和落地,内容包括四个部分:

  • 云端弹性能力

  • 弹性策略的推荐能力

  • 落地实施

  • 对未来的展望



01

云端弹性能力

PART1.


1.Kubernetes HPA

在讨论云端的弹性能力时,不得不提Kubernetes的HPA(Horizontal Pod Autoscaler),它允许根据实时监控指标自动调整工作负载的规模。HPA的运算公式如下:



该公式中  是HPA计算得出的期望副本数。Kubernetes的HPA控制器会定期利用这个公式来调节Deployment或任何支持scale子资源的工作负载的副本数量,目的是使得当前指标值(例如CPU使用率或用户定义的其他指标)接近或达到用户设定的期望指标值,从而实现副本数的自动调整。


HPA还支持配置多种精细化的弹性策略,例如稳定窗口和步进窗口等,这些策略可以帮助用户实现更加细致和控制性的扩缩容行为,以适应不同的业务需求和性能目标。


2.eBay中的工作负载

在eBay的云环境中,工作负载管理面临的挑战超出了Kubernetes单集群的能力范围。虽然HPA在单个Kubernetes集群内提供弹性扩缩容,但eBay的许多应用,尤其是那些需要高可用性的托管应用,要求实现跨地域的多活部署来满足灾难恢复需求。


eBay的云基础架构与公共云服务类似,分布在三个数据中心,每个数据中心包含多个可用区,每个可用区又有数个集群。为了适应这种复杂的分布式环境,eBay采用了特定的自定义资源来管理跨集群的应用部署和服务:


  • Federated Deployment:负责管理跨多个集群的应用部署。它允许一致地更新和扩展应用的版本和副本,确保在不同集群之间实现同步和一致性。

  • Access Point:负责管理跨多个集群的服务访问和负载均衡。它确保用户的请求能够按需地分发到不同集群上的服务,同时也处理跨集群的服务发现和网络路由。


3.分布式HPA

为了支持应用跨集群的弹性扩缩容能力,eBay Resource Management团队评估了两种主要方式:


  • 联邦HPA - 在联邦层面计算所需的副本数量,随后调整FederatedDeployment,如图2.3.1所示:



  • 分布式HPA - 将弹性伸缩策略分发到下属的所有集群,每个集群独立调整其内部的工作负载部署。


在项目设计阶段,权衡各种方案的优劣并作出决策是一项具有挑战的任务。印象特别深刻的是,最初团队倾向于采用联邦HPA的方案。一方面是因为它对现有系统的侵入最小,仅需对联邦部署(FederatedDeployment)做少量修改,同时不会影响PaaS层现有的工作模式,因为联邦部署的Spec保持不变;另一方面是因为我们希望能够同时处理自动调整应用在各个可用区分布的问题。


然而,工作量的大小或对现有系统的影响程度不应成为技术架构决策的决定性因素。当时eBay Resource Management团队总架构师反复提一个问题:这两个方案的本质区别在哪里?我们需要从原语(primitives)、契约(contract)、边界(boundary)这三个方面来思考。如果社区已经提供了HPA作为一个扩缩容的有效手段,那么除非我们能找到一个社区解决不了或不会去解决的边界,否则就不应该试图为了一些次要问题而绕过它。


在深入讨论比较和慎重考虑之后,我们认为社区的HPA完全可以满足我们的需求,并且决定弹性扩缩容不应同时去自动调整可用区,否则将会导致边界不清晰,增加系统的复杂性并提高出错的风险。因此,我们最终决定采用分布式HPA方案,如图2.3.2所展示。


下面是这两种方法的优缺点对比:


4.外部指标的获取

下一个关键问题是如何获取应用HPA所需的指标。Kubernetes HPA通常通过metrics.k8s.io API获取指标,这一API由metrics-server提供。然而metrics-server所提供的资源指标,仅包括Pod和容器的CPU和内存使用情况,这些资源指标对于满足生产环境中多样化工作负载的需求往往是不够的。例如,某些专注于AI训练或推理的应用会关注GPU使用率;而处理消息传递的应用可能更加关心消息队列积压(queue backlog)的大小。因此,在生产环境中,我们需要从更全面的监控系统来获取多样的指标。


在eBay内部,我们有一个统一监控系统Sherlock,这个系统基于Prometheus构建,负责收集所有应用的各项指标数据。eBay内部所有团队都是基于Sherlock的指标数据来管理各自的应用,因此我们也希望利用Sherlock中的这些指标来指导HPA的扩缩容决策。那么问题来了,我们如何有效地集成Sherlock与HPA,以便从Sherlock中获取所需的指标?


Kubernetes HPA支持额外的指标类型,包括:

  • 自定义指标

    custom.metrics.k8s.io API。

  • 外部指标

    external.metrics.k8s.io API。


为了从外部源获取指标,Kubernetes提供了Prometheus Adapter。但是,Prometheus Adapter要求使用静态配置的规则来获取指标,这意味着每次添加新指标时,我们需要更新configmap,并且需要重启Prometheus Adapter,这对于后期维护来说是一个重大的挑战。以下是一个配置规则的示例。


我们随后发现了KEDA(Kubernetes事件驱动的弹性扩缩容),这是由云原生基金会(CNCF)孵化的项目,它实现了动态的外部指标服务器。KEDA通过调协每个ScaledObject中定义的触发器,生成并更新对应的外部指标。这意味着我们可以利用KEDA从Sherlock实时获取应用性能指标数据,而无需为添加新的指标重新启动或重新配置整个系统。


以下是一个KEDA Prometheus Scaler的示例配置:


我们详细评估了KEDA Metrics Server和Prometheus Adapter:


结论显而易见,KEDA全方位胜出。


5.生产环境的部署

在部署之前,我们必须确保所有关键的性能、安全性和可观测性要求均能满足生产环境的要求。


虽然KEDA是一个开源项目,但我们全面评估之后发现它并未完全符合我们对生产的标准。比如:

  • KEDA默认配置不能满足我们的大规模部署需求,比如5分钟内处理10,000个scaledObjects的指标数据的调协。

  • KEDA服务账号需要访问所有命名空间中的secrets,在eBay的生产环境中,安全性至关重要,这显然是不能接受的。


于是我们向KEDA社区提出了相关问题,并积极贡献代码,提交了相应的PR。通过这些贡献,我们成功在所有集群中部署了KEDA。


此外在我们的方案中,我们扩展了联邦部署来支持弹性扩缩容策略,并通过联邦控制平面(FCP)的控制器将其同步到所有成员集群,而集群内的控制器则负责创建相应的Deployment和KEDA ScaledObject。KEDA控制器创建相应的HPA,HPA负责从KEDA的外部指标服务器获取指标,并根据定义的策略动态调整部署规模。具体参考图2.5


此外,为了在全局层面控制弹性扩缩容行为,我们实现了特定的准入Webhook,确保了在需要全局暂停弹性扩缩容时,能够快速反应并执行全局性的控制措施。我们还构建了相应的监控仪表板,以便实时跟踪和评估弹性扩缩容事件的有效性。


至此,万里长征已经迈出了第一步。




02

弹性策略的推荐能力

PART2.


接下来的重点是确定如何在eBay内部的所有相关应用中有效实施弹性扩缩容。


这里需要说明的是,为应用启用弹性扩缩容并非简单地切换一个开关那么直接。实际上,它需要定义一套量身定制的策略,这些策略必须充分考虑每个应用的独特需求,包括:

  • 最小副本数minReplicas和最大副本数maxReplicas,即工作负载的规模上下限。

  • 用于驱动扩缩容决策的指标及其相应的阈值。

  • 控制扩缩容行为的策略,这涉及到操作的频率和每次操作增加或减少的副本数量。防止频繁扩缩容导致Pod数量的过度波动,因为这可能会对APIServer、IP地址管理系统(IPAM)和防火墙等系统组件造成显著压力。


在eBay的通用集群上,运行着不同种类的工作负载:

  • 托管应用:构建在统一的框架上,并由容量规划团队来维护。

  • 通用应用:基于多种技术栈,由每个应用的管理者负责管理容量。


我们决定从托管应用开始着手,因为它们涵盖了几乎所有eBay的核心业务,并且有统一的监控指标。我们的目标是为这些托管应用持续提供弹性扩缩容策略的推荐并保持自动更新。

1.算法

最小副本数和最大副本数

为了提供最小副本数和最大副本数的推荐,首先需要了解应用期望的副本数范围。对于大部分在线应用来说,TPS通常是决定应用规模的关键指标。因此,推荐算法的核心在于计算每个副本能够处理的最佳TPS,从而基于应用级别的TPS,推导出该应用的期望副本数。


为了提升资源利用率,我们当然希望每个副本的处理能力尽可能高,但这受到两个主要因素的限制:一是延迟,二是CPU/内存。


延迟的限制通常是过去N天内的延迟表现,例如P90的延迟。当副本的延迟低于P90延迟时,我们认为它P95的TPS就是在该条件下可承受的合理TPS。同时,也需要收集该副本在当前延迟水平下的CPU和内存使用率。


CPU/内存的限制则来自于容量规划团队的约定,比如,为了满足区域故障转移的需求,CPU的使用率针对三级应用不应超过33%。


综合这些条件,我们可以计算出单副本在这些限制条件下的TPS能力:


确定最小副本数的另一个因素是应用级别的TPS。通常,最小副本数应该设置为该应用能够处理最低TPS时的副本数量。然而,由于当前基础设施的限制,新增Pod有时需要较长时间才能准备就绪。因此,我们必须确保应用的最小副本数在大多数情况下(包括区域故障转移和节假日高峰期)都能够处理所有流量。要计算应用级别的TPS,我们使用以下公式:


然后,我们便可以计算出最小副本数:

接下来,我们需要确定合适的最大副本数。


如果应用之前尚未启用弹性扩缩容,并且  低于当前副本数,则需要将maxReplicas的值保持在当前副本水平,以确保工作负载在出现突发流量时保持足够的弹性,以防估计不足。相反,如果minReplicas值高于当前副本数,为maxReplicas设定一个基于minReplicas的比例因子(例如1.5倍)通常就足以保证弹性。


如果该应用已经启用了弹性扩缩容,我们可以获取过去N天在每个集群的副本趋势数据,如果历史副本数曾经达到maxReplicas,这表明当前最大副本数不足以处理实际峰值流量,此时应当推荐更高的最大副本数:


指标和阈值

在制定基本的弹性扩缩容策略时,除了最大最小副本数,另一个关键在于选择正确的指标和阈值以确保既能有效扩容以应对流量高峰,又能在流量低谷时适当缩容以节约资源。我们最初考虑了CPU、内存和延迟这三个指标。然而,实践中我们观察到,如果同时使用这些指标,缩容就变得非常困难。


这个问题在于HPA的工作机制。当HPA配置了多个指标时,任何一个指标超过设定的阈值都会触发扩容。而缩容则需要所有监控指标都低于各自的阈值。虽然这样更加安全,保证在任何一个资源使用率较高时都不会进行缩容,但这样也会降低缩容的可能性,制约进一步提升使用率。


经过评估所有指标后,我们发现CPU使用率与应用流量的相关性最高,而内存和延迟则相关性不强。因此,对于大多数应用的弹性策略,我们决定仅选择CPU使用率作为扩缩容决策指标。


设定CPU使用率的阈值时,需要综合考虑容量规划团队定义的应用资源限制(硬阈值)和应用的历史性能数据。硬阈值是基于应用在满足区域故障转移的前提下所能支持的最大CPU使用率,历史性能数据则提供了实际运行情况下的资源使用信息。


因此,建议的CPU阈值应该是这两个考量的平衡点。在实际设置CPU使用率阈值时,最终采用两者较小值:


高级策略

现在我们已经有了基本的弹性扩缩容策略的推荐值,但为了确保应用在生产环境中的稳定性,仅此还不够。在生产环境中,通常来说我们需要更快速扩容以应对流量激增,尽可能缓慢缩容以确保应用的稳定。因此,还需要制定更精细化的策略来管理扩缩容行为。


下面是一个高级扩缩容策略的示例:

在这个策略中,触发扩容所需的指标必须至少连续超过阈值300秒。在扩容过程中,每个周期只能增加最多10%的副本数,每900秒进行一次检查。与之相对,进行缩容之前,指标需要连续低于阈值3600秒。在缩容过程中,每个周期最多减少5%的副本数,每1800秒进行一次检查。


最初,我们对所有工作负载实施了统一的扩缩容行为策略。然而,我们注意到对于某些应用,尤其是较小的应用,扩容速度过慢。例如,如果一个应用在6个集群中总共有60个副本,每个集群有10个副本,按照10%的扩容策略,每900秒只能增加1个副本,这在流量快速增加的情况下显然是不足的。为了解决这个问题,我们期望根据每个集群中的副本数量动态调整扩容的百分比值:


  • 如果集群中的minReplicas小于或等于10,那么scaleUp的PercentValue应设为100%,这样每个扩容周期Pod的数量将翻倍,也就是最多涨10个。

  • 如果集群中的minReplicas大于或等于100,那么scaleUp的PercentValue应设为20%,这样每个扩容周期Pod的数量将增加20%,也就是最多涨20个。

  • 如果集群中的minReplicas介于10到100之间,那么scaleUp的PercentValue应介于20%到100%之间,具体值根据副本数量按比例调整。


计算公式为


这个公式的设计是基于以下的线性关系:


通过这种方式,我们能够确保不同规模的应用都能在流量激增时及时扩容,提升应用可靠性。

2.工程实施

在着手实现推荐系统之前,我们首先需要明确以下两个核心问题:

  • 我们的目标最终状态是什么?

  • 推荐系统与工作负载之间如何交互,即二者之间的契约是什么?


我们设想的最终状态是一个能够全自动管理所有托管应用资源的系统,同时保留人工干预的可能性,以满足特定需求。为了实现这一点,推荐系统必须能够实时地根据各应用的性能指标和流量数据生成应用画像以及所需资源的推荐,并以一种可持续、可扩展和易于维护的方式将这些推荐传递给对应的工作负载。此外,该系统应包含一个管理控制台,供运维人员进行必要的操作调整


当然在实现最终状态的过程中,我们还需要有一个过渡阶段。这是因为我们对于算法能否完美适配所有托管应用的自信尚不足够。因此,在过渡阶段,我们需要容量团队专家的审核来帮助我们调优算法,提升其准确性。


关于契约,我们希望引入Recommendation API,此API负责定义应用级别的容量管理策略,包括集群分布策略,固定副本数,以及弹性扩缩容策略等。同时我们需要实现控制器来watch 所有Recommendation资源,并根据提供的策略来更新对应的工作负载。


以下是一个简单的Recommendation的示例:


综合以上考虑,整个推荐系统的架构大致包括以下几个关键组件,如图3.2所示:

Profiling Service

该服务会基于每个应用的历史数据通过上文提到的算法构建出应用画像,包括了应用的特性,比方是CPU密集型,内存密集型,还是IO密集型,通过机器学习(ML)平台持续生成副本数量以及CPU阈值的推荐值并存回Sherlock中。详细的流程和组件可以参考图3.2.1。


Recommendation Service

Recommendation Service是一个控制器,会持续观察联邦部署(FD)。当FD上注册有Recommendation的annotation(federateddeployment.tess.io/recommendation: hpa-strategy),该服务会:


  1. 根据应用类型和推荐类型创建相应的推荐引擎。

  2. 执行所有已注册的预检查插件,比如检查该应用是否符合被推荐的标准。

  3. 如果通过所有预检查插件,从Sherlock获取Profiling Service的输出结果(即原始推荐数据)。

  4. 对原始推荐数据进行周期控制、规范化处理,必要时也会覆盖原始推荐数据,并以步进数据取代,比如当前最小副本数为100,原始推荐的副本数为200,但是过去一周P95的CPU始终远低于CPU阈值,那么当前建议的最小副本数将会调整为90而非200。

  5. 结合必要的HPA策略以及上文提到的算法来构建最终的推荐内容,包括最小副本数(minReplicas)、最大副本数(maxReplicas)、度量指标和阈值、以及相应的高级策略。

  6. 处理后的推荐内容还会经过所有注册的后检查插件过滤,例如检查本次推荐的最小副本数和最大副本数之间的差距是否符合要求,确保有足够的弹性能力。

  7. 如果所有检查都通过,该服务将生成相应的推荐请求,这些请求将由容量团队进行审查批准并应用到目标工作负载上。


Recommendation Service参考了调度框架的设计(见图3.2.2),能够根据需求添加各种预检查和后检查插件。此外,也可以方便地扩展各种推荐引擎,以适应不同类型的应用或推荐类别,比如基于不同环境(生产和测试)的推荐引擎,基于不同策略(弹性扩缩容模式和固定副本模式)的推荐引擎等等。


Cloud Capacity Console

尽管我们的最终目标是实现完全自动化,但想要一步到位是不切实际的。毕竟事物的演进都是需要一个过程,尤其对于算法来说,鉴于线上应用的多样性,我们并不完全有信心说初期的算法能够完美适配所有应用,因此更难以说服容量规划团队接受全自动化的应用推荐。在这个过程中,我们需要解决两个问题:

  • 容量规划团队的工作是在保证站点安全性的前提下节省成本,实际操作的时候当然偏向安全,那么如何增强他们对推荐算法的信心?

  • 如何收集反馈,以方便快速迭代?


为了解决这些问题,我们邀请容量规划团队审核我们的推荐算法,以及所有生成的推荐结果。为此,我们提供了一个基于推荐的容量管理平台,即Cloud Capacity Console,如图3.2.3所示。容量规划团队可以使用该系统来审查、批准或拒绝推荐结果,并通过Recommendation API和Applier在工作负载上实施相应策略。


同时,Cloud Capacity Console也会记录所有的审查结果和拒绝的理由。这些反馈对我们改进和迭代算法至关重要。我们可以追踪批准与拒绝的比例趋势,从而观察到算法准确性的提升,这也有助于增强容量规划团队对算法的信任。


另外,即使是最高级别的自动驾驶,也必须允许在必要时人工接管。因此我们的系统也支持管理员必要时人工介入,管理各种托管应用的容量,比如直接调整最小副本数、暂停或恢复弹性扩缩容等操作。




03

落地实施

PART3.


上述所有能力都只是解决方案。我们希望在eBay所有可适用的应用上启用弹性扩缩容功能,从而提升自动化水平、优化资源利用率,降低成本。


然而,这是一项改变游戏规则的转变,它涉及从固定副本模式过渡到动态副本模式,必然会影响现有的用户体验。因此,整个落地实施过程并不是一帆风顺的,总会遇到一些意料之外的问题。以下是我们在实施过程中遇到的四类挑战:


与其他系统的冲突

正如之前提到的,我们选择了分布式HPA的解决方案,这对现有系统侵入型较大。


目前,我们正在一个过渡阶段,将所有托管应用从旧的Assimilation框架迁移到新的CPDLC框架。在此过程中,我们同时运营着两个PaaS系统,这两个系统过去都是基于固定副本数模式运行的,并不完全适应弹性扩缩容。


这里简单举两个例子:

  • 托管应用的框架支持流量镜像功能,用于测试。但流量镜像需要克隆一个只有一个副本的工作负载,这个工作负载是不允许扩缩容的。如果原始工作负载已经启用了弹性扩缩容,那么克隆出来的工作负载也会继承这个扩缩容策略,导致流量镜像不起作用。


  • 当用户通过老的PaaS系统部署新版本时,系统会在部署任务前记录副本数量。如果在部署过程中发生了缩容,部署完成后的副本数将与记录的数量不一致,便会导致本次部署任务失败。而部署任务的失败又会影响到Velocity(框架部门的关键评估指标之一)的考量。


虽然我们期望其他团队能升级他们的系统以支持弹性扩缩容,但我们不能强迫他们因我们的改变而作出改变。因此,我们尝试去理解对方的初始设计理念,互相审查设计,探讨背后的逻辑,最终通过双方共同的努力,解决了所有潜在的冲突。


比如,对于第一个例子,我们确保在选择启用弹性扩缩容的工作负载时不会选择用于流量镜像的工作负载,框架团队也确保在克隆工作负载时不会带上弹性扩缩容的策略。


对于第二个例子,PaaS团队在部署任务开始前后通过APIServer提供信号,我们根据这个信号确保在部署进行中暂停针对这个工作负载的扩缩容操作,以此来避免部署过程中的副本数变动。


来自其他团队的质疑

通常来说,引入新事物对所有人来说都是一个挑战。在实施初期,我们每天都会收到应用所有者和站点工程师的各种疑问。例如:


  • 我们的应用应该有30个实例,为什么现在只有16个?

  • 应用X目前出现问题,错误率上升了,这是不是弹性扩缩容导致的?

  • 我们的应用在实例数量上进行了硬编码以匹配分片数量,我们可以禁用弹性扩缩容吗?


为了顺利落地,将负反馈转化为正向动力非常重要,因此在这一阶段我们对每一个问题都耐心回复。例如:

  • 针对第一个问题,我们会详细地解释弹性扩缩容如何调整应用规模,以及这样做的好处。

  • 对于第二个问题,我们尽力帮助定位问题的根本原因,证明并非由弹性扩缩容引起的。同时,还要强调弹性扩缩容实际上可以帮助减少因流量突增引起的稳定性问题。

  • 针对第三个问题,我们深入了解了他们应用的设计细节,并在适当的情况下选择关闭弹性扩缩容功能。


此外,容量规划团队也在美国工作时间提供了极大的支持,帮助回答并解决这类问题。


当然,信任的建立不是一夜之间就能完成的,需要随着时间的积累逐渐建立起来。在这个过程中,所有相关者的支持对落地实施非常重要。


基础设施的限制

弹性扩缩容的有效性不仅取决于应用架构的支持,还依赖于一个高可扩展性的基础设施环境。然而,我们目前的基础设施并未完全适配于大规模的弹性伸缩需求。比如:


  • 在从Assimilation迁移到CPDLC的过程中,Assimilation应用的Pod转变为就绪状态可能需要较长时间,有时这个过程甚至会超过一小时。

  • 某些基础设施组件,例如硬件防火墙,无法同时处理成百上千个Pods同时扩展。


上述限制因素会影响到弹性扩缩容的SLA(我们希望弹性扩缩容能够在30分钟内将应用性能指标恢复到预定的阈值之下),因此在一定程度上阻碍了弹性扩缩容的广泛应用。


为应对这些限制,我们除了积极推动相关团队合作外,也在我们的层面上实施了多项改进。例如:


  • 我们引入了准入控制机制,对所有的扩缩容事件进行管理,并针对基础设施能力的限制对扩容操作实行了速率限制。我们参考了APIServer的优先级和流量模式(Priority and Flow Schema)来设定基于应用优先级的速率限制。

  • 针对Assimilation的应用,我们基于过去一段时间内的流量高峰期数据提出了建议,以保证在最小副本数配置下的系统稳定性,减少扩缩容频次。


不同应用的特征模式

不同的应用有不同的特征模式,一些应用对延迟非常敏感,另一些则不然;一些应用有TPS,另一些则没有;此外,不同应用的CPU使用率也有很大差异,有些应用的CPU使用率始终低于10%。


对于那些CPU使用率持续偏低的应用,最初我们有几个提议。其中一个是通过使用镜像流量进行压力测试。然而,这种方法无法完全模拟所有类型的请求,特别是写请求,并且在所有生产应用中广泛部署并不现实。


因此,我们决定采用插值算法去做预测。我们的做法是采样低利用率应用的所有副本的TPS与CPU配对数据,将它们拟合进线性回归模型,并预测当CPU使用率达到某一阈值时的TPS。这种方法对不少应用非常有效。


但是,当TPS与CPU的相关性不强时,如图4.1.4所示,插值算法就不再适用。为了解决这一问题,我们会首先计算相关系数;如果系数未达到预设的阈值,我们将放弃使用插值算法,转而采用逐步减少副本数量的策略,以便逐步提升CPU使用率,下次推荐的时候可以获取更多的数据点,最终帮助我们形成更为精确的优化推荐。




成 果


到目前为止,已有10%的托管应用启用了弹性扩缩容,并且新创建的CPDLC托管应用已经默认启用弹性扩缩容的自动推荐,最终我们期望所有适用的应用都能默认启用弹性扩缩容。


在已启用弹性扩缩容的托管应用中,我们观察到CPU利用率方面的显著提升:

  • 对于所有托管应用,CPU的实际使用量与请求量的平均比值为36.16%

  • 对于那些启用了弹性扩缩容的托管应用,这一比值提升到了45.98%


基于这些利用率提升,我们已经节约了超过2万个CPU核心。预计一旦所有托管应用都启用弹性扩缩容后,节约的核心数将达接近5万


等托管应用都成功启用后,我们还会进一步将推荐策略迁移到规模更大的通用应用上。


此外,弹性扩缩容也已应用于部份AI推理工作负载,成功地将GPU的平均利用率从9%提升至13%。这意味着在不增加现有GPU集群规模(3000+GPU核心)的前提下,能够节省更多的GPU资源,从而支持更多的推理和训练任务。



04

对未来的展望

PART3.


尽管在落地过程中我们已经解决了不少挑战,但仍有很大的改进空间和许多工作要做。


弹性扩缩容的改进

  • 定制化算法

目前我们使用的推荐算法虽然具有普适性,但并不能满足所有应用的需求。为此,下一阶段需要针对不同应用的独有特点,采用定制化的算法。


  • 预测模型

目前HPA所依赖的指标是实时的,对于那些启动时间较长的工作负载而言,并非理想的方案。因此,我们计划构建预测模型,使得弹性扩缩容能够以自适应模式工作。


  • 全自动审批

目前,弹性扩缩容策略的一部分推荐还依赖于人工审核和批准,这限制了我们调整扩缩容策略的频率,目前每周只能更新一次。因此,我们还需要持续提升推荐准确度并最终实现完全自动化。


资源优化的其他手段

此外,在提高资源利用率方面还有很多工作可以做,这一过程可以分为几个阶段进行:


  • 阶段一:提升应用利用率

在此阶段,除了利用HPA进行弹性扩缩容外,对于那些不适合弹性扩缩容的工作负载,或者那些副本数量已经很少但CPU利用率依然较低的工作负载,可以选择利用垂直自动伸缩器(VPA)来为这些工作负载提供规格建议并进行调整。


  • 阶段二:提高装箱率(Bin-packing Ratio)

第一阶段的目标是通过确定合适的规格和副本数量来提高应用的利用率,从而使节点能够容纳更多的Pods。


然而,如果如果应用数量或规模没有持续增长(Organical Growth)的话,这反而会导致节点装箱率降低。为了提升节点层面的装箱率,可以采用装箱感知调度和负载感知调度等策略,并结合下架多余的节点或缩减采购计划来实现目标。


  • 阶段三:跨集群平衡

在执行完前两个阶段之后,我们将能够提升单集群中节点的利用率。然而,不同集群之间的利用率还会存在差异。因此,还需要实施自动化的集群选择和部署策略,以平衡各个集群之间的资源利用率。


  • 阶段四:提高平均节点利用率

通常情况下,P95与平均利用率之间会存在显著差距,这主要是因为大部分在线应用都呈现出潮汐效应的使用模式,即有明显的高峰期和低谷期。


在这个阶段,可以考虑采取分级的QoS管理机制,并结合I/O隔离技术来实施在离线工作负载的混部。



05

感谢

PART3.

最后,我们需要感谢所有参与此项目的团队成员及兄弟团队:ESTools Team(Cloud Resource Management), Cloud Team, Capacity Team, Framework Team, AIOPS Team, AIP Team, SEC & SRE Team。


之后我们也会持续分享eBay在降本增效之路上的更多进展。



参考文献

Horizontal Pod Autoscaling | Kubernetes

design-proposals-archive/autoscaling/hpa-v2.md at main

https://github.com/kubernetes/kubernetes/tree/master/pkg/controller/podautoscaler

GitHub - kubernetes-sigs/prometheus-adapter: An implementation of the custom.metrics.k8s.io API using Prometheus 

KEDA

GitHub - kedacore/keda: KEDA is a Kubernetes-based Event Driven Autoscaling component. It provides event driven scale for any container running in Kubernetes

Remove the secret from clusterrole · Issue #3668 · kedacore/keda · GitHub

https://github.com/kedacore/keda/pull/3677 

A Measurement Study of Server Utilization in Public Clouds

Autopilot: workload autoscaling at Google Autopilot | Proceedings of the Fifteenth 

Borg: the Next Generation 

European Conference on Computer Systems

Kubernetes Autoscaling: 3 Methods and How to Make Them Great - Spot.io

Dynamic Admission Control | Kubernetes

API Priority and Fairness | Kubernetes

Everything you need to Know about Linear Regression

Cloud FinOps O’Reilly Book 

GitHub - kubernetes/autoscaler: Autoscaling components for Kubernetes 

GitHub - kubernetes-sigs/cluster-capacity  

GitHub - gocrane/crane: Crane is a FinOps Platform for Cloud Resource Analytics and Economics in Kubernetes clusters. The goal is not only to help users to manage cloud cost easier but also ensure the quality of applications.  

GitHub - karmada-io/karmada: Open, Multi-Cloud, Multi-Cluster Kubernetes Orchestration 

Katalyst (ByteDance’s Resource Optimization) GitHub - kubewharf/katalyst-core 

Kapacity (Intelligent HPA) GitHub - traas-stack/kapacity: An open cloud native capacity solution which helps you achieve ultimate resource utilization in an intelligent and risk-free way. 

Kepler (Sandbox, Power Level Exporter) GitHub - sustainable-computing-io/kepler: Kepler (Kubernetes-based Efficient Power Level Exporter) uses eBPF to probe performance counters and other system stats, use ML models to estimate workload energy consumption based on these stats, and exports them as Prometheus metrics 

Volcano (Incubating, Batch system scheduler) GitHub - volcano-sh/volcano: A Cloud Native Batch System (Project under CNCF) 

kubespray (Deploy a Production Ready K8S Cluster) GitHub - kubernetes-sigs/kubespray: Deploy a Production Ready Kubernetes Cluster 

Koordinator (Qos Scheduler, Colocation) GitHub - koordinator-sh/koordinator: A QoS-based scheduling system brings optimal layout and status to workloads such as microservices, web services, big data jobs, AI jobs, etc. 


eBay技术荟
eBay技术荟,与你分享最卓越的技术,最前沿的讯息,最多元的文化。
 最新文章