我正在努力为一项简单的任务最大化群集使用。
群集是1 + 2 x m3.xlarge,运行Spark 1.3.1,Hadoop 2.4,Amazon AMI 3.7
该任务读取文本文件的所有行并将其解析为csv。
当我将任务作为纱线群集模式提交时,我得到以下结果之一:
我的期望:
有时,当我使用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个执行程序并正确完成。
那么,驱动程序内存阻止我的任务获取执行程序的问题是什么?
驱动程序是否应在群集的主节点上与Yarn主容器一起执行,如解释here所述?
如何为我的火花作业驱动程序提供更多内存? (如果出现收集和其他一些有用的操作)
答案 0 :(得分:21)
最大化群集使用的解决方案是在EMR上安装spark并忘记手动调整执行程序内存和核心时忘记'-x'参数。
这个the docs很好地解释了在YARN上运行Spark时如何完成资源分配。
要记住的一件重要事情是所有执行者必须分配相同的资源!正如我们所说,Spark不支持异构执行程序。 (目前正在进行一些支持GPU的工作,但这是另一个主题)
因此,为了在为执行程序最大化内存的同时获得分配给驱动程序的最大内存,我应该像这样分割我的节点(这个post在第25页提供了很好的截图):
注意:另一个选项是来自主节点0的spark-submit
--master yarn --deploy-mode client
。是否有任何反例,这是一个坏主意?
在我的例子中,我最多可以拥有2个vcore的3个执行器,每个vron有4736 MB +具有相同规格的驱动程序。
4736内存源自yarn.nodemanager.resource.memory-mb
中定义的/home/hadoop/conf/yarn-site.xml
的值。在m3.xlarge上,它设置为11520 mb(有关每种实例类型的所有值,请参阅slideshare)
然后,我们得到:
(11520-1024)/ 2(每个节点的执行者)= 5248 => 5120(向下舍入为yarn.scheduler.minimum-allocation-mb中定义的256 MB增量)
7% * 5120 = 367四舍五入至384(内存开销)将在火花1.4中变为10%
5120 - 384 = 4736
其他有趣的链接:
答案 1 :(得分:2)
问题在于对Spark如何在YARN上工作的期望。当部署模式为cluster或master设置为yarn-cluster运行Spark时,驱动程序在主节点上执行 not ,但在其中一个从属节点上的Application Master容器中执行。有关详细信息,请参阅https://spark.apache.org/docs/latest/running-on-yarn.html
我希望发生的事情是集群无法满足驱动程序的内存要求(请记住,实际请求集群的内存是您要求的内存加上开销),因此永远等待分配应用程序主机的驱动程序跑或执行者。
要为驱动程序提供您请求的内存量,您需要使用其他从属服务器,以便同时为基于群集的驱动程序和执行程序提供资源。由于驱动程序的开销,我怀疑您可能需要使用具有更多内存的实例类型。当您为驱动程序请求8G时,请查看资源管理器日志并验证所请求的实际金额。
要在主节点上运行驱动程序,部署模式需要是客户端。如果您使用一步调用脚本将驱动程序jar本地化到主节点上,然后下一步可以调用部署模式客户端的spark-submit集并在本地主文件上引用JAR,则仍可以使用EMR步骤完成此操作系统
答案 2 :(得分:1)
Michel Lemay的帖子是很好的背景阅读,他给出了一个特定群集配置的答案。我已将该逻辑嵌入到电子表格中,该电子表格将显示任何群集的最佳选项。要使用,请填写群集中的节点数,虚拟核心/节点数以及可分配内存/节点数。执行此操作后,工作表将为您提供启动命令的选项,这些命令将充分利用您的群集同时用于客户端和每个节点有1个,2个,4个和8个执行程序的集群模式。我已经突出显示了每个节点对应2个执行程序的行,因为这一直是我测试中的最佳选择。您可以根据需要随意复制此工作表或添加不同群集类型的选项卡。
https://docs.google.com/spreadsheets/d/1VH7Qly308hoRPu5VoLIg0ceolrzen-nBktRFkXHRrY4/edit?usp=sharing
答案 3 :(得分:1)
以下是解决问题的方法:
通过将spark.executor.memory + driver-memory设置为低于任何给定MASTER节点的总和,YARN能够将Master和执行程序放置在给定节点上。您牺牲了其他节点上的一些丢失内存,但更重要的是我有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