【问题标题】:Spark resources not fully allocated on Amazon EMRSpark 资源未在 Amazon EMR 上完全分配
【发布时间】:2016-10-13 00:58:14
【问题描述】:

我正在尝试最大限度地利用集群来完成一项简单的任务。

集群为 1+2 x m3.xlarge,运行 Spark 1.3.1、Hadoop 2.4、Amazon AMI 3.7

任务读取文本文件的所有行并将它们解析为 csv。

当我以纱线集群模式火花提交任务时,我得到以下结果之一:

  • 0 执行者:作业无限等待,直到我手动杀死它
  • 1 个执行者:作业正在利用资源,只有 1 台机器在工作
  • 当我没有在驱动程序上分配足够的内存时出现 OOM

我的预期:

  • Spark 驱动程序在所有可用内存的集群主服务器上运行,外加 2 个 9404MB 的执行程序(由 install-spark 脚本定义)。

有时,当我使用 1 个执行程序“成功”执行时,克隆并重新启动该步骤会以 0 个执行程序结束。

我使用这个命令创建了我的集群:

aws emr --region us-east-1 create-cluster --name "Spark Test"
--ec2-attributes KeyName=mykey 
--ami-version 3.7.0 
--use-default-roles 
--instance-type m3.xlarge 
--instance-count 3 
--log-uri s3://mybucket/logs/ 
--bootstrap-actions Path=s3://support.elasticmapreduce/spark/install-spark,Args=["-x"] 
--steps Name=Sample,Jar=s3://elasticmapreduce/libs/script-runner/script-runner.jar,Args=[/home/hadoop/spark/bin/spark-submit,--master,yarn,--deploy-mode,cluster,--class,my.sample.spark.Sample,s3://mybucket/test/sample_2.10-1.0.0-SNAPSHOT-shaded.jar,s3://mybucket/data/],ActionOnFailure=CONTINUE

包含一些步骤变化,包括:

--driver-memory 8G --driver-cores 4 --num-executors 2


带有 -x 的 install-spark 脚本会生成以下 spark-defaults.conf:

$ cat spark-defaults.conf
spark.eventLog.enabled  false
spark.executor.extraJavaOptions         -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:MaxHeapFreeRatio=70
spark.driver.extraJavaOptions         -Dspark.driver.log.level=INFO
spark.executor.instances        2
spark.executor.cores    4
spark.executor.memory   9404M
spark.default.parallelism       8

更新 1

我在通用 JavaWordCount 示例中得到了相同的行为:

/home/hadoop/spark/bin/spark-submit --verbose --master yarn --deploy-mode cluster --driver-memory 8G --class org.apache.spark.examples.JavaWordCount /home/hadoop/spark/lib/spark-examples-1.3.1-hadoop2.4.0.jar s3://mybucket/data/

但是,如果我删除“--driver-memory 8G”,任务会被分配 2 个执行程序并正确完成。

那么,驱动程序内存阻止我的任务获取执行程序是怎么回事?

是否应该按照here 的说明在集群的主节点上与 Yarn 主容器一起执行驱动程序?

如何为我的 spark 作业驱动程序提供更多内存? (收集和其他一些有用的操作出现的地方)

【问题讨论】:

    标签: apache-spark hadoop-yarn emr


    【解决方案1】:

    最大化集群使用率的解决方案是在 EMR 上安装 spark 时忘记“-x”参数,并手动调整执行程序的内存和内核。

    post 很好地解释了在 YARN 上运行 Spark 时如何完成资源分配。

    要记住的重要一点是,所有执行程序必须分配相同的资源!正如我们所说,Spark 不支持异构执行器。 (目前正在进行一些工作以支持 GPU,但这是另一个主题)

    因此,为了获得分配给驱动程序的最大内存,同时最大化执行程序的内存,我应该像这样拆分我的节点(slideshare 在第 25 页给出了很好的屏幕截图):

    • 节点 0 - 主节点(纱线资源管理器)
    • 节点 1 - NodeManager(Container(Driver) + Container(Executor))
    • 节点 2 - NodeManager(Container(Executor) + Container(Executor))

    注意:另一种选择是从主节点 0 到 spark-submit--master yarn --deploy-mode client。有没有反例这是一个坏主意?

    在我的示例中,我最多可以有 3 个执行器,每个执行器 2 个 vcore,每个 4736 MB + 一个具有相同规格的驱动程序。

    4736 内存是从/home/hadoop/conf/yarn-site.xml 中定义的yarn.nodemanager.resource.memory-mb 的值派生而来的。在 m3.xlarge 上,它设置为 11520 mb(请参阅 here 了解与每个实例类型关联的所有值)

    那么,我们得到:

    (11520 - 1024) / 2(每个节点的执行器数)= 5248 => 5120(向下舍入到 256 mb 增量,如 yarn.scheduler.minimum-allocation-mb 中所定义)

    7% * 5120 = 367 四舍五入到 384(内存开销)将在 spark 1.4 中变为 10%

    5120 - 384 = 4736

    其他有趣的链接:

    【讨论】:

    • 是的,基本上用户需要调整设置以匹配所需的设置。关于在 yarn 上启动的 Spark 文档对此进行了很好的讨论。
    • 您的节点故障意味着驱动程序未在资源管理器(EMR 中的主实例)上运行。是这样吗? (试图把我的头绕在这一切上)(当作为纱线集群运行时)
    • 是的,就是这么说的。除非我弄错了,否则我在使用 yarn-cluster 模式时没有看到任何东西在主节点上运行。
    • 谢谢老兄。我不敢相信亚马逊把这件事搞砸了这么大。我一直在使用 EMR 在 YARN 上运行 spark,并且一直在摸索为什么每个节点只使用一个 vCPU。我宁愿他们只是不费心设置默认值,而不是设置非常无用的:-(
    • @MichelLemay 感谢您的出色回答,请问您为什么从节点的内存中减去 1024?它是为操作系统保留的吗?
    【解决方案2】:

    问题在于对 Spark 在 YARN 上的工作方式的期望。当 Spark 在集群或主节点的部署模式设置为 yarn-cluster 的情况下运行时,驱动程序不是在主节点上执行,而是在其中一个从节点上的应用程序主容器中执行。更多详情见https://spark.apache.org/docs/latest/running-on-yarn.html

    我预计发生的情况是集群无法满足驱动程序的内存要求(请记住,集群实际请求的内存是您要求的加上开销),因此永远等待分配 Application Master 驱动程序将运行或用于执行者。

    要为驱动程序提供您请求的内存量,您需要使用额外的从属设备,以便同时为基于集群的驱动程序和执行程序提供资源。由于驱动程序的开销,我怀疑您可能需要使用具有更多内存的实例类型。当您为驱动程序请求 8G 时,请查看资源管理器日志并验证请求的实际数量。

    要在主节点上运行驱动程序,部署模式需要是客户端。如果您使用一个步骤调用脚本将驱动程序 jar 本地化到主节点上,那么这仍然可以通过 EMR 步骤完成,然后下一步可以为部署模式客户端调用 spark-submit set 并引用本地主文件上的 JAR系统。

    【讨论】:

    • 那么我希望在 3 台机器设置上始终至少有一个执行程序。当我在 executor 部分查看 spark UI 时,我经常看到只有一个驱动程序而没有 executors。为什么 Spark 不对驱动程序本身执行任何操作?将驱动程序用于某些工作似乎是合理的。但是,根据 spark UI,它似乎根本没有做任何事情..
    • 驱动不适合执行器/并行工作。只是为了收集回来的任何东西和 SparkContext 交互/调度的处理。使用 3 台机器设置,容器将只有 2 个节点。如果您看到驱动程序但没有执行程序...则必须仔细查看驱动程序和资源管理器的日志以确定执行程序无法在第二个节点上出现的原因。
    【解决方案3】:

    Michel Lemay 的帖子是很好的背景阅读,他给出了 1 个特定集群配置的答案。我已将该逻辑嵌入到电子表格中,该电子表格将显示任何集群的最佳选项。要使用,请填写集群中的节点数,虚拟内核/节点的数量,以及可分配的内存/节点的数量。完成此操作后,工作表将为您提供启动命令选项,这些命令将充分利用您的集群以实现客户端和集群模式,每个节点有 1、2、4 和 8 个执行程序。我突出显示了对应于每个节点 2 个执行程序的行,因为这一直是我测试中的最佳选择。随意复制此工作表或根据需要为不同的集群类型添加选项卡。

    https://docs.google.com/spreadsheets/d/1VH7Qly308hoRPu5VoLIg0ceolrzen-nBktRFkXHRrY4/edit?usp=sharing

    【讨论】:

      【解决方案4】:

      这是我解决问题的方法:

      通过将 spark.executor.memory + driver-memory 设置为低于任何给定 MASTER 节点的总数,YARN 能够将 Master 和 executor 都放置在给定节点上。你牺牲了其他节点上的一些丢失内存,但更重要的是我让 CPU 运行。这是一个示例(在 r3.8xlarge 上):

      aws emr add-steps --cluster-id j-1234 --steps Type=Spark,Name=foob3,Args=[--conf,spark.memory.fraction=0.95,--conf,spark.memory.storageFraction=0.1,--conf,spark.yarn.executor.memoryOverhead=8000,--conf,spark.executor.memory=200g,--conf,spark.executor.cores=32,--conf,spark.executor.instances=4,--conf,spark.dynamicAllocation.enabled=false,--class,myclass.Foo,--deploy-mode,cluster,--master,yarn,--driver-memory,10g,s3://myjar-1.0-SNAPSHOT.jar],ActionOnFailure=CONTINUE
      

      【讨论】:

        猜你喜欢
        • 2016-02-03
        • 2017-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-07
        • 2015-12-27
        • 1970-01-01
        • 2019-02-12
        相关资源
        最近更新 更多