Who limits the resource efficiency of my datacenter: an analysis of Alibaba datacenter traces


这篇文章发在 IWQoS 2019,是包云岗老师团队的工作,是 Jing Guo 和 Zihao Chang 在阿里巴巴实习期间发表的文章。本文对阿里巴巴 2018 年公布的第二版开源数据进行了详细的分析,主要聚焦在数据中心资源使用效率上。

阿里巴巴在 2018 年 12 月公布了其第二版混部集群的开源数据,这版数据包含了4000+台机器的 8 天运行时数据,包括 4K 台机器、9K 个在线任务和 4M 个离线任务的静态和运行时数据。

需要注意的是,2017、2018 这两版数据,均是阿里巴巴内部私有云的集群数据,并不是阿里云的数据。

开源数据传送门:github.com/alibaba/clus

论文传送门:dl.acm.org/citation.cfm?

本文对阿里巴巴 2018 年的公开数据集进行了详细的分析,从在线任务和离线任务资源分配方式的不同切入,揭示了三个 insight:

  1. 在阿里巴巴的混部集群中,内存似乎成为了新的瓶颈,限制了资源使用效率的进一步提升。
  2. 离线任务在阿里巴巴的混部集群中优先顺序低于延迟敏感型任务,同时具有相对较低的资源 QoS 要求,被限制了在混部集群的可调度时间、资源使用等,同时部分任务也出现了重调度等问题
  3. 在这版数据集中,90%以上的在线应用为 Java 应用,大量封装在虚拟机中的 JVM,使集群中资源管理更加复杂,同时进一步限制了资源使用效率。

建议对本文感兴趣的小伙伴可以阅读一下论文原文,以下内容只是论文中的一小部分。

阿里巴巴混部集群架构

看过这篇文章(《集群调度框架的架构演进过程》)的小伙伴应该了解到,目前的集群作业调度框架有几种主流形式:单体式、两层架构、共享状态、分散式(具体可参考以上文章)。

因为一些历史原因,阿里巴巴的混部集群中,为了将在线任务和离线任务混合在一起运行,他们没有重新设计一个调度器,而是使用了一种共享状态和两层调度相混合的调度框架。如下图所示,Sigma 负责调度集群内的在线任务,Fuxi 负责调度集群内的离线任务。因为本身这两个调度框架是独立的,但为了实现混部和统一在离线资源池的目的,使用了一个协调的方式来解决调度的问题。Level-0(零层)就扮演了这么一个协调的角色,它负责两个调度器之间的数据传输、通信等等,通过这种方式来将两个独立的资源池合并起来。Level1 中有两个调度器(Sigma 和 Fuxi),每个调度器的 Master 节点都可以看到整个统一资源池中机器节点的状态,每台机器上都有这两个调度器的 agent。同时在调度器的上一层(Level2)是各个不同的业务,如搜索、资料库、MaxCompute 等。

这种共享状态和两层调度相结合的调度框架,在 2017 与 2018 年两年的双十一都得到了成功的验证。

在这样的调度架构下,在线和离线任务混合运行的方式也很特别

  • 在线任务由 Sigma 进行调度,均运行在容器中,调度粒度是容器
  • 离线任务由 Fuxi 进行调度,直接在物理机上运行,调度粒度是 instance (下面会介绍离线任务的 Job-task-instance 模型)

这种半容器式的作业运行方式下,由 cgroup 分组来限制两种作业的资源使用量。在线和离线作业生命周期的管理也依旧由各自的 agent 进行管理。

资源使用效率

那么在这样的调度架构和半容器式的作业运行方式下,整个集群的 CPU 和 Memory 使用情况如以下热图所示。横轴代表 8 天的时间,纵轴代表了 4K 台机器,图中每条水平的直线都代表这一台机器在这 8 天中每 15 分钟的平均资源利用率,其中颜色越红代表资源使用率越高。

CPU 利用率在时间维度和集群维度上能看到很强的周期性变化,每天早上 6 点左右集群 CPU 利用率到达了峰值(早上运行的有消耗大量资源的定时任务)。而内存利用率很奇怪,集群整体在 8 天维度下利用率都非常高,且没有呈现很强的周期性变化规律(公开的数据中,内存利用率中算上了 cache 等)。

从混部集群技术演进的角度来看,将阿里巴巴在 2017 年公开的数据集与 2018 年的数据集中 CPU 和 Memory 资源利用率相比较,可以看到 CPU 和 Memory 资源利用率都有了很大的提升,其中内存的提升尤为明显。在去掉 cache 等数据的干扰,也达到了很高的利用率。根据阿里工程师的确认,目前混部集群中经常遇到的一个问题就是,因为没有足够的 Memory 资源,无法调度更多的离线任务到机器上运行,进而导致无法进一步提升 CPU 的资源利用率。

资源分配方式

在阿里巴巴的混部集群中,因为其调度框架沿用了在线和离线任务自己的调度器,因此在线任务和离线任务使用了两种不同的资源分配方式,分别为保守式乐观式资源分配。

保守式分配

阿里公开 Trace 中的在线任务,均是延迟敏感型(latency-critical,LC)的在线应用,其包含我们平时经常使用的淘宝、天猫等应用,这些在线应用对延迟非常敏感,稍微的延迟增高都有可能造成用户的体验下降。为了保障这些 LC 应用的服务质量(Quality of Service,QoS),避免突发的流量引起性能波动通常为这些应用预留过多的资源(over-provisioning)。如下图所示,是在机器维度上,为线任务预留的资源量和使用率的分布图,其中横轴代表 4K 台物理机(根据为在线任务预留的资源多少排过序),红色和橙色的表示该机器上分配给在线任务的 CPU、Memory 资源总和。

可以看到,单单是在线任务,其基本上占用了所有机器的 CPU 资源,有些机器甚至仅给在线任务分配的 CPU 资源就出现了超卖现象(分配的 > 实际机器的量)。然而分配了这么多的资源,资源使用率并不高,可以看到机器上,在线任务平均使用的 CPU 资源只有 10% 左右,内存还好一些,大部分分配的资源都使用了。 但是因为 90%+ 的在线任务都是 Java 写的,调度器分配给容器一部分内存资源后,就相当于那部分资源无论用多少都被 JVM 占住了(绝大部分应用的 xms=xmx),就算是容器本身没有很好地用起来那部分内存资源,暂时也没办法分配给其他应用使用。

简单的一句话总结:为保障在线任务的服务质量,阿里采取了保守式的资源分配方式,为每个在线容器都分配过量的资源。

乐观式分配

与在线任务运行在容器中所不同的是,由 Fuxi 调度的离线任务是直接运行在物理机上的,其包括 SQL、MapReduce 等任务。离线作业可以用 Job-task-instance 模型来表示,用户提交的作业为 Job,每个 Job 会被拆分为多个 Task,这些 Task 之间可能存在 DAG 依赖,每个 task 都拥有一个或者多个 instance,同一个 task 的所有 instance 都是相同的二进位文件。因此对于离线任务而言,最小的调度粒度是 instance,最小的资源消耗单位也是 instance。

如下图所示,表示离线任务申请的资源数和实际使用的资源数目,可以看到绝大部分 instance 实际使用的资源数量均大于调度时申请的资源数目,有些甚至超过了很多倍。那么需要注意的是,数据集中 request 这个值是假的,是在调度时随便写的一个值,并且在调度时也不会根据这个值来进行调度,instance 被调度到一台机器上后,上面空闲的资源是可以随便用的(当然有 cgroup 会去限制可以使用的资源上限)。

同时,因为离线任务其优先顺序低于延迟敏感型在线任务,若在线任务的性能出现了波动,在线任务会优先抢占离线任务,并从技术上保障二者之间的资源隔离效果。首先会停止离线任务,若依旧没有改善会将离线任务 kill 掉,并将其重新调度到其他的节点上运行,因此这也是离线任务频繁经受重新调度的原因之一(资源不够、优先顺序等等问题也是原因之一)。进一步地,当在线任务空闲的时候,离线任务可以通过各种方式共享在线任务没有使用的各类资源,提高集群的资源使用效率。

简单的一句话总结:离线任务虽然看起来有 request 值的限制,但是实际上,在线任务空闲时,它可以直接使用机器上空闲的资源(依旧是有一定的限制),是一种乐观的资源分配方式(实际使用量 > 申请的量)。这种分配方式为整个集群带来了很大的弹性,即可以通过集群资源分时复用的方式,在集群空闲时(如凌晨)调度更多的离线任务到混部集群中,拉高整体集群的资源使用率。


推荐阅读:
相关文章