本文档描述了 FairScheduler
,这是 Hadoop 的一个可插入调度器,它允许 YARN 应用程序公平地共享大型集群中的资源。
公平调度是一种将资源分配给应用程序的方法,这样所有应用程序平均而言在一段时间内获得相等的资源份额。Hadoop NextGen 能够调度多种资源类型。默认情况下,公平调度程序仅根据内存做出调度公平性决策。它可以配置为使用 Ghodsi 等人开发的主导资源公平性概念,同时使用内存和 CPU 进行调度。当只有一个应用程序在运行时,该应用程序将使用整个集群。当提交其他应用程序时,释放的资源将分配给新应用程序,以便每个应用程序最终获得大致相同数量的资源。与形成应用程序队列的默认 Hadoop 调度程序不同,这可以让短应用程序在合理的时间内完成,同时不会饿死长期应用程序。这也是在多个用户之间共享集群的合理方式。最后,公平共享还可以与应用程序优先级一起使用 - 优先级用作权重,以确定每个应用程序应获得的总资源的份额。
调度程序进一步将应用程序组织成“队列”,并在这些队列之间公平地共享资源。默认情况下,所有用户共享一个名为“default”的队列。如果应用程序在容器资源请求中明确列出队列,则该请求将提交到该队列。还可以通过配置根据请求中包含的用户名分配队列。在每个队列中,调度策略用于在正在运行的应用程序之间共享资源。默认是基于内存的公平共享,但也可以配置 FIFO 和具有主导资源公平性的多资源。队列可以按层次结构排列以划分资源,并配置权重以按特定比例共享集群。
除了提供公平共享之外,公平调度程序还允许为队列分配有保证的最小份额,这对于确保某些用户、组或生产应用程序始终获得足够的资源非常有用。当队列包含应用程序时,它至少获得其最小份额,但当队列不需要其全部保证份额时,剩余部分将在其他正在运行的应用程序之间分配。这使调度程序能够保证队列的容量,同时在这些队列不包含应用程序时有效利用资源。
公平调度程序默认情况下允许所有应用程序运行,但也可以通过配置文件限制每个用户和每个队列的正在运行的应用程序数量。当用户必须一次提交数百个应用程序时,或者当一次运行太多应用程序会导致创建太多中间数据或太多上下文切换时,这可能非常有用,以提高性能。限制应用程序不会导致任何随后提交的应用程序失败,只会等待调度程序的队列,直到用户的一些早期应用程序完成。
公平调度程序支持分层队列。所有队列都从名为“root”的队列派生。可用资源按典型的公平调度方式分配给根队列的子队列。然后,子队列以相同的方式将其分配给它们的资源分配给它们的子队列。应用程序只能在叶队列上调度。队列可以通过将其作为父队列的子元素放置在公平调度程序分配文件中来指定为其他队列的子队列。
队列的名称以其父队列的名称开头,以句点作为分隔符。因此,根队列下的名为“queue1”的队列将称为“root.queue1”,而名为“parent1”的队列下的名为“queue2”的队列将称为“root.parent1.queue2”。在引用队列时,名称的根部分是可选的,因此 queue1 可以仅称为“queue1”,而 queue2 可以仅称为“parent1.queue2”。
此外,公平调度程序允许为每个队列设置不同的自定义策略,以允许以用户想要的任何方式共享队列的资源。可以通过扩展 org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.SchedulingPolicy
来构建自定义策略。FifoPolicy、FairSharePolicy(默认)和 DominantResourceFairnessPolicy 是内置的,可以随时使用。
某些附加组件尚未得到支持,这些附加组件存在于原始(MR1)公平调度程序中。其中包括使用自定义策略来控制对某些应用程序的优先级“提升”。
公平调度程序允许管理员配置策略,将提交的应用程序自动放置在适当的队列中。放置可以取决于提交者的用户和组以及应用程序传递的请求队列。策略由一组规则组成,这些规则按顺序应用于对传入应用程序进行分类。每条规则要么将应用程序放入队列,要么拒绝它,要么继续执行下一条规则。有关如何配置这些策略,请参阅下面的分配文件格式。
要使用公平调度程序,首先在 yarn-site.xml 中分配适当的调度程序类
<property> <name>yarn.resourcemanager.scheduler.class</name> <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value> </property>
自定义公平调度程序通常涉及更改两个文件。首先,可以通过在现有配置目录中的 yarn-site.xml 文件中添加配置属性来设置调度程序范围的选项。其次,在大多数情况下,用户会希望创建一个分配文件,其中列出存在的队列及其各自的权重和容量。分配文件每 10 秒重新加载一次,允许随时进行更改。
属性 | 说明 |
---|---|
yarn.scheduler.fair.allocation.file |
分配文件的路径。分配文件是一个 XML 清单,描述了队列及其属性,以及某些策略默认值。此文件必须采用下一节中描述的 XML 格式。如果给出了相对路径,则在类路径(通常包括 Hadoop conf 目录)中搜索该文件。默认为 fair-scheduler.xml。 |
yarn.scheduler.fair.user-as-default-queue |
在未指定队列名称的情况下,是否将与分配关联的用户名用作默认队列名称。如果将其设置为“false”或未设置,则所有作业都有一个名为“default”的共享默认队列。默认为 true。如果在分配文件中给出了队列放置策略,则忽略此属性。 |
yarn.scheduler.fair.preemption |
是否使用抢占。默认为 false。 |
yarn.scheduler.fair.preemption.cluster-utilization-threshold |
抢占启动后的利用率阈值。利用率计算为所有资源中使用率与容量的最大比率。默认为 0.8f。 |
yarn.scheduler.fair.sizebasedweight |
是否根据各个应用的大小为其分配份额,而不是向所有应用提供相等的份额,无论其大小如何。设置为 true 时,应用的权重由应用总请求内存的自然对数除以 2 的自然对数加 1 来计算。默认为 false。 |
yarn.scheduler.fair.assignmultiple |
是否允许在一次心跳中进行多个容器分配。默认为 false。 |
yarn.scheduler.fair.dynamic.max.assign |
如果 assignmultiple 为 true,则动态确定在一个心跳中可以分配的资源量。启用后,节点上大约一半的未分配资源将在单个心跳中分配给容器。默认为 true。 |
yarn.scheduler.fair.max.assign |
如果 assignmultiple 为 true 且 dynamic.max.assign 为 false,则在一个心跳中可以分配的最大容器量。默认为 -1,不设置限制。 |
yarn.scheduler.fair.locality.threshold.node |
对于在特定节点上请求容器的应用程序,自上次容器分配以来等待接受在另一个节点上放置的调度机会数。表示为 0 到 1 之间的一个浮点数,作为集群大小的一部分,表示要放弃的调度机会数。-1.0 的默认值表示不放弃任何调度机会。 |
yarn.scheduler.fair.locality.threshold.rack |
对于在特定机架上请求容器的应用程序,自上次容器分配以来等待接受在另一个机架上放置的调度机会数。表示为 0 到 1 之间的一个浮点数,作为集群大小的一部分,表示要放弃的调度机会数。-1.0 的默认值表示不放弃任何调度机会。 |
yarn.scheduler.fair.allow-undeclared-pools |
如果此值为 true,则可以在应用程序提交时创建新队列,无论它们是由提交者指定为应用程序的队列,还是由 user-as-default-queue 属性放置在那里。如果此值为 false,则任何时候将应用程序放置在分配文件中未指定的队列中,它将被放置在“default”队列中。默认为 true。如果在分配文件中给出了队列放置策略,则此属性将被忽略。 |
yarn.scheduler.fair.update-interval-ms |
锁定调度程序并重新计算公平份额、重新计算需求以及检查是否有任何内容应被抢占的时间间隔。默认为 500 毫秒。 |
yarn.resource-types.memory-mb.increment-allocation |
fairscheduler 以此值的增量授予内存。如果您提交的资源请求不是 memory-mb.increment-allocation 的倍数,则该请求将向上舍入到最接近的增量。默认为 1024 MB。 |
yarn.resource-types.vcores.increment-allocation |
fairscheduler 以此值的增量授予 vcore。如果您提交的资源请求不是 vcores.increment-allocation 的倍数,则该请求将向上舍入到最接近的增量。默认为 1。 |
yarn.resource-types.<resource>.increment-allocation |
fairscheduler 以此值的增量授予 <resource> 。如果您提交的资源请求不是 <resource>.increment-allocation 的倍数,则该请求将向上舍入到最接近的增量。如果未为资源指定此属性,则不会应用增量舍入。如果未指定单位,则假定该资源的默认单位。 |
yarn.scheduler.increment-allocation-mb |
内存的分配增量。不再首选。改为使用 yarn.resource-types.memory-mb.increment-allocation 。默认为 1024 MB。 |
yarn.scheduler.increment-allocation-vcores |
CPU vcore 的分配增量。不再首选。改为使用 yarn.resource-types.vcores.increment-allocation 。默认为 1。 |
分配文件必须采用 XML 格式。该格式包含五种类型的元素
队列元素:表示队列。队列元素可以选用一个可选属性“类型”,当设置为“父级”时,它将成为父级队列。当我们想要创建一个父级队列而不配置任何叶级队列时,这很有用。每个队列元素可能包含以下属性
minResources:队列有权获得的最小资源。对于单资源公平性策略,只使用内存,其他资源被忽略。如果队列的最小份额未得到满足,在同一父级下,它将在任何其他队列之前获得可用资源。在单资源公平性策略下,如果队列的内存使用率低于其最小内存份额,则认为该队列未得到满足。在主导资源公平性下,如果队列对其主导资源相对于集群容量的使用率低于其最小份额,则认为该队列未得到满足。如果在这种情况下有多个队列未得到满足,则资源将分配给相关资源使用率与其最小值比率最小的队列。请注意,当向队列提交应用程序时,低于其最小值的队列可能无法立即达到其最小值,因为正在运行的作业可能正在使用这些资源。
maxResources:队列可以分配的最大资源。不会向队列分配会使其总使用量超过此限制的容器。此限制会以递归方式强制执行,如果分配会使队列或其父级超过最大资源,则不会向队列分配容器。
maxContainerAllocation:队列可以为单个容器分配的最大资源。如果未设置此属性,则其值将从父队列继承。默认值为 yarn.scheduler.maximum-allocation-mb 和 yarn.scheduler.maximum-allocation-vcores。不能高于 maxResources。此属性对根队列无效。
maxChildResources:临时子队列可以分配的最大资源。子队列限制以递归方式强制执行,因此如果分配会使子队列或其父级超过最大资源,则不会分配容器。
旧格式:“X mb,Y 个 vcore”、“X% cpu,Y% 内存”、“X%”。如果没有提供单个百分比,则必须同时配置内存和 cpu,而其他资源类型将被忽略并设置为零。
新格式(推荐):“vcores=X、memory-mb=Y”或“vcores=X%、memory-mb=Y%”。如您所见,在这种格式中,可以指定一个百分比或一个整数资源值(无单位)。在后一种情况下,将根据为该资源配置的默认单位推断单位。当指定除内存和 CPU 之外的资源时,此格式是必需的。对于 minResources,任何未指定的资源都将设置为 0,对于 maxResources、maxContainerAllocation 和 maxChildResources,则将设置为该资源的最大值。
maxRunningApps:限制队列中一次运行的应用程序数
maxAMShare:限制队列公平份额中可用于运行应用程序主控程序的部分。此属性仅可用于叶队列。例如,如果设置为 1.0f,则叶队列中的 AM 可以占用内存和 CPU 公平份额的 100%。值 -1.0f 将禁用此功能,并且不会检查 amShare。默认值为 0.5f。
weight:以非比例方式与其他队列共享集群。权重默认为 1,权重为 2 的队列应接收的资源大约是权重为默认值的队列的两倍。
schedulingPolicy:设置任何队列的调度策略。允许的值为“fifo”/“fair”/“drf”或扩展 org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.SchedulingPolicy
的任何类。默认为“fair”。如果为“fifo”,则提交时间较早的应用程序优先获得容器,但如果在满足较早应用程序的请求后集群上还有剩余空间,则稍后提交的应用程序可能会同时运行。
aclSubmitApps:可以向队列提交应用程序的用户和/或组的列表。有关此列表的格式以及队列 ACL 如何工作的更多信息,请参阅下面的 ACL 部分。
aclAdministerApps:可以管理队列的用户和/或组的列表。目前,唯一的管理操作是终止应用程序。有关此列表的格式以及队列 ACL 如何工作的更多信息,请参阅下面的 ACL 部分。
minSharePreemptionTimeout:队列低于其最小份额的秒数,然后它将尝试抢占容器以从其他队列获取资源。如果未设置,则队列将从其父队列继承值。默认值为 Long.MAX_VALUE,这意味着在您设置有意义的值之前,它不会抢占容器。
fairSharePreemptionTimeout:队列低于其公平份额阈值的秒数,然后它将尝试抢占容器以从其他队列获取资源。如果未设置,则队列将从其父队列继承值。默认值为 Long.MAX_VALUE,这意味着在您设置有意义的值之前,它不会抢占容器。
fairSharePreemptionThreshold:队列的公平份额抢占阈值。如果队列在未收到 fairSharePreemptionThreshold*fairShare 资源的情况下等待 fairSharePreemptionTimeout,则允许其抢占容器以从其他队列获取资源。如果未设置,则队列将继承其父队列的值。默认值为 0.5f。
allowPreemptionFrom:确定调度程序是否允许从队列抢占资源。默认值为 true。如果队列将此属性设置为 false,则此属性将递归应用于所有子队列。
reservation:向 ReservationSystem
指示队列的资源可供用户预留。这仅适用于叶队列。如果未配置此属性,则叶队列不可预留。
用户元素:表示控制各个用户行为的设置。它们可以包含一个属性:maxRunningApps,对特定用户的运行中应用数量的限制。
A userMaxAppsDefault 元素:为未指定限制的任何用户设置默认运行中应用限制。
A defaultFairSharePreemptionTimeout 元素:为根队列设置公平份额抢占超时;被根队列中的 fairSharePreemptionTimeout 元素覆盖。默认设置为 Long.MAX_VALUE。
A defaultMinSharePreemptionTimeout 元素:为根队列设置最小份额抢占超时;被根队列中的 minSharePreemptionTimeout 元素覆盖。默认设置为 Long.MAX_VALUE。
A defaultFairSharePreemptionThreshold 元素:为根队列设置公平份额抢占阈值;被根队列中的 fairSharePreemptionThreshold 元素覆盖。默认设置为 0.5f。
A queueMaxAppsDefault 元素:为队列设置默认运行中应用限制;被每个队列中的 maxRunningApps 元素覆盖。
A queueMaxResourcesDefault 元素:为队列设置默认最大资源限制;被每个队列中的 maxResources 元素覆盖。
A queueMaxAMShareDefault 元素:为队列设置默认 AM 资源限制;被每个队列中的 maxAMShare 元素覆盖。
A defaultQueueSchedulingPolicy 元素:设置队列的默认调度策略;如果指定,则会被每个队列中的 schedulingPolicy 元素覆盖。默认为“fair”。
A reservation-agent 元素:设置 ReservationAgent
实现的类名,该实现尝试将用户的预订请求放入 Plan
中。默认值为 org.apache.hadoop.yarn.server.resourcemanager.reservation.planning.AlignedPlannerWithGreedy
。
A reservation-policy 元素:设置 SharingPolicy
实现的类名,该实现验证新预订是否违反任何不变量。默认值为 org.apache.hadoop.yarn.server.resourcemanager.reservation.CapacityOverTimePolicy
。
A reservation-planner 元素:设置 Planner
实现的类名,如果 Plan
容量低于(由于计划维护或节点故障)用户预订的资源,则调用该实现。默认值为 org.apache.hadoop.yarn.server.resourcemanager.reservation.planning.SimpleCapacityReplanner
,该值扫描 Plan
并贪婪地按接受顺序(LIFO)删除预订,直到预订资源在 Plan
容量内。
A queuePlacementPolicy 元素:包含规则元素列表,告诉调度程序如何将传入的应用程序放入队列中。规则按列出的顺序应用。规则可以采用参数。所有规则都接受“create”参数,该参数指示规则是否可以创建新队列。“Create”默认为 true;如果设置为 false,并且规则会将应用程序放入未在分配文件中配置的队列中,则我们继续执行下一条规则。最后一条规则必须是不可能发出继续的规则。有效规则为
specified:应用程序被放入它请求的队列中。如果应用程序未请求队列,即指定为“default”,则我们继续。如果应用程序请求的队列名称以句点开头或结尾,即如 “.q1” 或 “q1.” 这样的名称将被拒绝。
user:应用程序被放入提交该应用程序的用户的名称的队列中。用户名中的句点将替换为“_dot_”,即用户“first.last”的队列名称为“first_dot_last”。
primaryGroup:应用程序被放入提交该应用程序的用户的主要组的名称的队列中。组名中的句点将替换为“_dot_”,即组“one.two”的队列名称为“one_dot_two”。
secondaryGroupExistingQueue:应用程序被放入名称与提交该应用程序的用户的一个辅助组匹配的队列中。将选择第一个与已配置队列匹配的辅助组。组名中的句点将替换为“_dot_”,即具有“one.two”作为其辅助组之一的用户将被放入“one_dot_two”队列中(如果存在此类队列)。
nestedUserQueue:将应用放入队列中,队列名称为嵌套规则建议队列下的用户名称。这类似于“user”规则,不同之处在于“nestedUserQueue”规则中,可以在任何父队列下创建用户队列,而“user”规则仅在根队列下创建用户队列。请注意,仅当嵌套规则返回父队列时,才会应用 nestedUserQueue 规则。可以通过将队列的“type”属性设置为“parent”或在该队列下配置至少一个使其成为父队列的叶来配置父队列。有关示例用例,请参见示例分配。
default:将应用放入默认规则的“queue”属性中指定的队列中。如果未指定“queue”属性,则将应用放入“root.default”队列中。
reject:拒绝应用。
此处提供了一个示例分配文件
<?xml version="1.0"?> <allocations> <queue name="sample_queue"> <minResources>10000 mb,0vcores</minResources> <maxResources>90000 mb,0vcores</maxResources> <maxRunningApps>50</maxRunningApps> <maxAMShare>0.1</maxAMShare> <weight>2.0</weight> <schedulingPolicy>fair</schedulingPolicy> <queue name="sample_sub_queue"> <aclSubmitApps>charlie</aclSubmitApps> <minResources>5000 mb,0vcores</minResources> </queue> <queue name="sample_reservable_queue"> <reservation></reservation> </queue> </queue> <queueMaxAMShareDefault>0.5</queueMaxAMShareDefault> <queueMaxResourcesDefault>40000 mb,0vcores</queueMaxResourcesDefault> <!-- Queue 'secondary_group_queue' is a parent queue and may have user queues under it --> <queue name="secondary_group_queue" type="parent"> <weight>3.0</weight> <maxChildResources>4096 mb,4vcores</maxChildResources> </queue> <user name="sample_user"> <maxRunningApps>30</maxRunningApps> </user> <userMaxAppsDefault>5</userMaxAppsDefault> <queuePlacementPolicy> <rule name="specified" /> <rule name="primaryGroup" create="false" /> <rule name="nestedUserQueue"> <rule name="secondaryGroupExistingQueue" create="false" /> </rule> <rule name="default" queue="sample_queue"/> </queuePlacementPolicy> </allocations>
请注意,为了与原始 FairScheduler 向后兼容,“queue”元素可以命名为“pool”元素。
队列访问控制列表 (ACL) 允许管理员控制谁可以对特定队列执行操作。它们使用 aclSubmitApps 和 aclAdministerApps 属性进行配置,这些属性可以按队列设置。目前唯一受支持的管理操作是终止应用程序。管理员也可以向其提交应用程序。这些属性采用“user1,user2 group1,group2”或“group1,group2”之类的格式。如果用户/组是队列 ACL 或该队列任何祖先的队列 ACL 的成员,则允许对队列执行操作。因此,如果 queue2 在 queue1 内,user1 在 queue1 的 ACL 中,user2 在 queue2 的 ACL 中,则这两个用户都可以向 queue2 提交。
注意:分隔符是空格字符。要仅指定 ACL 组,请以空格字符开头。
默认情况下,根队列的 ACL 为“*”,因为 ACL 是向下传递的,这意味着每个人都可以向每个队列提交和终止应用程序。要开始限制访问,请将根队列的 ACL 更改为除“*”之外的其他内容。
预留访问控制列表 (ACL) 允许管理员控制谁可以对特定队列执行预留操作。它们使用 aclAdministerReservations、aclListReservations 和 aclSubmitReservations 属性进行配置,这些属性可以按队列设置。目前受支持的管理操作是更新和删除预留。管理员还可以提交和列出队列上的所有预留。这些属性采用“user1,user2 group1,group2”或“group1,group2”之类的格式。如果用户/组是预留 ACL 的成员,则允许对队列执行操作。请注意,任何用户都可以更新、删除或列出自己的预留。如果启用了预留 ACL 但未定义,则每个人都可以访问。
ReservationSystem
公平调度程序支持ReservationSystem,它允许用户提前预留资源。应用程序可以通过在提交期间指定reservationId
来请求运行时预留的资源。以下配置参数可以在 yarn-site.xml 中为ReservationSystem
进行配置。
属性 | 说明 |
---|---|
yarn.resourcemanager.reservation-system.enable |
必需参数:在ResourceManager中启用ReservationSystem 。预期布尔值。默认值为false,即默认情况下未启用ReservationSystem 。 |
yarn.resourcemanager.reservation-system.class |
可选参数:ReservationSystem 的类名。根据已配置的调度程序选择默认值,即如果配置了FairScheduler ,则为FairReservationSystem 。 |
yarn.resourcemanager.reservation-system.plan.follower |
可选参数:PlanFollower 的类名,它在计时器上运行,并将FairScheduler 与Plan 同步,反之亦然。根据已配置的调度程序选择默认值,即如果配置了FairScheduler ,则为FairSchedulerPlanFollower 。 |
yarn.resourcemanager.reservation-system.planfollower.time-step |
可选参数:PlanFollower 计时器的毫秒频率。预期长值。默认值为1000。 |
ReservationSystem
与公平调度程序队列层次结构集成,并且只能针对叶队列进行配置。详细说明请参阅分配文件格式
部分。
公平调度程序通过一些机制提供对运行时管理的支持
可以通过编辑分配文件来修改运行时的最小份额、限制、权重、抢占超时和队列调度策略。调度程序会在看到该文件被修改后 10-15 秒重新加载该文件。
可以通过 ResourceManager 的 Web 界面在http://*ResourceManager URL*/cluster/scheduler
处检查当前应用程序、队列和公平份额。
在 Web 界面上,可以查看每个队列的以下字段
已用资源 - 分配给队列内容器的资源总和。
活动应用程序数 - 队列中已收到至少一个容器的应用程序数。
挂起应用程序数 - 队列中尚未收到任何容器的应用程序数。
最小资源 - 为队列保证的已配置最小资源。
最大资源 - 允许队列使用的已配置最大资源。
瞬时公平份额 - 队列的瞬时公平资源份额。这些份额仅考虑活动队列(正在运行应用程序的队列),并用于调度决策。当其他队列未使用资源时,队列可能会被分配超出其份额的资源。资源消耗处于瞬时公平份额或低于瞬时公平份额的队列永远不会被抢占其容器。
稳定公平份额 - 队列的稳定公平资源份额。这些份额考虑所有队列,无论它们是否处于活动状态(正在运行应用程序)。这些份额计算频率较低,并且仅在配置或容量发生更改时才更改。它们旨在提供用户可以预期的资源的可视性,因此显示在 Web UI 中。
公平调度程序支持将正在运行的应用程序移动到不同的队列。这对于将重要应用程序移动到更高优先级的队列或将不重要的应用程序移动到较低优先级的队列很有用。可以通过运行 yarn application -movetoqueue appID -queue targetQueueName
来移动应用程序。
当应用程序移动到队列时,其现有分配将与新队列的分配一起计算,而不是旧队列的分配,以确定公平性。如果将应用程序的资源添加到该队列会违反其 maxRunningApps 或 maxResources 约束,则尝试将应用程序移动到队列将失败。
公平调度程序能够定期转储其状态。它默认情况下处于禁用状态。管理员可以通过将 org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler.statedump
日志级别设置为 DEBUG 来启用它。
默认情况下,公平调度程序日志转到资源管理器日志文件。公平调度程序状态转储可能会生成大量日志数据。取消 log4j.properties 中“公平调度程序状态转储”部分的注释,以将状态转储到单独的文件中。