在 YARN 上运行 Spark
- 安全性
- 在 YARN 上启动 Spark
- 准备工作
- 配置
- 调试你的应用程序
- 资源分配和配置概览
- 阶段级调度概览
- 重要说明
- Kerberos
- 配置外部 Shuffle 服务
- 使用 Apache Oozie 启动应用程序
- 使用 Spark 历史服务器替代 Spark Web UI
- 运行多个版本的 Spark Shuffle 服务
- 为 Spark 应用程序配置不同的 JDK
Spark 在 0.6.0 版本中增加了对在 YARN (Hadoop NextGen) 上运行的支持,并在后续版本中进行了改进。
安全性
认证等安全功能默认不启用。在部署面向互联网或不可信网络的集群时,务必保护集群访问以防止未经授权的应用程序在集群上运行。在运行 Spark 之前,请参阅 Spark 安全性 以及本文档中的特定安全章节。
在 YARN 上启动 Spark
截至 3.4.1 版本,Apache Hadoop 不支持 Java 17,而 Apache Spark 从 4.0.0 版本开始要求至少 Java 17,因此应为 Spark 应用程序配置不同的 JDK。详情请参阅 为 Spark 应用程序配置不同的 JDK。
确保 HADOOP_CONF_DIR
或 YARN_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 客户端程序,该程序会启动默认的 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 支持的 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。
为了让 YARN 能够访问 Spark 运行时 JAR 包,你可以指定 spark.yarn.archive
或 spark.yarn.jars
。详情请参阅 Spark 属性。如果既未指定 spark.yarn.archive
也未指定 spark.yarn.jars
,Spark 将创建一个包含 $SPARK_HOME/jars
下所有 JAR 包的 zip 文件并将其上传到分布式缓存。
配置
Spark on YARN 的大多数配置与其他部署模式相同。有关这些配置的更多信息,请参阅配置页面。以下是 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-dir
和 yarn.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
下,该目录通常根据 Hadoop 版本和安装配置为 /tmp/logs
或 $HADOOP_HOME/logs/userlogs
。查看容器日志需要访问包含日志的主机并在该目录中查找。子目录按应用程序 ID 和容器 ID 组织日志文件。日志也可以在 Spark Web UI 的“执行器”选项卡下查看,且无需运行 MapReduce 历史服务器。
要检查每个容器的启动环境,请将 yarn.nodemanager.delete.debug-delay-sec
增加到一个较大的值(例如 36000
),然后通过在启动容器的节点上访问 yarn.nodemanager.local-dirs
来访问应用程序缓存。此目录包含启动脚本、JAR 包以及用于启动每个容器的所有环境变量。此过程对于调试类路径问题特别有用。(请注意,启用此功能需要集群设置的管理员权限并重启所有节点管理器。因此,这不适用于托管集群)。
要为应用程序主进程或执行器使用自定义的 log4j2 配置,以下是可用选项
- 使用
spark-submit
上传自定义的log4j2.properties
文件,通过将其添加到与应用程序一起上传的--files
文件列表中。 - 将
-Dlog4j.configurationFile=<configuration file location>
添加到spark.driver.extraJavaOptions
(用于驱动程序)或spark.executor.extraJavaOptions
(用于执行器)。请注意,如果使用文件,应明确提供file:
协议,并且文件需要在所有节点上本地存在。 - 更新
$SPARK_CONF_DIR/log4j2.properties
文件,它将与其他配置一起自动上传。请注意,如果指定了多个选项,则其他 2 个选项的优先级高于此选项。
请注意,对于第一个选项,执行器和应用程序主进程将共享相同的 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 Application Master 使用的内存量,格式与 JVM 内存字符串相同(例如 512m , 2g )。在集群模式下,请改用 spark.driver.memory 。使用小写后缀,例如 |
1.3.0 |
spark.yarn.am.resource.{resource-type}.amount |
(无) |
在客户端模式下,为 YARN Application Master 使用的资源量。在集群模式下,请改用 spark.yarn.driver.resource.<resource-type>.amount 。请注意,此功能仅适用于 YARN 3.0+。有关参考,请参阅 YARN 资源模型文档。示例:要从 YARN 请求 GPU 资源,请使用: |
3.0.0 |
spark.yarn.applicationType |
SPARK |
定义更具体的应用程序类型,例如 SPARK 、SPARK-SQL 、SPARK-STREAMING 、SPARK-MLLIB 和 SPARK-GRAPH 。请注意不要超过 20 个字符。 |
3.1.0 |
spark.yarn.driver.resource.{resource-type}.amount |
(无) |
在集群模式下,为 YARN Application Master 使用的资源量。请注意,此功能仅适用于 YARN 3.0+。有关参考,请参阅 YARN 资源模型文档。 示例:要从 YARN 请求 GPU 资源,请使用: |
3.0.0 |
spark.yarn.executor.resource.{resource-type}.amount |
(无) |
每个执行器进程使用的资源量。请注意,此功能仅适用于 YARN 3.0+。有关参考,请参阅 YARN 资源模型文档。 示例:要从 YARN 请求 GPU 资源,请使用: |
3.0.0 |
spark.yarn.resourceGpuDeviceName |
yarn.io/gpu |
指定 Spark 资源类型 gpu 到表示 GPU 的 YARN 资源的映射。默认情况下,YARN 使用 yarn.io/gpu ,但如果 YARN 配置了自定义资源类型,则允许重新映射。在使用 spark.{driver/executor}.resource.gpu.* 配置时适用。 |
3.2.1 |
spark.yarn.resourceFpgaDeviceName |
yarn.io/fpga |
指定 Spark 资源类型 fpga 到表示 FPGA 的 YARN 资源的映射。默认情况下,YARN 使用 yarn.io/fpga ,但如果 YARN 配置了自定义资源类型,则允许重新映射。在使用 spark.{driver/executor}.resource.fpga.* 配置时适用。 |
3.2.1 |
spark.yarn.am.cores |
1 |
在客户端模式下,YARN Application Master 使用的核心数。在集群模式下,请改用 spark.driver.cores 。 |
1.3.0 |
spark.yarn.am.waitTime |
100s |
仅在 cluster 模式下使用。YARN Application Master 等待 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 ResourceManager 发送心跳的间隔(毫秒)。该值上限为 YARN 配置中过期间隔值的一半,即 yarn.am.liveness-monitor.expiry-interval-ms 。 |
0.8.1 |
spark.yarn.scheduler.initial-allocation.interval |
200ms |
当存在待处理的容器分配请求时,Spark 应用程序主进程向 YARN ResourceManager 积极发送心跳的初始间隔。它不应大于 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 ResourceManager,以便将应用程序从 ResourceManager UI 链接到 Spark 历史服务器 UI。对于此属性,YARN 属性可以用作变量,这些变量将在运行时由 Spark 替换。例如,如果 Spark 历史服务器与 YARN ResourceManager 在同一节点上运行,则可以设置为 ${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 Application Master。 |
1.3.0 |
spark.yarn.queue |
default |
应用程序提交到的 YARN 队列名称。 | 1.0.0 |
spark.yarn.jars |
(无) | 包含 Spark 代码的库列表,用于分发到 YARN 容器。默认情况下,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 上启动的 Application Master 进程。用户可以指定多个此类变量以设置多个环境变量。在 cluster 模式下,这控制 Spark 驱动程序的运行环境;在 client 模式下,它仅控制执行器启动器的运行环境。 |
1.1.0 |
spark.yarn.containerLauncherMaxThreads |
25 |
YARN Application Master 中用于启动执行器容器的最大线程数。 | 1.2.0 |
spark.yarn.am.extraJavaOptions |
(无) | 在客户端模式下,传递给 YARN Application Master 的额外 JVM 选项字符串。在集群模式下,请改用 spark.driver.extraJavaOptions 。请注意,使用此选项设置最大堆大小 (-Xmx) 是非法的。最大堆大小设置可以使用 spark.yarn.am.memory 进行设置。 |
1.3.0 |
spark.yarn.am.extraLibraryPath |
(无) | 设置在客户端模式下启动 YARN Application Master 时使用的特殊库路径。 | 1.4.0 |
spark.yarn.populateHadoopClasspath |
对于 with-hadoop Spark 发行版,此设置为 false;对于 no-hadoop 发行版,此设置为 true。 |
是否从 yarn.application.classpath 和 mapreduce.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 的最终状态完成,因为在某些情况下,无法判断应用程序是用户有意终止还是发生了实际错误。此配置更改了该行为,使得如果 Application Master 与驱动程序不干净地断开连接(即没有正确的关闭握手),应用程序将以 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)中抓取配置条目列表并发送给 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 容器可见)。 例如,如果网关节点在 |
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 appender 需要更改为使用 FileAppender 或其他可以在运行时处理文件被删除的 appender。根据 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 将 Application Master 服务作为客户端的一部分启动。 | 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}} | Resource Manager 的集群 ID。(通过 yarn.resourcemanager.cluster-id 配置) |
{{CONTAINER_ID}} | 容器 ID。 |
{{USER}} | 系统环境变量中的 SPARK_USER 。 |
{{FILE_NAME}} | stdout , stderr 。 |
例如,假设你想直接将日志 URL 链接指向作业历史服务器,而不是让 NodeManager 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.resourceGpuDeviceName
和 spark.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=2
和 spark.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 中定义的名称相匹配。
重要说明
- 核心请求在调度决策中是否被遵守取决于所使用的调度程序及其配置方式。
- 在
cluster
模式下,Spark 执行器和 Spark 驱动程序使用的本地目录将是为 YARN 配置的本地目录(Hadoop YARN 配置yarn.nodemanager.local-dirs
)。如果用户指定spark.local.dir
,它将被忽略。在client
模式下,Spark 执行器将使用为 YARN 配置的本地目录,而 Spark 驱动程序将使用在spark.local.dir
中定义的目录。这是因为在client
模式下,Spark 驱动程序不在 YARN 集群上运行,只有 Spark 执行器在运行。 --files
和--archives
选项支持使用 # 符号指定文件名,类似于 Hadoop。例如,您可以指定:--files localtest.txt#appSees.txt
,这将把您本地名为localtest.txt
的文件上传到 HDFS,但该文件将通过名称appSees.txt
进行链接,您的应用程序在 YARN 上运行时应使用名称appSees.txt
来引用它。- 如果将
SparkContext.addJar
函数与本地文件一起使用并在cluster
模式下运行,--jars
选项允许其正常工作。如果你使用 HDFS、HTTP、HTTPS 或 FTP 文件,则无需使用此选项。
Kerberos
Spark 中标准的 Kerberos 支持在安全性页面中介绍。
在 YARN 模式下,访问 Hadoop 文件系统时,除了 Hadoop 配置中的默认文件系统外,Spark 还会自动获取托管 Spark 应用程序暂存目录的服务所需的委托令牌。
YARN 特定的 Kerberos 配置
属性名称 | 默认值 | 含义 | 始于版本 |
---|---|---|---|
spark.kerberos.keytab |
(无) | 包含上述指定主体 keytab 的文件的完整路径。此 keytab 将通过 YARN 分布式缓存复制到运行 YARN Application Master 的节点,并将用于定期续订登录票证和委托令牌。等同于 --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 Resource Manager 不会为应用程序续订令牌。请注意,由于资源调度器不续订令牌,因此任何运行时间超过原始令牌过期时间并尝试使用该令牌的应用程序很可能会失败。 |
3.2.0 |
Kerberos 故障排除
调试 Hadoop/Kerberos 问题可能“很困难”。一个有用的技巧是通过设置 HADOOP_JAAS_DEBUG
环境变量来在 Hadoop 中启用 Kerberos 操作的额外日志记录。
export HADOOP_JAAS_DEBUG=true
JDK 类可以通过系统属性 sun.security.krb5.debug
和 sun.security.spnego.debug=true
配置,以启用对其 Kerberos 和 SPNEGO/REST 认证的额外日志记录。
-Dsun.security.krb5.debug=true -Dsun.security.spnego.debug=true
所有这些选项都可以在 Application Master 中启用
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 服务,请按照以下说明操作
- 使用 YARN profile 构建 Spark。如果你使用的是预打包发行版,请跳过此步骤。
- 定位
spark-<version>-yarn-shuffle.jar
。如果你正在自行构建 Spark,它应该在$SPARK_HOME/common/network-yarn/target/scala-<version>
下;如果你使用的是发行版,它应该在yarn
下。 - 将此 JAR 添加到集群中所有
NodeManager
的类路径中。 - 在每个节点的
yarn-site.xml
中,将spark_shuffle
添加到yarn.nodemanager.aux-services
,然后将yarn.nodemanager.aux-services.spark_shuffle.class
设置为org.apache.spark.network.yarn.YarnShuffleService
。 - 通过在
etc/hadoop/yarn-env.sh
中设置YARN_HEAPSIZE
(默认 1000)来增加NodeManager
的堆大小,以避免在 shuffle 期间出现垃圾回收问题。 - 重启集群中所有
NodeManager
。
当 shuffle 服务在 YARN 上运行时,以下额外的配置选项可用
属性名称 | 默认值 | 含义 | 始于版本 |
---|---|---|---|
spark.yarn.shuffle.stopOnFailure |
false |
当 Spark Shuffle 服务初始化失败时是否停止 NodeManager。这可以防止由于在未运行 Spark Shuffle 服务的 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 |
ROCKSDB | 当 YARN 中启用工作保留重启时,这用于指定 shuffle 服务状态存储中使用的基于磁盘的存储,支持 `ROCKSDB` 和 `LEVELDB`(已弃用),其中 `ROCKSDB` 作为默认值。RocksDB/LevelDB 中的原始数据存储现在不会自动转换为另一种存储类型。原始数据存储将保留,并在切换存储类型时创建新的数据存储。 | 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 网站上特定版本文档的“Authentication”部分。
对于 Spark 应用程序,Oozie 工作流必须设置为让 Oozie 请求应用程序所需的所有令牌,包括
- YARN 资源管理器。
- 本地 Hadoop 文件系统。
- 任何用作 I/O 源或目标的远程 Hadoop 文件系统。
- Hive — 如果使用。
- HBase — 如果使用。
- YARN 时间线服务器,如果应用程序与此交互。
为避免 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 历史服务器应用程序页面用作正在运行应用程序的跟踪 URL。这在安全集群上可能很受欢迎,或者为了减少 Spark 驱动程序的内存使用。要通过 Spark 历史服务器设置跟踪,请执行以下操作
- 在应用程序端,在 Spark 的配置中设置
spark.yarn.historyServer.allowTracking=true
。如果应用程序的 UI 被禁用,这将告诉 Spark 使用历史服务器的 URL 作为跟踪 URL。 - 在 Spark 历史服务器上,将
org.apache.spark.deploy.yarn.YarnProxyRedirectFilter
添加到spark.ui.filters
配置中的过滤器列表。
请注意,历史服务器信息可能与应用程序的实际状态不同步。
运行多个版本的 Spark Shuffle 服务
请注意,本节仅适用于在 YARN 2.9.0 及更高版本上运行的情况。
在某些情况下,可能需要运行使用不同 Spark 版本的 Spark Shuffle 服务的多个实例。这在例如运行混合了多个 Spark 版本应用程序的 YARN 集群时会很有用,因为给定版本的 shuffle 服务并非总是与其他 Spark 版本兼容。YARN 2.9.0 及更高版本支持在隔离的类加载器中运行 shuffle 服务(参见 YARN-4577),这意味着多个 Spark 版本可以在单个 NodeManager 中共存。从 YARN 2.10.2/3.1.1/3.2.0 开始,可以使用 yarn.nodemanager.aux-services.<service-name>.classpath
和 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>
为 Spark 应用程序配置不同的 JDK
在某些情况下,可能需要使用与 YARN 节点管理器不同的 JDK 来运行 Spark 应用程序,这可以通过为 YARN 容器和 spark-submit
进程设置 JAVA_HOME
环境变量来实现。
请注意,Spark 假定一个应用程序中运行的所有 JVM 进程都使用相同版本的 JDK,否则,你可能会遇到 JDK 序列化问题。
要配置 Spark 应用程序使用已预安装在所有节点 /opt/openjdk-17
处的 JDK
$ export JAVA_HOME=/opt/openjdk-17
$ ./bin/spark-submit --class path.to.your.Class \
--master yarn \
--conf spark.yarn.appMasterEnv.JAVA_HOME=/opt/openjdk-17 \
--conf spark.executorEnv.JAVA_HOME=/opt/openjdk-17 \
<app jar> [app options]
(可选)用户可能希望避免在 YARN 集群节点上安装不同的 JDK,在这种情况下,也可以使用 YARN 的分布式缓存分发 JDK。例如,要使用 Java 21 运行 Spark 应用程序,请准备一个 JDK 21 tarball openjdk-21.tar.gz
并将其解压到本地节点上的 /opt
,然后提交 Spark 应用程序。
$ export JAVA_HOME=/opt/openjdk-21
$ ./bin/spark-submit --class path.to.your.Class \
--master yarn \
--archives path/to/openjdk-21.tar.gz \
--conf spark.yarn.appMasterEnv.JAVA_HOME=./openjdk-21.tar.gz/openjdk-21 \
--conf spark.executorEnv.JAVA_HOME=./openjdk-21.tar.gz/openjdk-21 \
<app jar> [app options]