边城

软件就是驱动世界,改造世界

欢迎来到边城客栈


Hadoop-Yarn-02-容量调度抢占原理和使用

前言

   用户在使用Yarn资源时,一般情况我们都会把队列配置为弹性队列,如果资源空闲时,单用户单应用可以将整个集群的资源全部占用,如果没有开启抢占的情况下,这时有一个B任务提交,B任务只能等待
  A任务执行完毕,才可以获取到资源运行。严重影响了SLA和用户体验。
 上述的场景中,如果当B任务提交后,B任务可以将A任务的一部分资源抢占过来,B任务也可以运行,这样B任务不用一直等待。这就是Yarn的抢占功能。下面描述一下Yarn 容量调度器中抢占的使用和原理。

Yarn资源抢占功能

   前文的Yarn容量调度中,已经提及到最小资源配置和最大资源配置,Yarn的容量调度要求 子队列的所有的资源之和要等于100%,例如 如果root队列有A,B,C队列,A(min: 20%,max 20%*3) B(min: 30%,max     30%*3),C(min: 50%,max(50%*1))。
   这是如果B队列提交一个任务消耗了集群的90%资源,过一会C队列有一个用户提交了一个任务(需要30%资源),但是整体资源不够,如果开启抢占,这时C队列会抢占B队列的资源,B队列归还C队列资源。

​ Yarn的抢占从队列角度讲可以划分为队列之间抢占和队列内部抢占

#### 队列之间抢占

队列相关的所有信息均由ResourceManager负责。 ResourceManager中一个称为PreemptionMonitor的组件负责在需要时执行抢占。

​ 举例抢占:

​ A队列提交了App1,App2任务,配置容量为30%,但是其已经使用集群资源50%,B队列提交了App3,使用集群资源的50%。C队列提交了App4,但是此时集群没有资源。App4只能等待。

如果抢占开启后,Yarn会做如下流程:

1、扫描队列,从超额使用的队列中的应用程序中筛选要抢占的container

2. 通知AppMaster,准备要kill相应的容器

​ AppMaster比起RM来说对于自己的Application更为熟悉,AppMaster会折中考虑要kill掉的容器,并且在kill容器之前要进行保存要kill容器的工作,以便Appication再次获得资源时候,重新继续之前被kill掉的容器的工作。

3. 等待容器被kill

​ 将等待kill的容器添加到被kill的队列中,经过15s后,RM将kill掉该容器,归还资源到正在等待资源的Application。

队列内部抢占

​ 队列内部的抢占分为任务高优先级和用户限制两种方式。

任务高优方式

​ 根据应用程序优先级在队列上启用抢占可确保较高优先级的应用程序可以在需要时从较低优先级的应用程序抢占资源。

  • 没有抢占的队列上资源消耗的示例 将A队列设置配置容量为70%
  1. 用户提交优先级为p1的应用程序app1。因为没有其他应用程序在队列上运行,所以app1使用队列上可用的大部分资源。
  2. app1开始运行后不久,用户提交了另一个与app1具有相同优先级的应用程序app2。在这种情况下,app2使用队列上剩余的资源。
  3. 用户提交具有更高优先级p3的第三应用程序app3。

如果未在队列上启用抢占,则优先级较低的应用程序app1和app2会消耗队列的所有可用容量,而优先级较高的应用程序app3则资源不足。表格表示如下:

Application Priority 消耗的资源 等待的资源
app1 p1 50 20
app2 p2 20 20
app3 p0 0 70

图例表示如下:

  • 开启队列内部抢占后,app3可以抢占到app1和app2的资源。

表格表示如下:

Application Priority 抢占的资源 消耗的资源 等待的资源
app1 p1 16 34 36
app2 p2 9 1 39
app3 p3 0 35 45

图例表示如下:

用户高优方式

​ 在基于用户限制的队列上启用抢占,可确保将资源提交到特定队列的所有用户之间均匀分配资源。

  • 没有开启用户限制抢占的情况下

    假设一个队列qA,他的root.qA.capacity配置为100%,minimum-user-limit-percent配置为33%。代表向队列提交应用程序的前三个用户每个都可以使用至少33%的队列资源。如果这三个用户已经按照指定使用了队列的资源,那么任何其他用户都必须等待资源分配后再提交应用程序。

表格表示如下:

Application 用户 消耗的资源 等待的资源
app1 user1 60 30
app2 user2 20 25
app3 user3 20 25

图例表示如下:

  • 开启用户限制,队列内部抢占情况下: 表格表示如下:

| Application | 用户 | 抢占的资源 | 消耗的资源 | 等待的资源 | | ———– | ——– | ———- | ———- | ———- | | app1 | user1 | 26 | 34 | 56 | | app2 | user2 | 0 | 33 | 12 | | app3 | user3 | 0 | 33 | 12 | ​ 图例表示如下:

抢占调度配置详解

  • 队列之间抢占 继续强调:我们在使用容量调度时候,可以配置某个队列的最小和最大【最小为额定配置容量,不允许别人抢占】,最大为用户可以使用到整个集群最大资源量。队列之间的抢占就在于队列是容量是弹性的。可以在最大和最小之间弹性伸缩。 修改yarn-site.xml配置文件

yarn.resourcemanager.scheduler.monitor.enable

通知ResourceManager启用下一个配置属性指定的监视策略。将其设置为true以启用抢占默认为false,不启用

yarn.resourcemanager.scheduler.monitor.policies

指定如果通过先前属性启用了监视策略,则ResourceManager在启动时应加载的监视策略的列表。要启用抢占,必须将其设置为 org.apache.hadoop.yarn.server.resourcemanager.monitor.capacity.ProportionalCapacityPreemptionPolicy

yarn.resourcemanager.monitor.capacity.preemption.monitoring_interval

队列扫描时间 两次连续抢占策略之间的时间(以毫秒为单位),默认为3000(3秒)。对抢占策略的一次调用将扫描队列,正在运行的应用程序,容器,并决定要抢占哪个容器. 如果想要快速抢占,可以把该值设置 的低一些.

yarn.resourcemanager.monitor.capacity.preemption.total_preemption_per_round

每次轮询扫描抢占的资源大小,默认为0.1,为整个集群的10%.

yarn.resourcemanager.monitor.capacity.preemption.max_ignored_over_capacity

当配置为值x> = 0时,RM将等到队列使用的资源等于configure_capacity *(1 + x),然后再开始从中抢占容器。RM仅在其超出其保证容量的10%时才开始抢占该队列,可以避免分配的容量急剧波动。默认为0.1

yarn.resourcemanager.monitor.capacity.preemption.natural_termination_factor

每次轮询回收资源的比率,举个例子,有10G需要回收,如果配置为0.2,这时第一次轮询回收2G(20%10G),第二次回收1.6G(8G20%),第三次回收1.28G(6.4*0.2) … 可以越来越回收的慢,当然你可以增大该值,快 速回收.

  • 队列内部抢占 修改yarn-site.xml配置 yarn.resourcemanager.monitor.capacity.preemption.intra-queue-preemption.enabled

指定是为队列启用还是禁用队列内抢占。默认为false

yarn.resourcemanager.monitor.capacity.preemption.intra-queue-preemption.preemption-order-policy

指定队列可以抢占资源的顺序。可以将此属性配置为以下值之一: userlimit-first根据配置的用户限制启动队列内抢占。默认值是userlimit-first。 priority-first是根据应用程序优先级启动队列内抢占。修改 capacity-scheduler.xml配置

yarn.scheduler.capacity..intra-queue-preemption.disable_preemption

可以将此配置设置为true以有选择地禁用提交给定队列的应用程序容器的队列内抢占。仅当通过将yarn.resourcemanager.scheduler.monitor.enable配置为true,将yarn.resourcemanager.scheduler.monitor.policies设置为ProportionalCapacityPreemptionPolicy和yarn.resourcemanager.monitor.capacity.preemption.intra-queue启用系统范围的抢占时,此属性才适用-preemption.enabled为true。如果未为队列设置此属性,则该属性值将从队列的父级继承。默认值为false。

使用案例

1、参数配置

yarn-site.xml

    <property>
      <name>yarn.resourcemanager.scheduler.class</name>
      <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler</value>
    </property>
    
   <property>
      <name>yarn.resourcemanager.scheduler.monitor.enable</name>
      <value>true</value>
    </property> 
   
    <property>
      <name>yarn.resourcemanager.monitor.capacity.preemption.max_ignored_over_capacity</name>
      <value>0.0</value>
    </property>

capacity-scheduler.xml

yarn.scheduler.capacity.maximum-am-resource-percent=0.5
yarn.scheduler.capacity.maximum-applications=10000
yarn.scheduler.capacity.node-locality-delay=-1
yarn.scheduler.capacity.root.accessible-node-labels=*
yarn.scheduler.capacity.root.acl_administer_queue=*
yarn.scheduler.capacity.root.capacity=100
yarn.scheduler.capacity.root.default.acl_administer_jobs=*
yarn.scheduler.capacity.root.default.acl_submit_applications=*
yarn.scheduler.capacity.root.default.capacity=80
yarn.scheduler.capacity.root.default.default-application-priority=10
yarn.scheduler.capacity.root.default.disable_preemption=false
yarn.scheduler.capacity.root.default.maximum-capacity=100
yarn.scheduler.capacity.root.default.minimum-user-limit-percent=100
yarn.scheduler.capacity.root.default.state=RUNNING
yarn.scheduler.capacity.root.default.user-limit-factor=1.25
yarn.scheduler.capacity.root.highqueue.acl_administer_jobs=*
yarn.scheduler.capacity.root.highqueue.acl_submit_applications=*
yarn.scheduler.capacity.root.highqueue.capacity=20
yarn.scheduler.capacity.root.highqueue.default-application-priority=50
yarn.scheduler.capacity.root.highqueue.disable_preemption=false
yarn.scheduler.capacity.root.highqueue.maximum-capacity=100
yarn.scheduler.capacity.root.highqueue.minimum-user-limit-percent=100
yarn.scheduler.capacity.root.highqueue.state=RUNNING
yarn.scheduler.capacity.root.highqueue.user-limit-factor=5
yarn.scheduler.capacity.root.queues=default,highqueue

2、队列示意图

根队列为root,有两个子队列,default队列和highqueue队列,队列之间支持资源强制回收

default队列,Capacity 为80%,最大可以借用20%的资源达到100%

highqueue队列,Capacity为20%,最大可以借用80%的资源达到100%

测试方案

采用提交spark-sql任务来测试,spark任务可以一直占据资源而不退出,可以很好的观察资源的借用和强制回收

提交大任务到default队列

  bin/spark-sql --queue default --num-executors 100 --executor-memory 1G --master yarn

default队列,借用了额外的20%资源。

提交大任务到highqueue队列

bin/spark-sql --queue highqueue --num-executors 100 --executor-memory 1G --master yarn

highqueue队列会逐步强制回收属于自己的20%的资源

观察highqueu资源强制回收 最终稳定状态,基本上default队列占据80%,highqueue队列占据了20%左右的资源

Client日志或者AM日志 打印container被强制回收

21/01/14 11:42:26 ERROR cluster.YarnScheduler: Lost executor 43 on ngf129a30-core-instance-2v1b2gik-2.novalocal: Container container_1610537228551_0023_01_000044 on host: ngf129a30-core-instance-2v1b2gik-2.novalocal was preempted.

Preemption的executor日志

21/01/14 11:43:19 ERROR executor.CoarseGrainedExecutorBackend: RECEIVED SIGNAL TERM

总结

查看相关资料可以得知,2.8.5版本比2.7.5多了以下功能,支持user级别的权重weight,支持队列的优先级,支持用户update任务的优先级,支持reserved system,以上功能在2.7.3均不支持.以上为Yarn容量调度抢占功能详解,希望可以对读者起到帮助作用.

参考

  • http://hadoop.apache.org
  • https://blog.cloudera.com/better-slas-via-resource-preemption-in-yarns-capacityscheduler/
  • https://docs.cloudera.com/HDPDocuments/HDP3/HDP-3.1.5/data-operating-system/content/intra_queue_preemption_based_on_user_limit.html

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦