跳至主要內容

Yarn框架

Znyoung大数据Yarn

1 Apache Hadoop YARN

1.1 Yarn通俗介绍


Apache Hadoop YARN (Yet Another Resource Negotiator,另一种资源协调者)是一种新的 Hadoop 资源管理器,它是一个通用资源管理系统和调度平台,可为上层应用提供统一的资源管理和调度,它的引入为集群在利用率、资源统一管理和数据共享等方面带来了巨大好处。
可以把yarn理解为相当于一个分布式的操作系统平台,而mapreduce等运算程序则相当于运行于操作系统之上的应用程序,Yarn为这些程序提供运算所需的资源(内存、cpu)。

  • yarn并不清楚用户提交的程序的运行机制
  • yarn只提供运算资源的调度(用户程序向yarn申请资源,yarn就负责分配资源)
  • yarn中的主管角色叫ResourceManager
  • yarn中具体提供运算资源的角色叫NodeManager
  • yarn与运行的用户程序完全解耦,意味着yarn上可以运行各种类型的分布式运算程序,比如mapreduce、storm,spark,tez ……
  • spark、storm等运算框架都可以整合在yarn上运行,只要他们各自的框架中有符合yarn规范的资源请求机制即可
  • yarn成为一个通用的资源调度平台.企业中以前存在的各种运算集群都可以整合在一个物理集群上,提高资源利用率,方便数据共享

1.2 Yarn基本架构

|

YARN是一个资源管理、任务调度的框架,主要包含三大模块:ResourceManager(RM)、NodeManager(NM)、ApplicationMaster(AM)。
ResourceManager负责所有资源的监控、分配和管理;
ApplicationMaster负责每一个具体应用程序的调度和协调;
NodeManager负责每一个节点的维护。
对于所有的applications,RM拥有绝对的控制权和对资源的分配权。而每个AM则会和RM协商资源,同时和NodeManager通信来执行和监控task。

3. Yarn三大组件介绍

1.3.1 ResourceManager

  • ResourceManager负责整个集群的资源管理和分配,是一个全局的资源管理系统。
  • NodeManager以心跳的方式向ResourceManager汇报资源使用情况(目前主要是CPU和内存的使用情况)。ResourceManager只接受NodeManager的资源回报信息,对于具体的资源处理则交给NodeManager自己处理。
  • ResourceManager中的YARN Scheduler组件根据application的请求为其分配资源,不负责具体job的监控、追踪、运行状态反馈、启动等工作。

1.3.2 NodeManager

  • NodeManager是每个节点上的资源和任务管理器,它是管理这台机器的代理,负责该节点程序的运行,以及该节点资源的管理和监控。YARN集群每个节点都运行一个NodeManager。
  • NodeManager定时向ResourceManager汇报本节点资源(CPU、内存)的使用情况和Container的运行状态。当ResourceManager宕机时NodeManager自动连接ResourceManager备用节点。
  • NodeManager接收并处理来自ApplicationMaster的Container启动、停止等各种请求。

1.3.3 ApplicationMaster

  • 用户提交的每个应用程序均包含一个ApplicationMaster,它可以运行在ResourceManager以外的机器上。
  • 负责与ResourceManage调度器协商以获取资源(用Container表示)。
  • 将得到的任务进一步分配给内部的任务(资源的二次分配)。
  • 与NodeManager通信以启动/停止任务。
  • 监控所有任务运行状态,并在任务运行失败时重新为任务申请资源以重启任务。

1.4 Yarn运行流程

  • client向RM提交应用程序,其中包括启动该应用的ApplicationMaster的必须信息,例如ApplicationMaster程序、启动ApplicationMaster的命令、用户程序等。
  • ResourceManager启动一个container用于运行ApplicationMaster。
  • 启动中的ApplicationMaster向ResourceManager注册自己,启动成功后与RM保持心跳。
  • ApplicationMaster向ResourceManager发送请求,申请相应数目的container。
  • ResourceManager返回ApplicationMaster的申请的containers信息。申请成功的container,由ApplicationMaster进行初始化。container的启动信息初始化后,AM与对应的NodeManager通信,要求NM启动container。AM与NM保持心跳,从而对NM上运行的任务进行监控和管理。
  • container运行期间,ApplicationMaster对container进行监控。container通过RPC协议向对应的AM汇报自己的进度和状态等信息。
  • 应用运行期间,client直接与AM通信获取应用的状态、进度更新等信息。
  • 应用运行结束后,ApplicationMaster向ResourceManager注销自己,并允许属于它的container被收回。


1.5 Yarn的调度器Scheduler

理想情况下,我们应用对Yarn资源的请求应该立刻得到满足,但现实情况资源往往是有限的,特别是在一个很繁忙的集群,一个应用资源的请求经常需要等待一段时间才能的到相应的资源。在Yarn中,负责给应用分配资源的就是Scheduler。其实调度本身就是一个难题,很难找到一个完美的策略可以解决所有的应用场景。为此,Yarn提供了多种调度器和可配置的策略供我们选择。
在Yarn中有三种调度器可以选择:FIFO Scheduler ,Capacity Scheduler,Fair Scheduler。

1.5.1 FIFO Scheduler

FIFO Scheduler把应用按提交的顺序排成一个队列,这是一个先进先出队列,在进行资源分配的时候,先给队列中最头上的应用进行分配资源,待最头上的应用需求满足后再给下一个分配,以此类推。

FIFO Scheduler是最简单也是最容易理解的调度器,也不需要任何配置,但它并不适用于共享集群。大的应用可能会占用所有集群资源,这就导致其它应用被阻塞。在共享集群中,更适合采用Capacity Scheduler或Fair Scheduler,这两个调度器都允许大任务和小任务在提交的同时获得一定的系统资源。

1.5.2 Capacity Scheduler(Apache)

1.5.2.1 什么是Capacity Scheduler

Capacity Scheduler调度器以队列为单位划分资源。简单通俗点来说,就是一个个队列有独立的资源,队列的结构和资源是可以进行配置的,如下图:

default队列占30%资源,analystdev分别占40%和30%资源;类似的**,analyst和dev各有两个子队列,子队列在父队列的基础上再分配资源**。

  • 队列里的应用以FIFO方式调度,每个队列可设定一定比例的资源最低保证和使用上限;
  • 每个用户也可以设定一定的资源使用上限以防止资源滥用;
  • 而当一个队列的资源有剩余时,可暂时将剩余资源共享给其他队列。

1.5.2.2 调度器配置

CapacityScheduler的配置项包括两部分,其中一部分在yarn-site.xml中,主要用于配置YARN集群使用的调度器;另一部分在capacity-scheduler.xml配置文件中,主要用于配置各个队列的资源量、权重等信息。

1.5.2.2.1 一、开启调度器

在ResourceManager中配置使用的调度器,修改HADOOP_CONF/yarn-site.xml,设置属性:

1.5.2.2.2 二、配置队列

调度器的核心就是队列的分配和使用,修改HADOOP_CONF/capacity-scheduler.xml可以配置队列。Capacity调度器默认有一个预定义的队列:root所有的队列都是它的子队列。队列的分配支持层次化的配置,使用**.**来进行分割,比如:

案例:root下面有三个子队列

1.5.2.2.3 三、队列属性
  • 队列的资源容量占比(百分比):


系统繁忙时,每个队列都应该得到设置的量的资源;当系统空闲时,该队列的资源则可以被其他的队列使用。同一层的所有队列加起来必须是100%。

  • 队列资源的使用上限


系统空闲时,队列可以使用其他的空闲资源,因此最多使用的资源量则是该参数控制。默认是-1,即禁用。

  • 每个任务占用的最少资源


比如,设置成25%。那么如果有两个用户提交任务,那么每个任务资源不超过50%。如果3个用户提交任务,那么每个任务资源不超过33%。如果4个用户提交任务,那么每个任务资源不超过25%。如果5个用户提交任务,那么第五个用户需要等待才能提交。默认是100,即不去做限制。

  • 每个用户最多使用的队列资源占比


如果设置为50,那么每个用户使用的资源最多就是50%。

1.5.2.2.4 四、运行和提交应用限制
  • 设置系统中可以同时运行和等待的应用数量,默认是10000
  • 设置有多少资源可以用来运行app master,即控制当前激活状态的应用,默认是10%。
1.5.2.2.5 五、队列管理
  • 队列的状态,可以使RUNNING或者STOPPED


如果队列是STOPPED状态,那么新应用不会提交到该队列或者子队列。同样,如果root被设置成STOPPED,那么整个集群都不能提交任务了。现有的应用可以等待完成,因此队列可以优雅的退出关闭

  • 访问控制列表ACL:控制谁可以向该队列提交任务


限定哪些Linux用户/用户组可向给定队列中提交应用程序。如果一个用户可以向该队列提交,那么也可以提交任务到它的子队列。配置该属性时,**用户之间或用户组之间用“,”分割**,**用户和用户组之间用空格分割**,比如“**user1, user2 group1,group2**”

  • 设置队列的管理员的ACL控制


为队列指定一个管理员,该管理员可控制该队列的所有应用程序,比如杀死任意一个应用程序等。同样,该属性具有继承性,如果一个用户可以向某个队列中提交应用程序,则它可以向它的所有子队列中提交应用程序。

1.5.2.2.6 六、基于用户/组的队列映射
  • 映射单个用户或者用户组到一个队列


语法:[u or g]:[name]:[queue_name][,next_mapping]*,列表可以多个,之间以逗号分隔。%user放在[name]部分,表示已经提交应用的用户。如果队列名称和用户一样,那可以使用%user表示队列。如果队列名称和用户主组一样,可以使用%primary_group表示队列。 u:%user:%user 表示-已经提交应用的用户,映射到和用户名称一样的队列上。 u:user2:%primary_group表示user2提交的应用映射到user2主组名称一样的队列上。如果用户组并不多,队列也不多,建议还是使用简单的语法,而不要使用带%的。

  • 定义针对特定用户的队列是否可以被覆盖,默认值为false。
1.5.2.2.7 七、其他属性
  • 资源计算方法


默认是org.apache.hadoop.yarn.util.resource.DefaultResourseCalculator,它只会计算内存。DominantResourceCalculator则会计算内存和CPU。

  • 调度器尝试进行调度的次数


节点局部性延迟,在容器企图调度本地机栈容器后(失败),还可以错过错过多少次的调度次数。一般都是跟集群的节点数量有关。默认40(一个机架上的节点数)一旦设置完这些队列属性,就可以在web ui上看到了。

1.5.2.2.8 八、修改队列配置

如果想要修改队列或者调度器的配置,可以修改HADOOP_CONF_DIR/capacity-scheduler.xml,修改完成后,需要执行下面的命令:

** HADOOP_YARN_HOME/bin/yarn rmadmin -refreshQueues**

注意事项:

  • 队列不能被删除,只能新增;
  • 更新队列的配置需要是有效的值;
  • 同层级的队列容量限制相加需要等于100%;
  • 在MapReduce中,可以通过mapreduce.job.queuename属性指定要用的队列。如果队列不存在,在提交任务时就会收到错误。如果没有定义任何队列,所有的应用将会放在一个default队列中。

1.5.2.3 案例:Capacity调度器配置

假设有如下层次的队列:

1.5.2.3.1 step1、Capacity Scheduler 配置

上图中队列的一个调度器配置文件HADOOP_CONF/capacity-scheduler.xml

<configuration>
	<!-- 分为两个队列,分别为prod和dev -->
	<property>
		<name>yarn.scheduler.capacity.root.queues</name>
		<value>prod,dev</value>
	</property>
	<!-- dev继续分为两个队列,分别为eng和science -->
	<property>
		<name>yarn.scheduler.capacity.root.dev.queues</name>**
		<value>eng,science</value>
	</property>
	<!-- 设置prod队列40% -->
	<property>
		<name>yarn.scheduler.capacity.root.prod.capacity</name>**
		<value>40</value>**
	</property>
	<!-- 设置dev队列60% -->
	<property>
		<name>yarn.scheduler.capacity.root.dev.capacity</name>
		<value>60</value>
	</property>
	<!-- 设置dev队列可使用的资源上限为75% -->
	<property>
		<name>yarn.scheduler.capacity.root.dev.maximum-capacity</name>**
		<value>75</value>
	</property>**
	<!-- 设置eng队列50% -->
	<property>**
		<name>yarn.scheduler.capacity.root.dev.eng.capacity</name>**
		<value>50</value>
	</property>
	<!-- 设置science队列50% -->
	<property>
		<name>yarn.scheduler.capacity.root.dev.science.capacity</name>**
		<value>50</value>
	</property>
</configuration>

相关属性说明如下所示:

  • dev队列又被分成了engscience两个相同容量的子队列;
  • devmaximum-capacity属性被设置成了75%,所以即使prod队列完全空闲dev也不会占用全部集群资源,也就是说,prod队列仍有25%的可用资源用来应急;
  • engscience两个队列没有设置maximum-capacity属性,也就是说engscience队列中的job可能会用到整个dev队列的所有资源(最多为集群的75%);
  • 而类似的,prod由于没有设置maximum-capacity属性,它有可能会占用集群全部资源。
  • 对于Capacity调度器,队列名必须是队列树中的最后一部分,如果使用队列树则不会被识别。比如,在上面配置中,使用prodeng作为队列名是可以的,但是如果用root.dev.eng或者dev.eng是无效的。
1.5.2.3.2 step2、测试运行

上述配置队列形式如下所示:

启动ResouceManager,打开8088页面:

运行MapReduce中WordCount程序,指定运行队列prod

| HADOOP_HOME=/export/server/hadoop
HADOOPHOME/bin/yarnjar{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
HADOOPHOME/bin/yarnjar{HADOOP_HOME}/bin/yarn jar \\** **{HADOOP_HOME}/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.4.jar \
wordcount \

datas/input.data /datas/output2


查看8088界面如下所示:

1.5.2.3.3 Capacity官方默认配置

在HADOOP 安装目录中,官方自带默认配置HADOOP_CONF/capacity-scheduler.xml

**<configuration>**
	<property>
		<name>yarn.scheduler.capacity.maximum-applications</name>
		<value>10000</value>
		<description>
			Maximum number of applications that can be pending and running.
		</description>
	</property>
	<property>
		<name>yarn.scheduler.capacity.maximum-am-resource-percent</name>
		<value>0.1</value>
		<description>
			Maximum percent of resources in the cluster which can be used to run
			application masters i.e. controls number of concurrent running
			applications.
		</description>
	</property>
	<property>
		<name>yarn.scheduler.capacity.resource-calculator</name>
		<value>org.apache.hadoop.yarn.util.resource.DefaultResourceCalculator</value>
		<description>
			The ResourceCalculator implementation to be used to compare
			Resources in the scheduler.
			The default i.e. DefaultResourceCalculator only uses Memory while
			DominantResourceCalculator uses dominant-resource to compare
			multi-dimensional resources such as Memory, CPU etc.
		</description>
	</property>
	<property>
		<name>yarn.scheduler.capacity.root.queues</name>
		<value>default</value>
		<description>
			The queues at the this level (root is the root queue).
		</description>
	</property>
	<property>
		<name>yarn.scheduler.capacity.root.default.capacity</name>
		<value>100</value>
		<description>Default queue target capacity.</description>
	</property>
	<property>
		<name>yarn.scheduler.capacity.root.default.user-limit-factor</name>
		<value>1</value>
		<description>
			Default queue user limit a percentage from 0.0 to 1.0.
		</description>
	</property>
	<property>
		<name>yarn.scheduler.capacity.root.default.maximum-capacity</name>
		<value>100</value>
		<description>
			The maximum capacity of the default queue.
		</description>
	</property>
	<property>
		<name>yarn.scheduler.capacity.root.default.state</name>
		<value>RUNNING</value>
		<description>
			The state of the default queue. State can be one of RUNNING or STOPPED.
		</description>
	</property>
	<property>
		<name>yarn.scheduler.capacity.root.default.acl_submit_applications</name>
		<value>*</value>
		<description>
			The ACL of who can submit jobs to the default queue.
		</description>
	</property>
	<property>
		<name>yarn.scheduler.capacity.root.default.acl_administer_queue</name>
		<value>*</value>
		<description>
		    The ACL of who can administer jobs on the default queue.
		</description>
	</property>
	<property>
		<name>yarn.scheduler.capacity.node-locality-delay</name>
		<value>40</value>
		<description>
			Number of missed scheduling opportunities after which the CapacityScheduler
			attempts to schedule rack-local containers.
			Typically this should be set to number of nodes in the cluster, By default is setting
			approximately number of nodes in one rack which is 40.
		</description>
	</property>
	<property>
		<name>yarn.scheduler.capacity.queue-mappings</name>
		<value></value>
		<description>
			A list of mappings that will be used to assign jobs to queues
			The syntax for this list is [u&#124;g]:[name]:[queue_name][,next mapping]
			Typically this list will be used to map users to queues,
			for example, u:%user:%user maps all users to queues with the same name
			as the user.
		</description>
	</property>
	<property>
		<name>yarn.scheduler.capacity.queue-mappings-override.enable</name>
		<value>false</value>
		<description>**
			If a queue mapping is present, will it override the value specified
			by the user? This can be used by administrators to place jobs in queues
			that are different than the one specified by the user.
			The default is false.
		</description>
	</property>
</configuration>

1.5.3 Fair Scheduler(CDH)

在Fair调度器中,我们不需要预先占用一定的系统资源,Fair调度器会为所有运行的job动态的调整系统资源。如下图所示,当第一个大job提交时,只有这一个job在运行,此时它获得了所有集群资源;当第二个小任务提交后,Fair调度器会分配一半资源给这个小任务,让这两个任务公平的共享集群资源。
需要注意的是,在下图Fair调度器中,从第二个任务提交到获得资源会有一定的延迟,因为它需要等待第一个任务释放占用的Container。小任务执行完成之后也会释放自己占用的资源,大任务又获得了全部的系统资源。最终效果就是Fair调度器即得到了高的资源利用率又能保证小任务及时完成。

公平调度器 Fair Scheduler 最初是由 Facebook 开发设计使得 Hadoop 应用能够被多用户公平地共享整个集群资源,现被 Cloudera CDH 所采用。
Fair Scheduler 不需要保留集群的资源,因为它会动态在所有正在运行的作业之间平衡资源。

1.5.4 示例:Capacity调度器配置使用

调度器的使用是通过yarn-site.xml配置文件中的
yarn.resourcemanager.scheduler.class参数进行配置的,默认采用Capacity Scheduler调度器。
假设我们有如下层次的队列:
下面是一个简单的Capacity调度器的配置文件,文件名为capacity-scheduler.xml。在这个配置中,在root队列下面定义了两个子队列prod和dev,分别占40%和60%的容量。需要注意,一个队列的配置是通过属性yarn.sheduler.capacity.<queue-path>.<sub-property>指定的,<queue-path>代表的是队列的继承树,如root.prod队列,<sub-property>一般指capacity和maximum-capacity。

<configuration>
<property>
   <name>yarn.scheduler.capacity.root.queues</name>
   <value>prod,dev</value>
 </property>
<property>
   <name>yarn.scheduler.capacity.root.dev.queues</name>
   <value>mapreduce,spark</value>
 </property>
   <property>
   <name>yarn.scheduler.capacity.root.prod.capacity</name>
   <value>40</value>
 </property>
   <property>
   <name>yarn.scheduler.capacity.root.dev.capacity</name>
   <value>60</value>
 </property>
   <property>
   <name>yarn.scheduler.capacity.root.dev.maximum-capacity</name>
   <value>80</value>
 </property>
 <property>
   <name>yarn.scheduler.capacity.root.dev.mapreduce.capacity</name>
   <value>50</value>
 </property>
  <property>
   <name>yarn.scheduler.capacity.root.dev.spark.capacity</name>
   <value>50</value>
 </property>
</configuration> |

我们可以看到,dev队列又被分成了mapreduce和spark两个相同容量的子队列。dev的maximum-capacity属性被设置成了75%,所以即使prod队列完全空闲dev也不会占用全部集群资源,也就是说,prod队列仍有25%的可用资源用来应急。我们注意到,mapreduce和spark两个队列没有设置maximum-capacity属性,也就是说mapreduce或spark队列中的job可能会用到整个dev队列的所有资源(最多为集群的75%)。而类似的,prod由于没有设置maximum-capacity属性,它有可能会占用集群全部资源。
关于队列的设置,这取决于我们具体的应用。比如,在MapReduce中,我们可以通过mapreduce.job.queuename属性指定要用的队列。如果队列不存在,我们在提交任务时就会收到错误。如果我们没有定义任何队列,所有的应用将会放在一个default队列中。
注意:对于Capacity调度器,我们的队列名必须是队列树中的最后一部分,如果我们使用队列树则不会被识别。比如,在上面配置中,我们使用prod和mapreduce作为队列名是可以的,但是如果我们用root.dev.mapreduce或者dev. mapreduce是无效的。

1.6 .关于yarn常用参数设置

设置container分配最小内存
yarn.scheduler.minimum-allocation-mb 1024 给应用程序container分配的最小内存
设置container分配最大内存
yarn.scheduler.maximum-allocation-mb 8192 给应用程序container分配的最大内存
设置每个container的最小虚拟内核个数
yarn.scheduler.minimum-allocation-vcores 1 每个container默认给分配的最小的虚拟内核个数
设置每个container的最大虚拟内核个数
yarn.scheduler.maximum-allocation-vcores 32 每个container可以分配的最大的虚拟内核的个数
设置NodeManager可以分配的内存大小
yarn.nodemanager.resource.memory-mb 8192 nodemanager 可以分配的最大内存大小,默认8192Mb
定义每台机器的内存使用大小
yarn.nodemanager.resource.memory-mb 8192
定义交换区空间可以使用的大小
交换区空间就是讲一块硬盘拿出来做内存使用,这里指定的是nodemanager的2.1倍
yarn.nodemanager.vmem-pmem-ratio 2.1

上次编辑于:
贡献者: 麦正阳,znyoung