YARN 多租户资源隔离与队列调度配置实践

覆盖 Capacity Scheduler vs Fair Scheduler 选择、标签调度与队列容量弹性伸缩的完整配置

袋鼠云
袋鼠云
国产信创

YARN 多租户资源隔离的核心方案是:通过 Capacity Scheduler 的层级队列配置划分资源配额,结合 NodeLabel 实现物理节点级别的隔离,再利用资源抢占机制保障高优先级任务的资源供给。这套组合拳能从根本上解决"大任务饿死小任务"和"团队间资源互相挤占"的问题。

Capacity Scheduler 与 Fair Scheduler 的选型决策

在 YARN 的两大调度器中,Capacity Scheduler 是多租户场景的首选,原因在于它原生支持层级队列(Parent Queue 与 Leaf Queue 的树形结构)、容量保证(每个队列有 minimum and maximum capacity 硬约束)以及用户限制(user-limit-factor 控制单用户可超量使用的比例)。Fair Scheduler 虽然在纯共享场景下表现良好,但它的多级队列支持较弱,抢占逻辑也更简单,在大规模多租户集群中容易出现配置漂移。

选型时关注三个判断条件:第一,团队数量是否超过 5 个,超过则 Capacity Scheduler 的层级队列更易管理;第二,是否需要对不同团队设置资源使用上限(max capacity),这是 Capacity Scheduler 的原生能力,Fair Scheduler 需要额外插件;第三,是否需要在队列间实现资源借贷(即 A 队列空闲时 B 队列可临时使用),两者都支持,但 Capacity Scheduler 的容量弹性(maximum capacity 可设为大于 100% 的等效值)更精细。

实际生产环境中,绝大多数企业级 Hadoop 集群使用 Capacity Scheduler。如果你的团队正从 Fair Scheduler 迁移,核心工作是将 fair-scheduler.xml 中的队列定义转换为 capacity-scheduler.xml 中的 yarn.scheduler.capacity.<queue-path>.capacity 系列参数。

队列层级设计:从组织架构到资源拓扑

合理的队列设计应该映射真实的组织资源关系。一个典型的三层队列结构如下:

根队列(root) 作为集群的总容器,不直接运行任务。父队列(如 prod 和 dev) 按业务性质划分,prod 承载线上作业,dev 承载开发测试。叶队列(如 prod.etl、prod.ml、dev.sandbox) 是任务实际提交的目标。

配置容量时遵循两个原则:同级队列的 capacity 之和必须等于 100;max capacity 用于防止某个队列在空闲时段过度膨胀导致其他队列无法及时回收资源。例如 prod 队列的 capacity 设为 70%,max capacity 设为 85%;dev 队列 capacity 设为 30%,max capacity 设为 60%。这意味着 dev 队列在 prod 空闲时最多可用 60% 的集群资源,而非全部资源,从而避免 prod 突然有大批任务提交时 dev 占满了所有资源导致的冷启动延迟。

一个常见错误是将 max capacity 设为 100%,这会导致弹性资源借贷完全失效。另一个错误是叶队列的 capacity 之和不等于其父队列的 capacity,这在视觉上容易被忽略但会导致调度器行为异常。

大数据基础平台 EasyMR

统一存储、计算与运维,支撑批、流、OLAP 与湖仓一体的国产化大数据底座平台

了解产品

NodeLabel:从逻辑隔离到物理隔离

Capacity Scheduler 的队列隔离是逻辑层面的——所有队列共享同一组节点,只是通过配额控制使用比例。当某些任务对硬件有特殊需求(如 GPU 节点给 ML 训练、高内存节点给 Hive 查询)时,需要 NodeLabel 实现物理隔离。

NodeLabel 的工作方式是给节点打标签(如 gpu、highmem、ssd),然后在队列配置中绑定特定标签。例如 prod.ml 队列只分配到标记为 gpu 的节点上运行任务。具体配置步骤:首先在 yarn-site.xml 中启用标签功能(yarn.node-labels.enabled=true),指定标签存储目录;其次通过 yarn rmadmin 命令创建标签并分配给节点;最后在队列配置中设置 yarn.scheduler.capacity.<queue-path>.accessible-node-labels。

需要特别注意的是,NodeLabel 的资源隔离是单向的——标记了 gpu 标签的节点只能被绑定了 gpu 标签的队列使用,但没有标签的节点可以被所有队列使用。这意味着如果某个队列的标签节点不够用,它不会自动回退到无标签节点,而是直接失败。因此在规划标签节点数量时要留出 20% 左右的余量。

资源抢占:保证 SLA 的最后一道防线

当高优先级队列的资源被低优先级队列占用时,资源抢占(Resource Preemption)机制会回收被占用的容器。Capacity Scheduler 从 2.6 版本开始支持抢占,需要显式开启(yarn.scheduler.capacity.<queue-path>.preemption.enabled=true)。

抢占涉及四个关键参数:min-container-preemption-limit 定义单次回收的最小容器数,preemption-utilization 定义触发抢占的利用率阈值(默认 0.8,即队列使用率低于 80% 时才会被抢占),max-mam-container-preemption-seconds 定义最大抢占等待时间。

生产环境中建议分阶段启用抢占:先在 dev 队列上测试,确认不会误杀 prod 的关键任务;然后配置监控告警,当抢占频率超过每小时 5 次时触发人工审查;最后在 prod 内部也配置抢占,确保 ETL 和 ML 训练任务之间有优先级区分。

一个容易踩的坑是抢占的粒度——YARN 的抢占是基于资源百分比的,如果高优队列需要 40% 的资源而当前只用了 30%,它会尝试回收足够的容器来弥补这 10% 的差距。但如果低优队列里运行的都是大容器,实际回收的资源量可能超过或不足目标值。

国产信创

面向国产化替代与信创改造场景,支撑数据平台平滑迁移、统一纳管、性能保障与安全可控。

了解解决方案

队列容量弹性伸缩的实操配置

静态配额在业务波动时容易造成资源浪费。Capacity Scheduler 支持动态调整队列容量,核心手段有两种:一是通过 API 动态修改队列的 capacity 和 max capacity,无需重启 ResourceManager;二是结合 YARN 的标签系统在不同时段调整节点分配。

动态调整队列容量的操作流程:使用 yarn rmadmin -refreshQueue 命令刷新配置,该命令会读取更新后的 capacity-scheduler.xml 并立即生效。建议将这个流程封装成定时脚本或运维工具,例如白天将 prod 的 capacity 从 70% 提升到 80%,夜间将 dev 的 max capacity 放宽到 70% 以支持批量测试。

需要注意的是,容量调整不会迁移已经在运行的容器。如果 prod 队列已经占用了 80% 的资源,现在要把它的 max capacity 降到 70%,已经运行的任务不会被终止,只有新提交的任务会受到新限制。这时需要配合抢占机制才能真正释放超额资源。

对于使用袋鼠云 EasyMR 平台的团队,其内置的资源治理模块可以在可视化界面上完成队列容量调整、NodeLabel 分配和抢占策略配置,省去了手动编辑配置文件和执行命令行的步骤。平台还会自动监控各队列的资源使用趋势,在容量即将耗尽时发出预警。

失败模式与避坑指南

队列嵌套过深:层级超过三层会显著增加调试难度,且 ResourceManager 的配置解析开销也会增长。建议保持两到三层。

用户限制配置不当:user-limit-factor 默认为 1.0,意味着单个用户最多只能使用其队列的 100% 容量。如果同一团队内有多个用户提交任务,需要将此值设为大于 1(如 1.5),否则团队内部也会出现资源争夺。

忽略 AM 资源占用:Application Master 本身会占用队列资源(yarn.scheduler.capacity.<queue-path>.maximum-am-resource-percent),默认值为 0.1。如果队列里运行大量小任务,AM 资源占比会迅速上升,挤压实际计算资源。建议根据任务特征调整这个参数,小任务密集的队列可以设为 0.15,大任务为主的队列设为 0.05。

标签节点维护遗漏:新增节点后需要手动分配标签,否则新节点默认不带任何标签,不会被标签绑定的队列使用。建议在节点上线流程中加入标签分配检查步骤。

开启Data+AI 之旅

填写表单,获取专属解决方案

400-002-1024

工作日 9:00-18:00

关注公众号

获取最新产品动态与技术干货

关注公众号

企业微信

扫码添加企业微信