在学习Hadoop YARN—Hadoop 2.0新引入的通用资源管理系统过程当中,总会遇到Container这一律念,因为中文资料的缺少,不少人对Container这一律念仍很是的模糊。它与Linux Container是什么关系,它是否能像Linux Container那样为任务提供一个隔离环境?它表明计算资源,仍是仅仅是一个任务处理进程?本文将尝试介绍Container这一律念。java
在学习Container以前,你们应先了解YARN的基本架构、工做流程。好比,你们应该了解一个应用程序的运行过程以下:node
步骤1:用户将应用程序提交到ResourceManager上;安全
步骤2:ResourceManager为应用程序ApplicationMaster申请资源,并与某个NodeManager通讯,以启动ApplicationMaster; 架构
步骤3:ApplicationMaster与ResourceManager通讯,为内部要执行的任务申请资源,一旦获得资源后,将与NodeManager通讯,以启动对应的任务。app
步骤4:全部任务运行完成后,ApplicationMaster向ResourceManager注销,整个应用程序运行结束。异步
上述步骤中,步骤2~3涉及到资源申请与使用,而这正是Container出现的地方。ide
若是你你还不了解YARN的基本架构和工做原理,可阅读个人如下几篇文章:oop
YARN基本架构,YARN中的基本术语,YARN整套分析文章。学习
在YARN中,ResourceManager中包含一个插拔式的组件:资源调度器,它负责资源的管理和调度,是YARN中最核心的组件之一。优化
当向资源调度器申请资源,需向它发送一个ResourceRequest列表,其中,每一个ResourceRequest描述了一个资源单元的详细需求,而资源调度器则为之返回分配到的资源描述Container。每一个ResourceRequest可看作一个可序列化Java对象,包含的字段信息(直接给出了Protocol Buffers定义)以下:
message ResourceRequestProto {
optional PriorityProto priority = 1; // 资源优先级
optional string resource_name = 2; // 资源名称(指望资源所在的host、rack名称等)
optional ResourceProto capability = 3; // 资源量(仅支持CPU和内存两种资源)
optional int32 num_containers = 4; // 知足以上条件的资源个数
optional bool relax_locality = 5 [default = true]; //是否支持本地性松弛(2.1.0-beta以后的版本新增长的,具体参考个人这篇文章:Hadoop新特性、改进、优化和Bug分析系列3:YARN-392)
}
从上面定义能够看出,能够为应用程序申请任意大小的资源量(CPU和内存),且默认状况下资源是本地性松弛的,即申请优先级为10,资源名称为“node11”,资源量为<2GB, 1cpu>的5份资源时,若是节点node11上没有知足要求的资源,则优先找node11同一机架上其余节点上知足要求的资源,若是仍找不到,则找其余机架上的资源。而若是你必定要node11上的节点,则将relax_locality置为false。
发出资源请求后,资源调度器并不会立马为它返回知足要求的资源,而须要应用程序的ApplicationMaster不断与ResourceManager通讯,探测分配到的资源,并拉去过来使用。一旦分配到资源后,ApplicatioMaster可从资源调度器那获取以Container表示的资源,Container可看作一个可序列化Java对象,包含的字段信息(直接给出了Protocol Buffers定义)以下:
message ContainerProto {
optional ContainerIdProto id = 1; //container id
optional NodeIdProto nodeId = 2; //container(资源)所在节点
optional string node_http_address = 3;
optional ResourceProto resource = 4; //container资源量
optional PriorityProto priority = 5; //container优先级
optional hadoop.common.TokenProto container_token = 6; //container token,用于安全认证
}
通常而言,每一个Container可用于运行一个任务。ApplicationMaster收到一个或多个Container后,再次将该Container进一步分配给内部的某个任务,一旦肯定该任务后,ApplicationMaster需将该任务运行环境(包含运行命令、环境变量、依赖的外部文件等)连同Container中的资源信息封装到ContainerLaunchContext对象中,进而与对应的NodeManager通讯,以启动该任务。ContainerLaunchContext包含的字段信息(直接给出了Protocol Buffers定义)以下:
message ContainerLaunchContextProto {
repeated StringLocalResourceMapProto localResources = 1; //Container启动以来的外部资源
optional bytes tokens = 2;
repeated StringBytesMapProto service_data = 3;
repeated StringStringMapProto environment = 4; //Container启动所需的环境变量
repeated string command = 5; //Container内部运行的任务启动命令,若是是MapReduce的话,Map/Reduce Task启动命令就在该字段中
repeated ApplicationACLMapProto application_ACLs = 6;
}
每一个ContainerLaunchContext和对应的Container信息(被封装到了ContainerToken中)将再次被封装到StartContainerRequest中,也就是说,ApplicationMaster最终发送给NodeManager的是StartContainerRequest,每一个StartContainerRequest对应一个Container和任务。
总结上述可知,Container的一些基本概念和工做流程以下:
(1) Container是YARN中资源的抽象,它封装了某个节点上必定量的资源(CPU和内存两类资源)。它跟Linux Container没有任何关系,仅仅是YARN提出的一个概念(从实现上看,可看作一个可序列化/反序列化的Java类)。
(2) Container由ApplicationMaster向ResourceManager申请的,由ResouceManager中的资源调度器异步分配给ApplicationMaster;
(3) Container的运行是由ApplicationMaster向资源所在的NodeManager发起的,Container运行时需提供内部执行的任务命令(可使任何命令,好比java、Python、C++进程启动命令都可)以及该命令执行所需的环境变量和外部资源(好比词典文件、可执行文件、jar包等)。
另外,一个应用程序所需的Container分为两大类,以下:
(1) 运行ApplicationMaster的Container:这是由ResourceManager(向内部的资源调度器)申请和启动的,用户提交应用程序时,可指定惟一的ApplicationMaster所需的资源;
(2) 运行各种任务的Container:这是由ApplicationMaster向ResourceManager申请的,并由ApplicationMaster与NodeManager通讯以启动之。
以上两类Container可能在任意节点上,它们的位置一般而言是随机的,即ApplicationMaster可能与它管理的任务运行在一个节点上。
Container是YARN中最重要的概念之一,懂得该概念对于理解YARN的资源模型相当重要,但愿本文对学习Container这一律念有所帮助。