为什么EMR上的Yarn不会将所有节点都分配给运行Spark作业?

时间:2015-11-26 14:16:17

标签: apache-spark yarn emr amazon-emr elastic-map-reduce

我在Amazon Elastic Map Reduce(EMR)上运行Apache Spark上的工作。目前我正在emr-4.1.0上运行,其中包括Amazon Hadoop 2.6.0和Spark 1.5.0。

当我开始工作时,YARN正确地将所有工作节点分配给了火花作业(当然,其中一个用于驱动程序)。

我有魔力" maximResourceAllocation"属性设置为" true",以及spark属性" spark.dynamicAllocation.enabled"也设置为" true"。

但是,如果我通过向CORE工作计算机池添加节点来调整emr集群的大小,则YARN只会将一些的新节点添加到spark作业中。

例如,今天早上我有一个使用26个节点的工作(m3.2xlarge,如果这很重要) - 1个用于驱动程序,25个执行程序。我想加快工作,所以我尝试添加8个节点。 YARN已经获取了所有新节点,但只将其中一个分配给了Spark作业。 Spark成功地接收了新节点,并将其用作执行程序,但我的问题是为什么YARN让其他7个节点闲置?

由于显而易见的原因令人讨厌 - 即使他们没有被使用,我也必须为这些资源买单,而且我的工作根本没有加速!

有人知道YARN如何决定何时向运行的火花作业添加节点?什么变量发挥作用?记忆? V-核心?什么?

提前致谢!

2 个答案:

答案 0 :(得分:17)

好的,在@sean_r_owen的帮助下,我能够追踪到这一点。

问题在于:将spark.dynamicAllocation.enabled设置为true时,不应设置spark.executor.instances - 显式值将覆盖动态分配并将其关闭。事实证明,如果您不自己设置,EMR会将其设置在后台。要获得所需的行为,您需要将spark.executor.instances显式设置为0。

对于记录,这是我们在创建EMR集群时传递给--configurations标志的其中一个文件的内容:

[
    {
        "Classification": "capacity-scheduler",
        "Properties": {
            "yarn.scheduler.capacity.resource-calculator": "org.apache.hadoop.yarn.util.resource.DominantResourceCalculator"
        }
    },

    {
        "Classification": "spark",
        "Properties": {
            "maximizeResourceAllocation": "true"
        }
    },

    {
        "Classification": "spark-defaults",
        "Properties": {
            "spark.dynamicAllocation.enabled": "true",
            "spark.executor.instances": "0"
        }
    } 
]

这为我们提供了一个EMR集群,其中Spark在运行作业时使用所有节点,包括添加的节点。它似乎也使用全部/大部分内存和所有(?)内核。

(我不完全确定它使用的是所有实际核心;但它肯定使用了超过1个VCore,这是以前没有的,但是按照Glennie Helles的建议,它现在表现得更好并且使用了一半列出的VCores,似乎等于实际核心数...)

答案 1 :(得分:0)

我使用emr-5.20.0在几乎相同的设置下观察到了相同的行为。当群集已经运行但我使用TASK节点(以及一个CORE节点)时,我没有尝试添加节点。我正在使用InstanceFleets来定义MASTER,CORE和TASK节点(使用InstanceFleets我不知道我获得了哪些确切的InstanceType,这就是为什么我不想自己定义执行器,内核和内存的数量,但我想要自动最大化/优化的代码)。

这样,它仅使用两个TASK节点(可能是准备使用的前两个节点?),而在更多的TASK节点被置备并完成引导阶段时,它不会扩展。

在我的情况下起作用的是设置spark.default.parallelism参数(设置为我的TASK节点的内核总数),该参数与TASK InstanceFleet的TargetOnDemandCapacity或TargetSpotCapacity所使用的数量相同:

[
    {
        "Classification": "capacity-scheduler",
        "Properties": {
            "yarn.scheduler.capacity.resource-calculator": "org.apache.hadoop.yarn.util.resource.DominantResourceCalculator"
        }
    },
    {
        "Classification": "spark",
        "Properties": {
            "maximizeResourceAllocation": "true"
        }
    },
    {
        "Classification": "spark-defaults",
        "Properties": {
            "spark.dynamicAllocation.enabled": "true",
            "spark.default.parallelism", <Sum_of_Cores_of_all_TASK_nodes>
        }
    } 
]

出于完整性考虑:我正在使用一个CORE节点和几个TASK节点,主要是为了确保集群至少具有3个节点(1个MASTER,1个CORE和至少一个TASK节点)。在我尝试仅使用CORE节点之前,但是根据我的情况,核的数量是根据实际任务计算的,最终可能只有一个MASTER和一个CORE节点组成一个集群。使用maximizeResourceAllocation选项,这样的集群永远不会执行任何操作,因为运行yarn应用程序主文件的执行程序完全占据了单个CORE节点。