4 月 6 日,Apache Hadoop 正式发布了 3.1.0 版本,这是 2018 年 Hadoop 3.x 系列的第一个小版本,较之前的 Hadoop 3.0 有了一些重大改变。需要注意的是,这个版本还不适用于生产环境,如果需要在生产环境下使用的用户还需等待 3.1.1 或 3.1.2 版本发布。但 3.1.0 也有其重大意义,因为它终于支持 GPU 和 FPGA 了。
本文仅主要介绍hadoop3.x的一些重要改进及配置。
Hadoop 3.1.0 版本带来的重大变化简要介绍如下:
Yarn Service 服务框架为在 YARN 上长期运行的服务提供支持,作为一个容器编配平台来管理运行在 YARN 上那些被容器化的服务,支持 Docker 容器和传统容器。
Yarn Service框架提供一流的支持和API,以在YARN中本地托管长期运行的服务。简而言之,它作为一个容器编排平台,用于管理YARN上的容器化服务。它支持YARN中的docker容器和传统的基于进程的容器。
该框架的职责包括执行配置解决方案和安装,生命周期管理(如停止/启动/删除服务),向上/向下弯曲服务组件,在YARN上滚动升级服务,监控服务的健康状况和准备情况等。
①在YARN上运行的核心框架(ApplicationMaster),用作容器协调器,负责所有服务生命周期管理。
②一个restful API服务器,供用户与YARN交互,通过简单的JSON规范部署/管理他们的服务。
③由YARN服务注册表支持的DNS服务器,用于通过标准DNS查找在YARN上发现服务。
YARN服务框架可以轻松地将现有服务引入YARN。它隐藏了应用程序管理的所有复杂的低级细节,并使用户免于被迫编写新代码。新服务的开发人员不必担心YARN内部,只需要关注其服务的容器化。
此外,此功能的另一个巨大成功是,现在可以在单个平台中启用传统的批处理作业和长时间运行的服务!结合这些工作负载的好处有两方面:
· 由于只有一个集群可以处理,因此大大简化了集群操作。
· 使批处理作业和服务共享群集可以极大地提高资源利用率。
· 截至目前,YARN仅支持Nvidia GPU
· YARN节点管理器必须预先安装Nvidia驱动程序。
· 当Docker用作容器运行时,需要安装nvidia-docker 1.0(当前支持的版本在YARN中用于nvidia-docker)。
在resource-types.xml中
添加以下属性
yarn.resource-types
yarn.io/gpu
在yarn-site.xml中DominantResourceCalculator必须配置为启用GPU调度/隔离。
对于Capacity Scheduler,使用以下属性配置DominantResourceCalculator(在capacity-scheduler.xml中):
Property:yarn.scheduler.capacity.resource-calculator
Default value:org.apache.hadoop.yarn.util.resource.DominantResourceCalculator
在yarn-site.xml中
yarn.nodemanager.resource-plugins
yarn.io/gpu
这是在NodeManager端启用GPU隔离模块。
默认情况下,当设置了以上配置时,YARN将自动检测并配置GPU。当然你也可以通过配置文件设置一些自己想要的个性化设置,详情可以参照:Yarn的GPU隔离设置
通常,需要将以下配置添加到container-executor.cfg
[gpu]
module.enabled=true
当用户需要在非Docker环境下运行GPU应用程序时:
[cgroups]
##这应该与yarn-site.xml中的yarn.nodemanager.linux-container-executor.cgroups.mount-path相同
root=/sys/fs/cgroup
##这应该与yarn-site.xml中的yarn.nodemanager.linux-container-executor.cgroups.hierarchy相同
yarn-hierarchy=yarn
当用户需要在Docker环境下运行GPU应用程序时:
1)将GPU相关设备添加到docker部分:
用逗号分隔的值,你可以通过运行ls / dev / nvidia来获得这个*
[docker]
docker.allowed.devices=/dev/nvidiactl,/dev/nvidia-uvm,/dev/nvidia-uvm-tools,/dev/nvidia1,/dev/nvidia0
2)将nvidia-docker添加到卷驱动程序白名单。
[docker]
...
docker.allowed.volume-drivers
3)将nvidia_driver_ 添加到readonly挂载白名单。
[docker]
...
docker.allowed.ro-mounts=nvidia_driver_375.66
分布式shell当前支持指定除内存和vcores之外的其他资源类型。
不使用docker容器运行分布式shell(要求2个任务,每个任务有3GB内存,1个vcore,2个GPU设备资源):
yarn jar \
-jar \
-shell_command /usr/local/nvidia/bin/nvidia-smi \
-container_resources memory-mb=3072,vcores=1,yarn.io/gpu=2 \
-num_containers 2
您还可以使用Docker容器运行分布式shell。必须指定YARN_CONTAINER_RUNTIME_TYPE / YARN_CONTAINER_RUNTIME_DOCKER_IMAGE才能使用docker容器。
yarn jar \
-jar \
-shell_env YARN_CONTAINER_RUNTIME_TYPE=docker \
-shell_env YARN_CONTAINER_RUNTIME_DOCKER_IMAGE= \
-shell_command nvidia-smi \
-container_resources memory-mb=3072,vcores=1,yarn.io/gpu=2 \
-num_containers 2
· YARN支持FPGA资源,但目前只附带“IntelFpgaOpenclPlugin”
· YARN节点管理器必须预先安装供应商驱动程序并配置所需的环境变量
· Docker支持尚不支持
在resource-types.xml中
添加以下属性
yarn.resource-types
yarn.io/fpga
对于Capacity Scheduler,DominantResourceCalculator必须配置为启用FPGA调度/隔离。使用以下属性配置DominantResourceCalculator(在capacity-scheduler.xml中):
Property: yarn.scheduler.capacity.resource-calculator
Default value:org.apache.hadoop.yarn.util.resource.DominantResourceCalculator
在yarn-site.xml中
yarn.nodemanager.resource-plugins
yarn-io/fpga
这是在NodeManager端启用FPGA隔离模块。
默认情况下,当设置了以上配置时,YARN将自动检测并配置FPGA。当然你也可以通过配置文件设置一些自己想要的个性化设置,详情可以参照:Yarn的FPGA隔离设置
在container-executor.cfg中
通常,需要将以下配置添加到container-executor.cfg。fpag.major-device-number和allowed-device-minor-numbers是可选的允许设备。
[fpga]
module.enabled=true
fpga.major-device-number=## Major device number of FPGA, by default is 246. Strongly recommend setting this
fpga.allowed-device-minor-numbers=## Comma separated allowed minor device numbers, empty means all FPGA devices managed by YARN.
当用户需要在非Docker环境下运行FPGA应用程序时:
[cgroups]
root=/cgroup
yarn-hierarchy=yarn
分布式shell当前支持指定除内存和vcores之外的其他资源类型
不使用docker容器运行分布式shell(.bashrc包含一些与SDK相关的环境变量):
yarn jar \
-jar \
-shell_command "source /home/yarn/.bashrc && aocl diagnose" \
-container_resources memory-mb=2048,vcores=2,yarn.io/fpga=1 \
-num_containers 1
对于FPGA资源,容器可以具有环境变量“REQUESTED_FPGA_IP_ID”以使YARN下载并在启动之前为其刷新IP。例如,REQUESTED_FPGA_IP_ID =“matrix_mul”将在容器的本地目录中搜索名称中包含“matirx_mul”的IP文件(“.aocx”文件)(应用程序会首先分发它)。现版本只支持为所有设备刷新一个IP。如果用户没有设置此环境变量,会认为用户的应用程序可以自己找到IP文件。请注意,YARN中没有必要预先进行IP下载和重新编程,因为OpenCL应用程序可能会在运行中找到IP文件和重新编程设备。但YARN为容器做到这一点将实现最快的重新编程路径。
YARN允许应用程序以数据位置(对特定节点或机架的首选项)或(非重叠)节点标签的形式指定放置约束。本文档重点介绍YARN中更具表现力的放置约束。这些约束对于应用程序的性能和弹性至关重要,尤其是那些包含长期运行容器的应用程序,例如服务,机器学习和流式工作负载。
例如,在同一机架上共同定位作业的分配(亲和约束)可能是有益的,以降低网络成本,跨机器分布分配(反亲和约束)以最小化资源干扰,或允许达到特定节点组中的分配数量(基数约束)以在两者之间取得平衡。安置决定也会影响抵御能力。例如,放置在同一群集升级域中的分配将同时脱机。
应用程序可以指定约束而无需了解集群的底层拓扑(例如,一个不需要指定特定节点或机架应将其容器放置在哪里具有约束)或部署其他应用程序。目前支持应用程序内部约束,但遵循的设计是通用的,并且很快将添加对跨应用程序的约束的支持。此外,目前所有约束都很难,也就是说,如果由于当前集群条件或冲突约束而无法满足容器的约束,则容器请求将保持挂起或get将被拒绝。
请注意,在本文档中,我们使用“分配”的概念来指代在节点中分配的资源单元(例如,CPU和内存)。在YARN的当前实现中,分配对应于单个容器。但是,如果应用程序使用分配来生成多个容器,则分配可以对应于多个容器。
我们首先描述如何使用放置约束启用调度,然后提供如何使用分布式shell(一种允许在一组容器上运行给定shell命令的应用程序)来试验此功能的示例。
要启用放置约束,必须在conf / yarn-site.xml中将以下属性设置为placement-processor或scheduler:
属性:yarn.resourcemanager.placement-constraints.handler
描述:指定将使用哪个处理程序来处理PlacementConstraints。可接受的值包括:placement-processor,scheduler和disabled。
默认值:disabled
下面详细介绍一下三个放置约束应用程序的更多详细信息:
placement-processor:使用此处理程序,在调用容量或公平调度程序之前,将具有约束的容器的放置确定为预处理步骤。确定放置后,将调用capacity / fair调度程序来执行实际分配。此处理程序的优点是它支持所有约束类型(亲和性,反亲和性,基数)。此外,它一次考虑多个容器,这允许满足比一次一个容器方法可以实现的更多约束。由于它位于主调度程序之外,因此容量和公平调度程序都可以使用它。请注意,目前它没有考虑应用程序中的任务优先级,因为这些优先级可能与放置约束冲突。
scheduler:使用此处理程序,主调度程序将放置具有约束的容器(截至目前,只有容量调度程序支持SchedulingRequests)。它目前支持反亲和约束(无亲和力或基数)。与放置处理器相比,此处理程序的优点在于它遵循相同的队列排序规则(按利用率,优先级排序),应用程序(按FIFO /公平/优先级排序)和同一应用程序内的任务(优先级) )由现有的主调度程序强制执行。
disabled:使用此处理程序,如果应用程序询问SchedulingRequest,则将拒绝相应的分配调用。
所述放置处理器处理程序支持更宽范围的约束的并且可以允许放置更多的容器,特别是当应用程序有苛刻的约束或群集高度利用(由于考虑在时刻多个容器)。但是,如果在应用程序中尊重任务优先级对用户很重要并且使用容量调度程序,则应该使用调度程序处理程序。
用户可以通过以下命令使用分布式shell应用程序来试验放置约束:
$ yarn org.apache.hadoop.yarn.applications.distributedshell.Client -jar share/hadoop/yarn/hadoop-yarn-applications-distributedshell-3.1.0.jar -shell_command sleep -shell_args 10 -placement_spec PlacementSpec
其中PlacementSpec是以下形式:
PlacementSpec => "" | KeyVal;PlacementSpec
KeyVal => SourceTag=Constraint
SourceTag => String
Constraint => NumContainers | NumContainers,"IN",Scope,TargetTag | NumContainers,"NOTIN",Scope,TargetTag | NumContainers,"CARDINALITY",Scope,TargetTag,MinCard,MaxCard
NumContainers => int
Scope => "NODE" | "RACK"
TargetTag => String
MinCard => int
MaxCard => int
请注意,在distributed shell命令中指定-placement_spec参数时,不应使用-num-containers参数。如果-num-containers参数与-placement-spec一起使用,那么会忽略前者。这是因为在PlacementSpec中,我们确定每个标签的容器数量,使用-num-containers多余且可能存在冲突。此外,如果使用-placement_spec,将使用GUARANTEED执行类型请求所有容器。
PlacementSpec的一个示例如下:
zk=3,NOTIN,NODE,zk:hbase=5,IN,RACK,zk:spark=7,CARDINALITY,NODE,hbase,1,3
上面对两个约束进行了编码*:将3个带有标签“zk”(代表ZooKeeper)的容器与节点相互关联,即每个节点不要放置多个容器(请注意,在第一个约束中,约束的SourceTag和TargetTag是一致的); *将带有标签“hbase”的5个容器放置在一个机架上,在该机架上运行带有“zk”标签的容器(即,“hbase”容器不应放置在运行“zk”容器的机架上,因为“zk”是第二个约束的TargetTag); *在具有至少一个但不超过三个容器的节点中放置带有标记“spark”的7个容器,标记为“hbase”。
分配标记是应用程序可以与其容器(的组)相关联的字符串标记。标签用于标识应用程序的组件。例如,HBase Master分配可以用“hbase-m”标记,而Region Servers用“hbase-rs”标记。其他示例是“延迟关键”以指代分配的更一般要求,或“app_0041”来表示作业ID。分配标签在约束中起关键作用,因为它们允许引用共享公共标签的多个分配。
请注意,我们使用新的SchedulingRequest对象,而不是使用ResourceRequest对象来定义分配标记。这与ResourceRequest有许多相似之处,但更好地区分了所请求分配的大小(分配的数量和大小,优先级,执行类型等),以及规定应如何放置这些分配的约束(资源名称,放宽的位置) 。应用程序仍然可以使用ResourceRequest对象,但是为了定义分配标记和约束,它们需要使用SchedulingRequest对象。在单个AllocateRequest中,应用程序应使用ResourceRequest或SchedulingRequest对象,但不是两者。
分配标记和节点标签或节点属性(YARN-3409)之间的区别在于分配标记附加到分配而不是节点。当调度程序将分配分配给节点时,该分配的标记集将在分配期间自动添加到节点。因此,节点继承当前分配给节点的分配的标记。同样,机架继承其节点的标签。此外,类似于节点标签,与节点属性不同,分配标签没有附加值。如下所示,我们的约束可以引用分配标记,以及节点标签和节点属性。
应用程序可以使用PlacementConstraints中的公共API 来构造放置约束。在描述构建约束的方法之前,我们描述了PlacementTargets类的方法,这些方法用于构造将在约束中使用的目标表达式:
方法:allocationTag(String... allocationTags) 描述:在分配标记上构造目标表达式。如果存在具有给定标签之一的分配则满足
方法:allocationTagToIntraApp(String ... allocationTags) 描述:类似于allocationTag(String ...),但仅针对将使用此目标的应用程序的容器(应用程序内约束)
方法:nodePartition(String... nodePartitions) 描述:在节点分区上构造目标表达式。它满足属于某个nodePartitions的节点。
方法:nodeAttribute(String attributeKey, String... attributeValues) 描述:在节点属性上构造目标表达式。如果指定的节点属性具有指定值之一,则满足。
请注意,上面的nodeAttribute方法尚未起作用,因为它需要正在进行的节点属性功能。
用于构建约束的PlacementConstraints类的方法如下:
targetIn(String scope,TargetExpression ... targetExpressions) 创建一个约束,要求将分配放置在满足给定范围内所有目标表达式的节点上(例如,节点或机架)。例如,targetIn(RACK,allocationTag(“hbase-m”))允许在属于具有至少一个带有标记“hbase-m”的分区的机架的节点上进行分配。
targetNotIn(String scope,TargetExpression ... targetExpressions) 创建一个约束,该约束要求将分配放置在属于不满足任何目标表达式的范围(例如,节点或机架)的节点上。
cardinality(String scope,int minCardinality,int maxCardinality,String ... allocationTags) 创建限制给定范围(例如,节点或机架)内的分配数量的约束。例如,{@code cardinality(NODE,3,10,“zk”)}在具有标记“zk”且不超过10的不少于3个分配的节点上得到满足。
minCardinality(String scope,int minCardinality,String ... allocationTags) 与基数(String,int,int,String ...)类似,但仅确定最小基数(最大基数未绑定)。
maxCardinality(String scope,int maxCardinality,String ... allocationTags) 类似于基数(String,int,int,String ...),但仅确定最大基数(最小基数为0)。
targetCardinality(String scope,int minCardinality,int maxCardinality,String ... allocationTags) 该约束推广了基数和目标约束。考虑一组节点N,它们属于约束中指定的范围。如果目标表达式在节点集N中至少满足minCardinality时间并且至多满足maxCardinality时间,则满足约束。例如,targetCardinality(RACK,2,10,allocationTag(“zk”))要求将分配放置在具有标签“zk”的至少2个且最多10个其他分配的机架内。
所述PlacementConstraints类还包括用于构建化合物约束(和/或与多个约束表达式)方法。添加对复合约束的支持目前尚未应用。
应用程序必须指定将为其启用每个约束的容器。为此,应用程序可以提供从一组分配标签(源标签)到放置约束的映射。例如,此映射的条目可以是“hbase” - > constraint1,这意味着在使用标记“hbase”调度每个分配时将应用constraint1。
使用放置处理器处理程序时(请参阅启用放置约束),此约束映射在RegisterApplicationMasterRequest中指定。
使用调度程序处理程序时,也可以在每个SchedulingRequest对象中添加约束。每个这样的约束对该调度请求的标记有效。如果在RegisterApplicationMasterRequest和调度请求中都指定了约束,则后者会覆盖前者。
此外YARN还存在支持管理员为队列指定具体数目的资源(比如具体的内存数量、vcore 核数、GPU 等),而不是提供基于百分比的值,这让管理员能够更好地控制给定队列配置所需的资源。详情可见:Hadoop容量调度程序。