在 YARN 上运行 Spark

Spark 对 YARN (Hadoop NextGen) 的支持是从 0.6.0 版本开始的,后续的版本也在持续的改进。

在YARN上启动

首先要确保 HADOOP_CONF_DIR 或者 YARN_CONF_DIR 指向一个包含 Hadoop 集群客户端配置文件的目录。这些配置用于向 HDFS 写数据以及连接到 YARN 的 ResourceManager(资源管理器)。这个目录下的配置将会分发到 YARN 集群上的各个节点,这样应用程序使用的所有YARN 容器都将使用同样的配置。如果这些配置引用了 Java 系统属性或其它不属于 YARN 管理的环境变量,那么这些系统属性和环境变量也应该在 Spark 应用程序的配置中设置(包括 Driver、Executors,以及运行于 client 模式时的 YARN Application Master, 简称 AM)。

有两种部署模式可用于在 YARN 上启动 Spark 应用程序。在 cluster 模式下,Spark driver 在YARN Application Master中运行(运行于集群中),因此客户端可以在Spark应用启动之后关闭退出。而client模式下,Spark驱动器在客户端进程中,这时的YARN Application Master只用于向YARN申请资源。

不同于 Spark standalone 和 Mesos 模式,YARN 的master地址不是在–master参数中指定的,而是在Hadoop配置文件中设置。因此,这种情况下,–master只需设置为yarn。

以下用cluster模式启动一个Spark应用:

$ ./bin/spark-submit --class path.to.your.Class --master yarn --deploy-mode cluster [options] <app jar> [app options]

例如:

$ ./bin/spark-submit --class org.apache.spark.examples.SparkPi \
    --master yarn \
    --deploy-mode cluster \
    --driver-memory 4g \
    --executor-memory 2g \
    --executor-cores 1 \
    --queue thequeue \
    lib/spark-examples*.jar 10

以上例子中,启动了一个YARN客户端程序,使用默认的Application Master。而后SparkPi在Application Master中的子线程中运行。客户端会周期性的把Application Master的状态信息拉取下来,并更新到控制台。客户端会在你的应用程序结束后退出。参考“调试你的应用”,这一节说明了如何查看驱动器和执行器的日志。

要以client模式启动一个spark应用,只需在上面的例子中把cluster换成client。下面这个例子就是以client模式启动spark-shell:

$ ./bin/spark-shell --master yarn --deploy-mode client

增加其他JAR包

在cluster模式下,驱动器不在客户端机器上运行,所以SparkContext.addJar添加客户端本地文件就不好使了。要使客户端上本地文件能够用SparkContext.addJar来添加,可以用–jars选项:

$ ./bin/spark-submit --class my.main.Class \
    --master yarn \
    --deploy-mode cluster \
    --jars my-other-jar.jar,my-other-other-jar.jar \
    my-main-jar.jar \
    app_arg1 app_arg2

准备

在YARN上运行Spark需要其二进制发布包构建的时候增加YARN支持。二进制发布包可以在这里下载:downloads page 。

想要自己编译,参考这里: Building Spark

配置

大多数配置,对于YARN或其他集群模式下,都是一样的。详细请参考这里: configuration page。

以下是YARN上专有的配置项。

调试应用程序

在YARN术语集中,执行器和Application Master在容器(container)中运行。YARN在一个应用程序结束后,有两种处理容器日志的模式。如果开启了日志聚合(yarn.log-aggregation-enable),那么容器日志将被复制到HDFS,并删除本地日志。而后这些日志可以在集群任何节点上用yarn logs命令查看:

yarn logs -applicationId <app ID>

以上命令,将会打印出指定应用的所有日志文件的内容。你也可以直接在HDFS上查看这些日志(HDFS shell或者HDFS API)。这些目录可以在你的YARN配置中指定(yarn.nodemanager.remote-app-log-dir和yarn.nodemanager-remote-app-log-dir-suffix)。这些日志同样还可以在Spark Web UI上Executors tab页查看。当然,你需要启动Spark history server和 MapReduce history server,再在 yarn-site.xml 中配置好 yarn.log.server.url。Spark history server UI 将把你重定向到MapReduce history server 以查看这些聚合日志。

如果日志聚合没有开启,那么日志文件将在每台机器上的 YARN_APP_LOGS_DIR 目录保留,通常这个目录指向 /tmp/logs 或者 $HADOOP_HOME/log/userlogs(这取决于Hadoop版本和安全方式)。查看日志的话,需要到每台机器上查看这些目录。子目录是按 application ID 和 container ID来组织的。这些日志同样可以在 Spark Web UI 上 Executors tab 页查看,而且这时你不需要运行MapReduce history server。

如果需要检查各个容器的启动环境,可以先把 yarn.nodemanager.delete.debug-delay-sec 增大(如:36000),然后访问应用缓存目录yarn.nodemanager.local-dirs,这时容器的启动目录。这里包含了启动脚本、jar包以及容器启动所用的所有环境变量。这对调试 classpath 相关问题尤其有用。(注意,启用这个需要管理员权限,并重启所有的node managers,因此,对托管集群不适用)

要自定义Application Master或执行器的 log4j 配置,有如下方法: * 通过spark-submit –files 上传一个自定义的 log4j.properties 文件。 * 在 spark.driver.extraJavaOptions(对Spark驱动器)或者 spark.executor.extraJavaOptions(对Spark执行器)增加 -Dlog4j.configuration=<location of configuration file>。注意,如果使用文件,那么 file: 协议头必须显式写上,且文件必须在所节点上都存在。 * 更新 ${SPARK_CONF_DIR}/log4j.properties 文件以及其他配置。注意,如果在多个地方都配置了log4j,那么上面其他两种方法的配置优先级比本方法要高。 注意,第一种方法中,执行器和Application Master共享同一个log4j配置,在有些环境下(AM和执行器在同一个节点上运行)可能会有问题(例如,AM和执行器日志都写入到同一个日志文件)

如果你需要引用YARN放置日志文件的路径,以便YARN可以正确地展示和聚合日志,请在log4j.properties文件中使用spark.yarn.app.container.log.dir。例如,log4j.appender.file_appender.File=${spark.yarn.app.container.log.dir}/spark.log 。对于流式应用,可以配置RollingFileAppender,并将文件路径设置为YARN日志目录,以避免磁盘打满,而且这些日志还可以利用YARN的日志工具访问和查看。

重要提示

  • 对CPU资源的请求是否满足,取决于调度器如何配置和使用。
  • cluster模式下,Spark执行器(executor)和驱动器(driver)的local目录都由YARN配置决定(yarn.nodemanager.local-dirs);如果用户指定了spark.local.dir,这时候将被忽略。在client模式下,Spark执行器(executor)的local目录由YARN决定,而驱动器(driver)的local目录由spark.local.dir决定,因为这时候,驱动器不在YARN上运行。
  • 选项参数 –files和 –archives中井号(#)用法类似于Hadoop。例如,你可以指定 –files localtest.txt#appSees.txt,这将会把localtest.txt文件上传到HDFS上,并重命名为 appSees.txt,而你的程序应用用 appSees.txt来引用这个文件。
  • 当你在cluster模式下使用本地文件时,使用选项–jar 才能让SparkContext.addJar正常工作,而不必使用 HDFS,HTTP,HTTPS或者FTP上的文件。

在安全的集群中运行

在安全性方面,Kerberos用于安全的Hadoop集群,以对与服务和客户端关联的主体进行身份验证。这允许客户提出这些认证服务的请求;向经认证的校长授予权利的服务。

Hadoop服务发布hadoop令牌来授予对服务和数据的访问权限。客户必须首先获取他们将访问的服务的标记,并将其与在YARN集群中启动的应用程序一起传递。

对于Spark应用程序来与任何Hadoop文件系统(例如hdfs,webhdfs等),HBase和Hive进行交互,它必须使用启动应用程序的用户的Kerberos凭据来获取相关的令牌,也就是说,将成为Spark应用程序的启动。

这通常在启动时完成:在一个安全的集群中,Spark将自动获取集群的默认Hadoop文件系统的标记,并可能为HBase和Hive获取标记。

如果HBase位于类路径中,HBase配置声明应用程序是安全的(即,hbase-site.xml将hbase.security.authentication设置为kerberos),则将获得HBase令牌,并且spark.yarn.security.credentials.hbase.enabled没有设置为false。

同样,如果Hive位于类路径上,则会获得Hive标记,其配置包含“hive.metastore.uris”中的元数据存储的URI,并且spark.yarn.security.credentials.hive.enabled未设置为false。

如果应用程序需要与其他安全的Hadoop文件系统进行交互,则在启动时必须明确请求访问这些群集所需的令牌。这是通过将它们列在spark.yarn.access.hadoopFileSystems属性中完成的。

spark.yarn.access.hadoopFileSystems hdfs://ireland.example.org:8020/,webhdfs://frankfurt.example.org:50070/

Spark通过Java服务机制支持与其他安全感知服务的集成(请参阅java.util.ServiceLoader)。 要做到这一点,org.apache.spark.deploy.yarn.security.ServiceCredentialProvider的实现应该可用于Spark,方法是将它们的名称列在jar的META-INF / services目录下的相应文件中。 可以通过将spark.yarn.security.credentials {service} .enabled设置为false来禁用这些插件,其中{service}是凭证提供程序的名称。

配置外部的 Shuffle 服务

要在您的YARN集群中的每个NodeManager上启动Spark Shuffle服务,请按照以下说明进行操作:

1、使用YARN配置文件构建Spark。 如果您使用的是预打包发行版,请跳过此步骤。 2、找到spark- <version> -yarn-shuffle.jar。 这应该在$ SPARK_HOME / common / network-yarn / target / scala- <version>之下,如果你自己创建Spark,并且在使用分发的情况下使用yarn。 3、将此jar添加到群集中所有NodeManagers的类路径中。 4、在每个节点的yarn-site.xml中,将spark_shuffle添加到yarn.nodemanager.aux-services,然后将yarn.nodemanager.aux-services.spark_shuffle.class设置为org.apache.spark.network.yarn.YarnShuffleService。 5、通过在etc / hadoop / yarn-env.sh中设置YARN_HEAPSIZE(默认为1000)来增加NodeManager的堆大小,以避免在shuffle期间垃圾收集问题。 6、重新启动群集中的所有节点管理器。

在YARN上运行shuffle服务时,可以使用以下额外的配置选项:

使用 Apache Oozie启动应用程序

Apache Oozie can launch Spark applications as part of a workflow. In a secure cluster, the launched application will need the relevant tokens to access the cluster’s services. If Spark is launched with a keytab, this is automatic. However, if Spark is to be launched without a keytab, the responsibility for setting up security must be handed over to Oozie. The details of configuring Oozie for secure clusters and obtaining credentials for a job can be found on the Oozie web site in the “Authentication” section of the specific release’s documentation. For Spark applications, the Oozie workflow must be set up for Oozie to request all tokens which the application needs, including: * The YARN resource manager. * The local HDFS filesystem. * Any remote HDFS filesystems used as a source or destination of I/O. * Hive —if used. * HBase —if used. * The YARN timeline server, if the application interacts with this. To avoid Spark attempting —and then failing— to obtain Hive, HBase and remote HDFS tokens, the Spark configuration must be set to disable token collection for the services.

The Spark configuration must include the lines: spark.yarn.security.tokens.hive.enabled false spark.yarn.security.tokens.hbase.enabled false

The configuration option spark.yarn.access.namenodes must be unset.

Troubleshooting Kerberos

Debugging Hadoop/Kerberos problems can be “difficult”. One useful technique is to enable extra logging of Kerberos operations in Hadoop by setting the HADOOP_JAAS_DEBUG environment variable. bash export HADOOP_JAAS_DEBUG=true The JDK classes can be configured to enable extra logging of their Kerberos and SPNEGO/REST authentication via the system propertiessun.security.krb5.debug and sun.security.spnego.debug=true -Dsun.security.krb5.debug=true -Dsun.security.spnego.debug=true All these options can be enabled in the Application Master: spark.yarn.appMasterEnv.HADOOP_JAAS_DEBUG true spark.yarn.am.extraJavaOptions -Dsun.security.krb5.debug=true -Dsun.security.spnego.debug=true Finally, if the log level for org.apache.spark.deploy.yarn.Client is set to DEBUG, the log will include a list of all tokens obtained, and their expiry details

使用 Spark History Server 替代 Spark Web UI

It is possible to use the Spark History Server application page as the tracking URL for running applications when the application UI is disabled. This may be desirable on secure clusters, or to reduce the memory usage of the Spark driver. To set up tracking through the Spark History Server, do the following:

  • On the application side, set spark.yarn.historyServer.allowTracking=true in Spark’s configuration. This will tell Spark to use the history server’s URL as the tracking URL if the application’s UI is disabled.
  • On the Spark History Server, add org.apache.spark.deploy.yarn.YarnProxyRedirectFilter to the list of filters in the spark.ui.filters configuration.

Be aware that the history server information may not be up-to-date with the application’s state.