目录

大规模容器平台共享资源池的预算,分配,核算机制

转自知乎 https://zhuanlan.zhihu.com/p/408731614,略有修改

背景与挑战

背景

大型互联网公司内部资源池非常庞大。Google,Facebook 等公司都有统一的容器平台管理庞大的共享资源池,如 Borg,Twine 等等。大规模共享资源池可以提供许多好处,比如:

  • 应对单个任务突发资源上升需求;
  • 削峰填谷,混合部署,提高资源利用率;
  • 多地域提高可用性等能力;

挑战

平台不是全能的,许多理想需求和成本有矛盾性,不能无条件都满足。

  • 平台为了提高利用率,减低成本,通常会采取某种超卖(overcomitment)策略:让集群用的比较满,不能无限满足突发的资源需求;
  • 用户总是希望只为使用付费:在需要资源时快速获取,不需要时快速释放,这会导致平台难以预估平台需要准备的资源。过多预留会导致资源浪费,预留不足会导致资源补充(分钟级)耽误业务的紧急扩容需求;
  • 用户的任务是多种多样的:有些需要高可用性、资源的高保障,有些可以低频率的被抢占,有些可以排队,但是不能被抢占。

技术层面

管理层面

  • 共享资源池的用户较多,平台侧消耗在沟通的沉默成本巨大
  • 总体预算由少数中高层负责,如何高效合理的分配给大量具体项目的研发人员;

方案

解决上面的挑战需要从两个方面着手

  • 机制设计
  • 平台技术研发

平台技术研发方案有大量的资料讨论,然而顶层机制的讨论却非常少。常常导致负责技术的研发人员常常处于两难的"脑裂"的状态本文主要讨论资源的预算和分配这些机制的设计思路

综合考虑上述原因,除了搭建搞水平的技术,还有另外一个必要前提条件:预算、分配、核算机制。通过达成共识的机制,让业务(Consumer Based Expectiation)和平台(Service Level Expectation)通过技术手段做到成本和效率的平衡。

https://pic3.zhimg.com/80/v2-206024aba282352c9a6e6edcfed79546_1440w.webp

具体的,这套机制需要解决如下关键问题,其中着重关注问题 2 ~ 5:

  • 预算分配给业务
    • 共享池上的众多业务如何申请每个周期的预算总额;
  • 业务预算分配给项目
    • 获得预算的业务如何有效的将预算分配给具体需要使用资源的项目,比如视频业务需要转码项目,视频推荐排序项目,存储后台项目等。参与到项目中的研发需要使用共享资源池的算力来完成项目;
  • 项目任务分级配额
    • 研发为某个项目开发代码,提交计算任务到容器平台上会有不同的分级,对应不同的风险和定价策略。有些任务需要 “更可靠” 的资源预留,对应会有较高的定价。而部分批任务,离线任务可以运行在一定时间段内承担部分资源无法获得的情况,对应有较低的价格。具体表现为基于分级的差异化 SLO 和定价
    • 项目根据自己任务的实际情况,使用不同等级任务的配额;
  • 精算系统
    • 通常公司内精算系统在满足业务实际需求前提下,以最大化资源利用率为优化目标。而公有云则更倾向于最大化收入为目标;
    • 基于历史、当前和预测的资源用量,平台技术能力等数据;
    • 预测共享资源池还可以售卖的各级资源额度,以及对应的 SLO 和价格;
  • 核算
    • 资源用量可以归属到组,通过组可以回溯到上游平台,业务,实体人等维度;

预算

预算分配给业务

预算分配给业务往往是高层的决策。通过年度预算等和定期调整的方式进行。一般会参考:

  • 往年的成本;
  • 对于后续业务成长速度,规划,技术发展的预期;

预算中的一部分会被分配给研发项目,用来确定在容器平台中能够使用的资源。 预算的原始单位可能是具体的金额:

  • 金额具体如何转换成容器平台的物理资源通常是不公开的。可能会被加密成其他单位,比如 “人时”;
  • 换算的公式也可能是动态调整的,受众多因素影响:物理资源的成本变化,资源在不同区域的空闲情况,容器平台底层技术能力,用量是否突发超过预算等等;

比如一个亿的预算中,具体可能会表现成 10000 算力单元在容器平台能购买某个等级一定量的 CPU 核。

业务预算分配给项目

每个业务的发展都需要开展研发项目。比如接入层,后台的存储服务,训练召回排序模型,推理服务等等。这些项目最终被拆分到研发身上。他们为了完成工作需要在共享资源池上提交任务。

https://pic2.zhimg.com/80/v2-b1014d235e09d70f1342eac770dba999_1440w.webp

因此,需要将业务的预算拆解到各个项目上。这里主要通过组(group)的媒介来完成。一个或多个业务线将预算的一部分划归给某个具体的组,研发加入组后就可以用组的身份去容器平台提交任务了。具体如下:

  • 创建组,将业务预算(可能转换成对应容器、存储等的资源单位)绑定到某个组上;
  • 研发加入组,通过组的身份提交任务到容器平台;
  • 容器平台得知组需要使用多少资源,去预核算确认这个组拥有充足的预算;
  • 如果预算充足,容器平台调度任务;

“组” 的媒介提了许多好处,也有许多细节

  • “组” 解耦了公司的管理树,可以方便让多个业务协同共享资源,多个部门研发协同开发;
  • “组” 又可以进一步分类为 “资源组”,“人员组”。资源组仅有预算和身份能力,可以包含人员组,人员组可以包含人。解耦了资源和人的关系,人可以灵活加入和离去,但是项目可以持续的进行,使用资源;
  • “组” 也能解耦平台,多个平台基于统一的组体系,可以大幅简化跨平台的使用,结算等问题;

项目任务分级配额

前面的流程中存在一个比较大的问题,研发对于每个任务需要使用多少资源的判断是不准确的,而且通常是非常不准确。运行程序的研发和开发程序的研发往往不是一群人。即使研发运行的是自己的代码,也难以判断准确。具体表现如下:

  • 程序运行本身有不确定性,CPU 和内存的使用难以准确预估;
  • 在线服务存在潮汐现象,研发往往按照峰值资源用量来申请资源;
  • 为了保障在线服务的稳定性和不可预期的调用量增加,研发倾向于申请更多的资源;

综上,假如容器平台为所有计算任务预留的资源和研发申请的资源一样,必然导致巨大的资源浪费。经验性:

  • 在峰值,申请的资源也比实际使用多出 30% 以上;
  • 在波谷,申请的资源可能比实际使用多出的 70% 以内;

https://pic4.zhimg.com/80/v2-24384a5c41016f2782fb80782ecb6363_1440w.webp

如下图所示:

Usage 是实际程序运行使用的 CPU,会不断波动。 Allocation 是用户提交程序时申请的 CPU。通常超过 Usage,保障程序的运行速度等。 Reservation 是平台为用户预留的总 CPU。可能因为用户还没来得及提交,或者有任务停掉等原因,比 Allocation 要多。 Capactity 是整个集群实际物理 CPU 总量。通常会比 Reservation 多,可以被卖给其他用户。

https://pic4.zhimg.com/80/v2-3801c1c83a066ab71e67ae1e1123fe5f_1440w.webp

超卖

由于所有任务不太可能同时到达峰值(大多数情况都不再峰值),平台如果按峰值的总和预留资源会造成巨大的浪费。为了让资源池的利用率高起来,容器平台一般会对资源进行超卖。

举个例子,平台有 100 万核,卖给 A 业务 50 万核,A 大概率不会用到 50 万核,那么平台可以再卖 80 万核给 B 和 C。因为 B 和 C 大概率也不会用到 80 万核,所以平台的 100 万核(真实资源)大概率不会被 A,B 和 C 用满。 在大多数情况下,A,B,C 和平台都很 happy。A,B,C 感觉自己便宜的买到了更多东西。平台 “无中生有”,降低了公司的运营成本。

这有点像银行发放贷款,银行获得了100 万的储蓄,可以借 90 万给别人。只要存钱的人不一起来要这 100 万(大概率),银行就是安全的。

问题

前面反复提到了概率的问题。当某些特殊情况发生时,平台,A,B,C 可能就不太 happy了。比如,A 业务出了个爆款,用户量爆增,真的用到了 50 万核(甚至更多)。但是 B 和 C 已经用了 60 万核了(卖给他们 80 万)。A 现在只能用到 40 万核。。。A 会非常不 happy!

真实情况,很多公司平台如果有 100 万核,可能根本就不知道 A,B,C 分别预算多少。当任意一个业务量暴涨时,都会问平台要更多资源。而平台交不出来的话,就需要承担业务的损失。

一种比较简单的办法:平台囤积部分资源不用(小金库),假装资源已经都分配了。当 A,B,C 某个业务需要使用时,再分配这部分资源。这样会导致 A,B,C 都需要为这部分囤积浪费的资源买单,提高了单位资源成本。

分级配额机制

更合理的做法应该是分级,对不同级别基于对应的 SLO 和定价。类似 AWS 上的 Reserved Instance,OnDemand Instance 等。

SLO 一般会考虑两个维度:

  • Obtainability:用户想获得配额的资源时,有多大概率是能给的;
  • Availability:用户的任务正在运行时,有多大的概率资源要被回收;

基于以上两个维度,有 3 种场景的 SLO

  • Reserved(Or Prod):就是 Obtainability 和 Availability 是接近100%的,有较高定价;
  • Economy(Or Batch):研究表明,Obtainability 和 Availability 会在 98% 以上时,平台可以超卖相当可观的资源。而 98% 对于大多数离线任务,甚至部分在线服务都是可以接受的;
  • Opportunistic(Or Free):没有 SLO,但是在集群的缝隙通常也能获得一定的资源;

Pooling 机制

这是一种附加策略,单个组的预算是非常有限的,Pooling 是一种互助协议。如果 A 和 B 签订了协议,那么当 A 超过了配额时,A 可以临时借用 B 没有用的配额。

精算系统

前面提到的分级配额机制,通常需要一个精算系统的支持,对于大规模容器平台,可能有数百万到数千万核的算力资源。1% 的优化都能带来显著金钱上的节省。 精算系统可以和调度系统解耦,判断每台物理机在一定概率条件下,实际剩余的空闲资源。或者判断每个容器在一定概率条件下,实际使用的资源。(Usage vs Limit vs Capacity)

大致工作流程:

  • 获得如下数据
    • 资源池总体的容量情况
    • 历史,现在和对未来任务资源使用的预测
    • 平台的调度、隔离能力等技术指标
  • 数据科学家基于数据制定大致的分级策略,比如上文提到的 Prod, Batch, Free;
  • 精算系统计算出,在保障 SLO 的前提下,资源池的不同等级的资源还有多少可以被售卖;

假设平台有 100W 核,A,B,C 三个组过来申请配额:

  • A,B,C 为在线服务 A1,B1,C1 分别申请了 20W Prod,那么集群剩下 40W;
  • 精算系统通过测算,认为 99% 的概率下,集群能在 10 分钟内能够释放 60W 核的资源出来。或者说,这 60W 中,A1, B1, C1 同时需要使用 20W 中的一部分,导致只剩下 40W~60W 的概率小于 1%;
  • 平台会将 60W 核分配给 A,B,C 的 Batch。假设 A2,B2,C2 分别各申请获得 20W Batch;
  • Free 配额可以一定概率在低谷期获得 20W 的碎片资源,白天某些时段获得 5W 碎片资源,依然有利可图;

Priority 和 Quota

优先级和配额用于防止运行的比实际能容纳多的这种负载情况。每个任务都有一个 priority 优先级,一个小的正整数。高优先级的 task 可以在牺牲较低优先级的 task 来获取资源,甚至是以抢占方式。 可以为不同用途定义不同的优先级:监控、生产、批处理和 best effort。

针对生产级别的任务是禁止 task 互相抢占的。优先级决定任务处于运行还是等待状态。 Quota 配额被用于确定调度哪些任务。配额表示为一段时间内(通常为几个月)给定优先级的资源量(CPU、RAM、磁盘等)。这些值指定了用户的任务在请求时间段内可以使用的最大资源量。配额检查是准入控制的一部分,配额不足情况下,任务会被拒绝调度。

高优先级的配额成本比低优先级要高。生产级别的配额仅限于集群中实际可用资源,因此用户提交满足生产级别任务运行预期的资源配额。虽然不建议用户配置超买,但是很多用户都会比实际的需要配额要大,以防止后续用户增长可能造成的资源短缺。对于超买,应对方案就是超卖。

配额分配和物理容量设计密切相关,结果反映在不同数据中心的配额价格和可用性上。

Fine-grained resource requests

支持以 ms(毫秒)为单位请求 CPU,以 bytes(字节)为单位请求内存和磁盘空间。

核算

基于上文机制开发的系统,核算应该是可以完全自动化的。整个链条从最初的总预算开始到最后任务在 CPU 上运行都是在系统中可追溯的。大致过程如下

  • 容器平台会结算每个任务运行消耗的资源;
  • 每个运行任务可以自动关联到 “组” 上;
  • 组的创建是来自某个项目的申请,因此可以管理到具体的事上,比如训练精排模型;
  • 组的预算来自于一个或多个业务授予的,也可以自动化拆分;
  • 组的成员组成也是明确的(包括它的变化记录),可以自动归属到对应的研发身上;

角色与责任

在整个链条中有如下几类角色

  • 决策层:负责定期或按需 Review 业务的总体预算是否满足业务发展的总体开销,并且将获得的预算分配各个领域的负责人;
  • 领域负责人:通常可能是业务某个领域负责人等角色,负责将预算分配给各个项目组,并对分配的额度是否够用负责。如果额度不够导致了容器平台拒绝提供资源,由项目 Admin 和下级负责;
  • 项目组负责人:需要主动观测项目组下所有任务的资源使用情况,在需要时及时向领域负责人申请调整。如果没有及时调整,额度不够导致平台拒绝提供资源,由项目负责人负责
  • 研发:开发 Prod, Batch 等任务,优化任务的资源开销,尽可能在满足业务需求的前提下使用较低价格的资源等级;
  • 平台:对平台的健壮性,可观测性和承诺的 SLO 负责。在满足 SLO 前提下可以拒绝提供资源;

相关资料

Long-term SLOs for reclaimed cloud computing resources

Take it to the Limit: Peak Prediction-driven Resource Overcommitment in Datacenters

Flex,JSSP 2018

Nines are Not Enough: Meaningful Metrics for Clouds

Borg 2013

Next Borg