EMR集群忽略spark submit内存、核心等参数,无法充分利用集群资源
集群基础配置
- 集群规模:4台m4.4xlarge节点,其中1台Driver节点、3台Worker节点
- 单节点配置:16 vCore、64 GiB内存、128 GiB EBS存储
已测试的三种配置方案(均在同一数据管道运行测试)
- 方案1:仅开启
maximizeResourceAllocation,未配置其他spark-submit参数
仅启动了2个Executor,未达预期 - 方案2:完全使用spark-defaults默认配置,无自定义参数
启动的Executor资源配置偏低,资源利用率不足 - 方案3:参考EMR Spark内存优化最佳实践配置spark-submit参数,参数如下:
"--conf", "spark.executor.cores=5", "--conf", "spark.executor.memory=18g", "--conf", "spark.executor.memoryOverhead=3g", "--conf", "spark.executor.instances=9", "--conf", "spark.driver.cores=5", "--conf", "spark.driver.memory=18g", "--conf", "spark.default.parallelism=45", "--conf", "spark.sql.shuffle.partitions=45"
配置完成后仍无法用尽集群全部资源
问题更新
运行另一数据管道时,开启maximizeResourceAllocation的配置效果优于前述方案,但内存利用率和Executor数量仍未达预期。经EMR团队人员说明,EMR会将Executor合并为超级Executor来提升性能。
可按以下优先级排查调整:
核对YARN集群的可用资源配额
EMR的Worker节点会预留一部分资源给系统进程、YARN NodeManager等基础服务,不会把100%的硬件资源开放给Spark。m4.4xlarge单节点64G内存的默认YARN可分配内存通常为57G左右,单节点16核默认YARN可分配vCore为15核。你之前的配置单Worker节点计划跑3个Executor(5核+21G内存),合计15核+63G,已经超过了单节点的YARN可用内存上限,自然启动不了足额9个Executor。
可以调整参数适配实际YARN配额:将spark.executor.memory调整为17G,spark.executor.memoryOverhead调整为2G,单Executor总内存19G,3个Executor合计57G刚好匹配单Worker的YARN可用内存上限,即可启动满9个Executor。明确
maximizeResourceAllocation的生效限制
这个参数的逻辑是由EMR的动态资源分配逻辑自动计算Executor规格,但是它会优先遵守YARN的容器大小上限配置yarn.scheduler.maximum-allocation-mb和yarn.scheduler.maximum-allocation-vcores,如果没有调整过这两个YARN配置,默认单容器上限通常是8核32G。当作业数据量偏小时,EMR的自动调度逻辑会倾向于启动更少的大规格Executor(也就是你了解到的超级Executor),减少shuffle开销,确实属于预期行为。如果要强制启动更多Executor,可以手动关闭动态资源分配,配合固定的spark.executor.instances配置使用。排查其他遗漏配置项
- 确认没有开启Spark动态资源分配,动态资源分配会根据作业负载自动增减Executor数量,在作业数据量不大的情况下不会启动全部Executor
- 确认YARN调度器为公平调度器,且没有配置资源池配额限制,部分EMR集群默认会给default资源池设置最大资源配额,导致无法用尽全部集群资源
内容的提问来源于stack exchange,提问作者Mironor

