YARN允许应用程序以数据局部性(优先于特定节点或机架)或(不重叠)节点标签的形式指定放置约束。本文档重点介绍YARN中更具表现力的放置约束。这样的约束对于应用程序的性能和弹性至关重要,特别是那些包含长期运行的容器(例如服务,机器学习和流工作负载)的应用程序。
例如,将作业的分配放在同一机架上(亲和性约束)以减少网络成本,在机器之间分散分配(反亲和性约束)以最大程度地减少资源干扰或允许最多特定数量的分配可能是有益的。节点组中分配的数量(基数约束)以在两者之间取得平衡。放置决策也会影响弹性。例如,放置在同一群集升级域中的分配将同时脱机。
这些应用程序可以指定约束,而无需了解群集的基础拓扑(例如,无需指定容器应放置约束的特定节点或机架)或其他已部署的应用程序。当前,所有约束都很困难,也就是说,如果由于当前群集条件或冲突的约束而无法满足容器的约束,则容器请求将保持待处理或被拒绝。
请注意,在本文档中,我们使用“分配”的概念来指代在节点中分配的资源单位(例如,CPU和内存)。在YARN的当前实现中,分配对应于单个容器。但是,如果应用程序使用分配来产生多个容器,则分配可以对应于多个容器。
我们首先描述如何启用具有放置约束的计划,然后提供示例,说明如何使用分布式外壳(该应用允许在一组容器上运行给定的外壳命令)使用此功能。
要启用放置约束,必须在conf / yarn-site.xml中将以下属性设置为放置处理器或调度程序:
属性 | 描述 | 默认值 |
---|---|---|
yarn.resourcemanager.placement-constraints.handler | 指定将使用哪个处理程序来处理PlacementConstraints。可接受的值是:放置处理器,调度程序和禁用。 | 残障人士 |
现在,我们提供有关三个放置约束处理程序中每个处理程序的更多详细信息:
所述放置处理器处理程序支持更宽范围的约束的并且可以允许放置更多的容器,特别是当应用已经苛刻的限制或在群集高度利用(由于考虑在时刻多个容器)。但是,如果尊重应用程序中的任务优先级对用户很重要,并且使用了容量调度程序,则应该改用调度程序处理程序。
用户可以通过以下命令使用分布式外壳程序来试验放置约束:
$ yarn org.apache.hadoop.yarn.applications.distributedshell.Client -jar share / hadoop / yarn / hadoop-yarn-applications-distributedshell-3.2.1.jar -shell_command sleep -shell_args 10 -placement_spec PlacementSpec
其中PlacementSpec是以下形式:
PlacementSpec =>“” | PlacementExpr; PlacementSpec PlacementExpr => SourceTag,ConstraintExpr SourceTag =>字符串(NumContainers) ConstraintExpr => SingleConstraint | 复合约束 SingleConstraint =>“ IN”,Scope,TargetTag | “ NOTIN”,Scope,TargetTag | “ CARDINALITY”,范围,TargetTag,MinCard,MaxCard | NodeAttributeConstraintExpr NodeAttributeConstraintExpr => NodeAttributeName =值,NodeAttributeName!=值 CompositeConstraint => AND(ConstraintList)| 或(约束列表) ConstraintList =>约束| 约束:约束列表 NumContainers =>整数 范围=>“节点” | “架” TargetTag =>字符串 MinCard =>整数 MaxCard =>整数
注意:
PlacementSpec的示例如下:
zk(3),NOTIN,NODE,zk:hbase(5),IN,RACK,zk:spark(7),CARDINALITY,NODE,hbase,1,3
上面编码了三个约束:
下面的另一个示例演示了约束的复合形式:
zk(5),AND(IN,RACK,hbase:NOTIN,NODE,zk)
上面的约束使用并运算符AND来组合两个约束。当两个子约束均满足时,AND约束即满足。特定的PlacementSpec请求将5个“ zk”容器放置在运行至少一个“ hbase”容器的机架中以及没有运行“ zk”容器的节点上。类似地,OR运算符可用于定义在满足其子约束中的至少一个约束时满足的约束。请注意,如果“ zk”和“ hbase”是属于不同应用程序的容器(在实际用例中很可能是这种情况),则PlacementSpec中的分配标签应包含名称空间,如下所述(请参阅分配标签namespace) 。
分配标签是应用程序可以与其容器(组)关联的字符串标签。标签用于标识应用程序的组件。例如,HBase主站分配可以标记为“ hbase-m”,而区域服务器可以标记为“ hbase-rs”。其他示例是“延迟关键型”以指代更一般的分配要求,或“ app_0041”表示作业ID。分配标签在约束中起关键作用,因为它们允许引用共享同一标签的多个分配。
注意,我们使用新的SchedulingRequest对象代替使用ResourceRequest对象定义分配标签。这与ResourceRequest有很多相似之处,但是更好地分离了所请求分配的大小(分配的数量和大小,优先级,执行类型等),以及指示应如何放置这些分配的约束(资源名称,宽松的地理位置) 。应用程序仍然可以使用ResourceRequest对象,但是为了定义分配标签和约束,它们需要使用SchedulingRequest对象。在单个AllocateRequest中,应用程序应使用ResourceRequest或SchedulingRequest对象,但不是两个。
分配标签可能引用相同或不同应用程序的容器,并分别用于表示应用程序内或应用程序间的约束。我们使用分配标签名称空间来指定分配标签可以引用的应用程序范围。通过将分配标签与名称空间耦合,我们可以限制标签是否将目标定位于属于同一应用程序,特定应用程序组或集群中任何应用程序的容器。
当前,我们支持以下名称空间:
命名空间 | 句法 | 描述 |
---|---|---|
自 | 自我/ $ {allocationTag} | 分配标记引用当前应用程序的容器(将对其施加约束)。这是默认名称空间。 |
NOT_SELF | 非自身/ $ {allocationTag} | 分配标签仅引用不属于当前应用程序的容器。 |
所有 | 全部/ $ {allocationTag} | 分配标签是指任何应用程序的容器。 |
APP_ID | app-id / $ {applicationID} / $ {allocationTag} | 分配标签引用具有指定应用程序ID的应用程序的容器。 |
APP_TAG | app-tag / application_tag_name / $ {allocationTag} | 分配标签是指用指定的应用程序标签标记的应用程序容器。 |
要将分配标签名称空间ns附加到目标标签targetTag,我们在PlacementSpec中使用语法ns / allocationTag。请注意,默认名称空间是SELF,用于应用程序内约束。其余的名称空间标签用于指定应用间约束。如果未在标签旁边指定名称空间,则假定为SELF。
上面使用的示例约束可以使用命名空间进行扩展,如下所示:
zk(3),NOTIN,NODE,非自身/ zk:hbase(5),IN,RACK,all / zk:spark(7),CARDINALITY,NODE,app-id / appID_0023 / hbase,1,3
这些约束的语义如下:
分配标签和节点标签或节点属性之间的区别在于,分配标签是附加到分配而不是节点上的。当调度程序将分配分配给节点时,该分配的标记集会在分配持续时间内自动添加到节点。因此,节点继承了当前分配给该节点的分配的标签。同样,机架继承其节点的标签。而且,类似于节点标签并且与节点属性不同,分配标签没有附加值。如下所示,约束可以引用分配标记以及节点标签和节点属性。
应用程序可以使用PlacementConstraints中的公共API 来构造放置约束。在描述构建约束的方法之前,我们先描述PlacementTargets类的方法,这些方法用于构造将在约束中使用的目标表达式:
方法 | 描述 |
---|---|
distributionTag(String ... locationTags) | 在分配标签上构造目标表达式。如果存在具有给定标签之一的分配,则可以满足要求。 |
assignmentTagWithNamespace(字符串名称空间,字符串... | 与allocateTag(String ...)类似,但是允许为给定的分配标签指定名称空间。 |
nodePartition(String ... nodePartitions) | 在节点分区上构造目标表达式。对于属于nodePartitions之一的节点,它是满意的。 |
nodeAttribute(String attributeKey,String ... attributeValues) | 在节点属性上构造目标表达式。如果指定的节点属性具有指定的值之一,则可以满足要求。 |
请注意,上面的nodeAttribute方法尚不起作用,因为它需要正在进行的节点属性功能。
用于构建约束的PlacementConstraints类的方法如下:
方法 | 描述 |
---|---|
targetIn(字符串范围,TargetExpression ... targetExpressions) | 创建一个约束,该约束要求将分配放置在满足给定范围内的所有目标表达式的节点上(例如,节点或机架)。例如,targetIn(RACK,distributionTag(“ hbase-m”))允许在属于具有至少一个带有标签“ hbase-m”的分配的机架的节点上进行分配。 |
targetNotIn(字符串范围,TargetExpression ... targetExpressions) | 创建一个约束,该约束要求将分配放置在属于不满足任何目标表达式的作用域(例如,节点或机架)的节点上。 |
cardinality(字符串范围,int minCardinality,int maxCardinality,字符串... | 创建一个约束,以限制给定范围(例如,节点或机架)内的分配数量。例如,{@ code cardinality(NODE,3,10,“ zk”)}在带有标签“ zk”的分配不少于3个且不超过10个的节点上得到满足。 |
minCardinality(字符串范围,整数minCardinality,字符串... | 类似于cardinality(String,int,int,String ...),但是仅确定最小基数(最大基数是未绑定的)。 |
maxCardinality(字符串范围,int maxCardinality,字符串... | 与cardinality(String,int,int,String ...)类似,但是仅确定最大基数(最小基数为0)。 |
targetCardinality(字符串范围,int minCardinality,int maxCardinality,String ... | 该约束概括了基数约束和目标约束。考虑属于约束中指定的范围的一组节点N。如果在节点集N中至少满足最小表达式次数和最大满足最大次数,则满足约束条件。例如,targetCardinality(RACK,2、10,allocationTag(“ zk”))要求将分配放置在机架中,该机架具有至少2个和最多10个带有标签“ zk”的其他分配。 |
所述PlacementConstraints类还包括用于构建化合物约束(和/或与多个约束表达式)方法。正在增加对复合约束的支持。
应用程序必须指定将为其启用每个约束的容器。为此,应用程序可以提供从一组分配标签(源标签)到放置约束的映射。例如,此映射的条目可以是“ hbase”-> constraint1,这意味着在调度带有标签“ hbase”的每个分配时将应用constraint1。
使用放置处理器处理程序时(请参阅启用放置约束),此约束映射在RegisterApplicationMasterRequest中指定。
使用调度程序处理程序时,也可以在每个SchedulingRequest对象上添加约束。每个此类约束对于该调度请求的标签均有效。如果在RegisterApplicationMasterRequest和调度请求上都指定了约束,则后者将覆盖前者。