Lec 21 集群管理
Cluster Management
阅读资料
论文:Omega
《Omega:灵活、可扩展的大型计算集群调度器》
摘要
单体式集群调度器架构难以满足大规模和对快速响应变化需求的要求。我们提出了一种新的方法,通过并行性、共享状态和无锁的乐观并发控制来应对这些需求。我们将这种方法与现有的集群调度器设计进行了比较,评估了调度器之间干扰的程度及其实际影响,介绍了一些缓解干扰的技术,最后展示了一个使用案例,突出我们方法的优势——所有这些都基于Google的真实生产工作负载。
1. 引言
大规模集群非常昂贵,因此提高利用率和效率非常重要。通过同一台机器上运行混合工作负载,可以提高利用率的目的,同时也给调度策略带来难度。调度器的工作量大致与集群规模成正比,因此调度器有可能成为扩展性的瓶颈。
Google的生产作业调度器经历了下面所有情况。如图1所示,单体调度器对所有作业使用单一的集中调度算法(当时的调度器即属于此类)。两级调度器则拥有一个活动的资源管理器,向多个并行、独立的“调度框架”提供计算资源,如 Mesos(淘汰,被K8S取代了) 和 Hadoop-on-Demand (已淘汰)所使用的架构。

单体调度器难以扩展新策略和特化实现,且难以扩展到大规模集群;而两级调度架构虽然看似具备灵活性和并行性,但实际中受限于资源可见性和锁机制,既难以调度“挑剔”的任务,也无法做出需要全局视角的决策。
我们的解决方案是一种新的并行调度器架构,基于共享状态,使用无锁的乐观并发控制,以实现可扩展性和性能可扩展性。此架构正在用于 Google 的下一代集群管理系统 Omega(在Bory之前的一代)
本文的贡献如下:
- 提出集群调度器开发的轻量级分类法(第3节);
- 引入一种基于共享状态和无锁乐观并发控制的新调度器架构(第3.4节);
- 使用模拟和合成工作负载比较单体、两级和共享状态调度的性能(第4节);
- 使用基于生产调度器代码并由实际工作负载轨迹驱动的代码,详细探讨共享状态方法的行为(第5节);
- 通过一个用例展示共享状态方法的灵活性:我们添加了一个调度器,利用全局集群利用率信息调整运行中的 MapReduce 作业所分配的资源(第6节)。
2. 需求
集群调度器必须满足同时满足多个目标: 高资源利用率、用户自定义的调度约束、快速决策、公平性与业务优先级。其中一个复杂性的来源是工作负载和硬件的异构性。Google的生产集群上显示:
- 大多数任务(80%)是批处理,但服务类任务消耗了大部分资源(55%-80%)
- 批处理任务短小,调度速度重要,可容忍较低的调度质量。
- 服务类运行时间长,需高可用和稳定性,调度需要考虑容错
单一调度器会出现“队头阻塞”(head-of-line blocking)等性能问题;不同任务类型需要不同调度策略;需要一个既能灵活支持多样策略,又能扩展并行调度能力的新型调度架构

3. 分类法
调度任务的划分。调度任务可以通过以下方式在多个调度器之间分配:(1)不考虑工作负载类型的负载均衡。(2)将特定调度器专门分配给不同类型的工作负载。(3)以上两种方式的结合。我们关注有多少调度器实际参与处理这些队列。
资源选择方式。调度器可以选择整个集群的所有资源,或仅选择其中一部分以简化决策过程。如果允许调度器抢占已有任务,可提升调度灵活性,但也会造成被抢占任务的一部分计算资源浪费。
调度器间的干扰。如果多个调度器竞争资源,它们可能会同时尝试分配相同资源。悲观方法:保证某个资源一次只能被一个调度器访问,以避免冲突;乐观方法:先允许冲突发生,然后检测并撤销冲突的分配操作。乐观策略提升并行性,但若冲突频繁,可能会造成大量调度工作浪费。
分配粒度。由于一个作业通常包含多个任务,调度器可以采用不同的策略来调度:将所有任务以原子方式一次性全部调度(gang scheduling);增量式调度任务,找到资源就安排一个。原子调度可以通过资源“预占”来模拟——逐步获取资源直到能启动整个作业,但这可能导致资源浪费。
集群范围的行为。某些调度行为会。跨多个调度器,例如,实现不同类型的公平性;达成对工作相对重要性的共识(特别是涉及任务抢占时)。
3.1 单体式调度器
单体式调度器只有一个实例,没有并行性,所有调度逻辑和策略都集成在同一代码库中。实现简单,全局统一视角,但缺乏并行性、扩展性差、实现和维护多个复杂策略困难,单点性能瓶颈,容易出现队头阻塞
3.2 静态划分调度器
每个调度器负责一组固定的资源,例如 Hadoop 和 Dryad 中的方式。调度器无竞争,实现简单但会导致资源碎片化,导致利用率低。
3.3 二级调度器
中心调度器动态将资源分配给子调度器框架,每个框架再决定如何使用分到的资源。代表系统:Mesos、Hadoop-on-Demand(HOD)、YARN。Mesos 的机制:中心调度器按“资源提供(offer)”的方式分发空闲资源;次资源只提供给一个框架,避免冲突(悲观并发控制);使用 主导资源公平性(Dominant Resource Fairness, DRF) 实现公平分配;无法支持抢占,也无法看到全局状态;对 Google 的生产工作负载(服务类任务,生命周期长、资源需求大)不适合。
3.4 共享状态调度器
多个调度器并行访问整个集群的全局状态,共享同一个资源视图,使用乐观并发控制来解决冲突。机制:没有中央资源分配器;每个调度器拥有一份本地快照(频繁同步);做出决策后尝试原子提交更新共享状态(如果失败就回滚并重试);相当于一个分布式事务系统,提交过程是一个事务;支持 增量提交(只回滚冲突部分)或 原子提交(全部成功或全部失败)。
4. 设计比较
为了理解不同方法的权衡利弊,我们构建了两个模拟器:
- 轻量级模拟器
4.3 共享状态调度器:Omega
我们使用轻量级模拟器来探索 Omega 的共享状态模型。
5. 基于轨迹的仿真
高保真仿真器(high-fidelity simulator)是Google生产环境代码。它能正确处理任务的部署约束,和使用与生产环境一样的算法,并且可以加载实际生产环境中采集到的初始集群描述和详细工作负载轨迹。我们使用它来回答以下几个问题:
- 在现实世界的工作负载中,调度干扰的程度如何?在生产环境中,我们能接受多长的调度决策时间?(§5.1)
- 不同的冲突检测与解决策略在真实工作负载中会带来什么样的影响?(§5.2)
- 我们是否可以利用调度器对整个 cell 全部状态的访问优势?(§6)
这里还是做了几个简化。它不会模拟机器故障;它将资源分配固定为最初请求的大小;它也禁用了抢占(preemption),因为我们发现抢占对结果影响不大,但会显著拖慢模拟过程。
5.1 调度性能
图11 展示了服务类调度器的忙碌程度(busyness)如何随 t_job(service) 和 t_task(service) 变化而变化。调度器的忙碌程度在整个范围内始终保持较低水平,这表明 Omega 架构可以很好地扩展到较长决策时间的服务类作业上

扩展工作负载分析。我们还使用来自集群B的7天轨迹,评估共享状态架构的性能。该集群是 Google 最大、负载最重的集群之一。我们同样对 t_job(service) 进行了调整。在图12b中,当 t_job(service) 达到大约 10 秒时,冲突比率(conflict fraction)超过 1.0,意味着每次调度服务作业平均需要重试一次以上。
在大致相同的时间点上,我们未能满足服务调度器的 30 秒作业等待时间 SLO(服务级别目标)(见图12a),尽管调度器本身还没有饱和:额外的等待时间完全是由冲突引起的。为了确认这一点,我们估算了一个“无冲突”场景下调度器会花费的时间(见图12c的“no conflict”曲线),结果显示,有冲突时调度器的忙碌度比无冲突情况下高出约 40%。这比集群C的干扰程度要高得多,原因很可能是集群B中批处理作业(batch load)显著更高。
尽管冲突率相对较高,我们的实验表明:Omega 的共享状态架构依然可以支持每次调度决策耗时数秒的服务调度器。我们还研究了每个任务的决策时间对调度性能的影响,发现:在 t_job(service) = 0.1 秒的前提下,我们可以支持 t_task(service) = 1 秒,同时将冲突比率控制在 ≤ 0.2。换句话说,该架构既支持“每作业一次性决策时间较长”的调度器,也支持“每任务决策耗时较高”的调度器。

6. 灵活性:一个MapReduce调度器
论文: Borg
摘要
Google Borg 系统是一个集群管理器,运行着数千个应用程序的数以十万计的作业,跨多个由数万台机器组成的集群。
它通过以下手段实现了高资源利用率:接纳控制(admission control)、高效的任务打包(task-packing)、资源超额分配(over-commitment)、以及进程级别的性能隔离下的机器共享(machine sharing with process-level performance isolation)
Borg 支持高可用性应用,通过运行时特性最大程度地减少故障恢复时间,并通过调度策略降低相关故障发生的概率。它还通过以下方式简化了用户使用难度:提供声明式的作业规范语言、与名称服务集成、实时作业监控功能,以及用于分析和模拟系统行为的工具。
本文将概述 Borg 系统的架构和功能,解释其中的一些重要设计决策,量化分析若干策略选择的效果,并结合十年运维经验,对关键经验教训进行定性讨论。
1. 介绍
集群管理系统的内部代号是 Borg,它全程管理、调度、启动、重启以及监控 Google 运行的应用程序。
提供了三大好处:
- 向用户隐藏资源管理和故障处理的细节,用户只需专注于应用程序开发
- 高可靠性和可用性运行, 支持那些同样要求的应用程序
- 有效的在数以万计的机器上运行工作负载,是少有的能以这种弹性和完整程度的规模

2. 用户视角
Borg 的用户(users)是运行 Google 应用程序和服务的开发人员和系统管理员( SRE等)。用户以作业(jobs)的形式向 Borg 提交他们的工作,每个作业都由一个或多个运行相同程序(二进制)的任务(task)组成。每个job都在一个 Borg 单元(cell)中运行,即一组机器以单元的形式管理。
2.1 工作负载
主要有两种工作负载,第一种是不停止运行的服务,对延迟敏感(几个
在过去几年中,许多应用框架都是基于 Borg 构建的,有MapReduce系统(大多数都有一个控制器,负责提交一个 master 作业和一个或多个 worker 作业),和分布式存储系统。
在本文中,我们将优先级较高的 Borg 作业归类为“生产型”(production, 简写为 prod)作业,其余的归类为“非生产型”(non-production, 简写为 non-prod)作业。大多数长期运行的服务器作业是 prod 作业;而大多数批处理作业是 non-prod 作业。在一个典型的 cell 中,prod 作业被分配了约 70% 的总 CPU 资源,并占用了约 60% 的实际 CPU 使用量;它们被分配了约 55% 的总内存资源,却使用了约 85% 的内存。
2.2 集群和单元
一个cell中的机器属于同一个集群,这个集群是由高性能的数据中心级网络结构连接起来的。一个集群位于一个数据中心建筑内,而多个这样的建筑构成一个 site(站点)。一个集群通常承载一个大型 cell,并可能包含一些用于测试或特殊用途的小型 cell。我们始终严格避免任何单点故障的存在。
在排除测试用的 cell 后,cell 的中位规模大约为 1 万台机器,有些甚至远大于这个数。cell 内的机器在多个维度上是异构的(意味着性能、指标有差异),Borg 将用户从这些差异中抽象出来,负责决定任务在 cell 中的运行位置等调度器该做的事。
2.3 工作和任务
Borg的job包含了名称,所属以及拥有的task数量。Job有能够有限制(constraints)来强制其任务运行在有特定的属性的机器上,比如指定架构,OS版本,或者是外部IP地址等,限制可软可硬,前者用偏好(preferneces)更贴切,而不是要求(requirement)。一个Job只能运行在一个cell里面。
每个任务映射到一个机器上的一个容器中运行的一组Linux进程上。大部分负载不会运行在虚拟机上,因为我们不想为虚拟化的成本买单。
2.4 分配方式
2.5 优先级
2.6 命名和监控
2. Bory架构
一个cell包含了一组机器,一个逻辑控制器称为Borymaster和一个agent进程Borglet运行在每个机器上的。所有的组件都是用C++写的
Borgmaster
每个cell的Borymaster包含了两个进程,主进程和调度器,主进程处理来自客户端的RPC请求,要么是改变状态(e.g., 创建job)或者是提供只读的访问(e.g., lookup job)。主进程还能管理所有的系统内对象(机器、任务、分配等)的状态。除此之外,主进程与Borylets攻心,并提供web UI作为Sigma的备份。
Borgmaster 在逻辑上是一个单一的进程,但是实际上它有五个副本。每个副本都维护了该单元(cell)的大部分状态的内存副本。但不仅仅存储在内存中,还记录在一个高可用的、基于Paxos协议的分布式存储中,这个存储系统位于副本的本地磁盘。每个单元(cell)都有一个单一的选举主节点,它既是Paxos领导者,又是状态变更器,负责处理所有改变单元状态的操作,例如提交作业或终止机器上的任务。当单元启动或当选举的主节点发生故障时,会使用Paxos协议选举一个主节点;它会获取一个Chubby锁,以便其他系统可以找到它。选举主节点并切换到新主节点通常需要大约10秒,但在大单元中可能需要长达一分钟,因为一些内存状态需要重建。当一个副本从故障中恢复时,它会动态地从其他最新的Paxos副本中重新同步其状态。
Borgmaster 在某个时间点的状态称为 checkpoint,采用定期快照以及保存更改日志在 Paxos 存储。Checkpoint 有多个用途,包括将 Borgmaster 的状态恢复到过去的任意点(例如,在接收触发 Borg 中的软件缺陷请求前调试);在极端情况下需要手动维护;为将来的查询构建持久的事件日志和离线模拟。
一个高保真度的Borgmaster模拟器称为Fauxmaster,可以用来读取检查点文件,并包含生产环境Borgmaster代码的完整副本。它接受RPC来进行状态机更改和执行操作,例如“调度所有挂起的任务”。我们使用它来调试故障,通过与之交互,就像与一个实时的Borgmaster交互一样,模拟的Borglets重现检查点文件中的真实交互。用户可以逐步观察过去实际发生的系统状态变化。Fauxmaster对于容量规划(“这种类型的新增作业能容纳多少?”)以及在更改单元配置前的健全性检查(“此更改会驱逐任何重要作业吗?”)也很有用
调度
What is the problem the paper tackles? Why is it important? How do they tackle it? Advantages/disadvantages? Open questions for future work? Broader implications?