YARN 深度解析:分布式资源调度框架,到底在调度什么?
在 Hadoop 1.x 时代,JobTracker 既要管资源分配、又要管任务调度,还要管容错——一个组件扛所有,成了单点瓶颈,而且只支持 MapReduce。
YARN 的出现把 JobTracker 拆了:
- ResourceManager:管资源(CPU、内存)
- ApplicationMaster:管应用的执行逻辑
- NodeManager:管单节点上的资源
拆开之后,每个组件只做一件事,而且任何计算框架(MapReduce、Spark、Flink)都可以跑在 YARN 上——只要实现自己的 ApplicationMaster 就行。
YARN 的四个核心组件
| 组件 | 角色 | 类比 |
|---|---|---|
| ResourceManager(RM) | 全局资源总管 | 公司总部,管总预算 |
| NodeManager(NM) | 单节点资源管家 | 每个部门的行政,管本部门资源 |
| ApplicationMaster(AM) | 单个应用的调度员 | 项目经理,管自己的项目 |
| Container | 资源的容器 | 工位 + 电脑 + 工时的组合包 |
它们之间怎么配合?
flowchart TD
subgraph 集群节点
A[ResourceManager
全局资源管理器]
B[NodeManager
节点资源管理器]
C[NodeManager
节点资源管理器]
end
subgraph 应用程序
D[ApplicationMaster
应用主控]
E[Container
资源容器]
F[Container
资源容器]
end
A -- 资源分配 --> B
A -- 资源分配 --> C
A -- 启动/监控 --> D
D -- 申请资源 --> A
D -- 管理任务 --> E
D -- 管理任务 --> F
B -- 提供容器 --> E
C -- 提供容器 --> F
不是 RM 直接调度任务,RM 只管分配资源,具体的任务调度由每个应用的 AM 自己管。
一个 MapReduce 作业在 YARN 上怎么跑
第 1 步:提交作业
客户端向 RM 提交作业。RM 为这个作业启动一个 ApplicationMaster(MRAppMaster)。
第 2 步:AM 申请资源
AM 分析作业需要多少个 Map 和 Reduce 任务,向 RM 申请对应数量的 Container。
第 3 步:启动任务
AM 拿到 Container 后,告诉对应的 NM 在这些 Container 里启动 Map/Reduce 任务。
第 4 步:任务运行
Map 任务运行期间,AM 持续监控它们的状态。有任务失败了,AM 负责重新申请 Container 重启任务。
第 5 步:作业完成
所有任务完成后,AM 向 RM 汇报,释放所有 Container,AM 自己退出。
关键认知:RM 只负责”给资源”,不负责”怎么跑”。 怎么跑是 AM 的事。所以 Spark 有 Spark AM,Flink 有 Flink AM,各自管各自的。
三种调度器:怎么分配资源?
RM 把资源分给各应用,但”怎么分”由调度器决定。YARN 提供三种。
1. FIFO 调度器——先来先服务
所有应用排一个队,先提交的先拿资源,后提交的等着。
优点:简单,不用配置。
缺点:大作业堵后面所有小作业。
场景:单用户、测试集群。生产环境别用。
2. Capacity 调度器——划分几个固定队列
把资源切成几块(比如 80% 给生产队列,20% 给开发队列),每个队列内部按 FIFO 排队。
1 | <!-- 两个队列,daily 占 80%,dev 占 20% --> |
优点:不同部门/业务隔离,互不影响。
缺点:某个队列的资源如果闲置,别的队列也用不了。
场景:多租户生产环境,需要资源隔离。
3. Fair 调度器——动态平分
不固定划分资源,而是所有应用动态共享。两个应用同时跑,各分 50%;三个应用各分 33%。
优点:资源利用率高,小作业也能快速拿到资源。
缺点:配置稍复杂,小作业有启动延迟(因为要等资源动态分配)。
场景:共享集群,大量小作业和混合负载。
配置示例(fair-scheduler.xml)
1 | <allocations> |
三种调度器怎么选?
| 场景 | 推荐调度器 | 原因 |
|---|---|---|
| 单用户、测试 | FIFO | 最简单 |
| 多部门共享集群,需要资源配额保障 | Capacity | 队列隔离,保障 SLA |
| 大量小作业 + 混合负载 | Fair | 资源利用率高,小作业响应快 |
| 不知道选什么 | Fair | 大部分场景最通用 |
一句话总结调度器:
- FIFO:排队,一个做完下一个才能上
- Capacity:分几个窗口排队,各窗口独立
- Fair:不排队,所有人按需平分
调度器配置
1 | <!-- 指定调度器类型(Capacity/Fair) --> |
核心配置参数:给 NodeManager 划资源
每个 NodeManager 节点能提供多少 CPU 和内存给 YARN,需要配置。这是 YARN 最重要的参数。
1 | <!-- 该节点可分配的总资源 --> |
配置原则:
memory-mb和cpu-vcores给 YARN 用的资源,要预留系统资源(通常留 20% 给 OS)minimum-allocation设太小 → 调度开销大;设太大 → 小任务浪费资源- 一般:最小 1GB/1核,最大按节点资源 70% 设
两个经常开的”保命”开关
1 | <!-- 关掉物理内存检查 --> |
为什么关? 这两个参数默认开启,会检查 Container 的内存使用是否超出限制。但很多应用(尤其是 Spark)实际内存使用和 YARN 统计的有偏差,容易被误杀。生产环境通常关掉,用其他方式监控。
几个常见问题
1. 作业一直卡在 ACCEPTED 状态
说明在等资源。原因可能是:
- 集群资源满了,所有节点都在跑任务
- 单个 Container 申请的内存太大,没有节点能满足
- 队列容量限制达到上限
排查: 看 RM Web UI 的队列资源使用情况。如果资源满了,等现有任务结束;如果 Container 规格太大,调小 maximum-allocation-mb。
2. 任务被 NodeManager 杀掉
日志里看到 Container is running beyond memory limits。
可能是:
yarn.nodemanager.pmem-check-enabled=true导致内存超限被杀死- 应用实际内存超出申请量
解决: 关掉 pmem-check,或者调大 Container 内存申请量。
3. 节点被加入黑名单
AM 在某个节点上连续失败多次,RM 会把这个节点加入黑名单,不再分配任务。
排查节点本身的硬件或网络问题,修好后手动刷新黑名单:
1 | yarn node -update -blacklist -expire <expiry_time> |