4.2 YARN 资源调度与管理 4.2 YARN 资源调度与管理 4.2.1 YARN 资源管理框架概述 YARN的设计目标是将资源管理和作业调度/监控的功能从早期的MapReduce框架中分离出来,从而支持更多类型的计算框架(如MapReduce,Spark,Flink等)运行在Hadoop集群之上。YARN的核心思想是将集群资源抽象成可分配的“容器”(Container),并由资源管理器(ResourceManager)统一管理和调度这些容器资源。 YARN 架构的关键组件包括: ResourceManager (RM): 整个集群的资源管理器,负责集群资源的统一管理和调度。
YARN的设计目标是将资源管理和作业调度/监控的功能从早期的MapReduce框架中分离出来,从而支持更多类型的计算框架(如MapReduce,Spark,Flink等)运行在Hadoop集群之上。YARN的核心思想是将集群资源抽象成可分配的“容器”(Container),并由资源管理器(ResourceManager)统一管理和调度这些容器资源。
YARN 架构的关键组件包括:
ResourceManager (RM): 整个集群的资源管理器,负责集群资源的统一管理和调度。RM包含两个主要组件:
Scheduler (调度器): 根据应用程序的资源需求和调度策略,为应用程序分配资源 (Containers)。
ApplicationsManager (应用程序管理器): 负责管理集群中运行的所有应用程序,包括接受应用程序提交、启动ApplicationMaster以及监控ApplicationMaster的生命周期。
NodeManager (NM): 运行在集群中每个节点上的代理,负责管理节点上的资源和容器生命周期。NM定期向RM汇报节点资源使用情况,并接收和执行来自RM的容器管理指令。
ApplicationMaster (AM): 每个应用程序的管理者,负责与RM协商资源,并与NM协同工作来执行和监控Task。AM的主要职责包括:
向RM请求资源 (Containers)。
将应用程序的任务分解成具体的Task。
与NM通信,启动、监控和管理Container中的Task执行。
在Task执行失败时进行容错处理。
Containers: YARN 中的资源分配单位,是对节点上资源的抽象表示。一个Container 封装了一定量的CPU、内存、磁盘和网络资源。应用程序在Container中运行Task。
使用 Mermaid 绘制 YARN 资源管理框架图:
图 4.2-1 YARN 资源管理框架示意图
如上图所示,客户端提交应用程序到ResourceManager,ResourceManager负责资源调度和应用程序管理。每个应用程序都有一个ApplicationMaster,负责向ResourceManager请求资源,并将Task分配到NodeManager上的Container中执行。
YARN 资源调度的核心目标是有效地将集群资源分配给不同的应用程序,以满足各种应用程序的资源需求,并最大化集群资源的利用率。YARN 的调度器组件负责实现资源调度功能。
YARN 提供了多种调度器供用户选择,常见的调度器类型包括:
FIFO Scheduler (先进先出调度器): 最简单的调度器,将应用程序放入一个队列中,按照提交顺序依次执行。先提交的应用程序先获得资源,后提交的应用程序需要等待前面的应用程序执行完成释放资源后才能开始执行。
特点:
简单易实现。
容易造成资源饥饿,小作业可能需要等待大作业执行完成才能获得资源。
不适合多用户和多应用程序的生产环境。
Capacity Scheduler (容量调度器): 允许多个组织共享同一个Hadoop集群,通过容量队列的方式为每个组织分配一部分集群资源。每个队列都配置了最小容量和最大容量,保证每个组织能够获得一定的资源,同时也允许队列在资源空闲时使用超出其最小容量的资源。
特点:
支持多租户,可以为不同组织或用户分配不同的资源。
提供容量保证,每个队列可以获得最小资源容量。
队列之间可以共享资源,提高集群资源利用率。
支持队列的层次结构,方便资源管理和分配。
适用于需要资源隔离和容量保证的多用户环境。
Fair Scheduler (公平调度器): 目标是在所有运行的应用程序之间公平地分配资源。Fair Scheduler 将资源划分为调度池 (Pools),每个用户或组可以拥有一个或多个调度池。在每个调度池内,资源会在所有正在运行的应用程序之间公平共享。
特点:
公平共享资源,每个应用程序可以获得大致相同的资源份额。
支持最小资源保证,每个调度池可以配置最小资源份额。
支持资源抢占 (Preemption),当某个应用程序需要的资源超过其公平份额时,可以抢占其他应用程序的资源。
支持层次化的调度池结构,方便资源管理和分配。
适用于需要公平共享资源和动态资源分配的环境。
调度器选择:
选择哪种调度器取决于集群的使用场景和需求:
FIFO Scheduler: 适用于简单测试或开发环境,不推荐用于生产环境。
Capacity Scheduler: 适用于需要资源隔离和容量保证的多租户环境,例如企业内部的不同部门共享集群。
Fair Scheduler: 适用于需要公平共享资源和动态资源分配的环境,例如公有云平台或多用户共享的集群。
Capacity Scheduler 是生产环境中常用的调度器,它通过容量队列来管理资源。
Capacity Scheduler 的核心概念:
队列 (Queue): 资源分配的基本单位,每个队列都分配了一定的集群资源容量。队列可以是父队列或子队列,形成层次结构。
容量 (Capacity): 每个队列被分配的资源百分比,表示队列可以使用的最小资源量。
最大容量 (Maximum Capacity): 队列可以使用的最大资源百分比,即使集群有空闲资源,队列使用的资源也不能超过最大容量。
用户限制 (User Limit): 限制单个用户在队列中可以使用的资源百分比,防止单个用户过度占用队列资源。
状态 (State): 队列的状态,可以是 RUNNING (运行中) 或 STOPPED (停止)。
ACL (Access Control List): 访问控制列表,用于控制哪些用户可以向队列提交应用程序。
Capacity Scheduler 的队列层次结构:
Capacity Scheduler 支持多级队列层次结构,方便资源管理和分配。根队列 root 是所有队列的父队列,所有其他队列都是根队列的子队列或子孙队列。
使用 Mermaid 绘制 Capacity Scheduler 队列层次结构图:
图 4.2-2 Capacity Scheduler 队列层次结构示意图
Capacity Scheduler 配置示例 (capacity-scheduler.xml):
<?xml version="1.0"?> <configuration> <property> <name>yarn.scheduler.capacity.root.queues</name> <value>queueA,queueB</value> <description>Root queue's children queues.</description> </property> <property> <name>yarn.scheduler.capacity.root.queueA.capacity</name> <value>50</value> <description>Capacity of queue A in percentage.</description> </property> <property> <name>yarn.scheduler.capacity.root.queueA.maximum-capacity</name> <value>70</value> <description>Maximum capacity of queue A in percentage.</description> </property> <property> <name>yarn.scheduler.capacity.root.queueA.user-limit-factor</name> <value>1</value> <description>User limit factor for queue A.</description> </property> <property> <name>yarn.scheduler.capacity.root.queueA.state</name> <value>RUNNING</value> <description>State of queue A.</description> </property> <property> <name>yarn.scheduler.capacity.root.queueB.capacity</name> <value>50</value> <description>Capacity of queue B in percentage.</description> </property> <property> <name>yarn.scheduler.capacity.root.queueB.maximum-capacity</name> <value>100</value> <description>Maximum capacity of queue B in percentage.</description> </property> <property> <name>yarn.scheduler.capacity.root.queueB.user-limit-factor</name> <value>1</value> <description>User limit factor for queue B.</description> </property> <property> <name>yarn.scheduler.capacity.root.queueB.state</name> <value>RUNNING</value> <description>State of queue B.</description> </property> <!-- 可以继续配置子队列,例如 queueA 的子队列 --> <property> <name>yarn.scheduler.capacity.root.queueA.queues</name> <value>queueA1,queueA2</value> <description>Children queues of queue A.</description> </property> <property> <name>yarn.scheduler.capacity.root.queueA.queueA1.capacity</name> <value>60</value> <description>Capacity of queue A1 in percentage within queue A.</description> </property> <property> <name>yarn.scheduler.capacity.root.queueA.queueA2.capacity</name> <value>40</value> <description>Capacity of queue A2 in percentage within queue A.</description> </property> </configuration>
代码 4.2-1 Capacity Scheduler 配置文件示例
上述配置示例定义了两个顶级队列 queueA 和 queueB,分别分配了 50% 的容量。queueA 的最大容量为 70%,queueB 的最大容量为 100%。queueA 下面又定义了两个子队列 queueA1 和 queueA2,分别分配了 queueA 容量的 60% 和 40%。
Fair Scheduler 的目标是在所有应用程序之间公平地分配资源。它使用调度池 (Pools) 来组织资源,每个调度池可以配置最小资源份额、权重等属性。
Fair Scheduler 的核心概念:
调度池 (Pool): 资源分配的逻辑分组,可以根据用户、组或项目等划分调度池。
最小份额 (Minimum Share): 每个调度池保证可以获得的最小资源量。
权重 (Weight): 用于在调度池之间分配资源的比例,权重越高的调度池可以获得更多的资源。
抢占 (Preemption): 当某个调度池需要的资源超过其公平份额时,可以抢占其他调度池的资源。
放置约束 (Placement Constraints): 可以配置调度池的放置约束,例如指定调度池只能在特定的节点组上运行。
Fair Scheduler 的调度过程:
资源分配计算: Fair Scheduler 会定期计算每个调度池的公平资源份额,根据调度池的权重和当前集群的可用资源计算。
资源分配: Scheduler 会尽量满足每个调度池的最小资源份额,并在剩余资源中根据权重比例分配资源。
资源抢占: 如果某个调度池需要的资源超过其公平份额,并且集群资源紧张,Fair Scheduler 可以抢占其他调度池正在使用的资源,以保证资源分配的公平性。
Fair Scheduler 配置示例 (fair-scheduler.xml):
<?xml version="1.0"?> <allocations> <pool name="poolA"> <minResources>1024 MB, 1 vcores</minResources> <maxResources>2048 MB, 2 vcores</maxResources> <weight>2.0</weight> <schedulingPolicy>fair</schedulingPolicy> </pool> <pool name="poolB"> <minResources>512 MB, 0.5 vcores</minResources> <maxResources>1024 MB, 1 vcores</maxResources> <weight>1.0</weight> <schedulingPolicy>fair</schedulingPolicy> </pool> <user name="user1"> <maxRunningApps>5</maxRunningApps> <pool>poolA</pool> </user> <user name="user2"> <maxRunningApps>3</maxRunningApps> <pool>poolB</pool> </user> <defaultQueueSchedulingPolicy>fair</defaultQueueSchedulingPolicy> </allocations>
代码 4.2-2 Fair Scheduler 配置文件示例
上述配置示例定义了两个调度池 poolA 和 poolB。poolA 的最小资源为 1024MB 内存和 1 个 vcore,最大资源为 2048MB 内存和 2 个 vcores,权重为 2.0。poolB 的最小资源为 512MB 内存和 0.5 个 vcore,最大资源为 1024MB 内存和 1 个 vcores,权重为 1.0。用户 user1 属于 poolA,用户 user2 属于 poolB。
应用程序通过 ApplicationMaster 向 ResourceManager 请求资源。资源请求与分配流程通常如下:
ApplicationMaster 发送资源请求: ApplicationMaster 根据应用程序的需求,向 ResourceManager 发送资源请求,请求指定数量和类型的 Container。资源请求通常包括 CPU 核心数、内存大小等。
Scheduler 调度决策: ResourceManager 的 Scheduler 接收到资源请求后,根据当前集群资源使用情况和调度策略 (例如 Capacity Scheduler 或 Fair Scheduler),进行调度决策,选择合适的 NodeManager 分配 Container。
ResourceManager 分配 Container: ResourceManager 向选定的 NodeManager 发送 Container 分配指令,指定 Container 的资源规格和启动命令。
NodeManager 启动 Container: NodeManager 接收到 Container 分配指令后,在本地节点上启动 Container,并为 Container 分配指定的资源。
ApplicationMaster 接收 Container 信息: ResourceManager 将分配的 Container 信息 (例如 Container ID,NodeManager 地址等) 返回给 ApplicationMaster。
ApplicationMaster 启动 Task: ApplicationMaster 接收到 Container 信息后,与 NodeManager 通信,在 Container 中启动应用程序的 Task。
使用 Mermaid 绘制 资源请求与分配流程图:
图 4.2-3 资源请求与分配流程示意图
YARN 除了资源调度外,还负责集群资源的有效管理,包括资源隔离、资源监控和资源回收等。
YARN 通过 Container 技术实现资源隔离,每个 Container 运行在独立的进程环境中,拥有独立的资源配额 (CPU、内存等)。资源隔离可以防止不同应用程序之间的资源竞争和干扰,提高集群的稳定性和性能。
YARN 的资源隔离主要体现在以下几个方面:
CPU 隔离: 使用 Linux Cgroups 等技术限制 Container 可以使用的 CPU 核心数。
内存隔离: 使用 Linux Cgroups 等技术限制 Container 可以使用的内存大小。
磁盘 I/O 隔离: 限制 Container 可以使用的磁盘 I/O 带宽。
网络 I/O 隔离: 限制 Container 可以使用的网络 I/O 带宽。
YARN 提供全面的资源监控功能,可以实时监控集群的资源使用情况、应用程序的资源消耗情况等。监控信息可以通过 Web UI 或 API 接口获取。
YARN 资源监控主要包括:
集群资源监控: 监控集群的总资源量、可用资源量、已使用资源量等。
节点资源监控: 监控每个节点的 CPU 使用率、内存使用率、磁盘使用率、网络流量等。
队列资源监控 (Capacity Scheduler): 监控每个队列的已用容量、剩余容量、正在运行的应用程序数量等。
调度池资源监控 (Fair Scheduler): 监控每个调度池的已用资源、剩余资源、正在运行的应用程序数量等。
应用程序资源监控: 监控每个应用程序的 Container 数量、资源消耗量、运行状态等。
Container 资源监控: 监控每个 Container 的 CPU 使用率、内存使用率等。
当应用程序完成或发生错误时,YARN 会回收应用程序使用的 Container 资源,以便将资源重新分配给其他应用程序使用。资源回收过程由 NodeManager 负责,NodeManager 会定期向 ResourceManager 汇报 Container 的状态,ResourceManager 根据 Container 状态决定是否回收资源。
资源回收的主要流程包括:
Container 完成/失败: Container 中的 Task 执行完成或发生错误导致 Container 失败。
NodeManager 上报 Container 状态: NodeManager 检测到 Container 完成或失败,向 ResourceManager 上报 Container 状态。
ResourceManager 回收 Container 资源: ResourceManager 收到 Container 状态上报后,将 Container 标记为已完成或已失败,并回收 Container 占用的资源。
资源释放: NodeManager 释放 Container 占用的资源,例如 CPU、内存等。
本节将演示如何配置 YARN 使用 Capacity Scheduler 或 Fair Scheduler。
1. 配置 Capacity Scheduler:
修改 yarn-site.xml 配置文件,设置 yarn.resourcemanager.scheduler.class 属性为 org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler:
<property> <name>yarn.resourcemanager.scheduler.class</name> <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler</value> </property>
然后,配置 capacity-scheduler.xml 文件,定义队列层次结构和队列属性,例如 代码 4.2-1 所示的配置。
2. 配置 Fair Scheduler:
修改 yarn-site.xml 配置文件,设置 yarn.resourcemanager.scheduler.class 属性为 org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler:
<property> <name>yarn.resourcemanager.scheduler.class</name> <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value> </property>
然后,配置 fair-scheduler.xml 文件,定义调度池和调度策略,例如 代码 4.2-2 所示的配置。
3. 重启 ResourceManager 和 NodeManager:
修改配置文件后,需要重启 ResourceManager 和 NodeManager 服务,使配置生效。
# 重启 ResourceManager stop-yarn.sh start-yarn.sh # 或者分别重启 ResourceManager 和 NodeManager yarn-daemon.sh stop resourcemanager yarn-daemon.sh start resourcemanager yarn-daemon.sh stop nodemanager yarn-daemon.sh start nodemanager
注意: 在生产环境中修改 YARN 配置需要谨慎操作,建议在测试环境充分验证配置的正确性后再应用到生产环境。
本章节详细介绍了 YARN 的资源调度与管理机制,包括 YARN 资源管理框架、常见的调度器类型 (FIFO Scheduler, Capacity Scheduler, Fair Scheduler)、资源请求与分配流程、资源隔离、资源监控和资源回收等关键概念。通过代码实践,演示了如何配置 YARN 调度器。
理解 YARN 资源调度与管理对于高效运行 Hadoop 集群至关重要。合理选择和配置调度器,可以充分利用集群资源,满足不同应用程序的资源需求,并提高集群的整体性能和稳定性。在实际应用中,需要根据具体的业务场景和需求,选择合适的调度器和配置策略,并持续监控和优化集群资源管理,以达到最佳的资源利用率和应用程序性能。