在 YARN 上运行 Spark

对在 YARN(Hadoop NextGen) 上运行的支持是在 Spark 0.6.0 版本中添加的,并在后续版本中得到改进。

安全

安全功能(如身份验证)默认情况下未启用。在部署开放给互联网或不受信任网络的集群时,保护对集群的访问非常重要,以防止未经授权的应用程序在集群上运行。在运行 Spark 之前,请参阅 Spark 安全 以及本文档中的特定安全部分。

在 YARN 上启动 Spark

确保 HADOOP_CONF_DIRYARN_CONF_DIR 指向包含 Hadoop 集群(客户端)配置文件的目录。这些配置用于写入 HDFS 并连接到 YARN ResourceManager。此目录中包含的配置将分发到 YARN 集群,以便应用程序使用的所有容器使用相同的配置。如果配置引用了 YARN 未管理的 Java 系统属性或环境变量,则也应在 Spark 应用程序的配置中设置它们(驱动程序、执行器,以及在客户端模式下运行时的 AM)。

有两种部署模式可用于在 YARN 上启动 Spark 应用程序。在 cluster 模式下,Spark 驱动程序在由 YARN 在集群上管理的应用程序主进程中运行,客户端可以在启动应用程序后退出。在 client 模式下,驱动程序在客户端进程中运行,应用程序主进程仅用于向 YARN 请求资源。

与 Spark 支持的其他集群管理器不同,在这些管理器中,主机的地址在 --master 参数中指定,在 YARN 模式下,ResourceManager 的地址是从 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 \
    examples/jars/spark-examples*.jar \
    10

以上命令启动一个 YARN 客户端程序,该程序启动默认的应用程序主进程。然后,SparkPi 将作为应用程序主进程的子线程运行。客户端将定期轮询应用程序主进程以获取状态更新并在控制台中显示它们。您的应用程序运行完成后,客户端将退出。有关如何查看驱动程序和执行器日志,请参阅下面的 调试您的应用程序 部分。

要在 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 支持构建的 Spark 二进制发行版。二进制发行版可以从项目网站的 下载页面 下载。您可以下载两种 Spark 二进制发行版。一种是预先构建的,包含特定版本的 Apache Hadoop;此 Spark 发行版包含内置的 Hadoop 运行时,因此我们将其称为 with-hadoop Spark 发行版。另一种是预先构建的,使用用户提供的 Hadoop;由于此 Spark 发行版不包含内置的 Hadoop 运行时,因此它更小,但用户必须单独提供 Hadoop 安装。我们将此变体称为 no-hadoop Spark 发行版。对于 with-hadoop Spark 发行版,由于它已经包含内置的 Hadoop 运行时,因此默认情况下,当作业提交到 Hadoop Yarn 集群时,为了防止 jar 冲突,它不会将 Yarn 的类路径填充到 Spark 中。要覆盖此行为,您可以设置 spark.yarn.populateHadoopClasspath=true。对于 no-hadoop Spark 发行版,Spark 默认情况下会填充 Yarn 的类路径,以获取 Hadoop 运行时。对于 with-hadoop Spark 发行版,如果您的应用程序依赖于集群中仅有的某些库,您可以尝试通过设置上面提到的属性来填充 Yarn 类路径。如果您在这样做时遇到 jar 冲突问题,则需要将其关闭并将此库包含在您的应用程序 jar 中。

要自己构建 Spark,请参阅 构建 Spark

要使 Spark 运行时 jar 可从 YARN 端访问,您可以指定 spark.yarn.archivespark.yarn.jars。有关详细信息,请参阅 Spark 属性。如果既未指定 spark.yarn.archive 也未指定 spark.yarn.jars,Spark 将使用 $SPARK_HOME/jars 下的所有 jar 创建一个 zip 文件并将其上传到分布式缓存。

配置

大多数配置对于 YARN 上的 Spark 与其他部署模式相同。有关这些配置的更多信息,请参阅 配置页面。以下配置特定于 YARN 上的 Spark。

调试您的应用程序

在 YARN 术语中,执行器和应用程序主进程在“容器”中运行。YARN 有两种模式用于处理应用程序完成后容器日志。如果日志聚合已启用(使用 yarn.log-aggregation-enable 配置),则容器日志将复制到 HDFS 并在本地机器上删除。可以使用 yarn logs 命令从集群中的任何位置查看这些日志。

yarn logs -applicationId <app ID>

将打印出给定应用程序的所有容器的所有日志文件的内容。您也可以使用 HDFS shell 或 API 直接在 HDFS 中查看容器日志文件。它们所在目录可以通过查看您的 YARN 配置 (yarn.nodemanager.remote-app-log-diryarn.nodemanager.remote-app-log-dir-suffix) 找到。这些日志在 Spark Web UI 的“执行器”选项卡下也可用。您需要同时运行 Spark 历史服务器和 MapReduce 历史服务器,并在 yarn-site.xml 中正确配置 yarn.log.server.url。Spark 历史服务器 UI 上的日志 URL 将重定向到 MapReduce 历史服务器以显示聚合的日志。

当日志聚合未启用时,日志将保留在每个机器上的 YARN_APP_LOGS_DIR 下,该目录通常配置为 /tmp/logs$HADOOP_HOME/logs/userlogs,具体取决于 Hadoop 版本和安装。查看容器日志需要转到包含它们的宿主并查看此目录。子目录按应用程序 ID 和容器 ID 组织日志文件。这些日志在 Spark Web UI 的“执行器”选项卡下也可用,并且不需要运行 MapReduce 历史服务器。

要查看每个容器的启动环境,请将 yarn.nodemanager.delete.debug-delay-sec 增加到一个较大的值(例如 36000),然后通过 yarn.nodemanager.local-dirs 访问启动容器的节点上的应用程序缓存。此目录包含启动脚本、JAR 和用于启动每个容器的所有环境变量。此过程特别适用于调试类路径问题。(请注意,启用此功能需要对集群设置具有管理员权限并重新启动所有节点管理器。因此,这并不适用于托管集群)。

要为应用程序主进程或执行器使用自定义 log4j 配置,以下是选项

请注意,对于第一个选项,执行器和应用程序主程序将共享相同的 log4j 配置,这可能会在它们在同一节点上运行时导致问题(例如,尝试写入同一个日志文件)。

如果您需要参考在 YARN 中放置日志文件的正确位置,以便 YARN 可以正确地显示和聚合它们,请在您的 log4j2.properties 中使用 spark.yarn.app.container.log.dir。例如,appender.file_appender.fileName=${sys:spark.yarn.app.container.log.dir}/spark.log。对于流式应用程序,将 RollingFileAppender 配置为将文件位置设置为 YARN 的日志目录,可以避免由大型日志文件引起的磁盘溢出,并且可以使用 YARN 的日志实用程序访问日志。

要为应用程序主程序和执行器使用自定义的 metrics.properties,请更新 $SPARK_CONF_DIR/metrics.properties 文件。它将自动与其他配置一起上传,因此您无需使用 --files 手动指定它。

Spark 属性

属性名称默认值含义自版本
spark.yarn.am.memory 512m 在客户端模式下,用于 YARN 应用程序主程序的内存量,格式与 JVM 内存字符串相同(例如 512m2g)。在集群模式下,请改用 spark.driver.memory

使用小写后缀,例如 kmgtp,分别表示 kibibytes、mebibytes、gibibytes、tebibytes 和 pebibytes。

1.3.0
spark.yarn.am.resource.{resource-type}.amount (无) 在客户端模式下,用于 YARN 应用程序主程序的资源量。在集群模式下,请改用 spark.yarn.driver.resource.<resource-type>.amount。请注意,此功能只能与 YARN 3.0+ 一起使用。有关参考,请参阅 YARN 资源模型文档:https://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/ResourceModel.html

示例:要从 YARN 请求 GPU 资源,请使用:spark.yarn.am.resource.yarn.io/gpu.amount

3.0.0
spark.yarn.applicationType SPARK 定义更具体的应用程序类型,例如 SPARKSPARK-SQLSPARK-STREAMINGSPARK-MLLIBSPARK-GRAPH。请注意不要超过 20 个字符。 3.1.0
spark.yarn.driver.resource.{resource-type}.amount (无) 在集群模式下,用于 YARN 应用程序主程序的资源量。请注意,此功能只能与 YARN 3.0+ 一起使用。有关参考,请参阅 YARN 资源模型文档:https://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/ResourceModel.html

示例:要从 YARN 请求 GPU 资源,请使用:spark.yarn.driver.resource.yarn.io/gpu.amount

3.0.0
spark.yarn.executor.resource.{resource-type}.amount (无) 每个执行器进程使用的资源量。请注意,此功能只能与 YARN 3.0+ 一起使用。有关参考,请参阅 YARN 资源模型文档:https://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/ResourceModel.html

示例:要从 YARN 请求 GPU 资源,请使用:spark.yarn.executor.resource.yarn.io/gpu.amount

3.0.0
spark.yarn.resourceGpuDeviceName yarn.io/gpu 指定 gpu 的 Spark 资源类型与表示 GPU 的 YARN 资源的映射。默认情况下,YARN 使用 yarn.io/gpu,但如果 YARN 已配置为使用自定义资源类型,则允许重新映射它。在使用 spark.{driver/executor}.resource.gpu.* 配置时适用。 3.2.1
spark.yarn.resourceFpgaDeviceName yarn.io/fpga 指定 fpga 的 Spark 资源类型与表示 FPGA 的 YARN 资源的映射。默认情况下,YARN 使用 yarn.io/fpga,但如果 YARN 已配置为使用自定义资源类型,则允许重新映射它。在使用 spark.{driver/executor}.resource.fpga.* 配置时适用。 3.2.1
spark.yarn.am.cores 1 在客户端模式下,用于 YARN 应用程序主程序的内核数。在集群模式下,请改用 spark.driver.cores 1.3.0
spark.yarn.am.waitTime 100s 仅在 cluster 模式下使用。YARN 应用程序主程序等待 SparkContext 初始化的时间。 1.3.0
spark.yarn.submit.file.replication 默认的 HDFS 复制(通常为 3 上传到 HDFS 中用于应用程序的文件的 HDFS 复制级别。这些包括 Spark jar、应用程序 jar 和任何分布式缓存文件/存档。 0.8.1
spark.yarn.stagingDir 当前用户在文件系统中的主目录 提交应用程序时使用的暂存目录。 2.0.0
spark.yarn.preserve.staging.files false 设置为 true 以在作业结束时保留暂存文件(Spark jar、应用程序 jar、分布式缓存文件),而不是删除它们。 1.1.0
spark.yarn.scheduler.heartbeat.interval-ms 3000 Spark 应用程序主程序向 YARN 资源管理器发送心跳的间隔(毫秒)。该值上限为 YARN 配置中过期间隔值的一半,即 yarn.am.liveness-monitor.expiry-interval-ms 0.8.1
spark.yarn.scheduler.initial-allocation.interval 200ms 当存在待处理的容器分配请求时,Spark 应用程序主程序积极地向 YARN 资源管理器发送心跳的初始间隔。它不应大于 spark.yarn.scheduler.heartbeat.interval-ms。如果仍然存在待处理的容器,分配间隔将在连续的积极心跳中加倍,直到达到 spark.yarn.scheduler.heartbeat.interval-ms 1.4.0
spark.yarn.historyServer.address (无) Spark 历史服务器的地址,例如 host.com:18080。该地址不应包含方案 (http://)。默认情况下未设置,因为历史服务器是可选服务。此地址在 Spark 应用程序完成时提供给 YARN 资源管理器,以将资源管理器 UI 中的应用程序链接到 Spark 历史服务器 UI。对于此属性,可以使用 YARN 属性作为变量,这些变量将在运行时由 Spark 替换。例如,如果 Spark 历史服务器与 YARN 资源管理器运行在同一节点上,则可以将其设置为 ${hadoopconf-yarn.resourcemanager.hostname}:18080 1.0.0
spark.yarn.dist.archives (无) 要提取到每个执行器的运行目录中的存档的逗号分隔列表。 1.0.0
spark.yarn.dist.files (无) 要放置在每个执行器的运行目录中的文件的逗号分隔列表。 1.0.0
spark.yarn.dist.jars (无) 要放置在每个执行器的运行目录中的 jar 的逗号分隔列表。 2.0.0
spark.yarn.dist.forceDownloadSchemes (无) 要将资源下载到本地磁盘(在添加到 YARN 的分布式缓存之前)的方案的逗号分隔列表。用于 YARN 服务不支持 Spark 支持的方案(如 http、https 和 ftp)或需要在本地 YARN 客户端的类路径中的 jar 的情况。通配符 '*' 表示下载所有方案的资源。 2.3.0
spark.executor.instances 2 用于静态分配的执行器数量。使用 spark.dynamicAllocation.enabled 时,初始执行器集至少应与此数量一样大。 1.0.0
spark.yarn.am.memoryOverhead AM 内存 * 0.10,最小值为 384 spark.driver.memoryOverhead 相同,但用于客户端模式下的 YARN 应用程序主程序。 1.3.0
spark.yarn.queue default 提交应用程序的 YARN 队列的名称。 1.0.0
spark.yarn.jars (无) 包含要分发到 YARN 容器的 Spark 代码的库列表。默认情况下,YARN 上的 Spark 将使用本地安装的 Spark jar,但 Spark jar 也可以位于 HDFS 上的世界可读位置。这允许 YARN 在节点上缓存它,以便每次应用程序运行时都不需要分发它。例如,要指向 HDFS 上的 jar,请将此配置设置为 hdfs:///some/path。允许使用通配符。 2.0.0
spark.yarn.archive (无) 包含要分发到 YARN 缓存的所需 Spark jar 的存档。如果设置,此配置将替换 spark.yarn.jars,并且该存档将在所有应用程序的容器中使用。该存档应在其根目录中包含 jar 文件。与前面的选项一样,该存档也可以托管在 HDFS 上以加快文件分发速度。 2.0.0
spark.yarn.appMasterEnv.[EnvironmentVariableName] (无) 将由 EnvironmentVariableName 指定的环境变量添加到在 YARN 上启动的应用程序主程序进程中。用户可以指定多个这些变量以设置多个环境变量。在 cluster 模式下,这将控制 Spark 驱动程序的环境,而在 client 模式下,它只控制执行器启动器的环境。 1.1.0
spark.yarn.containerLauncherMaxThreads 25 在 YARN 应用程序主程序中用于启动执行器容器的线程的最大数量。 1.2.0
spark.yarn.am.extraJavaOptions (无) 要传递给客户端模式下的 YARN 应用程序主程序的额外 JVM 选项字符串。在集群模式下,请改用 spark.driver.extraJavaOptions。请注意,使用此选项设置最大堆大小 (-Xmx) 设置是非法的。最大堆大小设置可以使用 spark.yarn.am.memory 设置。 1.3.0
spark.yarn.am.extraLibraryPath (无) 在启动客户端模式下的 YARN 应用程序主程序时要使用的特殊库路径。 1.4.0
spark.yarn.populateHadoopClasspath 对于 with-hadoop Spark 发行版,此设置为 false;对于 no-hadoop 发行版,此设置为 true。 是否从 yarn.application.classpathmapreduce.application.classpath 中填充 Hadoop 类路径。请注意,如果将其设置为 false,则需要一个捆绑了 Hadoop 运行时的 with-Hadoop Spark 发行版,或者用户必须单独提供 Hadoop 安装。 2.4.6
spark.yarn.maxAppAttempts YARN 中的 yarn.resourcemanager.am.max-attempts 将尝试提交应用程序的最大次数。它不应大于 YARN 配置中的全局最大尝试次数。 1.3.0
spark.yarn.am.attemptFailuresValidityInterval (无) 定义 AM 故障跟踪的有效期。如果 AM 至少运行了定义的间隔,则 AM 故障计数将重置。如果未配置,则不会启用此功能。 1.6.0
spark.yarn.am.clientModeTreatDisconnectAsFailed false 将 yarn-client 不干净断开连接视为失败。在 yarn-client 模式下,应用程序通常始终以最终状态 SUCCESS 完成,因为在某些情况下,无法确定应用程序是用户有意终止的,还是发生了真正的错误。此配置更改了这种行为,以便如果应用程序主程序与驱动程序不干净地断开连接(即没有进行适当的关闭握手),则应用程序将以最终状态 FAILED 终止。这将允许调用者决定它是否确实是失败。请注意,如果设置了此配置,并且用户只是错误地终止了客户端应用程序,则它可能会显示状态 FAILED,而实际上它并没有真正失败。 3.3.0
spark.yarn.am.clientModeExitOnError false 在 yarn-client 模式下,如果此设置为 true,如果驱动程序获取到最终状态为 KILLED 或 FAILED 的应用程序报告,则驱动程序将停止相应的 SparkContext 并以代码 1 退出程序。请注意,如果此设置为 true,并且从另一个应用程序调用,它也将终止父应用程序。 3.3.0
spark.yarn.am.tokenConfRegex (无) 此配置的值是一个正则表达式,用于从作业的配置文件(例如 hdfs-site.xml)中 grep 一系列配置项并发送到 RM,RM 在更新委托令牌时会使用这些配置项。此功能的一个典型用例是在 YARN 集群需要与多个下游 HDFS 集群通信的环境中支持委托令牌,其中 YARN RM 可能没有配置(例如 dfs.nameservices、dfs.ha.namenodes.*、dfs.namenode.rpc-address.*)来连接到这些集群。在这种情况下,Spark 用户可以将配置值指定为 ^dfs.nameservices$|^dfs.namenode.rpc-address.*$|^dfs.ha.namenodes.*$,以从作业的本地配置文件中解析这些 HDFS 配置。此配置与 mapreduce.job.send-token-conf 非常相似。有关更多详细信息,请查看 YARN-5910。 3.3.0
spark.yarn.submit.waitAppCompletion true 在 YARN 集群模式下,控制客户端是否等待应用程序完成才退出。如果设置为 true,则客户端进程将保持活动状态并报告应用程序的状态。否则,客户端进程将在提交后退出。 1.4.0
spark.yarn.am.nodeLabelExpression (无) 一个 YARN 节点标签表达式,它限制了 AM 将被调度到的节点集。只有 YARN 2.6 或更高版本支持节点标签表达式,因此在针对早期版本运行时,此属性将被忽略。 1.6.0
spark.yarn.executor.nodeLabelExpression (无) 一个 YARN 节点标签表达式,它限制了执行器将被调度到的节点集。只有 YARN 2.6 或更高版本支持节点标签表达式,因此在针对早期版本运行时,此属性将被忽略。 1.4.0
spark.yarn.tags (无) 以逗号分隔的字符串列表,作为 YARN 应用程序标签传递,这些标签出现在 YARN ApplicationReports 中,可用于在查询 YARN 应用程序时进行过滤。 1.5.0
spark.yarn.priority (无) YARN 的应用程序优先级,用于定义待处理应用程序的排序策略,具有更高整数值的应用程序有更大的机会被激活。目前,YARN 仅在使用 FIFO 排序策略时支持应用程序优先级。 3.0.0
spark.yarn.config.gatewayPath (无) 在网关主机(启动 Spark 应用程序的主机)上有效的路径,但对于集群中其他节点中相同资源的路径可能有所不同。结合 spark.yarn.config.replacementPath,它用于支持具有异构配置的集群,以便 Spark 可以正确启动远程进程。

替换路径通常将包含对 YARN(以及因此对 Spark 容器可见)导出的某个环境变量的引用。

例如,如果网关节点在 /disk1/hadoop 上安装了 Hadoop 库,并且 Hadoop 安装的位置由 YARN 作为 HADOOP_HOME 环境变量导出,则将此值设置为 /disk1/hadoop,并将替换路径设置为 $HADOOP_HOME 将确保用于启动远程进程的路径正确引用本地 YARN 配置。

1.5.0
spark.yarn.config.replacementPath (无) 参见 spark.yarn.config.gatewayPath 1.5.0
spark.yarn.rolledLog.includePattern (无) Java 正则表达式,用于过滤与定义的包含模式匹配的日志文件,这些日志文件将以滚动方式聚合。这将与 YARN 的滚动日志聚合一起使用,要在 YARN 端启用此功能,应在 yarn-site.xml 中配置 yarn.nodemanager.log-aggregation.roll-monitoring-interval-seconds。Spark log4j 附加程序需要更改为使用 FileAppender 或其他可以处理文件在运行时被删除的附加程序。根据 log4j 配置中配置的文件名(如 spark.log),用户应设置正则表达式(spark*)以包含需要聚合的所有日志文件。 2.0.0
spark.yarn.rolledLog.excludePattern (无) Java 正则表达式,用于过滤与定义的排除模式匹配的日志文件,这些日志文件将不会以滚动方式聚合。如果日志文件名与包含模式和排除模式都匹配,则此文件最终将被排除。 2.0.0
spark.yarn.executor.launch.excludeOnFailure.enabled false 标志,用于启用排除存在 YARN 资源分配问题的节点。可以通过 spark.excludeOnFailure.application.maxFailedExecutorsPerNode 配置排除的错误限制。 2.4.0
spark.yarn.exclude.nodes (无) 以逗号分隔的 YARN 节点名称列表,这些节点将被排除在资源分配之外。 3.0.0
spark.yarn.metrics.namespace (无) AM 指标报告的根命名空间。如果未设置,则使用 YARN 应用程序 ID。 2.4.0
spark.yarn.report.interval 1s 集群模式下报告当前 Spark 作业状态的间隔。 0.9.0
spark.yarn.report.loggingFrequency 30 在记录下一个应用程序状态之前处理的应用程序报告的最大数量。如果状态发生变化,则无论处理的应用程序报告数量如何,都会记录应用程序状态。 3.5.0
spark.yarn.clientLaunchMonitorInterval 1s 在启动应用程序时,客户端模式 AM 请求状态的间隔。 2.3.0
spark.yarn.includeDriverLogsLink false 在集群模式下,客户端应用程序报告是否包含指向驱动程序容器日志的链接。这需要轮询 ResourceManager 的 REST API,因此它会给 RM 带来一些额外的负载。 3.1.0
spark.yarn.unmanagedAM.enabled false 在客户端模式下,是否使用未管理的 am 将应用程序主服务作为客户端的一部分启动。 3.0.0
spark.yarn.shuffle.server.recovery.disabled false 对于具有更高安全要求并希望其密钥未保存在数据库中的应用程序,将其设置为 true。此类应用程序的 shuffle 数据在外部 Shuffle 服务重启后将不会恢复。 3.5.0

SHS 自定义执行器日志 URL 的可用模式

模式含义
{{HTTP_SCHEME}} 根据 YARN HTTP 策略的 http://https://。(通过 yarn.http.policy 配置)
{{NM_HOST}} 运行容器的节点的“主机”。
{{NM_PORT}} 运行容器的节点管理器的“端口”。
{{NM_HTTP_PORT}} 运行容器的节点管理器 http 服务器的“端口”。
{{NM_HTTP_ADDRESS}} 分配容器的节点的 Http URI。
{{CLUSTER_ID}} 资源管理器的集群 ID。(通过 yarn.resourcemanager.cluster-id 配置)
{{CONTAINER_ID}} 容器的 ID。
{{USER}} 系统环境中的 SPARK_USER
{{FILE_NAME}} stdoutstderr

例如,假设您希望将日志 URL 链接指向作业历史服务器,而不是让节点管理器 http 服务器重定向它,您可以将 spark.history.custom.executor.log.url 配置如下

{{HTTP_SCHEME}}<JHS_HOST>:<JHS_PORT>/jobhistory/logs/{{NM_HOST}}:{{NM_PORT}}/{{CONTAINER_ID}}/{{CONTAINER_ID}}/{{USER}}/{{FILE_NAME}}?start=-4096

注意:您需要将 <JHS_HOST><JHS_PORT> 替换为实际值。

资源分配和配置概述

请确保您已阅读 配置页面 上的自定义资源调度和配置概述部分。本部分仅讨论资源调度的 YARN 特定方面。

YARN 需要配置为支持用户希望与 Spark 一起使用的任何资源。YARN 上的资源调度是在 YARN 3.1.0 中添加的。有关配置资源和正确设置隔离的更多信息,请参阅 YARN 文档。理想情况下,资源是隔离设置的,以便执行器只能看到分配给它的资源。如果您没有启用隔离,则用户有责任创建发现脚本,以确保资源不会在执行器之间共享。

YARN 支持用户定义的资源类型,但为 GPU(yarn.io/gpu)和 FPGA(yarn.io/fpga)内置了类型。因此,如果您使用的是这两种资源中的任何一种,Spark 可以将您对 Spark 资源的请求转换为 YARN 资源,您只需要指定 spark.{driver/executor}.resource. 配置。请注意,如果您使用的是 YARN 的 GPU 或 FPGA 的自定义资源类型,您可以使用 spark.yarn.resourceGpuDeviceNamespark.yarn.resourceFpgaDeviceName 更改 Spark 映射。如果您使用的是 FPGA 或 GPU 以外的资源,则用户有责任为 YARN(spark.yarn.{driver/executor}.resource.)和 Spark(spark.{driver/executor}.resource.)指定配置。

例如,用户希望为每个执行器请求 2 个 GPU。用户只需指定 spark.executor.resource.gpu.amount=2,Spark 将处理从 YARN 请求 yarn.io/gpu 资源类型。

如果用户拥有用户定义的 YARN 资源,我们称之为 acceleratorX,那么用户必须指定 spark.yarn.executor.resource.acceleratorX.amount=2spark.executor.resource.acceleratorX.amount=2

YARN 不会告诉 Spark 分配给每个容器的资源的地址。因此,用户必须指定一个发现脚本,该脚本在执行器启动时运行以发现哪些资源可用于该执行器。您可以在 examples/src/main/scripts/getGpusResources.sh 中找到示例脚本。该脚本必须设置执行权限,并且用户应设置权限以不允许恶意用户修改它。该脚本应将 ResourceInformation 类的格式的 JSON 字符串写入 STDOUT。这包含资源名称和可用于该执行器的资源地址数组。

阶段级调度概述

YARN 支持阶段级调度

需要注意的是,YARN 特定的是每个 ResourceProfile 需要在 YARN 上有不同的容器优先级。映射很简单,ResourceProfile ID 变成优先级,在 YARN 中数字越小优先级越高。这意味着较早创建的配置文件在 YARN 中将具有更高的优先级。通常情况下,这无关紧要,因为 Spark 在启动另一个阶段之前会完成一个阶段,唯一可能产生影响的情况是在作业服务器类型场景中,因此需要牢记这一点。请注意,自定义资源在基本默认配置文件和自定义 ResourceProfiles 之间的处理方式有所不同。为了允许用户请求具有额外资源的 YARN 容器,而 Spark 不在这些容器上进行调度,用户可以通过 spark.yarn.executor.resource. 配置指定资源。但是,这些配置仅在基本默认配置文件中使用,不会传播到任何其他自定义 ResourceProfiles。这是因为,如果您希望某个阶段没有这些资源,将无法删除它们。这会导致您的默认配置文件获得在 spark.yarn.executor.resource. 中定义的自定义资源,以及 Spark 定义的 GPU 或 FPGA 资源。Spark 将 GPU 和 FPGA 资源转换为 YARN 内置类型 yarn.io/gpu) 和 yarn.io/fpga,但不知道任何其他资源的映射。任何其他 Spark 自定义资源都不会传播到 YARN 的默认配置文件。因此,如果您希望 Spark 基于自定义资源进行调度,并从 YARN 请求该资源,则必须在 YARN (spark.yarn.{driver/executor}.resource.) 和 Spark (spark.{driver/executor}.resource.) 配置中指定它。如果您只想要具有额外资源的 YARN 容器,而 Spark 不使用它们进行调度,则请删除 Spark 配置。现在,对于自定义 ResourceProfiles,它目前没有办法只指定 YARN 资源,而 Spark 不在它们上进行调度。这意味着对于自定义 ResourceProfiles,我们将把 ResourceProfile 中定义的所有资源传播到 YARN。我们仍然将 GPU 和 FPGA 转换为 YARN 内置类型。这要求您指定的任何自定义资源的名称与其在 YARN 中的定义方式相匹配。

重要说明

Kerberos

Spark 中的标准 Kerberos 支持在 安全 页面中介绍。

在 YARN 模式下,当访问 Hadoop 文件系统时,除了 hadoop 配置中的默认文件系统之外,Spark 还将自动为托管 Spark 应用程序暂存目录的服务获取委托令牌。

YARN 特定的 Kerberos 配置

属性名称默认值含义自版本
spark.kerberos.keytab (无) 包含上面指定主体 keytab 的文件的完整路径。此 keytab 将通过 YARN 分布式缓存复制到运行 YARN 应用程序主机的节点,并将用于定期更新登录票证和委托令牌。等效于 --keytab 命令行参数。
(也适用于“local”主机。)
3.0.0
spark.kerberos.principal (无) 在安全集群上运行时,用于登录 KDC 的主体。等效于 --principal 命令行参数。
(也适用于“local”主机。)
3.0.0
spark.yarn.kerberos.relogin.period 1m 检查是否应该更新 kerberos TGT 的频率。这应该设置为小于 TGT 更新周期(或如果未启用 TGT 更新,则为 TGT 生命周期)的值。默认值对于大多数部署应该足够了。 2.3.0
spark.yarn.kerberos.renewal.excludeHadoopFileSystems (无) 将从资源调度程序的委托令牌更新中排除其主机的 Hadoop 文件系统的逗号分隔列表。例如,spark.yarn.kerberos.renewal.excludeHadoopFileSystems=hdfs://nn1.com:8032, hdfs://nn2.com:8032。目前已知这在 YARN 中有效,因此 YARN 资源管理器不会为应用程序更新令牌。请注意,由于资源调度程序不会更新令牌,因此任何运行时间超过原始令牌到期时间并尝试使用该令牌的应用程序都可能会失败。 3.2.0

Kerberos 故障排除

调试 Hadoop/Kerberos 问题可能很“困难”。一种有用的技术是通过设置 HADOOP_JAAS_DEBUG 环境变量来启用 Hadoop 中 Kerberos 操作的额外日志记录。

export HADOOP_JAAS_DEBUG=true

JDK 类可以通过系统属性 sun.security.krb5.debugsun.security.spnego.debug=true 来配置以启用其 Kerberos 和 SPNEGO/REST 身份验证的额外日志记录。

-Dsun.security.krb5.debug=true -Dsun.security.spnego.debug=true

所有这些选项都可以在应用程序主机中启用。

spark.yarn.appMasterEnv.HADOOP_JAAS_DEBUG true
spark.yarn.am.extraJavaOptions -Dsun.security.krb5.debug=true -Dsun.security.spnego.debug=true

最后,如果 org.apache.spark.deploy.yarn.Client 的日志级别设置为 DEBUG,则日志将包含所有获取的令牌及其到期详细信息的列表。

配置外部 Shuffle 服务

要在 YARN 集群中的每个 NodeManager 上启动 Spark Shuffle Service,请按照以下说明操作。

  1. 使用 YARN 配置文件 构建 Spark。如果您使用的是预先打包的发行版,请跳过此步骤。
  2. 找到 spark-<version>-yarn-shuffle.jar。如果您自己构建 Spark,它应该位于 $SPARK_HOME/common/network-yarn/target/scala-<version> 下,如果您使用的是发行版,它应该位于 yarn 下。
  3. 将此 jar 添加到集群中所有 NodeManager 的类路径中。
  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. 重新启动集群中的所有 NodeManager

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

属性名称默认值含义自版本
spark.yarn.shuffle.stopOnFailure false 在 Spark Shuffle Service 初始化失败时是否停止 NodeManager。这可以防止由于在未运行 Spark Shuffle Service 的 NodeManager 上运行容器而导致的应用程序失败。 2.1.0
spark.yarn.shuffle.service.metrics.namespace sparkShuffleService 在将 shuffle 服务指标发出到 NodeManager 的 Hadoop metrics2 系统时要使用的命名空间。 3.2.0
spark.yarn.shuffle.service.logs.namespace (未设置) 在形成用于从 YARN shuffle 服务发出日志的日志记录器名称时,将附加到类名称的命名空间,例如 org.apache.spark.network.yarn.YarnShuffleService.logsNamespaceValue。由于某些日志记录框架可能期望日志记录器名称看起来像类名称,因此通常建议提供一个值,该值将是一个有效的 Java 包或类名称,并且不包含空格。 3.3.0
spark.shuffle.service.db.backend LEVELDB 当在 YARN 中启用工作保留重启时,这用于指定 shuffle 服务状态存储中使用的磁盘基础存储,支持 `LEVELDB` 和 `ROCKSDB`,默认值为 `LEVELDB`。现在,`LevelDB/RocksDB` 中的原始数据存储不会自动转换为另一种存储类型。原始数据存储将被保留,并在切换存储类型时创建新的类型数据存储。 3.4.0

请注意,以上说明假设使用了默认的 shuffle 服务名称 spark_shuffle。可以在这里使用任何名称,但 YARN NodeManager 配置中使用的值必须与 Spark 应用程序中 spark.shuffle.service.name 的值匹配。

默认情况下,shuffle 服务将从 NodeManager 使用的 Hadoop 配置(例如 yarn-site.xml)获取所有配置。但是,也可以使用名为 spark-shuffle-site.xml 的文件独立配置 shuffle 服务,该文件应放置在 shuffle 服务的类路径中(默认情况下,它与 NodeManager 的类路径共享)。shuffle 服务将将其视为标准 Hadoop 配置资源,并将其覆盖在 NodeManager 的配置之上。

使用 Apache Oozie 启动您的应用程序

Apache Oozie 可以将 Spark 应用程序作为工作流的一部分启动。在安全集群中,启动的应用程序将需要相关的令牌才能访问集群的服务。如果 Spark 使用 keytab 启动,则这是自动的。但是,如果 Spark 要在没有 keytab 的情况下启动,则必须将设置安全性的责任交给 Oozie。

有关为安全集群配置 Oozie 以及为作业获取凭据的详细信息,可以在 Oozie 网站 上的特定版本的文档的“身份验证”部分找到。

对于 Spark 应用程序,Oozie 工作流必须设置为让 Oozie 请求应用程序所需的所有令牌,包括

为了避免 Spark 尝试(然后失败)获取 Hive、HBase 和远程 HDFS 令牌,Spark 配置必须设置为禁用这些服务的令牌收集。

Spark 配置必须包含以下行

spark.security.credentials.hive.enabled   false
spark.security.credentials.hbase.enabled  false

配置选项 spark.kerberos.access.hadoopFileSystems 必须取消设置。

使用 Spark 历史服务器替换 Spark Web UI

当应用程序 UI 被禁用时,可以使用 Spark History Server 应用程序页面作为正在运行的应用程序的跟踪 URL。这在安全集群中可能很方便,或者可以减少 Spark 驱动程序的内存使用。要通过 Spark History Server 设置跟踪,请执行以下操作:

请注意,历史服务器信息可能与应用程序的状态不一致。

运行多个版本的 Spark Shuffle 服务

请注意,本节仅适用于在 YARN 版本 >= 2.9.0 上运行时。

在某些情况下,可能需要运行多个使用不同 Spark 版本的 Spark Shuffle Service 实例。例如,当运行一个混合了运行多个 Spark 版本的应用程序的 YARN 集群时,这将非常有用,因为给定版本的 shuffle 服务并不总是与其他版本的 Spark 兼容。从 2.9.0 版本开始的 YARN 版本支持在隔离的类加载器中运行 shuffle 服务(参见 YARN-4577),这意味着多个 Spark 版本可以在单个 NodeManager 中共存。yarn.nodemanager.aux-services.<service-name>.classpath 以及从 YARN 2.10.2/3.1.1/3.2.0 开始的 yarn.nodemanager.aux-services.<service-name>.remote-classpath 选项可用于配置此项。请注意,YARN 3.3.0/3.3.1 存在一个问题,需要设置 yarn.nodemanager.aux-services.<service-name>.system-classes 作为解决方法。有关详细信息,请参见 YARN-11053。除了设置单独的类路径外,还需要确保两个版本向不同的端口广播。这可以通过使用上面描述的 spark-shuffle-site.xml 文件来实现。例如,您可能具有以下配置:

  yarn.nodemanager.aux-services = spark_shuffle_x,spark_shuffle_y
  yarn.nodemanager.aux-services.spark_shuffle_x.classpath = /path/to/spark-x-path/fat.jar:/path/to/spark-x-config
  yarn.nodemanager.aux-services.spark_shuffle_y.classpath = /path/to/spark-y-path/fat.jar:/path/to/spark-y-config

  yarn.nodemanager.aux-services = spark_shuffle_x,spark_shuffle_y
  yarn.nodemanager.aux-services.spark_shuffle_x.classpath = /path/to/spark-x-path/*:/path/to/spark-x-config
  yarn.nodemanager.aux-services.spark_shuffle_y.classpath = /path/to/spark-y-path/*:/path/to/spark-y-config

两个 spark-*-config 目录分别包含一个文件,spark-shuffle-site.xml。这些是 Hadoop 配置格式 中的 XML 文件,每个文件都包含一些配置,用于调整使用的端口号和指标名称前缀。

<configuration>
  <property>
    <name>spark.shuffle.service.port</name>
    <value>7001</value>
  </property>
  <property>
    <name>spark.yarn.shuffle.service.metrics.namespace</name>
    <value>sparkShuffleServiceX</value>
  </property>
</configuration>

两个服务的这两个值都应该不同。

然后,在 Spark 应用程序的配置中,一个应该配置为

  spark.shuffle.service.name = spark_shuffle_x
  spark.shuffle.service.port = 7001

另一个应该配置为

  spark.shuffle.service.name = spark_shuffle_y
  spark.shuffle.service.port = <other value>