YARN Capacity Scheduler (容量调度器) 不完全指南

本文翻译自Hadoop 官网,简要介绍YARN Capacity Scheduler (容量调度器) 及其主要配置。本文基于Hadoop 3.3.1。

简介

YARN 的调度器,包括 Capacity Scheduler (容量调度器),都是可插拔的 Hadoop 调度程序。容量调度器允许多租户安全地共享一个大型集群,以便应用程序在配额的限制下及时分配资源,同时最大限度地提高集群的吞吐量和利用率。其中心思想是 Hadoop 集群中的可用资源在多个组织之间共享,各个组织也可以访问其他人未使用的任何多余容量。这以具有成本效益的方式为组织提供了弹性。

跨组织共享集群需要对多租户的强大支持,因为每个组织都必须保证容量和安全措施,以确保共享集群不受单个流氓应用程序、用户或其集合的影响。容量调度器提供了一组严格的限制,以确保单个应用程序、用户或队列不会消耗集群中不成比例的资源。容量调度器提供的主要抽象是队列,它们通常由管理员设置,同时支持分层队列,以确保在允许其他队列使用空闲资源之前,在组织的子队列之间共享资源,从而实现让一个组织的应用程序之间共享空闲资源的特性。

功能

  • 分层队列 (Hierarchical Queues):支持队列分层结构,以确保在允许其他队列使用空闲资源之前在组织的子队列之间共享资源。
  • 容量保证 (Capacity Guarantees):队列被分配了一定的资源容量,提交到队列的所有应用程序都可以访问分配给队列的容量。管理员可以对分配给每个队列的容量配置软限制和可选的硬限制。
  • 安全性 (Security):每个队列都有严格的 ACL,用于控制哪些用户可以向哪些队列提交应用程序。此外,还有一些安全措施可确保用户无法查看和/或修改其他用户的应用程序。此外,还支持队列管理员和系统管理员角色。
  • 弹性 (Elasticity):可用资源可以分配给超出其容量的任何队列。当容量不足的队列需要这些资源时,随着这些资源上调度的任务完成,它们将分配给这些队列上的应用程序(也支持抢占)。这确保了资源以可预测和弹性的方式提供给队列,从而防止集群中的人为资源孤岛。
  • 多租户 (Multi-tenancy):提供全面的限制以防止单个应用程序、用户和队列从整体上独占队列或集群的资源。
  • 可操作性 (Operability):
    • 运行时配置 (Runtime Configuration):管理员可以在运行时以安全的方式更改队列定义和属性(例如容量、ACL)。管理员可以在运行时添加其他队列,但不能在运行时删除队列,除非队列已停止且没有挂起或正在运行的应用程序。
    • 排空应用程序 (Drain applications):管理员可以在运行时停止队列,以确保在现有应用程序运行完成前,不会提交新应用程序。如果队列处于 STOPPED 状态,则无法将新应用程序提交给其自身或其任何子队列。现有的应用程序继续完成,因此可以优雅地排空队列。
  • 基于资源的调度 (Resource-based Scheduling):支持资源密集型应用程序,可以选择指定比默认值更高的资源需求,从而适应具有不同资源需求的应用程序。目前该调度支持内存资源。
  • 基于默认或用户定义的放置规则的队列映射接口 (Queue Mapping Interface based on Default or User Defined Placement Rules):此功能允许用户根据某些默认放置规则将作业映射到特定队列。例如基于用户和组,或应用程序名称。用户还可以定义自己的放置规则。
  • 优先级调度 (Priority Scheduling):此功能允许以不同的优先级提交和调度应用程序。较高的整数值表示应用程序的优先级较高。目前仅 FIFO 排序策略支持应用程序优先级。
  • 绝对资源配置 (Absolute Resource Configuration):管理员可以为队列指定绝对资源,而不是提供基于百分比的值。
  • 子队列的动态自动创建和管理 (Dynamic Auto-Creation and Management of Leaf Queues):此功能支持与队列映射结合自动创建子队列,当前支持基于用户组的队列映射,以便将应用程序放置到队列。调度器还支持基于父队列上配置的策略对这些队列进行容量管理。

配置

使用CapacityScheduler

要让ResourceManager使用CapacityScheduler,在yarn-site.xml里进行如下配置(当前版本为默认值):

  • yarn.resourcemanager.scheduler.class: org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler

配置队列

capacity-scheduler.xml是CapacityScheduler的配置文件。CapacityScheduler 有一个名为 root 的预定义队列。系统中的所有队列都是该队列的子队列。CapacityScheduler 的配置使用称为队列路径的概念来配置队列的层次结构,队列路径是队列层次结构的完整路径,从 root 开始,以 .(点)作为分隔符。可以通过配置以下项目定义给定队列的子级,从root开始:yarn.scheduler.capacity.<queue-path>.queues。除非另有说明,否则子队列不会直接从父队列继承属性。

如下是一个示例,在root下有abc三个子队列,ab分别又有自己的子队列:

capacity-scheduler.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<property>
<name>yarn.scheduler.capacity.root.queues</name>
<value>a,b,c</value>
<description>当前等级的队列,root表示根队列</description>
</property>

<property>
<name>yarn.scheduler.capacity.root.a.queues</name>
<value>a1,a2</value>
<description>当前等级的队列,root表示根队列</description>
</property>

<property>
<name>yarn.scheduler.capacity.root.b.queues</name>
<value>b1,b2,b3</value>
<description>当前等级的队列,root表示根队列</description>
</property>

队列属性

资源分配

  • yarn.scheduler.capacity.<queue-path>.capacity:队列容量百分比 (%),值为浮点数(例如 12.5);或作为绝对资源分配的最小容量。每个级别的所有队列的容量总和必须等于 100,但是如果配置了绝对资源,则子队列的绝对资源总和可能小于其父队列的绝对资源容量。如果有空闲资源,队列中的应用程序可能会消耗比队列容量更多的资源。
  • yarn.scheduler.capacity.<queue-path>.maximum-capacity:最大队列容量百分比 (%),值为浮点数;或作为绝对资源分配的最大容量。这限制了队列中应用程序的弹性。浮点数的值介于 0 和 100 之间,管理员需要确保每个队列的绝对最大容量大于等于绝对容量。此外,将此值设置为 -1 会将最大容量设置为 100%。
  • yarn.scheduler.capacity.<queue-path>.minimum-user-limit-percent:如果有资源需求,每个队列都会在任何时刻强制限制分配给用户的资源百分比。用户限制可以在最小值和最大值之间变化,但不会小于此设置值。例如,假设该属性的值为 25,如果两个用户向一个队列提交了应用程序,则没有一个用户可以使用超过 50% 的队列资源。如果第三个用户提交程序,则没有一个用户可以使用超过 33% 的队列资源。对于 4 个或更多用户,任何用户都不能使用超过 25% 的队列资源。值为 100 表示不施加用户限制,默认值为 100,值指定为整数。
  • yarn.scheduler.capacity.<queue-path>.user-limit-factor:队列容量的倍数,可配置为允许单个用户获取更多资源。默认情况下,它设置为 1,这确保单个用户永远不会占用超过队列配置的容量,而不管集群有多空闲。值指定为浮点数。
  • yarn.scheduler.capacity.<queue-path>.maximum-allocation-mb:每个队列在资源管理器上分配给每个容器请求的最大内存限制。此设置覆盖集群配置 yarn.scheduler.maximum-allocation-mb。该值必须小于等于集群最大值。
  • yarn.scheduler.capacity.<queue-path>.maximum-allocation-vcores:每个队列在资源管理器中分配给每个容器请求的虚拟内核的最大限制。此设置会覆盖集群配置 yarn.scheduler.maximum-allocation-vcores。该值必须小于或等于集群最大值。
  • yarn.scheduler.capacity.<queue-path>.user-settings.<user-name>.weight:此浮点值用于计算队列中的用户限制资源值。该值将使每个用户的权重大于或小于队列中的其他用户。例如,如果用户 A 在队列中接收的资源比用户 B 和 C 多 50%,则用户 A 的此属性将设置为 1.5。用户 B 和 C 将默认为 1.0。

资源分配(使用绝对资源配置)

CapacityScheduler 支持绝对资源的配置,而不是按百分比提供队列容量。正如上面对 yarn.scheduler.capacity.<queue-path>.capacityyarn.scheduler.capacity.<queue-path>.max-capacity 的配置部分所述,管理员可以指定一个绝对资源值,如 [memory=10240,vcores=12]。 这表示 10GB 内存和 12 个 VCore。

正在运行和挂起的应用程序限制

CapacityScheduler 支持以下参数来控制正在运行和挂起的应用程序:

  • yarn.scheduler.capacity.maximum-applications / yarn.scheduler.capacity.<queue-path>.maximum-applications:系统中可以同时处于运行和挂起状态的最大应用程序数量。每个队列的限制与其队列容量和用户限制成正比。这是一个硬性限制,当达到此限制时提交的任何应用程序都将被拒绝。默认值为 10000。
  • yarn.scheduler.capacity.maximum-am-resource-percent / yarn.scheduler.capacity.<queue-path>.maximum-am-resource-percent:集群中可用于运行Application Master的最大资源百分比,以控制并发应用程序的数量。每个队列的限制与其队列容量和用户限制成正比。值为浮点数,即 0.5 = 50%。默认值为 10%。
  • yarn.scheduler.capacity.max-parallel-apps / yarn.scheduler.capacity.<queue-path>.max-parallel-apps:可以同时运行的最大应用程序数量。与 maximum-applications 不同,当达到此限制时,程序提交不会被拒绝,相反,它们保持在 ACCEPTED 状态,直到可以运行。默认情况下没有限制。

还可以限制每个用户的并行应用程序数量:

  • yarn.scheduler.capacity.user.max-parallel-apps:所有用户同时运行的最大应用程序数。默认无限制。
  • yarn.scheduler.capacity.user.<username>.max-parallel-apps:特定用户同时运行的最大应用程序数,会覆盖全局设置。

这些限制采用以下顺序进行评估:

  • maximum-applications:如果超过限制,提交将立即被拒绝。
  • max-parallel-apps:提交被接受,但应用程序不会转换到 RUNNING 状态,而是保持在 ACCEPTED 状态直到满足队列或用户限制。
  • maximum-am-resource-percent:如果有太多的 Application Master 正在运行,应用程序将保持在 ACCEPTED 状态,直到有足够的资源。

队列管理和权限

CapacityScheduler 支持以下参数来管理队列:

  • yarn.scheduler.capacity.<queue-path>.state:队列的状态,可以是 RUNNING 或 STOPPED 之一。如果队列处于 STOPPED 状态,则无法将新应用程序提交给其自身或其任何子队列。现有的应用程序可以继续完成,因此可以优雅地排空队列。
  • yarn.scheduler.capacity.root.<queue-path>.acl_submit_applications:控制谁可以向给定队列提交应用程序的 ACL。如果给定用户或组在给定队列或其某个父队列上具有必要的 ACL,则可以提交应用程序。如果未指定,此队列属性的 ACL 将从父队列继承。
  • yarn.scheduler.capacity.root.<queue-path>.acl_administer_queue:控制谁可以管理给定队列上的应用程序的 ACL。如果给定用户或组在给定队列或其某个父队列上具有必要的 ACL,则他们可以管理应用程序。如果未指定,此队列属性的 ACL 将从父队列继承。

ACL 的格式为 user1,user2 space group1,group2。 特殊值 * 表示任何人,空格则表示没有人。如果未指定,则默认为 * 用于 root 队列。

基于用户或组、应用程序名称或用户定义放置规则的队列映射

CapacityScheduler 支持以下参数来配置基于用户或组、用户和组,或应用程序名称的队列映射。用户还可以定义自己的放置规则:

  • yarn.scheduler.capacity.queue-mappings:该配置指定用户或组到特定队列的映射。可以将单个用户或用户列表映射到队列。语法为 [u or g]:[name]:[queue_name][,next_mapping]*。这里,ug 表示映射是针对用户还是针对组。用户的值是 u,组的值是 gname 表示用户名或组名。要指定为提交应用程序的用户,可以使用 %userqueue_name 指定应用程序必须映射到的队列名称。要指定与用户名相同的队列名称,可以使用 %user。要指定与用户所属的主要组名称相同的队列名称,可以使用 %primary_group。次要组可以引用为 %secondary_group
  • yarn.scheduler.queue-placement-rules.app-name:该配置指定 application_name 到特定队列的映射。可以将单个或多个应用程序映射到队列。语法为 [app_name]:[queue_name][,next_mapping]*。这里,app_name 表示要进行映射的应用程序名称。 queue_name 表示应用程序映射到的队列名称。要将当前应用程序的名称指定为 app_name,可以使用 %application
  • yarn.scheduler.capacity.queue-mappings-override.enable:用于指定是否可以覆盖用户指定的队列。这是一个布尔值,默认值为 false。

下面的示例均表示单个映射。如果使用逗号分隔值进行多个映射,则从左到右进行评估,并且将使用第一个有效映射。下面的示例顺序已根据运行时的实际执行顺序记录,以防止多重映射发生。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<property>
<name>yarn.scheduler.capacity.queue-mappings</name>
<value>u:%user:%primary_group.%user</value>
<description>用户映射的队列为用户名本身,父队列名称为主要用户组</description>
</property>
...
<property>
<name>yarn.scheduler.capacity.queue-mappings</name>
<value>u:%user:%secondary_group.%user</value>
<description>用户映射的队列为用户名本身,父队列名称为次要用户组</description>
</property>
...
<property>
<name>yarn.scheduler.capacity.queue-mappings</name>
<value>u:%user:%user</value>
<description>用户映射的队列为用户名本身</description>
</property>
...
<property>
<name>yarn.scheduler.capacity.queue-mappings</name>
<value>u:user2:%primary_group</value>
<description>user2映射到主要用户组表示的队列名</description>
</property>
...
<property>
<name>yarn.scheduler.capacity.queue-mappings</name>
<value>u:user3:%secondary_group</value>
<description>user3映射到次要用户组表示的队列名</description>
</property>
...
<property>
<name>yarn.scheduler.capacity.queue-mappings</name>
<value>u:user1:queue1</value>
<description>user1映射到queue1</description>
</property>
...
<property>
<name>yarn.scheduler.capacity.queue-mappings</name>
<value>g:group1:queue2</value>
<description>group1映射到queue2</description>
</property>
...
<property>
<name>yarn.scheduler.capacity.queue-mappings</name>
<value>u:user1:queue1,u:user2:queue2</value>
<description>user1映射到queue1,user2映射到queue2<description>
</property>

<property>
<name>yarn.scheduler.queue-placement-rules.app-name</name>
<value>appName1:queue1,%application:%application</value>
<description>appName1映射到queue1,否则使用与应用程序相同的队列名</description>
</property>

应用程序的队列生命周期

CapacityScheduler 支持以下应用程序生命周期的参数:

  • yarn.scheduler.capacity.<queue-path>.maximum-application-lifetime:提交到队列的应用程序的最大生命周期(以秒为单位)。任何小于或等于零的值都将被视为禁用。默认值为 -1。如果配置为正值,则提交到此队列的任何应用程序将在超过配置的生命周期后被杀死。用户还可以在应用程序提交上下文中指定每个应用程序的生命周期。但是,如果超过队列最大生命周期,用户生命周期将被覆盖。子队列将继承其父队列的值,也可以覆盖。 0 表示没有最大生命周期,并将覆盖父队列的设置。如果此属性未设置或设置为负数,则此队列的最大生命周期值将从其父队列继承。
  • yarn.scheduler.capacity.root.<queue-path>.default-application-lifetime:提交到队列的应用程序的默认生命周期(以秒为单位)。任何小于或等于零的值都将被视为禁用。如果提交应用升序时未设置最大生命周期,将会使用此值。子队列将继承其父队列的值,也可以覆盖。如果设置为小于或等于 0,则队列的最大值也必须是无限制的。默认生命周期不能超过最大生命周期。

应用程序优先级设置

应用程序优先级仅与 FIFO 排序策略一起使用。默认排序策略为 FIFO。应用程序的默认优先级可以是集群级别和队列级别。

  • 集群级别优先级:任何提交的优先级高于集群最大优先级的应用程序都将其优先级重置为集群最大优先级。使用 $HADOOP_HOME/etc/hadoop/yarn-site.xml 中的 yarn.cluster.max-application-priority配置项。
  • 子队列级别优先级:每个子队列由管理员提供默认优先级。队列的默认优先级将用于任何未指定优先级提交的应用程序。 使用 $HADOOP_HOME/etc/hadoop/capacity-scheduler.xml 中的 yarn.scheduler.capacity.root.<leaf-queue-path>.default-application-priority 配置项。

当应用程序移动到不同的队列时,应用程序的优先级不会改变。

CapacityScheduler 容器抢占 (Container Preemption)

CapacityScheduler 支持从资源使用量超过其保证容量的队列中抢占容器。为了支持抢占应用容器,需要在yarn-site.xml中开启以下配置参数:

  • yarn.resourcemanager.scheduler.monitor.enable:启用一组影响调度器的定期监控程序(在 yarn.resourcemanager.scheduler.monitor.policies 中指定)。默认值为 false
  • yarn.resourcemanager.scheduler.monitor.policies:与调度器交互的 SchedulingEditPolicy 类的列表。配置的策略需要与调度器兼容。默认值为 org.apache.hadoop.yarn.server.resourcemanager.monitor.capacity.ProportionalCapacityPreemptionPolicy, 与 CapacityScheduler 兼容。

在上述配置使用ProportionalCapacityPreemptionPolicy类时,可以在yarn-site.xml中使用以下配置参数来控制容器的抢占:

  • yarn.resourcemanager.monitor.capacity.preemption.observe_only:如果为 true,则运行策略,但不影响具有抢占功能的集群和终止事件。默认值为 false
  • yarn.resourcemanager.monitor.capacity.preemption.monitoring_interval:调用此策略的间隔时间(以毫秒为单位)。默认值为 3000。
  • yarn.resourcemanager.monitor.capacity.preemption.max_wait_before_kill:从应用程序请求抢占到终止容器之间的时间(以毫秒为单位)。默认值为 15000。
  • yarn.resourcemanager.monitor.capacity.preemption.total_preemption_per_round:单轮抢占资源的最大百分比。通过控制这个值,可以限制从集群中回收容器的速度。默认值为 0.1。
  • yarn.resourcemanager.monitor.capacity.preemption.max_ignored_over_capacity:超过目标容量并进行抢占时,最大可忽略的资源量。这定义了目标容量周围的死区,有助于防止计算的目标平衡值周围的颠簸和振荡。较高值会减缓达到容量的时间,并且(没有 natural.completions 时)它可能会阻止收敛到保证容量。默认值为 0.1。
  • yarn.resourcemanager.monitor.capacity.preemption.natural_termination_factor:给定一个计算的抢占目标,考虑容器自然过期并仅抢占该百分比的差值。这决定了几何收敛到死区的速率 (MAX_IGNORED_OVER_CAPACITY)。例如,终止因子为 0.5 将在 5 * #WAIT_TIME_BEFORE_KILL 内回收近 95% 的资源,即使没有自然终止。默认值为 0.2。

CapacityScheduler 支持在 capacity-scheduler.xml 中进行以下配置来控制对提交到队列的应用容器的抢占:

  • yarn.scheduler.capacity.<queue-path>.disable_preemption:此配置可以设置为 true 以选择性地禁用提交给给定队列的应用程序容器的抢占。此属性仅当将 yarn.resourcemanager.scheduler.monitor.enable 配置为 true 并将 yarn.resourcemanager.scheduler.monitor.policies 配置为 ProportionalCapacityPreemptionPolicy 来启用系统范围的抢占时适用。
  • yarn.scheduler.capacity.<queue-path>.intra-queue-preemption.disable_preemption:此配置可以设置为 true 以选择性地禁用提交给给定队列的应用程序容器的队列内抢占。此属性仅当将 yarn.resourcemanager.scheduler.monitor.enable 配置为 trueyarn.resourcemanager.scheduler.monitor.policies 配置为ProportionalCapacityPreemptionPolicy 来启动系统范围的抢占、以及 yarn.resourcemanager.monitor.capacity.preemption.intra-queue-preemption.enabledtrue 时适用。

预订属性 (Reservation Properties)

CapacityScheduler 支持以下参数来控制预订的创建、删除、更新和列表。请注意,任何用户都可以更新、删除或列出他们自己的预订。如果预订 ACL 已启用但未定义,则每个人都可以访问。

  • yarn.scheduler.capacity.root.<queue>.acl_administer_reservations:控制谁可以管理给定队列的预订的 ACL。如果未指定,此属性的 ACL 不会从父队列继承。
  • yarn.scheduler.capacity.root.<queue>.acl_list_reservations:控制谁可以列出给定队列的预订的 ACL。如果未指定,则此属性的 ACL 不会从父队列继承。
  • yarn.scheduler.capacity.root.<queue>.acl_submit_reservations:控制谁可以向给定队列提交预订的 ACL。如果未指定,则此属性的 ACL 不会从父队列继承。

使用 CapacityScheduler 配置预订系统 (ReservationSystem)

CapacityScheduler 支持 ReservationSystem,允许用户提前预订资源。应用程序可以通过在提交时指定reservationId 实现在运行时请求预订资源。 ReservationSystem 可以在 yarn-site.xml 中配置以下参数:

  • yarn.resourcemanager.reservation-system.enable: 必选参数,启用 ResourceManager 中的 ReservationSystem。默认值为 false。
  • yarn.resourcemanager.reservation-system.class: 可选参数,ReservationSystem 的类名。默认值是根据配置的调度器选择的,如果配置了 CapacityScheduler,则此项为 CapacityReservationSystem。
  • yarn.resourcemanager.reservation-system.plan.follower: 可选参数,在定时器上运行的 PlanFollower 的类名,将 CapacityScheduler 与 Plan 之间互相同步。默认值是根据配置的调度器选择的,如果配置了 CapacityScheduler,则此项为 CapacitySchedulerPlanFollower。
  • yarn.resourcemanager.reservation-system.planfollower.time-step: 可选参数,PlanFollower 计时器的频率(以毫秒为单位),默认值为 1000。

ReservationSystem 与 CapacityScheduler 队列层次结构集成,目前可以为任何子队列进行配置。 CapacityScheduler 支持通过以下参数来调整 ReservationSystem:

  • yarn.scheduler.capacity.<queue-path>.reservable: 必选参数,向ReservationSystem 表明队列的资源可供用户预订。默认值为 false。
  • yarn.scheduler.capacity.<queue-path>.reservation-agent: 可选参数,将用于确定 ReservationAgent 实现的类名,它会尝试将用户的预订请求放入 Plan 中。默认值为 org.apache.hadoop.yarn.server.resourcemanager.reservation.planning.AlignedPlannerWithGreedy
  • yarn.scheduler.capacity.<queue-path>.reservation-move-on-expiry: 可选参数,用于向 ReservationSystem 指定当关联的预订到期时,是否将应用移动到父预订队列或终止。默认值为 true,表示应用将移至可预订队列。
  • yarn.scheduler.capacity.<queue-path>.show-reservations-as-queues: 可选参数,用于在调度器 UI 中显示或隐藏预订队列。默认值为 false。
  • yarn.scheduler.capacity.<queue-path>.reservation-policy: 可选参数,用于确定 SharingPolicy 实现的类名,它将验证新预订是否遵循任何不变量。默认值是 org.apache.hadoop.yarn.server.resourcemanager.reservation.CapacityOverTimePolicy
  • yarn.scheduler.capacity.<queue-path>.reservation-window: 可选参数,表示如果满足 Plan 中的约束条件,SharingPolicy 将保持验证的时间(以毫秒为单位)。默认值为1天。
  • yarn.scheduler.capacity.<queue-path>.instantaneous-max-capacity: 可选参数,表示 SharingPolicy 允许单个用户在任何时间预订的最大容量。以百分比表示,默认值为 1,即 100%。
  • yarn.scheduler.capacity.<queue-path>.average-capacity: 可选参数,表示 SharingPolicy 允许单个用户预订的平均容量,该平均数将在 ReservationWindow 上总计。以百分比表示,默认值为 1,即 100%。
  • yarn.scheduler.capacity.<queue-path>.reservation-planner: 可选参数,用于确定当 Plan 容量低于(由于计划维护或节点故障)用户预订的资源时将调用的 Planner 实现。默认值为 org.apache.hadoop.yarn.server.resourcemanager.reservation.planning.SimpleCapacityReplanner,它扫描 Plan 并以相反的接受顺序 (LIFO) 贪婪地删除预订,直到预订的资源在 Plan 的容量内。
  • yarn.scheduler.capacity.<queue-path>.reservation-enforcement-window: 可选参数,表示如果满足 Plan 中的约束条件,Planner 将保持验证的时间(以毫秒为单位)。默认值为1小时。

子队列的动态自动创建和管理

CapacityScheduler 支持在启用此功能的父队列下自动创建子队列。

实现动态创建子队列所需的队列映射设置

yarn.scheduler.capacity.queue-mappings 中列出的用户组队列映射需要指定一个额外的父队列参数来标识需要在哪个父队列下自动创建子队列。 请注意,此类父队列还需要启用子队列的自动创建。举例如下:

1
2
3
4
5
6
7
8
<property>
<name>yarn.scheduler.capacity.queue-mappings</name>
<value>u:user1:queue1,g:group1:queue2,u:user2:%primary_group,u:%user:parent1.%user</value>
<description>
在这里,u:%user:parent1.%user 允许除了 user1,user2 之外的用户映射到与
它们名字相同的特定子队列,这些子队列在 parent1 之下,并将会自动创建。
</description>
</property>

父队列配置以实现动态自动创建与管理子队列

动态自动创建队列和管理功能与 CapacityScheduler 队列层次结构集成,可以为当前的父队列进行配置以自动创建子队列。此类父队列不支持其他预配置队列与自动创建的队列共存。 CapacityScheduler 支持以下参数来启用队列的自动创建:

  • yarn.scheduler.capacity.<queue-path>.auto-create-child-queue.enabled:必选参数,向 CapacityScheduler 指示需要为指定的父队列启用自动创建子队列。默认值为 false
  • yarn.scheduler.capacity.<queue-path>.auto-create-child-queue.management-policy:可选参数,用于确定 AutoCreatedQueueManagementPolicy 的实现的类名,该类名将动态管理子队列及其容量。默认值为 org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.queuemanagement.GuaranteedOrZeroCapacityOverTimePolicy。用户或组可能使用这些队列的时间很短,并很快停用它们。因此,在父队列下自动创建的子队列数量可能多于其保证容量。

使用 CapacityScheduler 配置自动创建的子队列

已启用自动创建子队列的父队列支持配置子队列的模板参数。自动创建的队列支持除队列 ACL、绝对资源配置之外的所有子队列配置参数。队列 ACL 则从当前父队列继承。

  • yarn.scheduler.capacity.<queue-path>.leaf-queue-template.capacity:必选参数,指定自动创建子队列的最小保证容量。当前自动创建的子队列不支持绝对资源配置。
  • yarn.scheduler.capacity.<queue-path>.leaf-queue-template.<leaf-queue-property>:可选参数,可以在自动创建的子队列上配置的其他队列参数,如 maximum-capacityuser-limit-factor 等。

示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<property>
<name>yarn.scheduler.capacity.root.parent1.auto-create-child-queue.enabled</name>
<value>true</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.parent1.leaf-queue-template.capacity</name>
<value>5</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.parent1.leaf-queue-template.maximum-capacity</name>
<value>100</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.parent1.leaf-queue-template.user-limit-factor</name>
<value>3.0</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.parent1.leaf-queue-template.ordering-policy</name>
<value>fair</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.parent1.GPU.capacity</name>
<value>50</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.parent1.accessible-node-labels</name>
<value>GPU,SSD</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.parent1.leaf-queue-template.accessible-node-labels</name>
<value>GPU</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.parent1.leaf-queue-template.accessible-node-labels.GPU.capacity</name>
<value>5</value>
</property>

用于自动创建队列管理的调度编辑策略配置 (Edit Policy Configuration)

管理员需要在 yarn.resourcemanager.scheduler.monitor.policies 配置中指定一个额外的 org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.QueueManagementDynamicEditPolicy 调度编辑策略到当前调度编辑策略列表中,在配置中以逗号分隔。

  • yarn.resourcemanager.monitor.capacity.queue-management.monitoring-interval:调用此 QueueManagementDynamicEditPolicy 策略之间的时间(以毫秒为单位)。默认值为 1500。

其他配置

资源计算器 (Resource Calculator)

  • yarn.scheduler.capacity.resource-calculator: ResourceCalculator 实现,用于比较调度器中的资源。 默认的 org.apache.hadoop.yarn.util.resource.DefaultResourceCalculator 仅使用内存,而 DominantResourceCalculator 则从多个维度比较主导资源,如内存、CPU 等。

数据局部性 (Data Locality)

CapacityScheduler 利用延迟调度(Dalay Scheduling)来满足任务局部性约束。局部性约束有 3 个级别:节点本地(node-local)、机架本地(rack-local)和关闭开关(off-switch)。当不能满足局部性时,调度器会计算错过的调度机会数量,并等待该计数达到阈值,然后再将局部性约束放宽到下一个级别。可以在以下属性中配置阈值:

  • yarn.scheduler.capacity.node-locality-delay: 错过调度机会的数量,在此之后 CapacityScheduler 尝试调度机架本地(rack-local)容器。通常,这应该设置为集群中的节点数,默认情况下为在一个机架中设置的节点数,大约为 40。值需要为整数。
  • yarn.scheduler.capacity.rack-locality-additional-delay: 超过节点本地(node-local)延迟的额外错过的调度机会数量,在此之后,CapacityScheduler 尝试调度关闭开关(off-switch)容器。默认情况下,此值设置为 -1,在这种情况下,根据公式 L * C / N 计算分配关闭开关(off-switch)容器的错过调度机会的数量,其中 L 是再资源请求里指定的位置(节点或机架)数目,C 是请求的容器数量,N 是集群的大小。

如果 YARN 与文件系统分开部署,则应禁用此功能,因为局部性没有意义。这可以通过将 yarn.scheduler.capacity.node-locality-delay 设置为 -1 来实现,在这种情况下,会忽略请求中的位置约束。

在每个 NodeManager 心跳之中的容器分配

CapacityScheduler 支持以下参数来控制在每个 NodeManager 心跳中可以分配多少容器:

  • yarn.scheduler.capacity.per-node-heartbeat.multiple-assignments-enabled: 是否允许在一个 NodeManager 心跳中分配多个容器。默认为 true。
  • yarn.scheduler.capacity.per-node-heartbeat.maximum-container-assignments: 如果 multiple-assignments-enabled 为 true,则在一次 NodeManager 心跳中可以分配的最大容器数量。默认值为 100,将此值设置为 -1 会禁用此限制。
  • yarn.scheduler.capacity.per-node-heartbeat.maximum-offswitch-assignments: 如果 multiple-assignments-enabled 为 true,则在一个 NodeManager 心跳中可以分配的关闭开关(off-switch)容器的最大数量。 默认为 1。

查看 CapacityScheduler 的配置

在集群安装与配置完成后,可以在 Web UI 里查看配置:

  • 正常启动 YARN 集群
  • 打开 ResourceManager Web UI
  • /scheduler 网页查看各个队列的资源使用情况

更改队列配置

更改队列、调度器属性和添加、删除队列可以通过两种方式完成,文件或 API。可以通过 yarn-site.xml 中的 yarn.scheduler.configuration.store.class 进行更改。允许的值为:file,允许通过文件修改属性;memory,允许通过 API 修改属性,但不会在重启时保持更改;leveldb,允许通过 API 修改属性并将更改存储在 leveldb 后备存储中;zk,允许通过 API 修改属性并将更改存储在 zookeeper 后备存储中。 默认值为 file

使用文件更改配置

要使用文件,您需要编辑 conf/capacity-scheduler.xml 并运行 yarn rmadmin -refreshQueues

通过文件删除队列需要两步:

  • 停止队列:在删除子队列之前,子队列不应有任何正在运行或挂起的应用程序,并且必须通过更改 yarn.scheduler.capacity.<queue-path>.state 来停止。在删除父队列之前,其所有子队列都不应有任何正在运行、挂起的应用程序,并且必须被停止。 父队列也需要被停止。
  • 删除队列:从文件中删除队列配置并按上述方式运行刷新。

使用API更改配置

通过 API 进行编辑使用调度器配置的后备存储。要启用此功能,可以在 yarn-site.xml 中配置以下参数。

此功能处于 alpha 阶段,可能会发生变化。

  • yarn.scheduler.configuration.store.class:要使用的后备存储类型,如上所述。
  • yarn.scheduler.configuration.mutation.acl-policy.class:可以配置ACL策略来限制哪些用户可以修改哪些队列。默认值为 org.apache.hadoop.yarn.server.resourcemanager.scheduler.DefaultConfigurationMutationACLPolicy,它只允许 YARN 管理员进行任何配置修改。另一个值是 org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.conf.QueueAdminConfigurationMutationACLPolicy,它允许队列的管理员进行队列修改。
  • yarn.scheduler.configuration.store.max-logs:如果使用 leveldb 或 zookeeper,配置更改会被审计记录在后备存储中。此配置控制要存储的审计日志的最大数量,超过时删除最旧的日志。默认值为 1000。
  • yarn.scheduler.configuration.leveldb-store.path:使用leveldb时配置的存储路径。默认值为 ${hadoop.tmp.dir}/yarn/system/confstore
  • yarn.scheduler.configuration.leveldb-store.compaction-interval-secs:使用 leveldb 时,压缩配置存储的间隔,以秒为单位。默认值为 86400,即一天。
  • yarn.scheduler.configuration.zk-store.parent-path:使用 zookeeper 时配置存储相关信息的 zookeeper 根节点路径。默认值为 /confstore

当通过 yarn.scheduler.configuration.store.class 启用调度器配置变更时,yarn rmadmin -refreshQueues 将被禁用,即不再可能通过文件更新配置。

关于如何通过 REST 更改调度器配置,请参阅 YARN Resource Manager REST API;关于如何通过命令行更改调度器配置,请参阅 YARN 命令参考

更新容器(实验功能,未来可能会有API更改)

一旦 ApplicationMaster 从 ResourceManager 接收到容器,它可以请求 ResourceManager 更新容器的某些属性。目前只支持两种类型的容器更新:

  • 资源更新:AM 可以请求 RM 更新容器的资源大小。例如:将容器从 2GB,2vcore 容器更改为 4GB,2vcore。
  • ExecutionType 更新:AM 可以请求 RM 更新容器的 ExecutionType。例如:将执行类型从 GUARANTEED 更改为 OPPORTUNISTIC,反之亦然。

AM 在 AllocateRequestProto 中填充了 updated_containers 字段,这是一个类型为 UpdateContainerRequestProto 的列表。AM 可以在同一个分配调用中发出多个容器更新请求。当前仅支持在一个更新请求中更改容器的资源更新或 ExecutionType,不能同时更新。

AM 还必须提供它从 RM 收到的最新 ContainerProto。这是 RM 将尝试更新的容器。如果 RM 能够更新所请求的容器,则更新后的容器将在相同分配调用或后续调用之一的 AllocateResponseProto 返回值中的 updated_containers 列表字段(列表中为 UpdatedContainerProto 类型)中返回。

UpdatedContainerProto 指定了在 Container 上执行的容器更新的类型以及更新的令牌。然后,AM 可以使用容器令牌来要求相应的 NM 启动容器(如果容器尚未启动)或使用更新的令牌更新容器。DECREASE_RESOURCEDEMOTE_EXECUTION_TYPE 容器更新是自动的,AM 不必明确要求 NM 减少容器的资源。其他更新类型需要 AM 明确要求 NM 更新容器。如果 yarn.resourcemanager.auto-update.containers 配置参数设置为 true(默认为 false),RM 将确保所有容器更新都是自动的。

活动

调度活动是在某些关键调度路径上用于调试的活动消息,它们可以通过 REST API 记录和公开,对调度器性能的影响很小。目前,支持两种类型的活动:调度器活动和应用程序活动。

调度器活动

调度器活动包括调度周期中有用的调度信息,这些信息说明了调度器如何分配容器。调度器活动 REST API (http://rm-http-address:port/ws/v1/cluster/scheduler/activities) 提供了一种启用调度器活动记录并从缓存中获取它们的方法。为了消除性能影响,调度器会在调度周期结束时自动禁用记录活动,您可以再次查询 REST API 以获取最新的调度器活动。

应用程序活动

应用程序活动包括指定应用程序中有用的调度信息,这些信息说明了如何满足或跳过需求。应用程序活动 REST API (http://rm-http-address:port/ws/v1/cluster/scheduler/app-activities/{appid}) 提供了一种方法,可以在几秒钟内记录指定应用程序的活动或从缓存中获取历史应用程序活动,可以通过 actions 参数指定包括 refresh (在一定时间内开启应用程序活动记录,默认为3秒) 和 get (获取历史活动记录) 在内的可用操作(默认两者皆有)。

活动配置

CapacityScheduler 支持通过以下参数来控制缓存大小和调度器、应用程序活动的期限:

  • yarn.resourcemanager.activities-manager.cleanup-interval-ms: 活动记录的清理间隔(以毫秒为单位),默认为 5000。
  • yarn.resourcemanager.activities-manager.scheduler-activities.ttl-ms: 调度器活动的存活时间(以毫秒为单位),默认为 600000。
  • yarn.resourcemanager.activities-manager.app-activities.ttl-ms: 应用程序活动的存活时间(以毫秒为单位),默认为 600000。
  • yarn.resourcemanager.activities-manager.app-activities.max-queue-length: 应用程序活动的最大队列长度,默认为 100。

Web UI

RM Web UI 上的应用程序尝试(Application Attempt)页面中提供了活动信息,其中聚合并显示了未完成的请求。只需单击刷新按钮即可获取最新活动信息。