58云动态资源调度策略


导读

58云计算平台(以下简称云平台)是58集团基于Kubernetes和Docker打造的私有云平台(Kubernetes简写为K8S),旨在为集团内部提供高效、便捷的一站式云化解决方案,具有简单,轻量的特点,能够高效利用物理资源,更快的部署和统一规范的标准化运行环境。通过云平台,业务团队可以实现服务标准化,上线流程规范化,资源利用合理化。

高效利用物理资源,是K8S等云化方案的主要目标之一,对企业而言也会有很大收益。而要实现这一目标却并非易事。本文主要讲述随着K8S在58集团应用规模的不断扩大调度策略逐步演进的历程。


原生调度的问题

在物理机等非云化场景下资源利用率较低,因为业务申请的资源是以整台物理机为单位的,在业务实施过程中,人力很难在业务与机器之间进行合理的调配。而在云化场景下通过统一资源调度与管控,我们可以获得动态调节分配资源的能力,这也是我们在云平台上做资源优化的基础。

58云动态资源调度策略

K8S总体上是master加node结构,如上图所示。K8S的调度工作主要由master组件中的scheduler模块负责,根据多种调度策略联合筛选,确定每个新创建的pod(容器)应该被调度到哪个node(物理机)上去。K8S提供多种调度策略,具体策略的分析不是本文要讨论的重点,此处不展开介绍。

K8S原生的调度策略比较简单,对于一些线下系统基本满足需求,但是对于追求最大化资源利用的线上系统来说并不适合。主要的原因在于两点:“基于申请量的调度”和“资源超分”。

1、基于申请量的调度

在K8S中容器的最大可用资源是在部署时指定的(即“申请量”),资源的“使用量”与“申请量”可能关联不大;比如某个业务申请了4核的cpu资源,实际使用量可能是0.5核,另一个业务申请了4核的cpu资源,则实际可能会使用3核。K8S的原生策略中,资源调度是以“申请量”为依据的,这样的调度策略会与实际使用情况脱节。

2、资源超分

由于基于“申请量”的调度策略会出现较严重的资源浪费。为了提升集群整体资源利用率,我们必须选择资源“超分”。资源超分是假设所有的容器都不会将资源用满,并且不会在同一时刻用满,基于此,我们不为容器按照1:1(实际需求:申请量)预留资源,而是提升这一比例,比如5:1,具体的比例需要根据不同系统来动态调节。在资源超分情况下,K8S原生调度策略的问题就被进一步放大。以一个与实际无关的指标做调度,会导致机器在利用率上倾斜很严重,机器频发“资源耗尽”问题,对系统稳定性构成风险,也阻碍了我们对资源的充分复用,无法体现云的优势。


k8s资源动态均衡性调度策略研究

为了更好的提升资源利用率,我们对调度策略进行了深入的研究与分析,不断迭代与演进。调度策略的演进主要分为两个阶段,基于使用量的调度策略与动态权重调度策略。

基于使用量的调度策略:在调度中用“使用量”替换“申请量”,从cpu单项资源考量,水平扩展到内存、磁盘等三项资源考量。

动态权重调度策略:着力解决多项资源策略如何共存的问题,避免相互影响,提升整体均衡性效果。


基于使用量的调度策略

1、单项资源均衡性

我们首先解决单项资源的调度问题,先从最关键的cpu资源入手。

因为“申请量”与“使用量”脱节是原生策略的关键缺陷,解决问题的关键就是开发一个以“使用量”为依据的调度策略,那么问题来了:“使用量”怎么算?一个业务容器,每分每秒cpu使用率都不一样。并且,每个业务容器受业务特征与用户行为的影响,一天当中的不同时段cpu利用率也存在明显的起伏差异。

58云动态资源调度策略


通过观察容器的监控数据,如上图所示,我们发现绝大部分业务,其资源利用率都有一个明显的规律性,因用户的访问习惯,每天的峰值和低谷时段,都是相对固定的。

因此,我们选定某一个时段作为“评估时段”。我们就以上午9时~10时这一小时的监控数据为基础进行整合计算。此外,每个业务每天的流量都可能有一定变化,所以我们以最近7天数据的平均值来估算一个容器在高峰时段的cpu消耗预期。

基于上述“预期使用量”数据,并使用与原生策略类似的模式所研究的K8S调度策略,相对于K8S原生策略,具有更好的应用性。

58云动态资源调度策略


衡量调度的效果,主要看cpu等资源在各个物理机之间分布的均衡性。如上图所示,我们绘制的正态分布曲线,自研策略分布曲线显著收窄,这说明机器间的cpu利用率分布更平均了,可见新策略的cpu均衡性大幅提高。

2、多项资源得分加权求和

针对cpu的调度策略调整获得了较好的效果。用类似的模式,我们将策略平移到内存、磁盘等资源。这里的关键问题是几种资源之间的得分加权方式。我们按照K8S原生的模式,以权重乘以单项得分,进行累加。这种权重计算方式我们在线上运行了很长时间,当发现某项资源出现严重倾斜时,通过调整权重的方式来达到平衡,但是这样的做法只能短期缓解,“摁下葫芦浮起瓢”。比如,增加cpu单项的权重以提升cpu的调度均衡性;而内存的权重便相对得被降低;当内存的均衡性不足时,我们只能加大内存的权重,cpu的权重又相对降低,cpu的均衡性又变差了。

有没有办法,让多个资源策略避免相互影响呢?

经过观察,我们注意到:容器对资源的需求,通常具有偏向性。容器A消耗大量cpu(比如10核),但内存的消耗却只有0.5G;相反,容器B可能消耗20G内存,cpu只占用0.2核。

物理机在使用上也普遍存在资源消耗不平衡,某台物理机可能cpu消耗了70%,而内存则只使用了20%。在“固定权重”的得分计算模式下,这种不平衡的情况,引起了此物理机得分一直很低,而导致它的80%的内存一直空闲。


动态权重调度策略

1、动态权重自动感知资源偏向性

认识到固定权重导致的问题,以及容器和物理机所展现出来的“资源偏向性”,我们决定设计一种“动态均衡性”策略。

新的策略主要满足以下几点:

a) 几项资源之间,权重动态计算,根据所调度的容器、备选物理机、以及集群总体资源情况,临时计算一个权重,每次调度都同;

b) 待调度容器对某项资源的需求越高,此项权重越高;

c) 某台物理机某项资源空闲程度越高,此项得分更高;

d) 集群总体更紧缺的资源,此项权重更高;

我们归纳为一个公式,如下:

58云动态资源调度策略

公式的细节略显枯燥,我们举个例子来说明“动态权重”的算法。

假设存在node-1和node2(node代表物理机)

  • node-1 cpu占用80%,内存占用30%,磁盘占用30%(注:此占用率是基于前文所述容器“预期使用量”数据进行累加计算得出,而非node实时监控数据)。
  • node-2 cpu占用40%,内存占用70%,磁盘占用30%。

如果按照“固定权重”的算法,假设三项资源的权重是比1:1:1。

  • node-1得分=2*1+7*1+7*1=16。
  • node-2得分=6*1+3*1+7*1=16。

得出node-1与node-2得分正好一样,但实际上两个node的资源情况存在明显的差异,一个偏向cpu,另一个偏向内存。并且,上述计算方法,也没有考虑不同容器的情况。

假设存在两个容器,pod-a和pod-b(pod代表容器,k8s里的容器对象)。

  • pod-a 预期使用:cpu 4.61核–内存3.02G –磁盘2.1G
  • pod-b 预期使用:cpu 0.26核–内存3.62G –磁盘1.8G

针对上述两个node和两个pod(容器),采用“动态均衡性”策略进行计算。首先计算pod的“资源需求度”,即前述公式中右侧分母中的三项。通过对pod的几项资源需求做初步计算,“资源需求度”以相对公平的方式,评估pod的几项资源需求“哪项需求更高”。计算方式就是:“pod某项资源需求量”/“此项资源在集群所有node的平均剩余量”。

  • pod-a 资源需求度:0.21 - 0.05 - 0.01 (分别是cpu - 内存 - 磁盘)
  • pod-b 资源需求度:0.00 - 0.06 - 0.01

基于“资源需求度”,我们进一步计算获得“动态权重”,计算方法就是:“某项资源的需求度”/ “三项资源需求度的均值”,代表了此项资源需求与其他几项的关系。

  • pod-a 权重:2.38 - 0.55 - 0.07(分别是cpu - 内存 - 磁盘)
  • pod-b 权重:0.07 - 2.65 - 0.28

基于“动态权重”数值,我们就可以最终计算出pod针对每个node的得分。首先是pod-a:

  • Pod-a 对node-1打分:0.2*10*2.38+0.7*10*0.55+0.7*10*0.07= 9.1
  • Pod-a 对node-2打分:0.6*10*2.38+0.3*10*0.55+0.7*10*0.07= 16.42

然后是pod-b对node分别打分:

  • Pod-b 对node-1打分:0.2*10*0.07+0.7*10*2.65+0.7*10*0.28= 20.65
  • Pod-b 对node-2打分:0.6*10*0.07+0.3*10*2.65+0.7*10*0.28= 10.33

通过上述例子可以看出,按照“固定权重”计算时node-1和node-2的得分相同。而采用“动态权重”计算时针对不同的pod(容器)我们获得了有显著差异的得分。Pod-a更大概率会被调度到node-2(16.42 > 9.1);pod-b更大概率会被调度到node-1(20.65 > 10.33)。最终结果,每个pod都尽可能找到了最适合自己资源需求的node。

供需双方的资源与需求实现互补,从理论分析来说,这样的调度特性,肯定能让集群整体获得优秀的资源均衡性。

2、动态均衡策略的效果

集群资源均衡性效果的评估,我们依然以正态分布曲线来衡量,主要对比cpu和内存的变化。

58云动态资源调度策略


上图所示红色箭头指向的曲线是cpu调度效果的变化。绿色箭头指向的曲线是内存调度效果的变化,两条曲线都明显收窄。

两项主要资源,均衡性数据同时获得大幅提升,设计理论推导符合预期。两项甚至更多项资源,从此可以和谐共生,在调度层面不再是“竞争者”。


从成本角度看策略的收益

通过对调度策略的优化以及相关保障机制,我们的研究将服务器的资源利用率提升了4倍以上,每年节约以千万级的资源成本。

资源和成本的缩减,直接因素是我们在用“超分”的方式提供资源。而“超分”的基础,离不开一套完善的“调度”策略与相关保障机制。只有这样,我们才能在“超分”的同时还能保障上层业务和云集群的稳定性。


总结与展望

我们对云平台调度策略的研究始终基于平台自身的业务特点,从实际需求和痛点出发,逐步完善和发展的。业界其他公司也大多对kubernetes调度策略做过自己的定制与扩展,主要采取诸如“资源预测”、“应用画像”、“反亲和调度”等思路。而我们所研究的云平台所采取的方案虽然在“资源预测”等方面与同行有一些共通性,不过“多种资源动态均衡”的思路有一定的创新性。后续,我们会逐步将在调度策略方面所做的工作回馈到开源社区。


参考文献:

1. https://github.com/kubernetes/kubernetes

2. https://kubernetes.io


作者简介:

陈鹏:架构师,来自58 TEG 云平台部, 主要负责云平台底层系统的架构与建设工作。


分享到:


相關文章: