YARN 资源调度那些事儿

时间:2022-06-13
本文章向大家介绍YARN 资源调度那些事儿,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

本篇文章简要介绍了YARN调度器,以及小米的探索与实践。

作者:小米运维

已获得原创公众号:小米运维授权,原文章地址:https://mp.weixin.qq.com/s?__biz=MzUxMDQxMDMyNg==&mid=2247483866&idx=1&sn=7eb0d8e3ef5f8928842e6925084ac6d3&chksm=f9022ae3ce75a3f5c6a2648835c686e93776c4bfe5cdc54865635c8ac757f8464f105818ab46&mpshare=1&scene=1&srcid=1009w3nIiRWdcNNlrg5DWWtV#rd

在小米的计算平台中,Yarn 服务充当了非常重要的角色,MapReduce,Hive、Spark,Spark-sql 等都需要运行在 Yarn 集群上。(本文提到的 YARN 针对 Hadoop2.x)

“我的作业为什么又失败了?”,

“凭什么他的作业拿的资源比我多?”,

“任务一直在 pending 啊,没法按时给老板交差!”

.....

作为用户你是否遇到过类似问题?作为管理员你是否收到过这些抱怨? 在生产环境中,成百上千甚至上万台机器的计算集群如何去调度资源,并让公司各个团队平稳高效的运行各种类型的作业呢?

本篇文章将浅析 YARN 调度器以及在小米的探索与实践。

什么是YARN?

Apache Hadoop YARN (Yet Another Resource Negotiator,另一种资源协调者)是一种新的 Hadoop 资源管理器,它是一个通用资源管理系统,可为上层应用提供统一的资源管理和调度,它的引入为集群在利用率、资源统一管理和数据共享等方面带来了巨大好处。也就是说 YARN 在 Hadoop 集群中充当资源管理和任务调度的框架。

YARN 基本结构:(图片来自 Apache Yarn 官网)

负责资源管理和调度的组件:全局的资源管理器 ResourceManager(RM)和每个应用程序的 ApplicationMaster(AM)。应用程序可以是单个作业,也可以是 DAG 作业。ResourceManager 和 NodeManager 组成数据计算框架。

ResourceManager 负责集群资源的统一管理和调度;

NodeManager 负责单节点资源管理和使用,处理来自 ResourceManager/ApplicationMaster 的命令;

ApplicationMaster 负责应用程序的管理;

Container 是对任务运行环境的抽象,描述任务运行资源(节点、内存、CPU), 启动命令以及环境。

调度器的选择

我们都希望自己提交的作业能够很快被调度并且拿到足够的资源保证 job 进行顺畅。对于共享型集群来说,保证每个作业可以被合理的调度并分配相应的资源,同时考虑成本问题,变得更加困难。但是通过不断的探索 Yarn 的调度策略与可配置方案也可以逐渐接近目标。

Yarn 提供了三种可用资源调度器 (直接从 MRv1 基础上修改而来的):

FIFO Scheduler ,Capacity Scheduler,Fair Scheduler。

FIFO Scheduler:从字面不难看出就是先进先出策略,所有的任务都放在一个队列中,只有执行完一个任务后,才会进行下一个。这种调度方式最简单,但真实场景中并不推荐,因为会有很多问题,比如如果有大任务独占资源,会导致其他任务一直处于 pending 状态等。

Capacity Scheduler:也就是所谓的容量调度,这种方案更适合多租户安全地共享大型集群,以便在分配的容量限制下及时分配资源。采用队列的概念,任务提交到队列,队列可以设置资源的占比,并且支持层级队列、访问控制、用户限制、预定等等配置。不过对于资源占用比需要不断的摸索与权衡。

如果选择 Cpapacity Scheduler,需要配置 ResourceManager 使用 CapacityScheduler,即 conf/yarn-site.xml 中设置属性:

Cpapacity Scheduler

<property>
  <name>yarn.resourcemanager.scheduler.class</name>
  <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler</value>
</property>

调度配置文件 etc/hadoop/capacity-scheduler.xml:

capacity-scheduler.xml

<property>
  <name>yarn.scheduler.capacity.root.queues</name>
  <value>a,b,c</value>
  <description>The queues at the this level (root is the root queue).  
  </description>
</property>
<property>
  <name>yarn.scheduler.capacity.root.a.queues</name>
  <value>a1,a2</value>
  <description>The queues at the this level (root is the root queue).  
  </description>
</property>
<property>
  <name>yarn.scheduler.capacity.root.b.queues</name>
  <value>b1,b2,b3</value>
  <description>The queues at the this level (root is the root queue).  
  </description>
</property>

Fair Scheduler:就是公平调度器,能够公平地共享大型集群中的资源,Fair 调度器会为所有运行的 job 动态的调整系统资源。当只有一个 job 在运行时,该应用程序最多可获取所有资源,再提交其他 job 时,资源将会被重新分配分配给目前的 job,这可以让大量 job 在合理的时间内完成,减少作业 pending 的情况。可见 Fair Schedule 比较适用于多用户共享的大集群。

如果选择 Fair Schedule,需要配置 ResourceManager 使用 Fair Scheduler,即 conf/yarn-site.xml 中设置属性:

Fair Scheduler

<property>
  <name>yarn.resourcemanager.scheduler.class</name>
  <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value>
</property>

调度配置文件 etc/hadoop/fair-scheduler.xml:

fair-scheduler.xml

<?xml version="1.0"?>
<allocations>
  <queue name="sample_queue">
    <minResources>10000 mb,0vcores</minResources>
    <maxResources>90000 mb,0vcores</maxResources>
    <maxRunningApps>50</maxRunningApps>
    <maxAMShare>0.1</maxAMShare>
    <weight>2.0</weight>
    <schedulingPolicy>fair</schedulingPolicy>
    <queue name="sample_sub_queue">
      <aclSubmitApps>charlie</aclSubmitApps>
      <minResources>5000 mb,0vcores</minResources>
    </queue>
    <queue name="sample_reservable_queue">
      <reservation></reservation>
    </queue>
  </queue>
  <queueMaxAMShareDefault>0.5</queueMaxAMShareDefault>
  <queueMaxResourcesDefault>40000 mb,0vcores</queueMaxResourcesDefault>
  <!-- Queue 'secondary_group_queue' is a parent queue and may have
       user queues under it -->
  <queue name="secondary_group_queue" type="parent">
  <weight>3.0</weight>
  <maxChildResources>4096 mb,4vcores</maxChildResources>
  </queue>
  <user name="sample_user">
    <maxRunningApps>30</maxRunningApps>
  </user>
  <userMaxAppsDefault>5</userMaxAppsDefault>
  <queuePlacementPolicy>
    <rule name="specified" />
    <rule name="primaryGroup" create="false" />
    <rule name="nestedUserQueue">
        <rule name="secondaryGroupExistingQueue" create="false" />
    </rule>
    <rule name="default" queue="sample_queue"/>
  </queuePlacementPolicy>
</allocations>

对比 Fari Scheduler 与 Capacity Scheduler:

随着 Hadoop 版本逐渐演化,Fair Scheduler 和 Capacity Scheduler 的功能越来越完善,因此两个调度器的功能也逐渐趋近,由于 Fair Scheduler 支持多种调度策略,因此可以认为 Fair Scheduler 具备了 Capacity Scheduler 的所有功能。

Capacity Scheduler 与 Fair Scheduler 比较表

Fair Scheduler(公平调度器)

实践与探索

通过分析常见的几种调度器,选用 Fair Schedule 调度器更适合共享型大集群,那么怎样的配置方案更适合多团队多用户呢?资源该按照什么比例分配给队列?用户的不同作业类型该如何区分?每个用户都希望自己可以享用更大的资源,又该如何保证成本问题?...... 实际情况下遇到的问题不计其数,不同的集群规模和应用场景也有不同阶段的问题,都是需要经过探索与实践去逐一攻破。

Fair Scheduler 支持的自定义配置项

minResource:最小资源保证

maxResource:最多可以使用的资源

maxRunningApps:最多同时运行作业数量

minSharePreemptionTimeout:最小共享量抢占时间

schedulingMode/schedulingPolicy:队列采用的调度模式

aclSubmitApps:可在队列中提交作业的用户列表

aclAdministerApps:队列的管理员列表

userMaxJobsDefault:用户的 maxRunningJobs 属性默认值

defaultMinSharePreemptionTimeout:队列 minSharePreemptionTimeout 属性默认值

defaultPoolSchedulingMode:队列 schedulerMode 属性默认值

fairSharePreemptionTimeout:公平共享量抢占时间

fairSharePreemptionThreshold:队列的公平份额抢占阈值,默认值是 0.5f

allowPreemptionFrom:确定是否允许调度程序抢占队列中的资源,默认为 true

(另外通过配置 yarn-site.xml 的 yarn.scheduler.fair.preemption 可以控制集群是否开启抢占功能)

抢占:当某个队列中有剩余资源,调度器会将这些资源共享给其他队列,而当该队列中有新的应用程序提交时,调度器会为它回收资源。那些超额使用的行为即为超发。

划分队列组织结构

合理的队列组织方案也十分重要,如下图就是小米的队列组织模型:

一级队列:root 队列下面分为三大队列

离线分析 MR/Spark 作业队列:默认开启抢占,大量离线作业比较耗费资源,但是作业等级不算高,因此为了提高资源的利用率,可以允许在集群资源空闲的时候尽可能的超发资源,当然也意味着超发的资源会被回收;

在线计算流式作业队列:针对于作业等级较高的服务,为了保证资源需要设置不支持抢占,当然也需要设置最大超发限制,避免出现集群大作业独占集群资源;

资源池 reserved 队列:预留资源来保证新队列增加,或者其他队列的资源增配相当于资源池的概念,当然也可用于作业超发使用。

二级 / 三级 / 四级队列:

二级队列可对应公司组织架构下的各个部门,三级队列可以对应到部门下的各个 team,每个 team 当然也有会不同的提交作业类型分组这就是四级队列。

资源与成本优化

资源与成本永远是最难平衡的问题,那么针对于共享集群该如何去平衡?

通过我们逐渐探索与实践,采用了这样的方案:

业务队列资源配额:若干队列仅靠管理员的人工评估无法完成,既然队列是归属团队的,我们提供一套系统,开放部分队列配置项让用户申请修改,可以按照实际需求申请计算资源;管理员重心则放在保证集群整体健康上,同时让计算资源不再成为各业务部门的发展瓶颈。

计算资源成本优化:既然开放了资源申请,当然也需要让用户有节约资源的意识,减少由于申请不合理或者作业本身的问题导致资源浪费。比如根据用户的队列资源情况生成每月或者每周的虚拟账单 (按照申请的 cpu 和内存进行费用计算),虚拟账单主要用于帮助业务评估投入产出,以及队列的资源调整;针对队列还可以做资源和作业的监控,让用户清楚的知道自己哪些作业需要优化,队列需要调整。

总结

可能资源调度并没有最优解,需要不断探索实践去寻找适合目前现状的方案;在发展的不同阶段遇到不同的问题,通过解决问题逐渐去优化和完善。

参考文献

Apache Yarn 官网:

https://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/YARN.html

《Hadoop 技术内幕: 深入解析 YARN 架构设计与实现原理》