学习Hadoop生态第一步:Yarn基本原理和资源调度解析!

本文作为《Hadoop从入门到精通》专题第二章的第一小节(第一章:《Hadoop生态系统及运行MapReduce任务介绍》,文章链接:http://blog.itpub.net/31077337/viewspace-2213549/),主要介绍如何从命令行开始使用Yarn以及解决使用资源调度过程中遇到的各种问题。一旦你开始了解Yarn,就会发现MapReduce是如何被重写为YARN应用程序的(MapReduce 2或MRv2),并了解MapReduce的体系结构更改。

2.1 Yarn概述

Yarn是Yet Another Resource Negotiator的缩写。根据Yarn中文官网的显示,这是一个快速、可靠、安全的依赖管理工具,目前提供的稳定版本为v1.9.4(截至发稿时)。在Hadoop 1.0及更早版本中,我们只能运行MapReduce,这导致图形处理、迭代计算等任务无法有效执行。在Hadoop 2.0及后续版本中,MapReduce的调度部分被外部化并重新编写为名为Yarn的新组件,Yarn最大的特点是执行调度与Hadoop上运行的任务类型无关。

图2.1 新旧Hadoop堆栈展示(Hadoop 1.0和Hadoop 2.0)

2.1.1 为什么选择Yarn?

首先,上文已经提到Yarn可在Hadoop上执行除MapReduce以外的工作。MapReduce是一个功能强大的分布式框架和编程模型,允许在多节点集群上执行基于批处理的并行化工作。尽管MapReduce功能强大,但它也有一些缺点,比如不适合实时甚至近实时的数据处理。但是,Yarn可以弥补MapReduce的不足,其核心是分布式调度程序,负责两项工作:

  • 响应客户端创建容器的请求——容器本质上可理解为一个进程(也有人理解为服务程序),其中包含允许使用的物理资源。

  • 监视正在运行的容器,并在需要时终止。如果YARN调度程序想要释放资源以便其他应用程序的容器运行,或者容器使用的资源多于其分配的资源,则可以选择终止容器。

2.1.2 Yarn组件

Yarn主要由ResourceManager、NodeManager、ApplicationMaster和Container等组件构成。Yarn框架执行主要功能,即在集群中调度资源(上文提到的容器)。集群中的应用程序与YARN框架通信,要求分配特定于应用程序的容器资源,Yarn框架会评估这些请求并尝试实现。Yarn调度的一个重要部分是监视当前正在执行的容器,一旦容器完成,调度程序就可以释放容量来安排其他工作。此外,每个容器都有一个协议,指定允许使用的系统资源,并在容器超出边界的情况下终止容器,以避免恶意影响其他应用程序。

Yarn框架有意设计的尽可能简单,它不知道或不关心正在运行的应用程序类型,不保留有关集群上执行内容的任何历史信息,这些设计是Yarn可以扩展到MapReduce之外的主要原因。

  • ResourceManager——Hadoop集群具有至少一个ResourceManager(RM)。ResourceManager是Yarn的主进程,其唯一功能是仲裁Hadoop集群上的资源,响应客户端创建容器请求,调度程序根据特定的多租户规则确定何人可以在何时何地创建容器,正如Hadoop 1.0版本,ResourceManager调度程序是可选择的,这意味着你可以选择最适合的调度程序,而实际创建的容器被委托给NodeManager。

  • NodeManager——NodeManager是在集群每个节点上运行的从属进程。它的主要工作是创建、监视和杀死容器。它为来自ResourceManager和ApplicationMaster的请求提供服务以创建容器,并向ResourceManager报告容器的状态。ResourceManager使用这些状态消息中包含的数据对请求做出调度决策。在非HA模式下,只存在ResourceManager单个实例。

Yarn应用程序具备在Hadoop上运行的特定功能,MapReduce是YARN应用程序的一个示例,Hoya等项目允许多个HBase实例在单个集群上运行,而Storm-yarn允许Storm在Hadoop集群内运行。

图2.2 YARN框架组件及其交互,不显示特定于应用程序的组件,比如YARN客户端,ApplicationMaster和容器等。

图2.3 YARN应用程序典型交互

Yarn应用程序涉及三大组件 - 客户端,ApplicationMaster(AM)和容器,如图2.3所示。启动新的Yarn应用程序需从Yarn客户端开始,该客户端与ResourceManager通信以创建新的Yarn ApplicationMaster实例,此过程Yarn客户端会让ResourceManager通知ApplicationMaster物理资源要求。

ApplicationMaster是Yarn应用程序主进程,不执行任何特定于应用程序的工作,因为这些函数被委托给容器。但是,它负责管理特定于应用程序的容器:询问ResourceManager其创建容器的意图,然后与NodeManager联系以实际执行容器创建。作为此过程的一部分,ApplicationMaster必须根据主机启动容器,并确定容器的内存和CPU要求以指定容器所需资源。

ResourceManager根据资源要求安排工作,它使主机能够运行混合容器,如图2.4所示。ApplicationMaster负责应用程序的特定容错,在容器失败时从ResourceManager接收状态消息,并基于具体事件采取操作(通过要求ResourceManager创建新容器解决)或忽略这些事件。

图2.4 在单个YARN管理的Hadoop节点上运行的各种容器配置

容器是由NodeManager代表ApplicationMaster创建的特定于应用程序的进程。ApplicationManager本身也是一个由ResourceManager创建的容器。由ApplicationManager创建的容器可以是任意进程——例如,容器进程可以是简单的Linux命令,例如awk,Python应用程序或可由操作系统启动的任何进程,这也是YARN强大功能的体现——可以在Hadoop集群的任何节点启动和管理任何进程。

2.1.3 Yarn配置

Yarn为各组件带来了强大的配置,例如UI、远程进程调用(RPC)等。在选择之前,你需要弄清楚想要访问的正在运行的Hadoop集群配置,你可以使用ResourceManager UI查看相关配置。

该功能的亮点在于UI不仅可以显示属性值,还可以显示文件来源。如果未在 site.xml文件中定义该值,则将显示默认值和文件名。该UI的另一功能是可显示来自多个文件的配置,包括HDFS、Yarn和MapReduce等文件,可以从NodeManager UI以相同的方式导航到单个Hadoop从属节点的配置。在使用由异构节点组成的Hadoop集群时,这一功能非常有用,因为这些集群通常会有不同的配置来满足不同的硬件资源。

图2.5 集群配置的YARN ResourceManager UI

2.1.4  Yarn开箱即用

Hadoop 2捆绑了两个Yarn应用程序——MapReduce 2和DistributedShell。如果你不清楚集群配置,则有两个办法可以解决:

  1. 检查yarn-site.xml的内容以查看属性值。如果不存在自定义值,则默认值将生效。

  2. 使用ResourceManager UI,它提供了有关运行配置的详细信息,包括默认值以及是否生效。

如果希望在Hadoop集群节点上运行Linux命令,可以使用与Hadoop捆绑在一起的DistributedShell示例应用程序。该应用程序也是在Hadoop集群中并行运行命令的便捷实用程序。

首先在单个容器中发出Linux find命令:

如果集群一切正常,则执行上述命令将出现以下消息:

INFO distributedshell.Client: Application completed successfully

你可以在此行之前的命令输出中看到其他日志记录语句,但它们都不包含find命令的实际结果。这是因为DistributedShell ApplicationMaster在单独的容器中启动find命令,并且find命令的标准输出被重定向到容器的日志输出目录。要查看命令输出,必须访问该目录。如果想访问容器日志文件,可以使用Yarn的UI和命令。Yarn中运行的每个容器都有自己的输出目录,其中包括标准输出等信息。

图2.6容器日志位置和数据保留

在使用Yarn命令行访问容器日志时,Yarn附带了用于访问应用程序日志的命令行界面(CLI)。但是,使用CLI的前提是知道应用程序ID。大多数Yarn客户端将在其输出和日志中显示应用程序ID。例如,之前执行的DistributedShell命令将应用程序ID回显到标准输出:

$ hadoop o.a.h.y.a.d.Client ... ... 
INFO impl.YarnClientImpl: 
Submitted application application_1388257115348_0008 to 
ResourceManager at /0.0.0.0:8032 
...

或者,我们可以使用CLI(使用yarn application -list)和ResourceManager UI进行浏览并找到应用程序ID。如果应用程序在运行时尝试使用CLI,则会显示以下错误消息:

$ yarn logs -applicationId application_1398974791337_0070 
Application has not completed. Logs are only available after 
an application completes

该消息表明:CLI仅在应用程序完成后才可用。在应用程序运行时,我们需要使用UI来访问容器日志。应用程序完成后,如果再次尝试运行该命令,则可能会看到以下输出:

$ yarn logs -applicationId application_1400286711208_0001 
Logs not available at /tmp/.../application_1400286711208_0001 
Log aggregation has not completed or is not enabled.

基本上,Yarn CLI仅在应用程序已完成且启用日志聚合时才有效。如果启用日志聚合,CLI将提供应用程序中所有容器日志,如下所示:

$ yarn logs -applicationId application_1400287920505_0002 
client.RMProxy: Connecting to ResourceManager at /0.0.0.0:8032
Container: container_1388248867335_0003_01_000002 
on localhost.localdomain_57276 
============================================================== 
LogType: stderr 
LogLength: 0 
Log Contents:
LogType: stdout
LogLength: 1355 
Log Contents: 
/tmp default_container_executor.sh 
/launch_container.sh 
/.launch_container.sh.crc 
/.default_container_executor.sh.crc 
/.container_tokens.crc 
/AppMaster.jar 
/container_tokens
Container: container_1400287920505_0002_01_000001 
on localhost.localdomain_57276 
================================================= 
LogType: AppMaster.stderr 
LogLength: 17170 
Log Contents: distributedshell.ApplicationMaster: Initializing ApplicationMaster 
...
LogType: AppMaster.stdout 
LogLength: 8458 
Log Contents: 
System env: key=TERM, val=xterm-256color 
...

上述输出显示了运行DistributedShell示例的日志内容。输出中有两个容器——用于执行的find命令和用于ApplicationMaster的命令。使用Yarn UI访问日志时,Yarn通过ResourceManager UI提供对ApplicationMaster日志的访问。在伪分布式设置上,将浏览器指向http:// localhost:8088 / cluster。如果正在使用多节点Hadoop集群,请将浏览器指向http://$yarn.resourcemanager.webapp.address/cluster,如图2.7所示。

不幸的是,ResourceManager为了保证轻量级,不会跟踪应用程序的容器ID。因此,ResourceManager UI仅提供访问应用程序ApplicationMaster日志的方法。一个典型的例子是DistributedShell应用程序,它不提供ApplicationMaster UI或跟踪启动的容器。

图2.7 显示ApplicationMaster容器的YARN ResourceManager UI

幸运的是,MapReduce Yarn应用程序提供了一个ApplicationMaster UI,你可以使用它来访问容器(map和reduce任务)日志,并在MapReduce作业完成后访问日志的JobHistory UI。当运行MapReduce作业时,ResourceManager UI会提供MapReduce ApplicationMaster UI的链接。

图2.8 访问正在运行作业的MapReduce UI

Yarn应用程序提供了一些方法来识别容器ID及其执行的主机,则可以使用NodeManager UI访问容器日志,也可以使用shell ssh到执行容器的从属节点。用于访问容器日志的NodeManager URL是http://:8042/node/containerlogs//。或者,你可以ssh到NodeManager主机并访问$yarn .nodemanager.log -dirs//中的容器日志目录。实际上,最佳建议是启用日志聚合,这将允许使用CLI,HDFS和UI(例如MapReduce ApplicationMaster和JobHistory)来访问应用程序日志。

日志聚合是Hadoop 1中缺少的功能,但Hadoop 2具有此功能,你可以通过多种方式访问聚合日志文件。如果启用日志聚合功能,它会在Yarn应用程序完成后将容器日志文件复制到Hadoop文件系统(如HDFS)中。默认情况下,此行为已禁用,需要将yarn.log-aggregation-enable设置为true以启用此功能。

使用CLI访问日志文件需要使用应用程序ID,可以使用命令行获取所有日志并将其写入控制台:

$ yarn logs -applicationId application_1388248867335_0003 Enabling log aggregation

如果yarn logs命令产生以下输出,那么很可能没有启用Yarn日志聚合:

Log aggregation has not completed or is not enabled.

图2.9 从本地文件系统到HDFS的日志文件聚合

这将转储Yarn应用程序的所有容器日志,每个容器输出都用一个标题表示容器ID,然后是容器输出目录中每个文件的详细信息。例如,如果运行了执行ls -l的DistributedShell命令,那么yarn logs命令的输出将产生如下所示的内容:

Container: container_1388248867335_0003_01_000002 on localhost ============================================================== 
LogType: stderr 
LogLength: 0 
Log Contents:
LogType: stdout
LogLength: 268 
Log Contents: 
total 32 -rw-r--r-- 1 aholmes 12:29 container_tokens
-rwx------ 1 aholmes 12:29 default_container_executor.sh 
-rwx------ 1 aholmes launch_container.sh 
drwx--x--- 2 aholmes tmp
Container: container_1388248867335_0003_01_000001 on localhost ============================================================== 
LogType: AppMaster.stderr 
(the remainder of the ApplicationMaster logs removed for brevity)

如上,stdout文件包含ls进程当前目录的列表,该目录是特定于容器的工作目录。同样,JobHistory UI也可以访问聚合日志。如果启用了日志聚合,则需要更新yarn-site.xml并将yarn.log.server.url设置为指向作业历史记录的服务器,以便ResourceManager UI呈现日志。

访问HDFS中的日志文件,默认情况下将进入HDFS中的以下目录:

/tmp/logs/${user}/logs/application_

我们可以通过yarn.nodemanager.remote-app-log-dir属性配置目录前缀。类似地,用户名之后的路径名(前一个示例中的“logs”,这是默认值)可以通过yarn.nodemanager.remote-app-log-dir-suffix自定义。本地文件系统和HDFS中的日志文件之间的差异如前所述,每个容器在本地文件系统中产生两个日志文件:一个用于标准输出,另一个用于标准错误。作为聚合过程的一部分,给定节点的所有文件将连接在一起,形成特定于节点的日志。例如,如果有五个容器在三个节点上运行,那么最终将在HDFS中使用三个日志文件。压缩默认情况下禁用聚合日志压缩,但你可以通过将yarn.nodemanager.log-aggregation.compression-type的值设置为lzo或gzip来启用,具体取决于压缩要求。从Hadoop 2.2开始,这是唯一支持的两种压缩编解码器。

当关闭日志聚合时,本地主机上的容器日志文件将保留为yarn.nodemanager.log.retain-seconds seconds,默认值为10,800(3小时)。打开日志聚合时,将忽略yarn.nodemanager.log.retain-seconds可配置,而是将本地容器日志文件复制到HDFS后立即删除。如果想将它们保留在本地文件系统上,那么所有这些都不会丢失 - 只需将yarn.nodemanager.delete.debug-delay-sec设置为想保留文件的值即可。请注意,这不仅适用于日志文件,还适用于与容器关联的所有其他元数据(例如JAR文件)。HDFS中文件的数据保留是通过设置不同的yarn.log-aggregation.retain-seconds来配置的。

替代解决方案

如果你有日志挖掘或者可视化方面的需求,你也可以考虑其他替代解决方案,例如Hunk,支持聚合来自Hadoop 1和Hadoop 2的日志;提供一流的查询、可视化和监控功能,就像普通的Splunk一样。如果要拥有日志管理过程,还可以使用Logstash、ElasticSearch和Kibana等工具设置查询和可视化管道。

2.1.5 Yarn面临的挑战

目前,我们使用Yarn时需要注意一些问题:Yarn不适用于长时间运行的进程,这受到了来自Impala和Tez等项目的挑战,这些项目受益于此类功能。目前,该功能正在引入YARN,国内不少企业也在这方面进行了相应的定制化;编写Yarn应用程序非常复杂,因为需要实现容器管理和容错,这可能需要一些复杂的ApplicationMaster和容器状态管理,以便在失败时可回滚至前一状态;原生Yarn不支持组合调度,即并行快速启动大量容器的能力,这是Impala和Hamster(OpenMPI)等项目的一大优势。到目前为止,本节一直专注于Yarn的核心功能,下一节将为大家介绍MapReduce如何作为YARN应用程序工作等内容。

请使用浏览器的分享功能分享到微信等