YARN — 资源调度
什么是 YARN
YARN(Yet Another Resource Negotiator)是 Hadoop 2.0 引入的集群资源管理系统,将资源管理与作业调度分离,使 Hadoop 集群不再局限于 MapReduce,可以运行 Spark、Flink、Tez 等多种计算框架。
核心设计目标:
- 资源管理与计算框架解耦
- 多租户资源隔离
- 高可用(ResourceManager HA)
- 细粒度资源分配(CPU + 内存)
架构设计
┌─────────────────────────────────────────────────────────────┐
│ YARN 集群 │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ ResourceManager(RM) │ │
│ │ - 全局资源管理 │ │
│ │ - 接收应用提交 │ │
│ │ - 调度器(Scheduler) │ │
│ │ - ApplicationManager │ │
│ └──────────────────────────┬───────────────────────────┘ │
│ │ │
│ ┌──────────────────────────▼───────────────────────────┐ │
│ │ NodeManager(NM)集群 │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ │ │
│ │ │ NodeManager 1 │ │ NodeManager 2 │ │ │
│ │ │ Container │ │ Container │ │ │
│ │ │ [AM] │ │ [Task] │ │ │
│ │ │ Container │ │ Container │ │ │
│ │ │ [Task] │ │ [Task] │ │ │
│ │ └─────────────────┘ └─────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘核心组件:
- ResourceManager(RM):全局资源管理,负责资源分配和调度
- NodeManager(NM):节点资源管理,启动和监控 Container
- ApplicationMaster(AM):每个应用的管理者,向 RM 申请资源
- Container:资源分配单位(CPU + 内存),在 NM 上运行
作业提交流程
1. 客户端提交应用(spark-submit / flink run)
│
▼
2. ResourceManager 分配 Container,启动 ApplicationMaster
│
▼
3. ApplicationMaster 向 RM 注册,申请资源(Container)
│
▼
4. RM 根据调度策略分配 Container(在哪个 NM 上)
│
▼
5. AM 与对应 NM 通信,启动 Container(运行 Task)
│
▼
6. Task 执行,AM 监控进度
│
▼
7. 应用完成,AM 向 RM 注销,释放资源调度器
FIFO 调度器
最简单,先进先出,不支持多队列,不适合生产环境。
Capacity 调度器(默认)
xml
<!-- capacity-scheduler.xml -->
<configuration>
<!-- 定义队列 -->
<property>
<name>yarn.scheduler.capacity.root.queues</name>
<value>default,production,development</value>
</property>
<!-- 各队列容量(百分比,总和 = 100) -->
<property>
<name>yarn.scheduler.capacity.root.default.capacity</name>
<value>20</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.production.capacity</name>
<value>60</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.development.capacity</name>
<value>20</value>
</property>
<!-- 最大容量(可以借用空闲资源) -->
<property>
<name>yarn.scheduler.capacity.root.production.maximum-capacity</name>
<value>80</value>
</property>
<!-- 用户限制(单用户最多使用队列的 50%) -->
<property>
<name>yarn.scheduler.capacity.root.production.user-limit-factor</name>
<value>0.5</value>
</property>
</configuration>Fair 调度器
公平调度,所有应用平均分配资源,支持抢占:
xml
<!-- fair-scheduler.xml -->
<allocations>
<queue name="production">
<minResources>10000 mb, 10 vcores</minResources>
<maxResources>90000 mb, 90 vcores</maxResources>
<weight>3</weight>
<schedulingPolicy>fair</schedulingPolicy>
</queue>
<queue name="development">
<minResources>5000 mb, 5 vcores</minResources>
<weight>1</weight>
</queue>
<!-- 抢占配置 -->
<defaultMinSharePreemptionTimeout>300</defaultMinSharePreemptionTimeout>
<fairSharePreemptionTimeout>600</fairSharePreemptionTimeout>
</allocations>提交作业到指定队列
bash
# Spark 提交到 production 队列
spark-submit \
--master yarn \
--queue production \
--driver-memory 4g \
--executor-memory 8g \
--executor-cores 4 \
--num-executors 20 \
myapp.jar
# MapReduce 提交到指定队列
hadoop jar myapp.jar MyJob \
-Dmapreduce.job.queuename=production \
input output资源配置
xml
<!-- yarn-site.xml -->
<!-- NodeManager 可用内存(根据机器内存设置,留 20% 给 OS) -->
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>24576</value> <!-- 24GB -->
</property>
<!-- NodeManager 可用 CPU 核数 -->
<property>
<name>yarn.nodemanager.resource.cpu-vcores</name>
<value>16</value>
</property>
<!-- Container 最小内存 -->
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>1024</value>
</property>
<!-- Container 最大内存 -->
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>16384</value>
</property>
<!-- 开启 cgroup 资源隔离(CPU 隔离) -->
<property>
<name>yarn.nodemanager.container-executor.class</name>
<value>org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor</value>
</property>常用命令
bash
# 查看集群资源
yarn node -list
yarn node -status <node-id>
# 查看队列信息
yarn queue -status default
yarn queue -status production
# 查看应用列表
yarn application -list
yarn application -list -appStates RUNNING
yarn application -list -appTypes SPARK
# 查看应用详情
yarn application -status <application-id>
# 终止应用
yarn application -kill <application-id>
# 查看应用日志
yarn logs -applicationId <application-id>
yarn logs -applicationId <application-id> -containerId <container-id>
# 查看 ResourceManager 状态
yarn rmadmin -getServiceState rm1
yarn rmadmin -getServiceState rm2
# 刷新队列配置(不重启)
yarn rmadmin -refreshQueues
# 查看节点标签
yarn node -list -showDetailsYARN HA 配置
xml
<!-- yarn-site.xml -->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>yarn-cluster</value>
</property>
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>rm-host1</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>rm-host2</value>
</property>
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>zk1:2181,zk2:2181,zk3:2181</value>
</property>
<!-- 自动故障切换 -->
<property>
<name>yarn.resourcemanager.ha.automatic-failover.enabled</name>
<value>true</value>
</property>节点标签(Node Labels)
节点标签用于将不同硬件配置的节点分组,实现精细化调度:
bash
# 添加节点标签
yarn rmadmin -addToClusterNodeLabels "gpu,ssd,highmem"
# 给节点打标签
yarn rmadmin -replaceLabelsOnNode "node1:gpu node2:gpu node3:ssd"
# 队列绑定标签
# capacity-scheduler.xml
# yarn.scheduler.capacity.root.gpu-queue.accessible-node-labels=gpu
# yarn.scheduler.capacity.root.gpu-queue.accessible-node-labels.gpu.capacity=100bash
# 提交作业到 GPU 节点
spark-submit \
--master yarn \
--queue gpu-queue \
--conf spark.yarn.am.nodeLabelExpression=gpu \
--conf spark.executor.nodeLabelExpression=gpu \
myapp.jar