1. 资源调度与隔离
在YARN中,资源管理由ResourceManager和NodeManager共同完成,其中,ResourceManager中的调度器负责资源的分配,而NodeManager则负责资源的供给和隔离。
资源调度:ResourceManager将某个NodeManager上资源分配给任务;
资源隔离:NodeManager需按照要求为任务提供相应的资源,甚至保证这些资源应具有独占性,为任务运行提供基础的保证;
Hadoop YARN同时支持内存和CPU两种资源的调度,先品味一下内存和CPU这两种资源的特点,这是两种性质不同的资源。内存资源的多少会会决定任务的生死,如果内存不够,任务可能会运行失败;相比之下,CPU资源则不同,它只会决定任务运行的快慢,不会对生死产生影响。
1.1 Memory 资源
YARN允许用户配置每个节点上可用的物理内存资源,注意,这里是“可用的”,因为一个节点上的内存会被若干个服务共享,比如一部分给YARN,一部分给HDFS,一部分给HBase等,YARN配置的只是自己可以使用的,配置参数如下:
参数一:yarn.nodemanager.resource.memory-mb
该节点上YARN可使用的物理内存总量,默认是8192(MB);
如果设置为-1,并且yarn.nodemanager.resource.detect-hardware-capabilities 为true时,将会自动计算操作系统内存进行设置。
参数二:yarn.nodemanager.vmem-pmem-ratio
任务每使用1MB物理内存,最多可使用虚拟内存量,默认是2.1
参数三:yarn.nodemanager.pmem-check-enabled
是否启动一个线程检查每个任务正使用的物理内存量,如果任务超出分配值,则直接将其杀掉,默认是true。
参数四:yarn.nodemanager.vmem-check-enabled
是否启动一个线程检查每个任务正使用的虚拟内存量,如果任务超出分配值,则直接将其杀掉,默认是true。
参数五:yarn.scheduler.minimum-allocation-mb
单个任务可申请的最少物理内存量,默认是1024(MB),如果一个任务申请的物理内存量少于该值,则该对应的值改为这个数。
参数六:yarn.scheduler.maximum-allocation-mb
单个任务可申请的最多物理内存量,默认是8192(MB)。
默认情况下,YARN采用了线程监控的方法判断任务是否超量使用内存,一旦发现超量,则直接将其杀死。由于Cgroups对内存的控制缺乏灵活性(即任务任何时刻不能超过内存上限,如果超过,则直接将其杀死或者报OOM),而Java进程在创建瞬间内存将翻倍,之后骤降到正常值,这种情况下,采用线程监控的方式更加灵活(当发现进程树内存瞬间翻倍超过设定值时,可认为是正常现象,不会将任务杀死),因此YARN未提供Cgroups内存隔离机制。
1.2 CPU 资源
在YARN中,CPU资源的组织方式仍在探索中,当前只是非常粗粒度的实现方式。CPU被划分成虚拟CPU(CPU virtua* Core),此处的虚拟CPU是YARN自己引入的概念,初衷是,考虑到不同节点的CPU性能可能不同,每个CPU具有的计算能力也是不一样的,比如某个物理CPU的计算能力可能是另外一个物理CPU的2倍,此时可以通过为第一个物理CPU多配置几个虚拟CPU弥补这种差异。用户提交作业时,可以指定每个任务需要的虚拟CPU个数。
在YARN中,CPU相关配置参数如下:
参数一:yarn.nodemanager.resource.cpu-vcores
该节点上YARN可使用的虚拟CPU个数,默认是8,注意,目前推荐将该值设值为与物理CPU核数数目相同。如果你的节点CPU核数不够8个,则需要调减小这个值。
如果设置为-1,并且yarn.nodemanager.resource.detect-hardware-capabilities为true时,将会自动计算操作系统CPU 核数进行设置。
参数二:yarn.scheduler.minimum-allocation-vcores
单个任务可申请的最小虚拟CPU个数,默认是1,如果一个任务申请的CPU个数少于该数,则该对应的值改为这个数。
参数三:yarn.scheduler.maximum-allocation-vcores
单个任务可申请的最多虚拟CPU个数,默认是4。
由于CPU资源的独特性,目前这种CPU分配方式仍然是粗粒度的。
2. 资源调度器
2.1 概述
在YARN中,负责给应用分配资源的就是Scheduler。其实调度本身就是一个难题,很难找到一个完美的策略可以解决所有的应用场景。为此,YARN提供了多种调度器和可配置的策略供选择。
在YARN中有三种调度器可以选择:FIFO Scheduler(先进先出调度器) ,Capacity Scheduler(容量调度器),Fair Scheduler(公平调度器)。
默认情况下,Apache版本YARN使用的是Capacity调度器。如果需要使用其他的调度器,可以在yarn-site.xml中的yarn.resourcemanager.scheduler.class进行配置,具体的配置方式如下:
在YARN WebUI界面:http://node2.itcast.cn:8088/cluster
在YARN中,有层级队列组织方法,它们构成一个树结构,且根队列叫做root。所有的应用都运行在叶子队列中(即树结构中的非叶子节点只是逻辑概念,本身并不能运行应用)。对于任何一个应用,都可以显式地指定它属于的队列,也可以不指定从而使用username或者default队列。下图就是一个队列的结构:
2.2 FIFO Scheduler(先进先出调度器)
FifoScheduler是MRv1中JobTracker原有的调度器实现,此调度器在YARN中保留了下来。FifoScheduler是一个先进先出的思想,即先来的Application先运行。调度工作不考虑优先级和范围,适用于负载较低的小规模集群。当使用大型共享集群时,它的效率较低且会导致一些问题。
FifoScheduler拥有一个控制全局的队列queue,默认queue名称为default,该调度器会获取当前集群上所有的资源信息作用于这个全局的queue。
FifoScheduler将所有的Application按照提交时候的顺序来执行,只有当上一个Job执行完成之后后面的Job才会按照队列的顺序依次被执行。虽然单一的FIFO调度实现简单,但是对于很多实际的场景并不能满足要求,催发了Capacity调度器和Fair调度器的出现。
2.3 Capacity Scheduler(容量调度器)
Capacity 调度器允许多个组织共享整个集群,每个组织可以获得集群的一部分计算能力。通过为每个组织分配专门的队列,然后再为每个队列分配一定的集群资源,这样整个集群就可以通过设置多个队列的方式给多个组织提供服务了。
Capacity调度器可以理解成一个个的资源队列,这个资源队列是用户自己去分配的。队列内部又可以垂直划分,这样一个组织内部的多个成员就可以共享这个队列资源了,在一个队列内部,资源的调度是采用的是先进先出(FIFO)策略。
2.3.1 什么是Capacity Scheduler
Capacity Scheduler调度器以队列为单位划分资源。简单通俗点来说,就是一个个队列有独立的资源,队列的结构和资源是可以进行配置的,如下图:
default队列占30%资源,analyst和dev分别占40%和30%资源;类似的,analyst和dev各有两个子队列,子队列在父队列的基础上再分配资源。
队列里的应用以FIFO方式调度,每个队列可设定一定比例的资源最低保证和使用上限;
每个用户也可以设定一定的资源使用上限以防止资源滥用;
而当一个队列的资源有剩余时,可暂时将剩余资源共享给其他队列。
2.3.2 调度器特性
CapacityScheduler是一个可插拔调度程序,它被设计为以队列为单位划分资源、易于操作的方式在多租户模式下安全的共享大型集群,同时能保证每个组所需资源的保证,当容量不够用时还可以使用其他组多余的容量。这种方式最大程度地提高集群的吞吐量和利用率,以便在分配的容量约束下及时为其应用程序分配资源。CapacityScheduler的特性如下:
层次化的队列设计(Hierarchica* Queues)
层次化的队列设计保证了子队列可以使用父队列设置的全部资源。这样通过层次化的管理,更容易合理分配和限制资源的使用。
容量保证(Capacity Guarantees)
队列上都会设置一个资源的占比,可以保证每个队列都不会占用整个集群的资源。
安全(Security )
每个队列又严格的访问控制。用户只能向自己的队列里面提交任务,而且不能修改或者访问其他队列的任务。
弹性分配(Elasticity )
空闲的资源可以被分配给任何队列。当多个队列出现争用的时候,则会按照比例进行平衡。
多租户租用(Multi-tenancy)
通过队列的容量限制,多个用户就可以共享同一个集群,同事保证每个队列分配到自己的容量,提高利用率。
操作性(Operability)
Yarn支持动态修改调整容量、权限等的分配,可以在运行时直接修改;
提供管理员界面,显示当前的队列状况;管理员可以在运行时,添加一个队列;但是不能删除一个队列;
管理员可以在运行时暂停某个队列,可以保证当前的队列在执行过程中,集群不会接收其他的任务。如果一个队列被设置成了stopped,那么就不能向它或者子队列上提交任务了。
基于资源的调度(Resource-based Scheduling)
协调不同资源需求的应用程序,比如内存、CPU、磁盘等等。
基于用户/组的队列隐射(Queue Mapping based o> User or Group)
允许用户基于用户或者组去映射一个作业到特定队列。
2.3.3 调度器配置
CapacityScheduler的配置项包括两部分,其中一部分在yarn-site.xml中,主要用于配置YARN集群使用的调度器;另一部分在capacity-scheduler.xml配置文件中,主要用于配置各个队列的资源量、权重等信息。
2.3.3.1 一、开启调度器
在ResourceManager中配置使用的调度器,修改HADOOP_CONF/yarn-site.xml,设置属性:
yarn.resourcemanager.scheduler.class org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler
2.3.3.2 二、配置队列
调度器的核心就是队列的分配和使用,修改HADOOP_CONF/capacity-scheduler.xml可以配置队列。Capacity调度器默认有一个预定义的队列:root,所有的队列都是它的子队列。队列的分配支持层次化的配置,使用.来进行分割,比如:
案例:root下面有三个子队列
2.3.3.3 三、队列属性
队列的资源容量占比(百分比):
系统繁忙时,每个队列都应该得到设置的量的资源;当系统空闲时,该队列的资源则可以被其他的队列使用。同一层的所有队列加起来必须是100%。
队列资源的使用上限
系统空闲时,队列可以使用其他的空闲资源,因此最多使用的资源量则是该参数控制。默认是-1,即禁用。
每个任务占用的最少资源
比如,设置成25%。那么如果有两个用户提交任务,那么每个任务资源不超过50%。如果3个用户提交任务,那么每个任务资源不超过33%。如果4个用户提交任务,那么每个任务资源不超过25%。如果5个用户提交任务,那么第五个用户需要等待才能提交。默认是100,即不去做限制。
每个用户最多使用的队列资源占比
如果设置为50,那么每个用户使用的资源最多就是50%。
2.3.3.4 四、运行和提交应用限制
设置系统中可以同时运行和等待的应用数量,默认是10000
设置有多少资源可以用来运行app master,即控制当前激活状态的应用,默认是10%。
2.3.3.5 五、队列管理
队列的状态,可以使RUNNING或者STOPPED
如果队列是STOPPED状态,那么新应用不会提交到该队列或者子队列。同样,如果root被设置成STOPPED,那么整个集群都不能提交任务了。现有的应用可以等待完成,因此队列可以优雅的退出关闭。
访问控制列表ACL:控制谁可以向该队列提交任务
限定哪些Linux用户/用户组可向给定队列中提交应用程序。如果一个用户可以向该队列提交,那么也可以提交任务到它的子队列。配置该属性时,用户之间或用户组之间用“,”分割,用户和用户组之间用空格分割,比如“user1, user2 group1,group2”。
设置队列的管理员的ACL控制
为队列指定一个管理员,该管理员可控制该队列的所有应用程序,比如杀死任意一个应用程序等。同样,该属性具有继承性,如果一个用户可以向某个队列中提交应用程序,则它可以向它的所有子队列中提交应用程序。
2.3.3.6 六、基于用户/组的队列映射
映射单个用户或者用户组到一个队列
语法:[u or g]:[name]:[queue_name][,next_mapping],列表可以多个,之间以逗号分隔。%user放在[name]部分,表示已经提交应用的用户。如果队列名称和用户一样,那可以使用%user表示队列。如果队列名称和用户主组一样,可以使用%primary_group表示队列。 u:%user:%user 表示-已经提交应用的用户,映射到和用户名称一样的队列上。 u:user2:%primary_group表示user2提交的应用映射到user2主组名称一样的队列上。如果用户组并不多,队列也不多,建议还是使用简单的语法,而不要使用带%的。
定义针对特定用户的队列是否可以被覆盖,默认值为false。
2.3.3.7 七、其他属性
资源计算方法
默认是org.apache.hadoop.yarn.util.resource.DefaultResourseCalculator,它只会计算内存。DominantResourceCalculator则会计算内存和CPU。
调度器尝试进行调度的次数
节点局部性延迟,在容器企图调度本地机栈容器后(失败),还可以错过错过多少次的调度次数。一般都是跟集群的节点数量有关。默认40(一个机架上的节点数)一旦设置完这些队列属性,就可以在web ui上看到了。
2.3.3.8 八、修改队列配置
如果想要修改队列或者调度器的配置,可以修改HADOOP_CONF_DIR/capacity-scheduler.xml,修改完成后,需要执行下面的命令:
HADOOP_YARN_HOME/bin/YARN rmadmi> -refreshQueues
注意事项:
队列不能被删除,只能新增;
更新队列的配置需要是有效的值;
同层级的队列容量限制相加需要等于100%;
在MapReduce中,可以通过mapreduce.job.queuename属性指定要用的队列。如果队列不存在,在提交任务时就会收到错误。如果没有定义任何队列,所有的应用将会放在一个default队列中。
2.3.4 案例:Capacity调度器配置
假设有如下层次的队列:
2.3.4.1 step1、Capacity Scheduler 配置
上图中队列的一个调度器配置文件HADOOP_CONF/capacity-scheduler.xml:
yarn.scheduler.capacity.root.queues prod,dev yarn.scheduler.capacity.root.dev.queues eng,science yarn.scheduler.capacity.root.prod.capacity 40 yarn.scheduler.capacity.root.dev.capacity 60 yarn.scheduler.capacity.root.dev.maximum-capacity 75 yarn.scheduler.capacity.root.dev.eng.capacity 50 yarn.scheduler.capacity.root.dev.science.capacity 50
相关属性说明如下所示:
dev队列又被分成了eng和science两个相同容量的子队列;
dev的maximum-capacity属性被设置成了75%,所以即使prod队列完全空闲dev也不会占用全部集群资源,也就是说,prod队列仍有25%的可用资源用来应急;
eng和science两个队列没有设置maximum-capacity属性,也就是说eng或science队列中的job可能会用到整个dev队列的所有资源(最多为集群的75%);
而类似的,prod由于没有设置maximum-capacity属性,它有可能会占用集群全部资源。
对于Capacity调度器,队列名必须是队列树中的最后一部分,如果使用队列树则不会被识别。比如,在上面配置中,使用prod和eng作为队列名是可以的,但是如果用root.dev.eng或者dev.eng是无效的。
2.3.4.2 step2、测试运行
上述配置队列形式如下所示:
启动ResouceManager,打开8088页面:
运行MapReduce中WordCount程序,指定运行队列prod
HADOOP_HOME=/export/server/hadoop${HADOOP_HOME}/bin/YARN jar ${HADOOP_HOME}/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.4.jar wordcount -Dmapreduce.job.queuename=prod datas/input.data /datas/output
查看8088界面如下所示:
不指定运行队列,默认运行在default队列,如果找不到default队列将会报如下错误。
HADOOP_HOME=/export/server/hadoop${HADOOP_HOME}/bin/YARN jar ${HADOOP_HOME}/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.4.jar wordcount datas/input.data /datas/output2
查看8088界面如下所示:
2.3.5 Capacity官方默认配置
在HADOOP 安装目录中,官方自带默认配置HADOOP_CONF/capacity-scheduler.xml:
yarn.scheduler.capacity.maximum-applications 10000 Maximum number of applications that ca> be pending and running. yarn.scheduler.capacity.maximum-am-resource-percent 0.1 Maximum percent of resources i> the cluster which ca> be used to run applicatio> masters i.e. controls number of concurrent running applications. yarn.scheduler.capacity.resource-calculator org.apache.hadoop.yarn.util.resource.DefaultResourceCalculator The ResourceCalculator implementatio> to be used to compare Resources i> the scheduler. The default i.e. DefaultResourceCalculator only uses Memory while DominantResourceCalculator uses dominant-resource to compare multi-dimensiona* resources such as Memory, CPU etc. yarn.scheduler.capacity.root.queues default The queues at the this leve* (root is the root queue). yarn.scheduler.capacity.root.default.capacity 100 Default queue target capacity. yarn.scheduler.capacity.root.default.user-limit-factor 1 Default queue user limit a percentage from 0.0 to 1.0. yarn.scheduler.capacity.root.default.maximum-capacity 100 The maximum capacity of the default queue. yarn.scheduler.capacity.root.default.state RUNNING The state of the default queue. State ca> be one of RUNNING or STOPPED. yarn.scheduler.capacity.root.default.acl_submit_applications The AC* of who ca> submit jobs to the default queue. yarn.scheduler.capacity.root.default.acl_administer_queue The AC* of who ca> administer jobs o> the default queue. yarn.scheduler.capacity.node-locality-delay 40 Number of missed scheduling opportunities after which the CapacityScheduler attempts to schedule rack-loca* containers. Typically this should be set to number of nodes i> the cluster, By default is setting approximately number of nodes i> one rack which is 40. yarn.scheduler.capacity.queue-mappings A list of mappings that wil* be used to assig> jobs to queues The syntax for this list is [u|g]:[name]:[queue_name][,next mapping] Typically this list wil* be used to map users to queues, for example, u:%user:%user maps al* users to queues with the same name as the user. yarn.scheduler.capacity.queue-mappings-override.enable false If a queue mapping is present, wil* it override the value specified by the user? This ca> be used by administrators to place jobs i> queues that are different tha> the one specified by the user. The default is false.
2.4 Fair Scheduler(公平调度器)
FairScheduler是Hadoop可插拔的调度程序,提供了YARN应用程序公平地共享大型集群中资源的另一种方式。FairScheduler是一个将资源公平的分配给应用程序的方法,使所有应用在平均情况下随着时间的流逝可以获得相等的资源份额。
2.4.1 什么是Fair Scheduler
Fair Scheduler 设计目标是为所有的应用分配公平的资源(对公平的定义通过参数来设置)。公平调度是一个分配资源给所有application的方法,平均来看,是随着时间的进展平等分享资源的。
公平调度可以在多个队列间工作。如上图所示,假设有两个用户A和B,分别拥有一个队列:
当A启动一个job而B没有任务时,A会获得全部集群资源;
当B启动一个job后,A的job会继续运行,不过一会儿之后两个任务会各自获得一半的集群资源。
如果此时B再启动第二个job并且其它job还在运行,则它将会和B的第一个job共享B这个队列的资源,也就是B的两个job会各自使用四分之一的集群资源,而A的job仍然用于集群一半的资源,结果就是资源最终在两个用户之间平等的共享。
FairScheduler将应用组织到队列中,并在这些队列之间公平地共享资源。默认情况下,所有用户共享一个名为default的队列。如果应用明确在容器资源请求中指定了队列,则该请求将提交到指定的队列。可以通过配置,根据请求中包含的用户名或组分配队列。在每个队列中,使用调度策略在运行的应用程序之间共享资源。默认设置是基于内存的公平共享,但是也可以配置具有优势资源公平性的FIFO和多资源。
分层队列:队列可以按层次结构排列以划分资源,并可以配置权重以按特定比例共享集群。
基于用户或组的队列映射:可以根据提交任务的用户名或组来分配队列。如果任务指定了一个队列,则在该队列中提交任务。
资源抢占:根据应用的配置,抢占和分配资源可以是友好的或是强制的。默认不启用资源抢占。
保证最小配额:可以设置队列最小资源,允许将保证的最小份额分配给队列,保证用户可以启动任务。当队列不能满足最小资源时,可以从其它队列抢占。当队列资源使用不完时,可以给其它队列使用。这对于确保某些用户、组或生产应用始终获得足够的资源。
允许资源共享:即当一个应用运行时,如果其它队列没有任务执行,则可以使用其它队列,当其它队列有应用需要资源时再将占用的队列释放出来。所有的应用都从资源队列中分配资源。
默认不限制每个队列和用户可以同时运行应用的数量。可以配置来限制队列和用户并行执行的应用数量。限制并行执行应用数量不会导致任务提交失败,超出的应用会在队列中等待。
2.4.2 启用 Fair Scheduler
要使用Fair Scheduler,首先在yarn-site.xml配置文件进配置:
yarn.resourcemanager.scheduler.class org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler
2.4.3 资源配置文件
Fair Scheduler的配置文件,位于类路径下,默认文件名fair-scheduler.xml,通过属性指定:
yarn.scheduler.fair.allocation.file fair-scheduler.xml
若没有fair-scheduler.xml这个配置文件,Fair Scheduler采用的分配策略:调度器会在用户提交第一个应用时为其自动创建一个队列,队列的名字就是用户名,所有的应用都会被分配到相应的用户队列中。
2.4.4 Fair Scheduler 配置
定制Fair Scheduler涉及到2个文件。首先,scheduler有关的选项可以在yarn-site.xml中配置。此外,多数情况,用户需要创建一个“allocation”文件来列举存在的queues和它们相应的weights和capacities。这个“allocation”文件每隔10秒钟加载一次,更新的配置可以更快的生效。
2.4.4.1 调度器级别的参数
在HADOOP_CONF/yarn-site.xml中,主要用于配置调度器级别的参数。
属性一:是否将与allocation有关的username作为默认的queue name,当queue name没有指定的时候。如果设置成false(且没有指定queue name) 或者没有设定,所有的jobs将共享“default” queue。
属性二:是否使用“preemption”(优先权,抢占),默认为fasle
属性三:启动抢占后的资源利用率阈值。利用率是计算所有资源中容量使用的最大比率。 默认值是0.8f。
属性四:在一个队列内部分配资源时,默认情况下,采用公平轮询的方法将资源分配各个应用程序,而该参数则提供了另外一种资源分配方式:按照应用程序资源需求数目分配资源,即需求资源数量越多,分配的资源越多。默认情况下,该参数值为false。
属性五:是在允许在一个心跳中,发送多个container分配信息
属性六:如果assignmultuple为true,在一次心跳中,最多发送分配container的个数。默认为-1,无限制。
属性七:一个float值,在0~1之间,表示在等待获取满足node-local条件的containers时,最多放弃不满足node-local的container的机会次数,放弃的nodes个数为集群的大小的比例。默认值为-1.0表示不放弃任何调度的机会。
属性八:当应用程序请求某个机架上资源时,它可以接受的可跳过的最大资源调度机会。
属性九:是否根据application的大小(job的个数)作为权重。默认为false,如果为true,那么复杂的application将获取更多的资源。
属性十:如果设置为true,application提交时可以创建新的队列,要么是application指定了队列,或者是按照user-as-default-queue放置到相应队列。如果设置为false,任何时间一个app要放置到一个未在分配文件中指定的队列,都将被放置到“default”队列。默认是true。如果一个队列放置策略已经在分配文件中指定,本属性将会被忽略。
属性十一:默认值500ms,锁住调度器重新进行计算作业所需资源的间隔
2.4.4.2 分配文件队列的参数
可以在分配(allocation)文件中配置每一个队列,并且可以像Capacity Scheduler一样分层次配置队列,分配文件每10秒重载一次,因此允许在运行时进行修改。
简单配置案例
队列的层次
通过嵌套元素实现的。所有的队列都是root队列的孩子,即使没有配到元素里。在这个配置中,把dev队列有分成了eng和science两个队列。
Fair Scheduler中的队列有一个权重属性(权重就是对公平的定义),并把这个属性作为公平调度的依据。在每个资源池的配置项中,有个weight属性(默认为1),标记了资源池的权重,当资源池中有任务等待,并且集群中有空闲资源时候,每个资源池可以根据权重获得不同比例的集群空闲资源。
例子中,当调度器分配集群40:60资源给prod和dev时便视作公平,eng和science队列没有定义权重,则会被平均分配。
权重并不是百分比,把上面的40和60分别替换成2和3,效果也是一样的。注意,对于在没有配置文件时,按用户自动创建的队列,它们仍有权重并且权重值为1。
比如,资源池businessA和businessB的权重分别为2和1,这两个资源池中的资源都已经跑满了,并且还有任务在排队,此时集群中有30个Container的空闲资源,那么,businessA将会额外获得20个Container的资源,businessB会额外获得10个Container的资源。
队列的默认调度策略(整体)
通过顶级元素进行配置,如果没有配置,默认采用公平调度。每个队列内部仍可以有不同的调度策略。
针对Apache Hadoop来说,Fair Scheduler默认的调度策略(scheduling policy)是基于内存
CDH版本的YARN默认采用的调度策略是Fair Scheduler的DRF策略,即基于vcore和内存的策略,而不是只基于内存的调度策略。
每个队列的调度策略
尽管是Fair Scheduler,其仍支持在队列级别进行FIFO Schedule。每个队列的调度策略可以被其内部的 元素覆盖。
例子中,prod队列就被指定采用FIFO进行调度,所以,对于提交到prod队列的任务就可以按照FIFO规则顺序的执行了。需要注意,prod和dev之间的调度仍然是公平调度,同样eng和science也是公平调度。
队列的设置
Fair Scheduler采用了一套基于规则的系统来确定应用应该放到哪个队列。
例子中, 元素定义了一个规则列表,其中的每个规则会被逐个尝试直到匹配成功。
所有Rule接受create参数,用于表明该规则是否能够创建新队列。create默认值为true;如果设置为false并且Rule要放置app到一个allocations file没有配置的队列,那么继续应用下一个Rule;
上例第一个规则specified,则会把应用放到它指定的队列中,若这个应用没有指定队列名或队列名不存在,则说明不匹配这个规则,然后尝试下一个规则;
primaryGroup规则会尝试把应用放在以用户所在的Unix组名命名的队列中,如果没有这个队列,不创建队列转而尝试下一个规则;
当前面所有规则不满足时,则触发default规则,把应用放在dev.eng队列中;
可以不配置queuePlacementPolicy规则,调度器则默认采用如下规则:
简单的配置策略:使得所有的应用放入同一个队列(default),这样就可以让所有应用之间平等共享集群而不是在用户之间。
运行Apps数量限制及AM资源限制
对特定用户可以运行的apps的数量限制
设置任意用户(没有特定限制的用户)运行app的默认最大数量限制
设置队列的默认运行app数量限制,可以被任一队列的maxRunningApps元素覆盖
设置队列的默认AM共享资源限制;可以被任一队列的maxAMShare 元素覆盖
抢占(Preemption)
当一个job提交到一个繁忙集群中的空队列时,job并不会马上执行,而是阻塞直到正在运行的job释放系统资源。为了使提交job的执行时间更具预测性(可以设置等待的超时时间),Fair调度器支持抢占。
抢占就是允许调度器杀掉占用超过其应占份额资源队列的containers,这些containers资源便可被分配到应该享有这些份额资源的队列中。需要注意抢占会降低集群的执行效率,因为被终止的containers需要被重新执行。
通过设置一个全局的参数yarn.scheduler.fair.preemption=true来启用抢占功能。此外,还有两个参数用来控制抢占的过期时间(这两个参数默认没有配置,需要至少配置一个来允许抢占Container):
u 公平共享抢占的默认阈值
配置文件中的顶级元素为所有队列配置这个阈值;还可在元素内配置元素来为某个队列指定超阈值,默认是0.5。
u 公平共享抢占的默认超时时间
配置文件中的顶级元素为所有队列配置这个超时时间;还可在元素内配置元素来为某个队列指定超时时间。
如果队列在fair share preemptio> timeout指定时间内未获得平等的资源的一半(这个比例可以配置),调度器则会进行抢占containers。
u 默认最小共享抢占超时时间
配置文件中的顶级元素为所有队列配置这个超时时间;还可在元素内配置元素来为某个队列指定超时时间。
如果队列在minimum share preemptio> timeout指定的时间内未获得最小的资源保障,调度器就会抢占containers。
u 哪些情况下会发生抢占
最小资源抢占, 当前queue的资源无法保障时,而又有apps运行,需要向外抢占;
公平调度抢占, 当前queue的资源为达到max,而又有apps运行,需要向外抢占;
最小最大资源设置
资源设置格式:X 表示内存,单位为MB;Y 表示虚拟CPU Core核数;注意分隔符
最小资源保证:
u 在每个资源池中,允许配置该资源池的最小资源,这是为了防止把空闲资源共享出去还未回收的时候,该资源池有任务需要运行时候的资源保证。
u 比如,资源池businessA中配置了最小资源为(5vCPU,5GB),那么即使没有任务运行,Yarn也会为资源池businessA预留出最小资源,一旦有任务需要运行,而集群中已经没有其他空闲资源的时候,最小资源也可以保证资源池businessA中的任务可以先运行起来,随后再从集群中获取资源。
u 如果一个队列的最小共享未能得到满足,那么它将会在相同parent下其他队列之前获得可用资源。在单一资源公平策略下,一个队列如果它的内存使用量低于最小内存值则认为是未满足的。
u 在DRF策略下,如果一个队列的主资源是低于最小共享的话则认为是未满足的。如果有多个队列未满足的情况,资源分配给相关资源使用量和最小值之间比率最小的队列。
u 注意一点,有可能一个队列处于最小资源之下,但是在它提交application时不会立刻达到最小资源,因为已经在运行的job会使用这些资源。
最大资源限制
u 最多可以使用的资源量,fair scheduler会保证每个队列使用的资源量不会超过该队列的最多可使用资源量。
u 对于单一资源公平策略,vcores的值会被忽略。一个队列永远不会分配资源总量超过这个限制。
2.4.4.3 资源调度分配案例一
根据用户组分配资源池 ,假设在生产环境Yarn中,总共有四类用户需要使用集群,开发用户、测试用户、业务1用户、业务2用户。为了使其提交的任务不受影响,在Yarn上规划配置了五个资源池,分别为 dev_group(开发用户组资源池)、test_group(测试用户组资源池)、business1_group(业务1用户组资源池)、business2_group(业务2用户组资源池)、default(只分配了极少资源)。并根据实际业务情况,为每个资源池分配了相应的资源及优先级等。
相关配置如下:
30 drf 2000 mb, 1 vcores 10000 mb, 1 vcores 1 fifo 0.5 200000 mb, 33 vcores 300000 mb, 90 vcores 150 drf 2.5 dev_group hadoop,dev_group 70000 mb, 20 vcores 95000 mb, 25 vcores 60 fair 1 test_group hadoop,test_group 75000 mb, 15 vcores 100000 mb, 20 vcores 80 drf 1 business1_group hadoop,business1_group 75000 mb, 15 vcores 102400 mb, 20 vcores 80 drf 1 business2_group hadoop,business2_group
2.4.4.4 资源调度分配案例二
由于公司的hadoop集群的计算资源不是很充足,需要开启yarn资源队列的资源抢占。
只有一个队列的资源小于设置的 最小资源时,才有可能启动资源抢占。
只要所有的资源队列的最小资源之和小于等于集群的资源总量就都是合理的。如果最小资源之和大于集群的资源总量,同时又开启了资源抢占模式,那么资源调度就会不停的处于资源抢占的模式(这样的逻辑当然是不合理的了)。
所有队列的最大资源配置之和可以大于集群的资源总量是合理的
每个队列的最大资源配置 只要小于等于集群的资源总量 就也是合理的。
drf 300
第一:三个资源队列default,online,develop,bi四个队列;集群的共有24core,48G内存
该示例的最小资源之和是100%,最大资源之和可以大于资源总量,最大值可以根据实际中的情况来划分。例如在线上要优先保证线上资源,所以online队列的最小资源比例为70%,最大为100%;develop,和bi的最小资源都是可以为0的,这样才能保证在紧急情况下online可以抢占100%的资源。
第二:queuePlacementPolicy
2.4.5 演示Fair Scheduler
下面以三台机器为例,进行初步设置,运行程序MapReduce或Spark程序演示。
开启Fair Scheduler,相关参数配置,添加到HADOOP_CONF/yarn-site.xml中
yarn.resourcemanager.scheduler.class org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler yarn.scheduler.fair.allocation.file fair-scheduler.xml yarn.scheduler.fair.user-as-default-queue true yarn.scheduler.fair.allow-undeclared-pools false
资源队列配置,文件HADOOP_CONF/fair-scheduler.xml,内容如下:
drf 30 fair 55 15 fifo
启动ResouceManager,打开8088页面
运行MapReduce中WordCount程序,指定运行队列batch_mr
HADOOP_HOME=/export/server/hadoop${HADOOP_HOME}/bin/YARN jar ${HADOOP_HOME}/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.4.jar wordcount -Dmapreduce.job.queuename=batch_mr datas/input.data /datas/output
不指定运行队列,默认运行在default队列
HADOOP_HOME=/export/server/hadoop${HADOOP_HOME}/bin/YARN jar ${HADOOP_HOME}/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.4.jar wordcount datas/input.data /datas/output
2.4.6 Fair Scheduler 整体结构
公平调度器的运行流程就是RM去启动FairScheduler,SchedulerDispatcher两个服务,这两个服务各自负责update线程,handle线程。
update线程有两个任务:(1)更新各个队列的资源(Instantaneous Fair Share),(2)判断各个leaf队列是否需要抢占资源(如果开启抢占功能);
handle线程主要是处理一些事件响应,比如集群增加节点,队列增加APP,队列删除APP,APP更新container等。
3. YARN 核心参数
在实际项目生产环境,需要调整配置YARN相关核心参数的值,才能更好的管理资源、调度任务执行及使用资源。
3.1 RM 核心参数
针对ResourceManager主节点来说,需要设置调度器类型及请求线程数据量:
参数一:yarn.resourcemanager.scheduler.class
设置YARN使用调度器,默认值:(不同版本YARN,值不一样)
u Apache 版本 YARN ,默认值为容量调度器;
org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler
u CDH 版本 YARN ,默认值为公平调度器;
org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler
参数二:yarn.resourcemanager.scheduler.client.thread-count
ResourceManager处理调度器请求的线程数量,默认50,如果YARN运行任务Job比较多,可以将值调整大一下。
3.2 NM 核心参数
NodeManager运行在每台机器上,负责具体的资源管理
参数一:yarn.nodemanager.resource.detect-hardware-capabilities
是否让yarn自己检测硬件进行配置,默认false,如果设置为true,那么就会自动探测NodeManager所在主机的内存和CPU。
参数二:yarn.nodemanager.resource.count-logical-processors-as-cores
是否将虚拟核数当作CPU核数,默认false。
参数三:yarn.nodemanager.resource.pcores-vcores-multiplier
虚拟核数和物理核数乘数,例如:4核8线程,该参数就应设为2,默认1.0。
参数四:yarn.nodemanager.resource.memory-mb
NodeManager使用内存,默认8G
参数五:yarn.nodemanager.resource.system-reserved-memory-mb
此参数,仅仅当上述参数一为true和参数四为-1时,设置才生效;
默认值:20% of (system memory - 2HADOOP_HEAPSIZE)
参数六:yarn.nodemanager.resource.cpu-vcores
NodeManager使用CPU核数,默认8个。
参数七:其他参数,使用默认值即可
参数:yarn.nodemanager.pmem-check-enabled,是否开启物理内存检查限制container,默认打开;
参数:yarn.nodemanager.vmem-check-enabled,是否开启虚拟内存检查限制container,默认打开;
参数:yarn.nodemanager.vmem-pmem-ratio,虚拟内存物理内存比例,默认2.1;
3.3 Contanier 核心参数
当应用程序提交运行至YARN上时,无论是AppMaster运行,还是Task(MapReduce框架)或Executor(Spark框架)或TaskManager(Flink框架)运行,NodeManager将资源封装在Contanier容器中,以便管理和监控,核心配置参数如下所示:
参数一:yarn.scheduler.minimum-allocation-mb
单个任务可申请的最少物理内存量,默认是1024(MB),如果一个任务申请的物理内存量少于该值,则该对应的值改为这个数。
参数二:yarn.scheduler.maximum-allocation-mb
单个任务可申请的最多物理内存量,默认是8192(MB)。
参数三:yarn.scheduler.minimum-allocation-vcores
单个任务可申请的最小虚拟CPU个数,默认是1,如果一个任务申请的CPU个数少于该数,则该对应的值改为这个数。
参数四:yarn.scheduler.maximum-allocation-vcores
单个任务可申请的最多虚拟CPU个数,默认是4。