YARN 资源调度
概述
YARN(Yet Another Resource Negotiator)是 Hadoop 的资源调度平台:它把集群的 CPU 和内存统一收口,按需分配给不同计算框架(MapReduce、Spark、Flink 等)。理解 YARN 的关键是三个概念:资源如何抽象(Container)、谁负责分配(ResourceManager)、怎么分配(调度器)。本文从架构到调度器逐个讲透。
一、YARN 的角色架构
┌──────────────────────────────────────────────┐
│ ResourceManager(RM) │
│ ├─ Scheduler:资源分配决策 │
│ ├─ ApplicationsManager:应用生命周期管理 │
│ └─ 全局资源视图与状态机 │
└──────────────┬───────────────────────────────┘
│ 心跳 / 资源汇报 / 命令下发
┌──────────────┴───────────────────────────────┐
│ NodeManager(NM)× N │
│ ├─ 管理本节点资源与 Container │
│ ├─ 启动/监控/清理 Container │
│ └─ 上报本节点状态给 RM │
└──────────────┬───────────────────────────────┘
│ 提交应用 / 申请资源 / 汇报进度
┌──────────────┴───────────────────────────────┐
│ ApplicationMaster(AM)× 应用 │
│ └─ 每个应用一个,负责向 RM 申请资源 │
│ 并调度任务到 Container 执行 │
└──────────────────────────────────────────────┘| 角色 | 职责 | 部署位置 |
|---|---|---|
| ResourceManager | 全局资源管理、调度、应用管理 | 独立节点(或 HA 双节点) |
| NodeManager | 单节点资源管理、Container 生命周期 | 每台计算节点 |
| ApplicationMaster | 单个应用的任务调度 | 运行在某节点的 Container 中 |
| Container | 资源抽象:CPU + 内存的分配单位 | 节点上动态创建 |
RM 与 NM 解耦资源管理:RM 做全局决策,NM 做本地执行,中间通过心跳通信。
二、资源抽象:Container
Container 是 YARN 的最小资源分配单位,封装 CPU 与内存:
xml
<!-- 单个 Container 的默认资源配置(yarn-site.xml) -->
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>65536</value> <!-- 节点可用总内存 -->
</property>
<property>
<name>yarn.nodemanager.resource.cpu-vcores</name>
<value>32</value> <!-- 节点可用总 vcore -->
</property>
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>1024</value> <!-- 最小内存单元 -->
</property>
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>16384</value> <!-- 最大内存单元 -->
</property>特点:
- 资源分配以 Container 为单位,按需申请、用完释放
- AM 可以动态向 RM 申请更多 Container(扩容)或释放(缩容)
- 资源隔离:内存由操作系统隔离,CPU 通过 vcore 配额控制
三、应用执行流程
以提交一个 MapReduce 作业为例:
1. Client 提交应用 → RM(ApplicationsManager 创建应用状态机)
2. RM 为应用分配第一个 Container(AM 容器)
3. 应用启动 ApplicationMaster
4. AM 向 RM 的 Scheduler 申请资源(Container)
5. RM 分配可用节点上的 Container
6. AM 通过 NM 启动 Container,运行任务(Map/Reduce)
7. AM 持续监控任务进度,失败则重新申请执行
8. 应用完成,AM 注销,RM 回收资源Client RM NM AM Container
│提交│ │ │ │
├────▶ │ │ │
│ │分配AM│ │ │
│ ├────▶ │ │
│ │ │启动AM│
│ │ ├────▶ │
│ │ 申请资源 │
│ │◀────────────┤
│ │ 分配 Container
│ │─────────────────▶
│ │ NM 启动 Container
│ │ ──────────────▶
│ │ 任务执行...
│◀──┤ 完成/注销关键机制
| 机制 | 说明 |
|---|---|
| AM 失败重启 | AM 崩溃后由 RM 重新分配 Container 重启,作业不丢失 |
| 任务失败重试 | Container 中的任务失败,AM 重新申请执行 |
| 节点故障 | NM 心跳超时,RM 把该节点 Container 标记失败并重调度 |
| 资源释放 | 作业完成后所有 Container 归还集群 |
四、调度器:资源怎么分
YARN 提供三种调度器,在 yarn-site.xml 中配置:
xml
<property>
<name>yarn.resourcemanager.scheduler.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler</value>
</property>4.1 FIFO Scheduler
队列:单个先进先出队列
┌────────────┐
│ 作业A(大) │ ← 先提交,占满资源
│ 作业B │ ← 必须等 A 完成
└────────────┘| 优点 | 缺点 |
|---|---|
| 实现简单、吞吐高 | 先来先服务,小作业被大作业阻塞,无优先级 |
适用:单用户、作业类型单一的实验环境。
4.2 Capacity Scheduler(默认)
按队列预留容量分配资源:
根队列
├── 离线队列(50%)── 批处理作业
├── 实时队列(30%)── 交互式查询
└── 默认队列(20%)
队列间:容量隔离,可弹性借用(借出的资源任务到达时可抢占回来)
队列内:支持 FIFO 与优先级| 特性 | 说明 |
|---|---|
| 容量保证 | 每个队列保证最低容量 |
| 弹性 | 空闲队列容量可被其他队列借用 |
| 抢占(preemption) | 借出的资源可被抢回,保证容量承诺 |
| 多租户 | 按团队/业务划分队列,互不饿死 |
配置示例(capacity-scheduler.xml):
xml
<property>
<name>yarn.scheduler.capacity.root.queues</name>
<value>offline,realtime,default</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.offline.capacity</name>
<value>50</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.realtime.capacity</name>
<value>30</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.default.capacity</name>
<value>20</value>
</property>适用:多团队共享集群、需要容量隔离的生产环境。
4.3 Fair Scheduler
公平分享:所有运行中的作业平均获得资源,新作业到达时资源被重新分配:
作业A:50%(独占)
作业B 提交 → A 降到 50%,B 得 50%
作业C 提交 → 各得 33%| 特性 | 说明 |
|---|---|
| 公平性 | 作业间按权重均分资源 |
| 动态调整 | 新作业到达自动重新分配 |
| 权重 | 支持配置队列权重(weight) |
| 抢占 | 延迟调度(delay scheduling)、资源抢占 |
适用:多用户共享、希望作业间公平竞争的场景。
4.4 三种调度器对比
| 维度 | FIFO | Capacity | Fair |
|---|---|---|---|
| 核心思想 | 先来先服务 | 队列容量保证 | 作业公平分享 |
| 响应及时性 | 差 | 中 | 好 |
| 吞吐 | 高 | 中高 | 中 |
| 多租户 | 不支持 | 好 | 好 |
| 抢占 | 无 | 有 | 有 |
| 适用 | 实验环境 | 生产主流 | 多用户共享 |
五、调度器选择建议
| 场景 | 推荐 |
|---|---|
| 多团队共享、容量隔离 | Capacity(业界主流) |
| 用户多、作业杂、追求公平 | Fair |
| 单用户测试 | FIFO |
选择时重点考虑:是否有明确的业务队列边界、是否容忍资源抢占、作业响应时延要求。
六、资源隔离与安全
| 机制 | 说明 |
|---|---|
| 内存隔离 | Container 内存超限被 NM 杀掉(cgroup) |
| CPU 隔离 | cgroup 限制 CPU 配额 |
| 磁盘隔离 | Container 本地目录配额 |
| 队列访问控制 | ACL 控制谁可以向队列提交作业 |
| 认证 | Kerberos 认证用户身份 |
常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
| 作业一直等待 | 队列资源不足 / AM 未获取容器 | 检查队列容量、应用并发 |
| Container 被杀 | 内存超限(OOM) | 调大 container 内存或优化作业 |
| 队列间资源抢占告警 | 抢占开启且容量紧张 | 调整容量配比与抢占策略 |
| 节点资源被占满 | NM 配置过大 | 校验 yarn.nodemanager.resource.* |
七、YARN 与计算框架的关系
| 框架 | 运行方式 |
|---|---|
| MapReduce | 作业直接提交到 YARN,经典组合 |
| Spark | Spark on YARN(yarn-client / yarn-cluster 模式) |
| Flink | Flink on YARN,Session / Per-Job 模式 |
| Tez | 供 Hive 等上层框架使用 |
YARN 的价值在于多框架共存:一套集群资源,批、流、SQL 各取所需,互不抢占——这就是"通用资源调度"的意义。
八、小结
| 维度 | 要点 |
|---|---|
| 架构 | RM 全局调度 + NM 本地执行 + AM 应用管理 |
| 资源 | Container = CPU + 内存的最小分配单位 |
| 流程 | 提交 → 启 AM → 申请容器 → 执行任务 → 释放 |
| 调度器 | FIFO 简单、Capacity 容量隔离、Fair 公平分享 |
| 生产选择 | 多租户用 Capacity,多用户公平用 Fair |
参考链接: