0%

Yarn

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
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 两个队列,daily 占 80%,dev 占 20% -->
<property>
<name>yarn.scheduler.capacity.root.queues</name>
<value>daily,dev</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.daily.capacity</name>
<value>80</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.dev.capacity</name>
<value>20</value>
</property>

优点:不同部门/业务隔离,互不影响。
缺点:某个队列的资源如果闲置,别的队列也用不了。

场景:多租户生产环境,需要资源隔离。

3. Fair 调度器——动态平分

不固定划分资源,而是所有应用动态共享。两个应用同时跑,各分 50%;三个应用各分 33%。

优点:资源利用率高,小作业也能快速拿到资源。
缺点:配置稍复杂,小作业有启动延迟(因为要等资源动态分配)。

场景:共享集群,大量小作业和混合负载。

配置示例(fair-scheduler.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<allocations>  
<!-- 队列权重配置 -->
<queue name="daily">
<weight>80</weight> <!-- 权重 80 -->
<schedulingPolicy>fair</schedulingPolicy> <!-- 队列内按公平策略 -->
</queue>
<queue name="dev">
<weight>20</weight> <!-- 权重 20 -->
</queue>

<!-- 应用放置策略 -->
<queuePlacementPolicy>
<rule name="specified" /> <!-- 优先使用指定队列 -->
<rule name="default" queue="daily" /> <!-- 默认放入 daily 队列 -->
</queuePlacementPolicy>
</allocations>

三种调度器怎么选?

场景 推荐调度器 原因
单用户、测试 FIFO 最简单
多部门共享集群,需要资源配额保障 Capacity 队列隔离,保障 SLA
大量小作业 + 混合负载 Fair 资源利用率高,小作业响应快
不知道选什么 Fair 大部分场景最通用

一句话总结调度器:

  • FIFO:排队,一个做完下一个才能上
  • Capacity:分几个窗口排队,各窗口独立
  • Fair:不排队,所有人按需平分
调度器配置
1
2
3
4
5
<!-- 指定调度器类型(Capacity/Fair) -->  
<property>
<name>yarn.resourcemanager.scheduler.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler</value>
</property>

核心配置参数:给 NodeManager 划资源

每个 NodeManager 节点能提供多少 CPU 和内存给 YARN,需要配置。这是 YARN 最重要的参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 该节点可分配的总资源 -->
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>12288</value> <!-- 12GB,预留一部分给操作系统 -->
</property>
<property>
<name>yarn.nodemanager.resource.cpu-vcores</name>
<value>6</value> <!-- 6核,预留2核给操作系统 -->
</property>

<!-- 单个 Container 的最小/最大规格 -->
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>1024</value> <!-- 最小1GB -->
</property>
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>8192</value> <!-- 最大8GB -->
</property>

配置原则:

  • memory-mbcpu-vcores 给 YARN 用的资源,要预留系统资源(通常留 20% 给 OS)
  • minimum-allocation 设太小 → 调度开销大;设太大 → 小任务浪费资源
  • 一般:最小 1GB/1核,最大按节点资源 70% 设

两个经常开的”保命”开关

1
2
3
4
5
6
7
8
9
10
11
<!-- 关掉物理内存检查 -->
<property>
<name>yarn.nodemanager.pmem-check-enabled</name>
<value>false</value>
</property>

<!-- 关掉虚拟内存检查 -->
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>

为什么关? 这两个参数默认开启,会检查 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>

欢迎关注我的其它发布渠道