YARN 资源队列规划与 Capacity Scheduler 配置指南
按多租户 SLA 规划队列层级,配置容量、ACL 与抢占并验证调整生效
多业务共享一个 YARN 集群时,资源争抢的根子通常是"队列规划缺位":所有作业挤在 default 队列,重要任务被无差别排队。Capacity Scheduler 的正确打开方式是按 SLA 分池:给每类业务划保障资源(Capacity)和弹性上限(MaxCapacity),用 ACL 管住谁能提交,用抢占兜住关键任务的时效,再定期验证容量调整是否生效。本文给出一套"保障资源-弹性资源-ACL-抢占"四位一体的规划模板和验证步骤,参数细节以 Capacity Scheduler 官方文档 为准。
规划原则:先分池,再分级
队列设计从"业务 SLA 分层"出发,而不是从"组织架构"出发。通用模板是两层树形结构:
- 一级队列 = 业务类型:ETL(离线加工)、ADHOC(临时查询)、REALTIME(实时/准实时)、SERVICE(对外服务作业),各占一个池;
- 二级队列 = 部门或项目:一级队列下按部门或项目细分,便于定位作业、做配额与审计;
- default 队列:保留一个容量很小的兜底队列,接收未显式指定队列的作业,避免乱提交污染核心队列。
SLA 越硬(对外服务、核心报表),Capacity 越高;探索型 ad-hoc 查询给低 Capacity、高 MaxCapacity,让它在集群空闲时借用资源。队列层级建议控制在两层到三层:层级越深,容量配置与排障越复杂,大部分集群两层就够用。
capacity-scheduler.xml 模板
Capacity Scheduler 的配置在 capacity-scheduler.xml,核心是队列树、容量与 ACL。下面是一个最小可用模板:
<configuration>
<!-- 顶层队列 -->
<property>
<name>yarn.scheduler.capacity.root.queues</name>
<value>etl,adhoc,realtime,default</value>
</property>
<!-- ETL:保障 40%,上限 60% -->
<property>
<name>yarn.scheduler.capacity.root.etl.capacity</name>
<value>40</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.etl.maximum-capacity</name>
<value>60</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.etl.acl_submit_applications</name>
<value>etl_group,data_engineer</value>
</property>
<!-- ADHOC:保障 20%,上限 100%(空闲时可用满) -->
<property>
<name>yarn.scheduler.capacity.root.adhoc.capacity</name>
<value>20</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.adhoc.maximum-capacity</name>
<value>100</value>
</property>
<!-- REALTIME:保障 30%,上限 40% -->
<property>
<name>yarn.scheduler.capacity.root.realtime.capacity</name>
<value>30</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.realtime.maximum-capacity</name>
<value>40</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.realtime.acl_submit_applications</name>
<value>realtime_group</value>
</property>
<!-- default:兜底 10% -->
<property>
<name>yarn.scheduler.capacity.root.default.capacity</name>
<value>10</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.default.maximum-capacity</name>
<value>30</value>
</property>
</configuration>要点:同一层级的 capacity 之和必须等于 100,否则配置刷新会失败或行为异常;maximum-capacity 不能小于 capacity。
二级队列与资源比例计算
二级队列沿用同一套语义,root.etl.queues 定义子队列,子队列 capacity 之和为 100:
<property>
<name>yarn.scheduler.capacity.root.etl.queues</name>
<value>report,dev</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.etl.report.capacity</name>
<value>60</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.etl.dev.capacity</name>
<value>40</value>
</property>以 1000 vcore 的集群为例:ETL 保障 40% 即 400 vcore,其中核心报表子队列占 60%(240 vcore)、数据开发占 40%(160 vcore);ETL 上限 60% 意味着最多借到 600 vcore。规划时先把每个业务的 SLA 量化成"最低并发核数",再换算成百分比,而不是凭感觉分配数字。
大数据基础平台 EasyMR
统一存储、计算与运维,支撑批、流、OLAP 与湖仓一体的国产化大数据底座平台
Capacity 与 MaxCapacity 的语义
- capacity:队列在集群繁忙时的最低保障比例,是 SLA 的量化表达;
- maximum-capacity:队列能借到的上限;集群有空闲时,低保障队列可以借到自己的 maximum-capacity,实现"保障 + 弹性";
- user-limit-factor:控制单个用户最多能用该队列多少倍容量(默认 1,即单用户最多用满整个队列),防止一个用户的任务占满共享队列;
- minimum-user-limit-percent:限制单用户在集群繁忙时至少能拿到该队列多少比例的资源,避免某个用户长期占满共享队列;多团队共用的队列建议设置,与 user-limit-factor 配合使用。
典型坑:把所有队列 maximum-capacity 都设 100,等于放弃隔离,低优任务可以在高峰期把高优队列的资源全部借走;反过来 maximum-capacity 设得太死,又浪费空闲资源。折中做法:核心业务队列设 50%-80% 上限,ad-hoc 队列放开到 100%。
ACL:谁能提交,谁能管理
Capacity Scheduler 的 ACL 分两类:
acl_submit_applications:谁能往这个队列提交作业;acl_administer_queue:谁能管理该队列(杀作业、改优先级等)。
写法支持用户和用户组(组名加前缀):user1,user2 group1,group2,默认 * 表示所有人。生产建议:
- 核心队列一律显式列出可提交的用户或组,不依赖默认全开;
- ad-hoc 队列可以放开提交,但配合
yarn.scheduler.maximum-allocation-mb等配额限制单作业资源; - 管理权限收敛给平台运维用户,避免业务方误杀他人作业。
抢占:关键任务的保命手段
抢占(Preemption)解决的是"保障资源被占用、关键任务进不来"的场景。启用方式:
<property>
<name>yarn.resourcemanager.scheduler.monitor.enable</name>
<value>true</value>
</property>
<property>
<name>yarn.resourcemanager.monitor.capacity.preemption.max_wait_before_kill</name>
<value>30000</value>
</property>- 默认策略是 ProportionalCapacityPreemptionPolicy:定期检查各队列是否低于 capacity,超出部分先等空闲资源、再按策略终止低优作业;
- 抢占的代价是杀任务重算:被抢占的任务可能反复失败重试,所以参数要保守——
max_wait_before_kill给足等待时间(默认 15 秒,可调大),total_preemption_per_cycle限制单轮抢占比例; - 强 SLA 队列(realtime、核心 ETL)建议开抢占;ad-hoc 队列通常不开,避免探索型作业互相杀。
先靠容量与弹性解决大部分问题,抢占只作为最后兜底,而不是默认开启。
国产信创
面向国产化替代与信创改造场景,支撑数据平台平滑迁移、统一纳管、性能保障与安全可控。
队列映射与提交规范
队列规划好之后,还要让作业真正落到对的队列里:
- Spark 用
--queue etl.report指定队列,MapReduce 用mapreduce.job.queuename,Flink on YARN 用-yarnqueue; - 业务方不传队列时作业会落到 default,所以 default 容量要小、ACL 要收紧,倒逼业务显式声明队列;
- 如果集群有统一网关或入口层,可以在入口做"用户-队列"映射,把提交规范固化下来,避免业务方随意指定高保障队列。
同时注意:Capacity 是比例不是绝对值,集群扩容后各队列实际资源同比例放大,需要按业务量定期复评,而不是一次配完永久不动。建议每季度按任务数、资源使用率与作业延迟复评一次容量比例;容量调整走"变更 → 低峰刷新 → 观察 1-2 个调度周期"的闭环。
容量调整生效验证
修改 capacity-scheduler.xml 后无需重启 ResourceManager,执行:
yarn rmadmin -refreshQueues然后按下面步骤验证是否真正生效:
- 看 UI:ResourceManager Web UI 的 Scheduler 页签,核对各队列 capacity、maximum-capacity 数值;
- 看日志:RM 日志中应出现队列刷新成功的记录,配置非法时(如容量和不为 100)刷新会报错;
- 实测排队:分别向高优、低优队列提交测试作业,观察 pending 与 running 比例是否符合预期;
- 观察抢占:开启抢占后,制造一次"低优占满、高优提交"的场景,确认高优作业能按预期进入;
- 回归:容量调整影响所有在跑作业的调度,变更放在低峰窗口,观察 1-2 个调度周期再继续。
注意:绝大多数参数通过 -refreshQueues 即时生效,但队列层级结构(新增或删除队列)在部分版本需要重启 RM,变更结构前先确认版本行为,别在高峰期踩坑。
常见失败模式对照
- 某层 capacity 之和不为 100 → 刷新失败,逐层检查;
- maximum-capacity 小于 capacity → 配置非法;
- 全部队列放开 maximum-capacity → 隔离失效,核心任务资源被借走;
- 没配 default 队列 → 未指定队列的作业提交失败;
- ACL 写错(用户或组名不匹配)→ 合法用户被拒,先看
yarn application报错信息定位; - 抢占参数过激进 → 作业反复被杀,宁可先关掉抢占排查容量;
- 只调容量不实测验证 → 配置刷新成功不等于调度行为符合预期,一定要用测试作业实测排队与抢占效果。
队列规划是一次投入、长期受益的工作:先按 SLA 分池定保障与弹性,再收敛 ACL,抢占兜底,最后用刷新验证闭环。集群规模变大后,这类多队列、多租户的调度治理更需要稳定的平台支撑,袋鼠云大数据基础平台 EasyMR 基于开源 Hadoop 自研增强,在一站式平台内提供 YARN 资源调度与 EasyManager 的多集群运维、实时监控告警能力,可以把队列容量变更与集群巡检统一到平台化流程里。


