Spark提交至YuniKorn时如何实现资源动态分配?
Spark on YuniKorn 资源动态分配实践
Spark 配合 YuniKorn 完全可以实现资源动态分配——运行时按需扩容executor,任务完成后自动释放闲置executor。针对你遇到的「查询完成后executor未被移除」问题,结合实践经验从配置和环境层面逐一排查:
1. 补全Spark动态分配的核心依赖配置
你的配置遗漏了动态分配生效的关键前提:必须启用外部shuffle服务,否则Spark会因担心丢失executor上的shuffle数据,拒绝回收闲置executor。需要添加:
conf.set('spark.shuffle.service.enabled', True)
注意:该服务需在集群节点提前部署(YARN环境需每个节点启动shuffle服务,K8s环境需配置shuffle服务Sidecar)。
2. 理解minExecutors的约束
你设置了spark.dynamicAllocation.minExecutors=2,这意味着Spark会始终保留至少2个executor,仅会回收超出此数量的闲置实例。如果你的作业运行时未扩容到超过2个executor,自然不会有executor被移除。
- 若希望任务完成后尽可能释放资源,可将
minExecutors设为0,但需注意初始executors配置的配合,避免后续任务启动的冷启动延迟。
3. 检查YuniKorn侧的资源回收开关
YuniKorn自身配置会直接影响资源回收逻辑:
- 确认
yunikorn-site.xml中application.resource.reclaim.enabled设为true,允许调度器主动回收应用闲置资源。 - 检查作业所在队列的
minResource配置,若队列设置了最小资源配额,YuniKorn会确保应用占用资源不低于该值,导致executor无法被回收。 - 避免开启YuniKorn的gang scheduling( gang调度会为作业预留固定资源,阻止动态缩容)。
4. 处理Jupyter环境的特殊情况
Jupyter中Spark会话长期驻留,即使单个查询完成,Spark仍会默认预留资源应对后续任务,需手动触发回收:
- 清除缓存数据:执行
spark.catalog.clearCache(),若executor上存储了缓存的RDD/DataFrame,Spark会无限期保留该executor(除非设置了spark.dynamicAllocation.cachedExecutorIdleTimeout)。 - 取消后台残留任务:执行
spark.sparkContext.cancelAllJobs(),避免未完成的后台任务阻止executor被标记为闲置。
5. 补充优化配置
针对闲置executor回收,可添加以下配置优化效果:
# 缓存executor的闲置超时(默认无限期,有缓存时不会回收) conf.set('spark.dynamicAllocation.cachedExecutorIdleTimeout', '60s') # 调整资源申请的等待阈值,避免频繁扩容缩容 conf.set('spark.dynamicAllocation.schedulerBacklogTimeout', '5s')
内容的提问来源于stack exchange,提问作者Philipp Steiner
相关产品推荐
相关产品推荐

