仓库规模操作系统的背景之集群调度

前言

本文是Malte Schwarzkopf的博士论文《Operating system support for warehouse-scale computing》一个翻译版本,融入了作者自身的经验和理解,读者如果想阅读原文,可以访问:http://people.csail.mit.edu/malte/pub/dissertations/phd-final.pdf

编写本文的目的是提供一个中文版本的文档,同时为自己保留一份学习笔记,供日后事件参考以及优化调整。当然,优化调整部分不能更新在公网,因为笔者同一时间在公司内网发布了改文章,相应部分只会更新在公司内网的文章中。

集群调度

如前节所述,集群调度器是当今用作数据中心操作系统的基础设施系统的关键部分。此外,硬件异构性和同位干扰带来的挑战可以通过良好的集群级调度来解决或至少减轻。

当然,计算资源(比如机器)来调度任务(比如并行任务)不是一个新问题。在CPU调度方面存在大量的前期工作,但是操作系统 CPU调度器不同于集群调度器:它们在上下文切换期间短时间内被调用,并且在做出决策时阻塞用户空间进程。相比之下,集群调度器与集群工作负载一起连续运行;它的调度决策持续时间更长;并且它具有比单机CPU调度器更复杂的设计目标。

在本节中,我概述了现有集群调度器的设计目标以及它们是如何实现的。表2.8总结了每个系统的核心设计目标。

 

表2.8:集群调度器及其设计目标。✔️表示该属性是一个设计目标,✘表示它不是一个目标并且不受支持。(✔️)表示系统可以通过其API支持该目标,内置支持。

调度程序体系结构

现有集群调度器的体系结构主要分为:中心调度和分布式调度,图2.9说明了我讨论的方法。

图2.9:不同集群调度器架构的比较。灰色框表示集群机器,彩色圆圈对应于不同应用程序的任务。

扫描二维码关注公众号,回复: 4737276 查看本文章

大多数早期的集群调度器都是较大的单体:它们具有简单、中心化的体系结构,并且通过相同的逻辑处理所有决策。通常,单体调度程序在专用机器上或作为集群管理器的一部分运行。这种方法的优点是相对简单:所有状态都保存在一个地方,并且只有一个决策实体(图2.9a)。调度器容错可以通过主/从热备或通过从先前保存的检查点重新启动调度器来实现。

然而,近期工作引入了分布式集群调度器体系结构,然而目的不同:

专用框架之间的资源共享:数据中心同时运行许多基础设施系统和应用程序(参看以前的章节),这需要跨用户和系统划分集群资源。许多基础设施系统还执行它们自己的应用程序级任务调度(例如,MapReduce分配map和reduce任务)。因此,两级调度器有一个资源管理器来分配资源和一个程序级调度器来分配应用级任务到匹配的资源。资源管理器比单体调度器简单,因为它忽略了应用程序语义和调度策略。相比之下,应用程序调度器使用应用指定的调度逻辑来调度任务,但是只查看它们分配到的资源(图2.9b)。

Yahoo的Hadoop-on-Demand(HoD)是一个早期的两级调度器。它结合了TORQUE资源管理器和Maui HPC调度器,从共享池中分配用户集群。随后,Mesos和YARN设计了正规的两级体系结构,通过提供(Mesos)或请求(YARN)来复用资源。笔者几年前设计并实现的基于海量视频、图片的高性能计算平台PCC(high Performance Cluster Computing)也是两级架构,分为OS和Framwork两层,OS层模拟操作系统提供资源管理,Framwork为不同的业务(视频、图片)实现针对性任务调度。

工程复杂性:集群工作负载的多样化需求使得管理大型组织和持续迭代单个调度器基线代码具有挑战性。

Google的Omega集群管理器因此引入了部分分布式、共享状态、分布式逻辑调度器架构。Omega支持同一集群内多个共存的调度器。调度器可以基于不同的实现并分布式运行,每个都处理部分工作负载。然而,不同于两级调度器,所有调度器都包含完全共享的、弱一致性的集群状态副本。它们通过针对集群状态发出乐观并发的事务来改变集群状态(图2.9c)。事务可能产生成功的任务放置,或失败就需要重新尝试。Microsoft的Apollo对这个模型做了更进一步的研究,仅发现并解决集群机器中工作端(worker-side,我的理解是相比于管理端,通用节点统称为工作端)队列的冲突。

对非常短的任务的可伸缩性。一些交互式查询的分析型工作负载必须在几秒钟内返回信息的,为了促进这一点,工作被分解成大量非常短暂的任务。这种小的任务粒度增加了利用率,并且减少了掉队任务(traggler task,我的理解是由于某种原因执行速度偏离了预期的任务)对作业完成时间的影响。

短任务只存在亚秒的持续时间,因此调度开销(无论中心式调度还是共享状态的事务)可能很大。Sparrow完全分布式调度器通过完全避免共享状态和协调来解决这个问题。相反,集群机直接从调度器拉取任务以响应探测(图2.9d)。

不同的解决方案适合不同的环境,没有哪个架构比其他架构更好一说。

数据局部性

数据的引用位置在计算机系统许多工程优化是关键,尤其是处理器中高速缓存机制的有效性。分布式系统也有“位置”的概念:如果任务的输入不在本机上,则必须通过网络获取,这必然会引起延迟并增加网络利用率。为了避免这种成本,集群调度器旨在增加对本地数据进行操作的任务数量。

Google的MapReduce优先地将map任务安排在输入数据块可用或者在相同叶子交换机的机器上,并且其他系统也采用类似的优化。相关研究性工作进一步完善了这个概念:延迟调度拖延任务启动,希望任务“运动”会有更好的位置可用;Scarlett增加了普通输入数据的副本,以数据本地化程度;Quincy权衡迁移已经运行的任务并重启他们带来的开销。

早期的工作针对磁盘位置进行了优化,因为从本地磁盘读取数据比通过网络传输更快。然而,数据中心网络带宽增加了,使得本地磁盘和远程磁盘之间的差异越来越小。然而,位置仍然很重要:许多数据处理框架和存储系统在RAM中缓存数据,使得内存中对象的位置成为一个重要的问题。此外,最近的机器学习工作负载对GPU具有局部约束,并且需要仔细布置以确保其任务之间足够的网络带宽。即使基于NVMe闪存设备的网络存储(每个机器上没有本地数据)也需要需要小心地在具有足够CPU和网络容量的位置上布置工作负载。

此外,机器内也有的位置概念:NUMA系统中的“相对比较远”的内存访问成本很高,PCIe设备的位置对于高性能网络访问很重要。关于机器内这种细粒度位置的信息通常只对本地内核CPU调度器可用,而对集群调度器不可用。

关于NUMA的说明:虽然内存直接attach在CPU上,但是由于内存被平均分配在了各个die上。只有当CPU访问自身直接attach内存对应的物理地址时,才会有较短的响应时间(后称Local Access)。而如果需要访问其他CPU attach的内存的数据时,就需要通过inter-connect通道访问,响应时间就相比之前变慢了(后称Remote Access)。所以NUMA(Non-Uniform Memory Access)就此得名。如下图所示:

约束条件

对于一些特别应用仅仅资源平等并不适合:特定硬件特性的可用性(例如基于闪存的存储或通用GPU加速器)、软件兼容性约束(例如特定内核版本)以及同位首选项(接近关键服务或远离负面干扰应用程序)全部有助于任任务调度。

因此,调度有时受到布局限制。这样的约束在实践中非常常见:例如,50%的Google Borg任务具有某种简单形式的与机器属性相关的放置(placement,理解为任务放置在机器上运行)约束,13%的生产工作负载具有复杂的约束。

一般有三种类型的约束:

软约束:指定“优先”位置,指示任务受益于某个属性的存在。例如,I/O密集型工作负载(如日志爬行)可能对具有闪存的机器具有软约束。调度器可以选择忽略软约束并继续调度任务。

硬约束:相比之下,调度器必须满足硬约束。具有硬约束的任务直到找到满足其要求的位置才能被调度(或者抢占)。在闪存示例中,如果任务不能使用较慢的存储设备执行则此约束是适当的(例如,支持分布式事务系统的快速、持久日志)。同样,需要特定硬件加速器的应用程序将使用硬约束(比如基于GPU的AI应用)。

复杂约束:在本质上可以是硬约束或软约束,但是对于调度器来说很难处理。不仅依赖于机器属性,还依赖于机器上运行的其他任务和其他并发放置(比如某个资源最多支持多少个应用并发使用)决策的组合约束是复杂约束的典型示例。在上面提到的闪存示例中,组合约束可以指示一次只能运行一个任务使用机器上的闪存设备。

   熟悉Kubernetes的读者不难发现亲和性(affinity)与本文讨论的约束非常相似,而本文提到很多次的Google Borg,Kubernetes就是他的开源版本,就要像MapReduce/GFS的开源版本是Hadoop一样。

约束减少了给定任务可用的可能放置数量,因此导致增加的调度延迟。

许多调度器支持约束,但是对于所支持的类型几乎各不相同。例如,Sparrow和Choosy只支持硬约束,并将它们用作调度时的过滤器。另一方面,Quincy通过每个任务放置首选项支持软约束,但不支持硬约束。 Quasar支持软高级性能约束,但是依赖于调度器的配置和通过纠正措施满足它们性能的预测机制。

相比之下,YARN的资源管理器支持软约束和硬约束,alsched不仅二者都支持,也支持复杂约束。然而,tetrisched随后也提出对软约束的支持是足够的,并且提供了一些很吸引人的特色。

对约束的支持是高级调度策略的表示、调度器复杂性和作业等待时间之间的权衡。由于工作负载和操作环境的不同,不同的集群调度器做出不同的选择。

公平

大多数仓库规模的数据中心由单个机构运营,但是仍然运行来自不同组织单元、团队或外部客户的大量工作负载。这些用户可能会采取敌对行为,以便增加它们在集群资源中的份额。因此,集群调度器分配共享资源,并且旨在提供公平性。

有些系统依靠任务通量趋向用户的公平共享,资源根据用户的公平共享提供给用户,但是如果分配变得不公平,则运行任务不被抢占。Hadoop Fair Scheduler(HFS)就是这样一种基于通量的方法,它通过将MapReduce分成“作业池”(HFS)来公平地分享它。Sparrow分布式调度器使用类似的方法:任务在每个worker处经历加权公平排队,并且当任务以不同的速率运行时,集群的公平共享显现出来。

相比之下,Quincy抢占运行任务以强制执行公平份额。它将调度问题建模为网络流优化,每当其求解器运行时强制执行更新的公平共享。为了保证进度,Quincy不会在任务运行一段时间后抢占它们;因此,暂时的不公平仍然存在。

一些策略支持多个资源维度上的公平共享:例如,主导资源公平算法(Dominant Resource Fairness  DRF)通过确保每个用户在所有维度上至少接收到他的合理份额来提供多维最大最小公平(max-min fairness)。DRF已经被证明具有激励用户共享资源和诚实地陈述其需求的特性。DRF变体也存在于关于放置约束(Choosy中的受约束最大最小公平CMMF)和分层分配委托(H-DRF)的公平分配。

虽然强公平性很吸引人,但尚不清楚它在单一机构的数据中心中有多大用处。有趣的是,许多生产系统依赖带外(out-of-bands)机制来确保近似公平的共享。此外,即使调度器可以分配公平的资源共享,异构性和干扰也会导致看似相同的资源分配但实际差异显著。

动态资源调整

大多数集群调度系统假设所有作业的任务要么具有统一的资源需求(例如,具有固定大小的MapReduce工作“槽”),要么用户在作业提交时指定资源需求(例如,在Borg、YARN和Mesos)。

然而,一些集群调度器支持动态调整资源分配。这对于利用闲置资源、deadline内完成工作或应对变化的负载是有益的。

Omega的MapReduce调度器在可能的情况下试图分配额外的资源以增加并行度;如果分配的资源没有得到充分利用,Apollo同样会在作业内试图启动额外任务。

如果SCOPE作业存在超过deadline的风险,Jockey动态地增加资源分配,如果存在余量,则减少其资源分配。类似地,Quasar基于同位和机器类型自动申请“正确大小”的资源并选择最佳可用资源;它增加资源分配,直到满足用户指定的性能约束为止。最后,Borg的“资源回收”机制动态地将任务的资源请求减少到围绕其实际使用的边缘值,以便减少预留过多资源并提高利用率。

这些例子强调了资源分配可以由调度器动态调整。然而,最通常的情况是,让应用程序内省它们的性能并在必要时请求额外的资源。

总结

正如我在前面节中已经讨论的,良好的调度决策对于集群资源的有效使用至关重要。本节已经调查了许多现有的集群调度器。我从研究它们的体系结构开始,然后讨论了几个理想的特性:支持集群内局部性、放置约束、公平性和动态资源调整。

然而,现有的调度器很少有能够解决前面强调的机器异构性和工作负载干扰挑战。然而,在集群资源高利用率条件下实现确定性工作负载性能,集群调度器必须:

  1. 集成机器级信息和集群级信息,基于细粒度任务分析、机器类型和位置信息做调度决策;
  2. 通过定位那些可以很好工作在一起的任务避免存在负面干扰的工作负载共享硬件;
  3. 灵活的、允许根据工作负载指定的调度策略,以便调度器能够针对期望的用例进行定制。

后面的章节我会讨论一个支持这些目标的新调度器。

猜你喜欢

转载自blog.csdn.net/weixin_42663840/article/details/85537597