我在YARN Fair Scheduled队列上重新平衡Apache Spark作业资源时遇到问题。
对于测试,我已经配置Hadoop 2.6(也尝试过2.7)在MacOS上与本地HDFS一起以伪分布式模式运行。对于作业提交,使用Spark网站上的"为Hadoop 2.6及更高版本预构建Spark 1.4"(也尝试过1.5)分发版。
当在Hadoop MapReduce作业上进行基本配置测试时,Fair Scheduler的工作原理与预期一致:当集群的资源超过某个最大值时,计算公平份额,并根据这些计算抢占和平衡不同队列中的作业的资源。
同样的测试用Spark作业运行,在这种情况下,YARN为每个作业做出正确的公平份额计算,但是Spark容器的资源没有重新平衡。
以下是我的配置文件:$ HADOOP_HOME/etc/hadoop/yarn-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.aux-services.spark_shuffle.class</name>
<value>org.apache.spark.network.yarn.YarnShuffleService</value>
</property>
<property>
<name>yarn.resourcemanager.scheduler.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value>
</property>
<property>
<name>yarn.scheduler.fair.preemption</name>
<value>true</value>
</property>
</configuration>
$ HADOOP_HOME/etc/hadoop/fair-scheduler.xml
<?xml version="1.0" encoding="UTF-8"?>
<allocations>
<defaultQueueSchedulingPolicy>fair</defaultQueueSchedulingPolicy>
<queue name="prod">
<weight>40</weight>
<schedulingPolicy>fifo</schedulingPolicy>
</queue>
<queue name="dev">
<weight>60</weight>
<queue name="eng" />
<queue name="science" />
</queue>
<queuePlacementPolicy>
<rule name="specified" create="false" />
<rule name="primaryGroup" create="false" />
<rule name="default" queue="dev.eng" />
</queuePlacementPolicy>
</allocations>
$ HADOOP_HOME/etc/hadoop/core-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://localhost:9000</value>
</property>
</configuration>
$ HADOOP_HOME/etc/hadoop/core-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
</configuration>
测试用例是:
在权重为40的"prod"队列上运行一个作业(必须分配所有资源的40%),如预期的那样,该作业占用所有需要的空闲资源(62.5%的集群资源)。
./bin/spark-submit --class org.apache.spark.examples.SparkPi
--master yarn-cluster
--driver-memory 512M
--executor-memory 768M
--executor-cores 1
--num-executors 2
--queue prod
lib/spark-examples*.jar 100000
之后,在权重为60的"dev.eng"队列上运行相同的作业,这意味着该作业必须分配所有资源的60%,并将第一个作业的资源减少到约40%。
./bin/spark-submit --class org.apache.spark.examples.SparkPi
--master yarn-cluster
--driver-memory 512M
--executor-memory 768M
--executor-cores 1
--num-executors 2
--queue dev.eng
lib/spark-examples*.jar 100000
不幸的是,集群资源没有变化——第一个作业占62.5%,第二个作业占37.5%。
您需要在分配xml中设置一个抢占超时。一个是最小份额,一个是公平份额,都以秒为单位。缺省情况下,不设置超时时间。
摘自Hadoop: The Definitive Guide第4版
如果队列等待的时间与它的最小共享抢占超时时间一样长,而没有收到它的最小保证共享,那么调度器可能会抢占其他容器。为所有队列设置默认超时的defaultMinSharePreemptionTimeout顶层元素分配文件,并在每个队列的基础上设置minSharePreemptionTimeout元素
同样,如果队列在相同时间内保持低于公平份额的一半由于公平共享抢占超时,那么调度程序可以抢占其他容器。为所有队列设置默认超时defaultFairSharePreemptionTimeout分配中的顶级元素通过设置fairSharePreemptionTimeout,在每个队列的基础上在排队。阈值也可以从其默认值0.5更改通过设置defaultFairSharePreemptionThreshold和fairSharePreemptionThreshold(每个队列上)。
Fair Scheduler不会为第一个作业杀死容器,它只是等待一些资源被释放并保留它们供第二个作业使用。如果第一个作业没有释放资源,则调度器不能将这些资源分配给第二个作业。
在MapReduce作业中,每个map或reduce任务都需要实例化一个新的容器,如果超过了它的引用(基于队列容量),调度程序可以阻止该作业实例化一个新的容器。
在Spark中,事情是不同的,执行器在作业开始时被启动,不同的任务(阶段)被发送给它们。那么资源没有被释放,它们不能被重新分配。
可能是动态分配可以帮助:http://spark.apache.org/docs/1.6.1/configuration.html#dynamic-allocation