在 Kubernetes 上运行 Spark
Running Spark on Kubernetes - Spark 3.5.3 Documentation
在 Kubernetes 上运行 Spark
Spark 可以在Kubernetes管理的集群上运行。此功能利用了 Spark 中新增的原生 Kubernetes 调度程序。
安全
默认情况下,身份验证等安全功能未启用。部署对互联网或不受信任的网络开放的集群时,确保对集群的访问安全非常重要,以防止未经授权的应用程序在集群上运行。在运行 Spark 之前,请参阅Spark 安全性和本文档中的特定安全部分。
用户身份
从项目提供的 Dockerfile 构建的镜像包含一个默认USER指令,其默认 UID 为185
。这意味着生成的镜像将在容器内以此 UID 运行 Spark 进程。安全意识强的部署应考虑提供自定义镜像,其中的USER
指令指定其所需的非特权 UID 和 GID。生成的 UID 应在其补充组中包括根组,以便能够运行 Spark 可执行文件。使用提供的脚本构建自己的镜像的用户docker-image-tool.sh
可以使用该-u <uid>
选项来指定所需的 UID。
或者,可以使用Pod 模板功能向Spark 提交的 Pod添加带有 的安全上下文。这可用于覆盖图像本身中的指令。请记住,这需要用户的配合,因此可能不是共享环境的合适解决方案。如果集群管理员希望限制 Pod 可以作为其运行的用户,则应使用Pod 安全策略。runAsUser
USER
卷装载
如本文档后面使用 Kubernetes 卷中所述,K8S 上的 Spark 提供了配置选项,允许将某些卷类型安装到驱动程序和执行程序 Pod 中。特别是,它允许使用hostPathKubernetes 文档中所述的已知安全漏洞的卷。
集群管理员应该使用Pod 安全策略hostPath
来限制适合其环境的卷挂载能力。
先决条件
- 正在运行的 Kubernetes 集群,版本 >= 1.24,并使用kubectl配置访问权限 。如果您还没有运行的 Kubernetes 集群,则可以使用 minikube在本地计算机上设置测试集群。
- 我们建议使用启用了 DNS 插件的最新版本的 minikube。
- 请注意,默认的 minikube 配置不足以运行 Spark 应用程序。我们建议使用 3 个 CPU 和 4g 内存,以便能够使用单个执行器启动一个简单的 Spark 应用程序。
- 检查您的 Spark 环境的kubernetes-client 库版本,以及它与您的 Kubernetes 集群版本的兼容性。
- 您必须具有适当的权限才能列出、创建、编辑和删除 集群中的Pod
kubectl auth can-i <list|create|edit|delete> pods
。您可以通过运行来验证是否可以列出这些资源。- 必须允许驱动程序 pod 使用的服务帐户凭据来创建 pod、服务和配置映射。
- 您必须在集群中配置Kubernetes DNS 。
工作原理
spark-submit
可以直接用来向 Kubernetes 集群提交 Spark 应用,提交机制如下:
- Spark 创建一个在Kubernetes pod中运行的 Spark 驱动程序。
- 驱动程序创建在 Kubernetes Pod 中运行的执行器并连接到它们,然后执行应用程序代码。
- 当应用程序完成时,执行器容器终止并被清理,但驱动程序容器会保留日志并在 Kubernetes API 中保持“完成”状态,直到最终被垃圾收集或手动清理。
请注意,在完成状态下,驱动程序舱不使用任何计算或内存资源。
驱动程序和执行程序 pod 调度由 Kubernetes 处理。与 Kubernetes API 的通信通过 fabric8 完成。可以使用节点选择器使用其配置属性在可用节点子集上调度驱动程序和执行程序 pod。将来的版本中 可以使用更高级的调度提示,例如节点/pod 亲和性。
向 Kubernetes 提交应用程序
Docker 镜像
Kubernetes 要求用户提供可部署到 Pod 内容器中的映像。这些映像旨在在 Kubernetes 支持的容器运行时环境中运行。Docker 是 Kubernetes 经常使用的容器运行时环境。Spark(从 2.3 版开始)附带一个 Dockerfile,可用于此目的,或根据单个应用程序的需求进行自定义。您可以在目录中找到它kubernetes/dockerfiles/
。
Spark 还附带一个bin/docker-image-tool.sh
脚本,可用于构建和发布 Docker 镜像以供 Kubernetes 后端使用。
用法示例:
$ ./bin/docker-image-tool.sh -r <repo> -t my-tag build
$ ./bin/docker-image-tool.sh -r <repo> -t my-tag push
这将使用默认提供的项目进行构建Dockerfiles
。要查看可用于自定义此工具行为的更多选项(包括提供自定义)Dockerfiles
,请使用标志运行-h
。
默认bin/docker-image-tool.sh
构建用于运行 JVM 作业的 docker 镜像。您需要选择构建其他语言绑定 docker 镜像。
示例用法
# To build additional PySpark docker image
$ ./bin/docker-image-tool.sh -r <repo> -t my-tag -p ./kubernetes/dockerfiles/spark/bindings/python/Dockerfile build
# To build additional SparkR docker image
$ ./bin/docker-image-tool.sh -r <repo> -t my-tag -R ./kubernetes/dockerfiles/spark/bindings/R/Dockerfile build
您还可以直接使用Apache Spark Docker 镜像(例如apache/spark:<version>
)。
集群模式
要以集群模式启动 Spark Pi,
$ ./bin/spark-submit \
--master k8s://https://<k8s-apiserver-host>:<k8s-apiserver-port> \
--deploy-mode cluster \
--name spark-pi \
--class org.apache.spark.examples.SparkPi \
--conf spark.executor.instances=5 \
--conf spark.kubernetes.container.image=<spark-image> \
local:///path/to/examples.jar
Spark 主服务器可以通过传递--master
命令行参数来指定spark-submit
,也可以通过设置 spark.master
应用程序的配置来指定,其 URL 格式为k8s://<api_server_host>:<k8s-apiserver-port>
。必须始终指定端口,即使它是 HTTPS 端口 443。在主服务器字符串前加上 ,k8s://
将导致 Spark 应用程序在 Kubernetes 集群上启动,并通过 来联系 API 服务器api_server_url
。如果 URL 中未指定 HTTP 协议,则默认为https
。例如,将主服务器设置为 ,k8s://example.com:443
相当于将其设置为k8s://https://example.com:443
,但若要通过其他端口不使用 TLS 进行连接,则将主服务器设置为k8s://http://example.com:8080
。
spark.app.name
在 Kubernetes 模式中,由或--name
参数 指定的 Spark 应用程序名称spark-submit
默认用于命名创建的 Kubernetes 资源,例如驱动程序和执行程序。因此,应用程序名称必须由小写字母数字字符组成,-
并且.
必须以字母数字字符开头和结尾。
如果您已经设置了 Kubernetes 集群,则发现 apiserver URL 的一种方法是通过执行kubectl cluster-info
。
$ kubectl cluster-info
Kubernetes master is running at http://127.0.0.1:6443
在上面的示例中,可以通过spark-submit
将其指定 --master k8s://http://127.0.0.1:6443
为 spark-submit 的参数来使用特定的 Kubernetes 集群。此外,还可以使用身份验证代理kubectl proxy
与 Kubernetes API 进行通信。
本地代理可以通过以下方式启动:
$ kubectl proxy
如果本地代理在 localhost:8001 上运行,--master k8s://http://127.0.0.1:8001
则可以将其用作 spark-submit 的参数。最后,请注意,在上面的示例中,我们指定了一个具有特定 URI 的 jar,其方案为local://
。此 URI 是 Docker 镜像中已有的示例 jar 的位置。
客户端模式
从 Spark 2.4.0 开始,可以在客户端模式下在 Kubernetes 上运行 Spark 应用程序。当您的应用程序在客户端模式下运行时,驱动程序可以在 pod 内或物理主机上运行。在客户端模式下运行应用程序时,建议考虑以下因素:
客户端模式网络
Spark 执行程序必须能够通过可从 Spark 执行程序路由的主机名和端口连接到 Spark 驱动程序。Spark 在客户端模式下工作所需的特定网络配置将因设置而异。如果在 Kubernetes pod 内运行驱动程序,则可以使用 无头服务来允许您的驱动程序 pod 通过稳定的主机名从执行程序路由。部署无头服务时,请确保服务的标签选择器仅匹配驱动程序 pod 而不匹配其他 pod;建议为驱动程序 pod 分配足够唯一的标签,并在无头服务的标签选择器中使用该标签。通过 指定驱动程序的主机名spark.driver.host
,并将您的 spark 驱动程序的端口指定为spark.driver.port
。
客户端模式 Executor Pod 垃圾收集
如果您在 pod 中运行 Spark 驱动程序,强烈建议将其设置spark.kubernetes.driver.pod.name
为该 pod 的名称。设置此属性后,Spark 调度程序将使用 OwnerReference 部署执行程序 pod ,这反过来将确保一旦从集群中删除驱动程序 pod,应用程序的所有执行程序 pod 也将被删除。驱动程序将在指定的命名空间中查找具有给定名称的 pod spark.kubernetes.namespace
,并将指向该 pod 的 OwnerReference 添加到每个执行程序 pod 的 OwnerReference 列表中。请小心避免将 OwnerReference 设置为实际上不是该驱动程序 pod 的 pod,否则当删除错误的 pod 时,执行程序可能会过早终止。
如果您的应用程序未在 pod 内运行,或者当spark.kubernetes.driver.pod.name
您的应用程序实际在 pod 中运行时未设置,请记住,当应用程序退出时,执行程序 pod 可能无法从集群中正确删除。Spark 调度程序会尝试删除这些 pod,但如果对 API 服务器的网络请求因任何原因失败,这些 pod 将保留在集群中。执行程序进程在无法到达驱动程序时应退出,因此,在应用程序退出后,执行程序 pod 不应消耗集群中的计算资源(CPU 和内存)。
您可以使用它spark.kubernetes.executor.podNamePrefix
来完全控制执行器 pod 名称。设置此属性后,强烈建议使其在同一命名空间中的所有作业中保持唯一。
身份验证参数
在客户端模式下对 Kubernetes 身份验证参数使用精确的前缀spark.kubernetes.authenticate
。
IPv4 和 IPv6
从 3.4.0 开始,Spark 通过 IPv4/IPv6 双栈网络 功能额外支持仅 IPv6 环境,该功能允许将 IPv4 和 IPv6 地址分配给 Pod 和服务。根据 K8s 集群功能,spark.kubernetes.driver.service.ipFamilyPolicy
和 spark.kubernetes.driver.service.ipFamilies
可以分别是SingleStack
、PreferDualStack
和之一,以及、、和RequireDualStack
之一。默认情况下,Spark 使用和 。IPv4
IPv6
IPv4,IPv6
IPv6,IPv4
spark.kubernetes.driver.service.ipFamilyPolicy=SingleStack
spark.kubernetes.driver.service.ipFamilies=IPv4
若要仅使用IPv6
,您可以使用以下内容提交您的工作。
...
--conf spark.kubernetes.driver.service.ipFamilies=IPv6 \
在DualStack
环境中,您可能还需要java.net.preferIPv6Addresses=true
JVM 和SPARK_PREFER_IPV6=true
Python 来使用IPv6
。
依赖管理
如果应用程序的依赖项都托管在远程位置(如 HDFS 或 HTTP 服务器),则可以通过其适当的远程 URI 来引用它们。此外,应用程序依赖项可以预先安装到自定义 Docker 镜像中。可以通过使用local://
URI 引用这些依赖项和/或 SPARK_EXTRA_CLASSPATH
在 Dockerfile 中设置环境变量将它们添加到类路径中。local://
在 中引用自定义 Docker 镜像中的依赖项时也需要该方案spark-submit
。我们支持使用方案或不使用方案(使用完整路径)从提交客户端的本地文件系统获取依赖项file://
,其中目标应该是与 Hadoop 兼容的文件系统。使用 S3 的典型示例是通过传递以下选项:
...
--packages org.apache.hadoop:hadoop-aws:3.2.2
--conf spark.kubernetes.file.upload.path=s3a://<s3-bucket>/path
--conf spark.hadoop.fs.s3a.access.key=...
--conf spark.hadoop.fs.s3a.impl=org.apache.hadoop.fs.s3a.S3AFileSystem
--conf spark.hadoop.fs.s3a.fast.upload=true
--conf spark.hadoop.fs.s3a.secret.key=....
--conf spark.driver.extraJavaOptions=-Divy.cache.dir=/tmp -Divy.home=/tmp
file:///full/path/to/app.jar
应用程序 jar 文件将上传到 S3,然后在启动驱动程序时将其下载到驱动程序 pod 并添加到其类路径中。Spark 将在上传路径下生成一个具有随机名称的子目录,以避免与并行运行的 spark 应用程序发生冲突。用户可以根据需要管理创建的子目录。
客户端方案支持应用程序 jar 以及属性spark.jars
、spark.files
和指定的依赖项spark.archives
。
重要提示:所有客户端依赖项都将以平面目录结构上传到给定路径,因此文件名必须是唯一的,否则文件将被覆盖。此外,请确保派生的 k8s 映像中的默认 ivy 目录具有所需的访问权限或按上述方式修改设置。如果您--packages
在集群模式下使用,后者也很重要。
机密管理
Kubernetes Secrets可用于为 Spark 应用程序提供访问受保护服务的凭据。要将用户指定的 secret 挂载到驱动程序容器中,用户可以使用表单的配置属性spark.kubernetes.driver.secrets.[SecretName]=<mount path>
。类似地,表单的配置属性spark.kubernetes.executor.secrets.[SecretName]=<mount path>
可用于将用户指定的 secret 挂载到执行程序容器中。请注意,假定要挂载的 secret 与驱动程序和执行程序 pod 位于同一命名空间中。例如,要将名为 secret 的 secret 挂载spark-secret
到驱动程序和执行程序容器中的路径 /etc/secrets
上,请将以下选项添加到spark-submit
命令中:
--conf spark.kubernetes.driver.secrets.spark-secret=/etc/secrets
--conf spark.kubernetes.executor.secrets.spark-secret=/etc/secrets
要通过环境变量使用秘密,请在命令中使用以下选项spark-submit
:
--conf spark.kubernetes.driver.secretKeyRef.ENV_NAME=name:key
--conf spark.kubernetes.executor.secretKeyRef.ENV_NAME=name:key
Pod 模板
Kubernetes 允许从模板文件定义 pod。Spark用户同样可以使用模板文件来定义 Spark 配置不支持的驱动程序或执行程序 pod 配置。为此,请指定 spark 属性spark.kubernetes.driver.podTemplateFile
并spark.kubernetes.executor.podTemplateFile
指向进程可访问的文件spark-submit
。
--conf spark.kubernetes.driver.podTemplateFile=s3a://bucket/driver.yml
--conf spark.kubernetes.executor.podTemplateFile=s3a://bucket/executor.yml
为了允许驱动程序 pod 访问执行器 pod 模板文件,该文件将在创建时自动挂载到驱动程序 pod 中的卷上。Spark 在解组这些模板文件后不进行任何验证,而是依靠 Kubernetes API 服务器进行验证。
需要注意的是,Spark 对某些 pod 配置有自己的偏好,因此 pod 模板中的某些值将始终被 Spark 覆盖。因此,此功能的用户应注意,指定 pod 模板文件只会让 Spark 在 pod 构建过程中以模板 pod 而不是空 pod 启动。有关详情,请参阅将被 spark 覆盖的 pod 模板值的完整列表。
Pod 模板文件还可以定义多个容器。在这种情况下,您可以使用 spark 属性 spark.kubernetes.driver.podTemplateContainerName
和spark.kubernetes.executor.podTemplateContainerName
来指示应使用哪个容器作为驱动程序或执行程序的基础。如果未指定,或者容器名称无效,Spark 将假定列表中的第一个容器将是驱动程序或执行程序容器。
使用 Kubernetes 卷
用户可以将以下类型的 Kubernetes卷挂载到驱动程序和执行程序 Pod 中:
- hostPath:将文件或目录从主机节点的文件系统中挂载到 pod 中。
- emptyDir:当将 pod 分配给节点时创建的最初为空的卷。
- nfs:将现有的 NFS(网络文件系统)挂载到 pod 中。
- persistentVolumeClaim:将其挂载
PersistentVolume
到 pod 中。
注意:有关卷挂载的安全问题,请参阅本文档的安全部分。
要将上述任何类型的卷安装到驱动程序舱,请使用以下配置属性:
--conf spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.path=<mount path>
--conf spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.readOnly=<true|false>
--conf spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.subPath=<mount subPath>
具体来说,VolumeType
可以是以下值之一:、、和。hostPath
是您emptyDir
想要在pod 规范中的字段下用于卷的名称。nfs
persistentVolumeClaim
VolumeName
volumes
每种支持的卷类型可能有一些特定的配置选项,可以使用以下形式的配置属性来指定:
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].options.[OptionName]=<value>
例如,可以使用以下属性指定nfs
具有卷名的服务器和路径:images
spark.kubernetes.driver.volumes.nfs.images.options.server=example.com
spark.kubernetes.driver.volumes.nfs.images.options.path=/data
并且,可以使用以下属性指定persistentVolumeClaim
具有卷名称的声明名称:checkpointpvc
spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.options.claimName=check-point-pvc-claim
将卷挂载到执行器容器的配置属性使用前缀spark.kubernetes.executor.
而不是spark.kubernetes.driver.
。
例如,您可以使用OnDemand
声明名称和选项为storageClass
每个执行器挂载动态创建的持久卷声明sizeLimit
,如下所示。这在动态分配的情况下很有用。
spark.kubernetes.executor.volumes.persistentVolumeClaim.data.options.claimName=OnDemand
spark.kubernetes.executor.volumes.persistentVolumeClaim.data.options.storageClass=gp
spark.kubernetes.executor.volumes.persistentVolumeClaim.data.options.sizeLimit=500Gi
spark.kubernetes.executor.volumes.persistentVolumeClaim.data.mount.path=/data
spark.kubernetes.executor.volumes.persistentVolumeClaim.data.mount.readOnly=false
有关每种受支持的卷类型的可用选项的完整列表,请参阅下面的Spark 属性部分。
面向 PVC 的执行器 pod 分配
由于磁盘是重要的资源类型之一,Spark 驱动程序通过一组配置提供细粒度的控制。例如,默认情况下,按需 PVC 由执行程序拥有,PVC 的生命周期与其所有者执行程序紧密相关。但是,按需 PVC 可以由驱动程序拥有,并在 Spark 作业的生命周期内由其他执行程序重用,方法是使用以下选项。这减少了 PVC 创建和删除的开销。
spark.kubernetes.driver.ownPersistentVolumeClaim=true
spark.kubernetes.driver.reusePersistentVolumeClaim=true
此外,自 Spark 3.4 起,Spark 驱动程序能够进行面向 PVC 的执行器分配,这意味着 Spark 会计算作业可以拥有的已创建 PVC 总数,如果驱动程序拥有的 PVC 数量已达到最大数量,则暂停创建新的执行器。这有助于将现有 PVC 从一个执行器转换到另一个执行器。
spark.kubernetes.driver.waitToReusePersistentVolumeClaim=true
本地存储
Spark 支持在 shuffle 和其他操作期间使用卷来溢出数据。要使用卷作为本地存储,卷的名称应以 开头spark-local-dir-
,例如:
--conf spark.kubernetes.driver.volumes.[VolumeType].spark-local-dir-[VolumeName].mount.path=<mount path>
--conf spark.kubernetes.driver.volumes.[VolumeType].spark-local-dir-[VolumeName].mount.readOnly=false
具体来说,如果作业需要执行器中进行大量的混洗和排序操作,则可以使用持久卷声明。
spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.options.claimName=OnDemand
spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.options.storageClass=gp
spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.options.sizeLimit=500Gi
spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.mount.path=/data
spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.mount.readOnly=false
要通过内置KubernetesLocalDiskShuffleDataIO
插件启用随机数据恢复功能,我们需要具备以下条件。您可能还想spark.kubernetes.driver.waitToReusePersistentVolumeClaim
另外启用。
spark.kubernetes.executor.volumes.persistentVolumeClaim.spark-local-dir-1.mount.path=/data/spark-x/executor-x
spark.shuffle.sort.io.plugin.class=org.apache.spark.shuffle.KubernetesLocalDiskShuffleDataIO
如果未将卷设置为本地存储,Spark 将在 shuffle 和其他操作期间使用临时暂存空间将数据溢出到磁盘。使用 Kubernetes 作为资源管理器时,将创建 pod,并为环境变量中列出的每个目录安装一个emptyDir卷。如果没有明确指定目录,则会创建并适当配置默认目录。spark.local.dir
SPARK_LOCAL_DIRS
emptyDir
卷使用 Kubernetes 的临时存储功能,并且不会在 Pod 的生命周期之外持续存在。
使用 RAM 进行本地存储
emptyDir
卷默认使用节点后备存储进行临时存储,这种行为可能不适合某些计算环境。例如,如果您有无盘节点,并且远程存储通过网络挂载,那么让大量执行器对此远程存储进行 IO 实际上可能会降低性能。
在这种情况下,可能需要spark.kubernetes.local.dirs.tmpfs=true
在配置中进行设置,这将导致emptyDir
卷配置为RAM 支持的卷。当像这样配置时,Spark 的本地存储使用量将计入您的 pod 内存使用量,因此您可能希望通过适当tmpfs
增加值来增加内存请求。spark.{driver,executor}.memoryOverheadFactor
自省和调试
这些是调查正在运行/已完成的 Spark 应用程序、监控进度和采取行动的不同方法。
访问日志
可以使用 Kubernetes API 和 CLI 访问日志kubectl
。当 Spark 应用程序正在运行时,可以使用以下方式从应用程序流式传输日志:
$ kubectl -n=<namespace> logs -f <driver-pod-name>
如果安装在集群上,也可以通过Kubernetes 仪表板访问相同的日志 。
当存在日志收集系统时,您可以在 Spark DriverExecutors
选项卡 UI 中公开它。例如,
spark.executorEnv.SPARK_EXECUTOR_ATTRIBUTE_APP_ID='$(SPARK_APPLICATION_ID)'
spark.executorEnv.SPARK_EXECUTOR_ATTRIBUTE_EXECUTOR_ID='$(SPARK_EXECUTOR_ID)'
spark.ui.custom.executor.log.url='https://log-server/log?appId=&execId='
访问驱动程序 UI
可以使用 本地访问与任何应用程序相关的 UI kubectl port-forward。
$ kubectl port-forward <driver-pod-name> 4040:4040
然后,可以通过 访问 Spark 驱动程序 UI http://localhost:4040
。
调试
可能会出现几种类型的故障。如果 Kubernetes API 服务器拒绝来自 spark-submit 的请求,或者由于其他原因拒绝连接,则提交逻辑应指示遇到的错误。但是,如果在应用程序运行期间出现错误,通常最好的调查方法可能是通过 Kubernetes CLI。
要获取有关驱动程序舱周围所做的调度决策的一些基本信息,您可以运行:
$ kubectl describe pod <spark-driver-pod>
如果 pod 遇到运行时错误,可以使用以下命令进一步探测状态:
$ kubectl logs <spark-driver-pod>
可以用类似的方式检查失败的执行器 pod 的状态和日志。最后,删除驱动程序 pod 将清理整个 spark 应用程序,包括所有执行器、相关服务等。驱动程序 pod 可以被认为是 Spark 应用程序的 Kubernetes 表示。
Kubernetes 功能
配置文件
您的 Kubernetes 配置文件通常位于.kube/config
您的主目录或环境变量指定的位置KUBECONFIG
。Kubernetes 上的 Spark 将尝试使用此文件对用于与 Kubernetes 集群交互的 Kubernetes 客户端进行初始自动配置。提供了各种 Spark 配置属性,允许进一步自定义客户端配置,例如使用替代身份验证方法。
上下文
Kubernetes 配置文件可以包含多个上下文,允许在不同的集群和/或用户身份之间切换。默认情况下,Kubernetes 上的 Spark 在执行 Kubernetes 客户端的初始自动配置时将使用您当前的上下文(可以通过运行来检查kubectl config current-context
)。
为了使用备用上下文,用户可以通过 Spark 配置属性指定所需的上下文,spark.kubernetes.context
例如spark.kubernetes.context=minikube
。
命名空间
Kubernetes 有命名空间的概念。命名空间是一种在多个用户之间划分集群资源的方式(通过资源配额)。Kubernetes 上的 Spark 可以使用命名空间来启动 Spark 应用程序。这可以通过配置来利用spark.kubernetes.namespace
。
Kubernetes 允许使用ResourceQuota在各个命名空间上设置资源、对象数量等的限制。管理员可以结合使用命名空间和 ResourceQuota 来控制运行 Spark 应用程序的 Kubernetes 集群中的共享和资源分配。
RBAC
在启用了RBAC的 Kubernetes 集群中,用户可以配置 Kubernetes RBAC 角色以及 Kubernetes 上各个 Spark 组件用来访问 Kubernetes API 服务器的服务账户。
Spark 驱动程序 pod 使用 Kubernetes 服务帐户访问 Kubernetes API 服务器以创建和监视执行程序 pod。驱动程序 pod 使用的服务帐户必须具有适当的权限,驱动程序才能执行其工作。具体而言,至少必须向服务帐户授予 或 Role,ClusterRole以允许驱动程序 pod 创建 pod 和服务。默认情况下,如果在创建 pod 时未指定服务帐户,则驱动程序 pod 会自动分配default
由 指定的命名空间中的服务帐户。spark.kubernetes.namespace
根据部署的 Kubernetes 版本和设置,此default
服务帐户可能具有或不具有允许驱动程序 pod 在默认 Kubernetes RBAC策略下创建 pod 和服务的角色。有时用户可能需要指定一个具有正确角色的自定义服务帐户。Kubernetes 上的 Spark 支持通过配置属性指定驱动程序 pod 要使用的自定义服务帐户 spark.kubernetes.authenticate.driver.serviceAccountName=<service account name>
。例如,要使驱动程序 pod 使用spark
服务帐户,用户只需在spark-submit
命令中添加以下选项:
--conf spark.kubernetes.authenticate.driver.serviceAccountName=spark
要创建自定义服务帐号,用户可以使用该kubectl create serviceaccount
命令。例如,以下命令将创建一个名为的服务帐号spark
:
$ kubectl create serviceaccount spark
要授予服务帐户Role
或ClusterRole
,需要RoleBinding
或。要创建或,用户可以使用(或 为)命令。例如,以下命令在 命名空间中创建一个 并将其授予上面创建的服务帐户:ClusterRoleBinding
RoleBinding
ClusterRoleBinding
kubectl create rolebinding
clusterrolebinding
ClusterRoleBinding
edit
ClusterRole
default
spark
$ kubectl create clusterrolebinding spark-role --clusterrole=edit --serviceaccount=default:spark --namespace=default
请注意,Role
只能使用 授予对单个命名空间内资源(如 Pod)的访问权限,而 ClusterRole
可用于授予对跨所有命名空间的集群范围资源(如节点)以及命名空间资源(如 Pod)的访问权限。对于 Kubernetes 上的 Spark,由于驱动程序始终在同一命名空间中创建执行程序 Pod,因此Role
就足够了,尽管用户也可以使用ClusterRole
。有关 RBAC 授权以及如何为 Pod 配置 Kubernetes 服务帐户的更多信息,请参阅 使用 RBAC 授权和 为 Pod 配置服务帐户。
Spark 应用程序管理
Kubernetes 通过集群模式下的 spark-submit CLI 工具提供简单的应用程序管理。用户可以通过提供提交作业时打印的提交 ID 来终止作业。提交 ID 的格式如下namespace:driver-pod-name
。如果用户省略命名空间,则使用当前 k8s 上下文中设置的命名空间。例如,如果用户设置了特定的命名空间,如下所示kubectl config set-context minikube --namespace=spark
,则默认使用该spark
命名空间。另一方面,如果没有将命名空间添加到特定上下文,则默认考虑所有命名空间。这意味着操作将影响所有与给定提交 ID 匹配的 Spark 应用程序,而不管命名空间如何。此外,用于应用程序管理的 spark-submit 使用与提交驱动程序相同的后端代码,因此spark.kubernetes.context
可以重复使用相同的属性(如等)。
例如:
$ spark-submit --kill spark:spark-pi-1547948636094-driver --master k8s://https://192.168.2.8:8443
用户还可以使用以下--status
标志列出申请状态:
$ spark-submit --status spark:spark-pi-1547948636094-driver --master k8s://https://192.168.2.8:8443
这两个操作都支持 glob 模式。例如,用户可以运行:
$ spark-submit --kill spark:spark-pi* --master k8s://https://192.168.2.8:8443
上述命令将终止所有具有特定前缀的应用程序。
用户可以通过属性指定 pod 终止的宽限期spark.kubernetes.appKillPodDeletionGracePeriod
,使用--conf
as 方法来提供它(所有 K8s pod 的默认值为30 秒)。
未来工作
目前正在开发或计划开发多个 Spark on Kubernetes 功能。这些功能有望最终融入到 spark-kubernetes 集成的未来版本中。
其中包括:
- 外部 Shuffle 服务
- 作业队列和资源管理
配置
有关 Spark 配置的信息,请参阅配置页面。以下配置特定于 Kubernetes 上的 Spark。
Spark 属性
属性名称 | 默认 | 意义 | 自版本起 |
---|---|---|---|
spark.kubernetes.context | (none) | 用于 Kubernetes 客户端库的初始自动配置的用户 Kubernetes 配置文件中的上下文。如果未指定,则使用用户当前上下文。 注意:许多自动配置的设置可以通过使用其他 Spark 配置属性来覆盖,例如spark.kubernetes.namespace 。 | 3.0.0 |
spark.kubernetes.driver.master | https://kubernetes.default.svc | 驱动程序用于请求执行器的内部 Kubernetes 主服务器(API 服务器)地址,或仅驱动程序 pod 模式的“local[*]”。 | 3.0.0 |
spark.kubernetes.namespace | default | 用于运行驱动程序和执行程序容器的命名空间。 | 2.3.0 |
spark.kubernetes.container.image | (none) | 用于 Spark 应用程序的容器镜像。通常采用以下形式example.com/repo/spark:v1.0.0 。此配置是必需的,并且必须由用户提供,除非为每种不同的容器类型提供了明确的镜像。 | 2.3.0 |
spark.kubernetes.driver.container.image | (value of spark.kubernetes.container.image) | 用于驱动程序的自定义容器映像。 | 2.3.0 |
spark.kubernetes.executor.container.image | (value of spark.kubernetes.container.image) | 用于执行器的自定义容器镜像。 | 2.3.0 |
spark.kubernetes.container.image.pullPolicy | IfNotPresent | 在 Kubernetes 中拉取镜像时使用的容器镜像拉取策略。有效值为Always 、Never 和IfNotPresent 。 | 2.3.0 |
spark.kubernetes.container.image.pullSecrets | 用于从私有镜像注册表中提取镜像的 Kubernetes 机密的逗号分隔列表。 | 2.4.0 | |
spark.kubernetes.allocation.batch.size | 5 | 每轮执行器 pod 分配中一次启动的 pod 数量。 | 2.3.0 |
spark.kubernetes.allocation.batch.delay | 1s | 每轮执行程序 pod 分配之间的等待时间。指定小于 1 秒的值可能会导致 Spark 驱动程序的 CPU 使用率过高。 | 2.3.0 |
spark.kubernetes.authenticate.submission.caCertFile | (没有任何) | 启动驱动程序时通过 TLS 连接到 Kubernetes API 服务器的 CA 证书文件路径。此文件必须位于提交机器的磁盘上。将其指定为路径而不是 URI(即不提供方案)。在客户端模式下,请改用spark.kubernetes.authenticate.caCertFile 。 | 2.3.0 |
spark.kubernetes.authenticate.submission.clientKeyFile | (没有任何) | 启动驱动程序时用于向 Kubernetes API 服务器进行身份验证的客户端密钥文件的路径。此文件必须位于提交计算机的磁盘上。将其指定为路径而不是 URI(即不提供方案)。在客户端模式下,请spark.kubernetes.authenticate.clientKeyFile 改用。 | 2.3.0 |
spark.kubernetes.authenticate.submission.clientCertFile | (没有任何) | 启动驱动程序时用于向 Kubernetes API 服务器进行身份验证的客户端证书文件的路径。此文件必须位于提交计算机的磁盘上。将其指定为路径而不是 URI(即不提供方案)。在客户端模式下,请spark.kubernetes.authenticate.clientCertFile 改用。 | 2.3.0 |
spark.kubernetes.authenticate.submission.oauthToken | (没有任何) | 启动驱动程序时针对 Kubernetes API 服务器进行身份验证时使用的 OAuth 令牌。请注意,与其他身份验证选项不同,这应该是用于身份验证的令牌的精确字符串值。在客户端模式下,请改用spark.kubernetes.authenticate.oauthToken 。 | 2.3.0 |
spark.kubernetes.authenticate.submission.oauthTokenFile | (没有任何) | 启动驱动程序时,包含针对 Kubernetes API 服务器进行身份验证时要使用的令牌的 OAuth 令牌文件路径。此文件必须位于提交计算机的磁盘上。将其指定为路径而不是 URI(即不提供方案)。在客户端模式下,请改用spark.kubernetes.authenticate.oauthTokenFile 。 | 2.3.0 |
spark.kubernetes.authenticate.driver.caCertFile | (没有任何) | 请求执行程序时从驱动程序 pod 通过 TLS 连接到 Kubernetes API 服务器的 CA 证书文件路径。此文件必须位于提交机器的磁盘上,并将上传到驱动程序 pod。将其指定为路径而不是 URI(即不提供方案)。在客户端模式下,改用 spark.kubernetes.authenticate.caCertFile 。 | 2.3.0 |
spark.kubernetes.authenticate.driver.clientKeyFile | (没有任何) | 请求执行程序时,用于从驱动程序 pod 向 Kubernetes API 服务器进行身份验证的客户端密钥文件的路径。此文件必须位于提交机器的磁盘上,并将作为 Kubernetes 机密上传到驱动程序 pod。将其指定为路径而不是 URI(即不提供方案)。在客户端模式下,改用spark.kubernetes.authenticate.clientKeyFile 。 | 2.3.0 |
spark.kubernetes.authenticate.driver.clientCertFile | (没有任何) | 请求执行器时,从驱动程序 pod 向 Kubernetes API 服务器进行身份验证的客户端证书文件路径。此文件必须位于提交机器的磁盘上,并将作为 Kubernetes 机密上传到驱动程序 pod。将其指定为路径而不是 URI(即不提供方案)。在客户端模式下,改用spark.kubernetes.authenticate.clientCertFile 。 | 2.3.0 |
spark.kubernetes.authenticate.driver.oauthToken | (没有任何) | 请求执行程序时从驱动程序 pod 向 Kubernetes API 服务器进行身份验证时使用的 OAuth 令牌。请注意,与其他身份验证选项不同,这必须是用于身份验证的令牌的精确字符串值。此令牌值作为 Kubernetes 机密上传到驱动程序 pod。在客户端模式下,请改用spark.kubernetes.authenticate.oauthToken 。 | 2.3.0 |
spark.kubernetes.authenticate.driver.oauthTokenFile | (没有任何) | 包含从驱动程序 pod 请求执行程序时针对 Kubernetes API 服务器进行身份验证时要使用的令牌的 OAuth 令牌文件路径。请注意,与其他身份验证选项不同,此文件必须包含用于身份验证的令牌的精确字符串值。此令牌值作为机密上传到驱动程序 pod。在客户端模式下,请改用 spark.kubernetes.authenticate.oauthTokenFile 。 | 2.3.0 |
spark.kubernetes.authenticate.driver.mounted.caCertFile | (没有任何) | 请求执行程序时,从驱动程序 pod 通过 TLS 连接到 Kubernetes API 服务器的 CA 证书文件路径。此路径必须可从驱动程序 pod 访问。将其指定为路径而不是 URI(即不提供方案)。在客户端模式下,请 spark.kubernetes.authenticate.caCertFile 改用。 | 2.3.0 |
spark.kubernetes.authenticate.driver.mounted.clientKeyFile | (没有任何) | 请求执行程序时,从驱动程序 pod 向 Kubernetes API 服务器进行身份验证的客户端密钥文件路径。此路径必须可从驱动程序 pod 访问。将其指定为路径而不是 URI(即不提供方案)。在客户端模式下,请 spark.kubernetes.authenticate.clientKeyFile 改用。 | 2.3.0 |
spark.kubernetes.authenticate.driver.mounted.clientCertFile | (没有任何) | 请求执行程序时,从驱动程序 pod 向 Kubernetes API 服务器进行身份验证的客户端证书文件路径。此路径必须可从驱动程序 pod 访问。将其指定为路径而不是 URI(即不提供方案)。在客户端模式下,请 spark.kubernetes.authenticate.clientCertFile 改用。 | 2.3.0 |
spark.kubernetes.authenticate.driver.mounted.oauthTokenFile | (没有任何) | 包含 OAuth 令牌的文件路径,用于在请求执行程序时从驱动程序 pod 向 Kubernetes API 服务器进行身份验证。此路径必须可从驱动程序 pod 访问。请注意,与其他身份验证选项不同,此文件必须包含用于身份验证的令牌的精确字符串值。在客户端模式下,请改用spark.kubernetes.authenticate.oauthTokenFile 。 | 2.3.0 |
spark.kubernetes.authenticate.driver.serviceAccountName | default | 运行驱动程序 pod 时使用的服务帐号。驱动程序 pod 在从 API 服务器请求执行程序 pod 时使用此服务帐号。请注意,此帐号不能与 CA 证书文件、客户端密钥文件、客户端证书文件和/或 OAuth 令牌一起指定。在客户端模式下,请改用spark.kubernetes.authenticate.serviceAccountName 。 | 2.3.0 |
spark.kubernetes.authenticate.executor.serviceAccountName | (value of spark.kubernetes.authenticate.driver.serviceAccountName) | 运行执行器 pod 时使用的服务帐号。如果未设置此参数,则回退逻辑将使用驱动程序的服务帐号。 | 3.1.0 |
spark.kubernetes.authenticate.caCertFile | (没有任何) | 在客户端模式下,请求执行器时通过 TLS 连接到 Kubernetes API 服务器的 CA 证书文件路径。将其指定为路径而不是 URI(即不提供方案)。 | 2.4.0 |
spark.kubernetes.authenticate.clientKeyFile | (没有任何) | 在客户端模式下,请求执行器时用于向 Kubernetes API 服务器进行身份验证的客户端密钥文件的路径。将其指定为路径而不是 URI(即不提供方案)。 | 2.4.0 |
spark.kubernetes.authenticate.clientCertFile | (没有任何) | 在客户端模式下,请求执行器时用于向 Kubernetes API 服务器进行身份验证的客户端证书文件的路径。将其指定为路径而不是 URI(即不提供方案)。 | 2.4.0 |
spark.kubernetes.authenticate.oauthToken | (没有任何) | 在客户端模式下,请求执行器时向 Kubernetes API 服务器进行身份验证时使用的 OAuth 令牌。请注意,与其他身份验证选项不同,这必须是用于身份验证的令牌的精确字符串值。 | 2.4.0 |
spark.kubernetes.authenticate.oauthTokenFile | (没有任何) | 在客户端模式下,请求执行器时针对 Kubernetes API 服务器进行身份验证时使用的包含 OAuth 令牌的文件的路径。 | 2.4.0 |
spark.kubernetes.driver.label.[LabelName] | (没有任何) | 将 指定的标签添加LabelName 到驱动程序 pod。例如spark.kubernetes.driver.label.something=true 。请注意,Spark 还会将自己的标签添加到驱动程序 pod 以用于记账目的。 | 2.3.0 |
spark.kubernetes.driver.annotation.[AnnotationName] | (没有任何) | 将 指定的 Kubernetes注解AnnotationName 添加到驱动程序 pod。例如,spark.kubernetes.driver.annotation.something=true 。 | 2.3.0 |
spark.kubernetes.driver.service.label.[LabelName] | (没有任何) | 将指定的 Kubernetes标签LabelName 添加到驱动程序服务。例如spark.kubernetes.driver.service.label.something=true 。请注意,Spark 还会将自己的标签添加到驱动程序服务以用于记账目的。 | 3.4.0 |
spark.kubernetes.driver.service.annotation.[AnnotationName] | (没有任何) | 将 指定的 Kubernetes注解AnnotationName 添加到驱动服务。例如,spark.kubernetes.driver.service.annotation.something=true 。 | 3.0.0 |
spark.kubernetes.executor.label.[LabelName] | (没有任何) | 将 指定的标签添加LabelName 到执行程序 pod。例如 。spark.kubernetes.executor.label.something=true 请注意,Spark 还会将自己的标签添加到执行程序 pod 以用于记账目的。 | 2.3.0 |
spark.kubernetes.executor.annotation.[AnnotationName] | (没有任何) | 将 指定的 Kubernetes注释AnnotationName 添加到执行器 pod。例如,spark.kubernetes.executor.annotation.something=true 。 | 2.3.0 |
spark.kubernetes.driver.pod.name | (没有任何) | 驱动程序 pod 的名称。在集群模式下,如果未设置,驱动程序 pod 名称将设置为“spark.app.name”,后缀为当前时间戳,以避免名称冲突。在客户端模式下,如果您的应用程序在 pod 内运行,强烈建议将其设置为驱动程序在其中运行的 pod 的名称。在客户端模式下设置此值可让驱动程序成为其执行程序 pod 的所有者,从而允许集群对执行程序 pod 进行垃圾回收。 | 2.3.0 |
spark.kubernetes.executor.podNamePrefix | (没有任何) | 执行器 pod 名称前使用的前缀。它必须符合 Kubernetes DNS 标签名称定义的规则。该前缀将用于生成 形式的执行器 pod 名称,其中 `id` 是一个正整数值,因此 `podNamePrefix` 的长度需要小于或等于 47(= 63 - 10 - 6)。 podNamePrefix−exec−podNamePrefix−exec−id | 2.3.0 |
spark.kubernetes.submission.waitAppCompletion | true | 在集群模式下,是否等待应用程序完成后再退出启动器进程。如果更改为 false,启动器在启动 Spark 作业时将具有“即发即弃”行为。 | 2.3.0 |
spark.kubernetes.report.interval | 1s | 集群模式下当前 Spark 作业状态的报告间隔。 | 2.3.0 |
spark.kubernetes.executor.apiPollingInterval | 30s | 针对 Kubernetes API 服务器进行轮询以检查执行器状态的间隔。 | 2.4.0 |
spark.kubernetes.driver.request.cores | (没有任何) | 指定驱动程序 pod 的 CPU 请求。值符合 Kubernetes 约定。示例值包括 0.1、500m、1.5、5 等,CPU 单位的定义记录在CPU 单位中。如果设置了,这优先spark.driver.cores 于指定驱动程序 pod CPU 请求。 | 3.0.0 |
spark.kubernetes.driver.limit.cores | (没有任何) | 为驱动程序 pod 指定硬 CPU限制。 | 2.3.0 |
spark.kubernetes.executor.request.cores | (没有任何) | 指定每个执行器 pod 的 CPU 请求。值符合 Kubernetes约定。示例值包括 0.1、500m、1.5、5 等,CPU 单位的定义记录在CPU 单位中。这与 不同spark.executor.cores :它仅用于指定执行器 pod 的 CPU 请求(如果已设置),并且优先于spark.executor.cores 。任务并行性(例如执行器可以同时运行的任务数)不受此影响。 | 2.4.0 |
spark.kubernetes.executor.limit.cores | (没有任何) | 为 Spark 应用程序启动的每个执行器 pod 指定硬 CPU限制。 | 2.3.0 |
spark.kubernetes.node.selector.[labelKey] | (没有任何) | 添加到驱动程序 pod 和执行程序 pod 的节点选择器,其键labelKey 和值作为配置的值。例如,设置spark.kubernetes.node.selector.identifier 为myIdentifier 将导致驱动程序 pod 和执行程序具有一个带有键identifier 和值的 节点选择器myIdentifier 。可以通过使用此前缀设置多个配置来添加多个节点选择器键。 | 2.3.0 |
spark.kubernetes.driver.node.selector.[labelKey] | (没有任何) | 添加到驱动程序 pod 的驱动程序节点选择器,其键labelKey 和值作为配置的值。例如,设置spark.kubernetes.driver.node.selector.identifier 为myIdentifier 将导致驱动程序 pod 具有一个带有键identifier 和值的 节点选择器myIdentifier 。可以通过使用此前缀设置多个配置来添加多个驱动程序节点选择器键。 | 3.3.0 |
spark.kubernetes.executor.node.selector.[labelKey] | (没有任何) | 添加到执行器 pod 的执行器节点选择器,其键labelKey 和值作为配置的值。例如,设置spark.kubernetes.executor.node.selector.identifier 为myIdentifier 将导致执行器具有一个带有键identifier 和值的 节点选择器myIdentifier 。可以通过使用此前缀设置多个配置来添加多个执行器节点选择器键。 | 3.3.0 |
spark.kubernetes.driverEnv.[EnvironmentVariableName] | (没有任何) | 将指定的环境变量添加EnvironmentVariableName 到Driver进程中。用户可以指定多个来设置多个环境变量。 | 2.3.0 |
spark.kubernetes.driver.secrets.[SecretName] | (没有任何) | 将名为 的Kubernetes Secret 添加SecretName 到值中指定的路径上的驱动程序 pod。例如, spark.kubernetes.driver.secrets.spark-secret=/etc/secrets 。 | 2.3.0 |
spark.kubernetes.executor.secrets.[SecretName] | (没有任何) | 将名为 的Kubernetes Secret 添加SecretName 到值中指定的路径上的执行器 pod。例如, spark.kubernetes.executor.secrets.spark-secret=/etc/secrets 。 | 2.3.0 |
spark.kubernetes.driver.secretKeyRef.[EnvName] | (没有任何) | 将引用的Kubernetes Secret key 数据中 key 所引用的值作为环境变量添加到驱动程序容器中,名称为 EnvName (区分大小写)。例如 , spark.kubernetes.driver.secretKeyRef.ENV_VAR=spark-secret:key | 2.4.0 |
spark.kubernetes.executor.secretKeyRef.[EnvName] | (没有任何) | 将引用的Kubernetes Secret key 数据中 key 所引用的值作为环境变量添加到执行器容器中,名称为 EnvName (区分大小写)。例如 , spark.kubernetes.executor.secrets.ENV_VAR=spark-secret:key | 2.4.0 |
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.path | (没有任何) | 将名为类型的Kubernetes 卷 添加到值中指定的路径上的驱动程序 pod。例如, 。 VolumeName VolumeType spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.mount.path=/checkpoint | 2.4.0 |
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.subPath | (没有任何) | 指定从卷挂载到驱动程序容器的 子路径spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.mount.subPath=checkpoint 。 | 3.0.0 |
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.readOnly | (没有任何) | 指定已安装的卷是否为只读。例如, spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.mount.readOnly=false 。 | 2.4.0 |
spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].options.[OptionName] | (没有任何) | 配置Kubernetes 卷选项传递给 Kubernetes 作为OptionName 具有指定值的键,必须符合 Kubernetes 选项格式。例如, spark.kubernetes.driver.volumes.persistentVolumeClaim.checkpointpvc.options.claimName=spark-pvc-claim 。 | 2.4.0 |
spark.kubernetes.executor.volumes.[VolumeType].[VolumeName].mount.path | (没有任何) | 将类型为的Kubernetes 卷 添加到值中指定的路径上的执行器 pod。例如, 。 VolumeName VolumeType spark.kubernetes.executor.volumes.persistentVolumeClaim.checkpointpvc.mount.path=/checkpoint | 2.4.0 |
spark.kubernetes.executor.volumes.[VolumeType].[VolumeName].mount.subPath | (没有任何) | 指定要从卷挂载到执行器容器的 子路径spark.kubernetes.executor.volumes.persistentVolumeClaim.checkpointpvc.mount.subPath=checkpoint 。 | 3.0.0 |
spark.kubernetes.executor.volumes.[VolumeType].[VolumeName].mount.readOnly | 错误的 | 指定已安装的卷是否为只读。例如, spark.kubernetes.executor.volumes.persistentVolumeClaim.checkpointpvc.mount.readOnly=false 。 | 2.4.0 |
spark.kubernetes.executor.volumes.[VolumeType].[VolumeName].options.[OptionName] | (没有任何) | 配置Kubernetes 卷选项以具有指定值的键传递给 Kubernetes OptionName 。例如, spark.kubernetes.executor.volumes.persistentVolumeClaim.checkpointpvc.options.claimName=spark-pvc-claim 。 | 2.4.0 |
spark.kubernetes.local.dirs.tmpfs | false | 配置Spark 驱动程序和执行程序 pod 中emptyDir 用于备份的卷以使用备份,即 RAM。有关此内容的更多讨论,请参阅本页前面的 本地存储。SPARK_LOCAL_DIRS tmpfs | 3.0.0 |
spark.kubernetes.memoryOverheadFactor | 0.1 | 这将设置内存开销因子,当 为时, 它将向非 JVM 内存分配内存,包括堆外内存分配、非 JVM 任务、各种系统进程和tmpfs 基于 的本地目录。对于基于 JVM 的作业,此值默认为 0.10,对于非 JVM 作业,此值默认为 0.40。这样做是因为非 JVM 任务需要更多的非 JVM 堆空间,并且此类任务通常会因“内存开销超出”错误而失败。这会以更高的默认值来避免此错误。这将被和明确设置的值覆盖。 spark.kubernetes.local.dirs.tmpfs true spark.driver.memoryOverheadFactor spark.executor.memoryOverheadFactor | 2.4.0 |
spark.kubernetes.pyspark.pythonVersion | "3" | 这将设置用于运行驱动程序和执行程序容器的 docker 镜像的主要 Python 版本。它只能是“3”。此配置从 Spark 3.1.0 开始已弃用,并且实际上无操作。用户应设置“spark.pyspark.python”和“spark.pyspark.driver.python”配置或“PYSPARK_PYTHON”和“PYSPARK_DRIVER_PYTHON”环境变量。 | 2.4.0 |
spark.kubernetes.kerberos.krb5.path | (none) | 指定要挂载在驱动程序和执行器上以进行 Kerberos 交互的 krb5.conf 文件的本地位置。需要注意的是,定义的 KDC 需要在容器内部可见。 | 3.0.0 |
spark.kubernetes.kerberos.krb5.configMapName | (none) | 指定要挂载到驱动程序和执行程序上以进行 Kerberos 交互的 ConfigMap 的名称(包含 krb5.conf 文件)。定义的 KDC 需要在容器内部可见。ConfigMap 还必须位于驱动程序和执行程序 pod 的同一命名空间中。 | 3.0.0 |
spark.kubernetes.hadoop.configMapName | (none) | 指定要安装在驱动程序和执行器上以进行自定义 Hadoop 配置的 ConfigMap 的名称,其中包含 HADOOP_CONF_DIR 文件。 | 3.0.0 |
spark.kubernetes.kerberos.tokenSecret.name | (none) | 指定存储现有委托令牌的密钥的名称。这样,作业用户就无需提供任何 Kerberos 凭据来启动作业。 | 3.0.0 |
spark.kubernetes.kerberos.tokenSecret.itemKey | (none) | 指定存储现有委托令牌的数据的项目键。这样,作业用户就无需提供任何 Kerberos 凭据来启动作业。 | 3.0.0 |
spark.kubernetes.driver.podTemplateFile | (没有任何) | 指定包含驱动程序pod 模板的 本地文件。例如 spark.kubernetes.driver.podTemplateFile=/path/to/driver-pod-template.yaml | 3.0.0 |
spark.kubernetes.driver.podTemplateContainerName | (没有任何) | 指定要用作给定pod 模板 中驱动程序基础的容器名称。例如spark.kubernetes.driver.podTemplateContainerName=spark-driver | 3.0.0 |
spark.kubernetes.executor.podTemplateFile | (没有任何) | 指定包含执行器pod 模板 的本地文件。例如 spark.kubernetes.executor.podTemplateFile=/path/to/executor-pod-template.yaml | 3.0.0 |
spark.kubernetes.executor.podTemplateContainerName | (没有任何) | 指定要用作给定pod 模板 中执行器基础的容器名称。例如spark.kubernetes.executor.podTemplateContainerName=spark-executor | 3.0.0 |
spark.kubernetes.executor.deleteOnTermination | 真的 | 指定在发生故障或正常终止时是否应删除执行器容器。 | 3.0.0 |
spark.kubernetes.executor.checkAllContainers | false | 指定在确定 pod 状态时,执行器 pod 是否应该检查所有容器(包括 sidecar)还是仅检查执行器容器。 | 3.1.0 |
spark.kubernetes.submission.connectionTimeout | 10000 | kubernetes 客户端用于启动驱动程序的连接超时时间(以毫秒为单位)。 | 3.0.0 |
spark.kubernetes.submission.requestTimeout | 10000 | kubernetes 客户端用于启动驱动程序的请求超时时间(以毫秒为单位)。 | 3.0.0 |
spark.kubernetes.trust.certificates | false | 如果设置为 true,则客户端仅使用令牌就可提交给 kubernetes 集群。 | 3.2.0 |
spark.kubernetes.driver.connectionTimeout | 10000 | 驱动程序中的 kubernetes 客户端请求执行器时使用的连接超时(以毫秒为单位)。 | 3.0.0 |
spark.kubernetes.driver.requestTimeout | 10000 | 驱动程序中的 kubernetes 客户端在请求执行器时使用的请求超时时间(以毫秒为单位)。 | 3.0.0 |
spark.kubernetes.appKillPodDeletionGracePeriod | (没有任何) | 指定使用 spark-submit 删除 Spark 应用程序时的宽限期(以秒为单位)。 | 3.0.0 |
spark.kubernetes.dynamicAllocation.deleteGracePeriod | 5s | 在强制终止之前,等待执行者正常关闭的时间有多长。 | 3.0.0 |
spark.kubernetes.file.upload.path | (没有任何) | 集群模式下spark提交端存储文件的路径。例如: spark.kubernetes.file.upload.path=s3a://<s3-bucket>/path 文件应指定为file://path/to/file 或绝对路径。 | 3.0.0 |
spark.kubernetes.executor.decommissionLabel | (没有任何) | 应用于退出或退役的 pod 的标签。旨在与 pod 中断预算、删除成本等一起使用。 | 3.3.0 |
spark.kubernetes.executor.decommissionLabelValue | (没有任何) | spark.kubernetes.executor.decommissionLabel 启用 时与标签一起应用的值 。 | 3.3.0 |
spark.kubernetes.executor.scheduler.name | (没有任何) | 为每个执行器 pod 指定调度程序名称。 | 3.0.0 |
spark.kubernetes.driver.scheduler.name | (没有任何) | 指定驱动程序 pod 的调度程序名称。 | 3.3.0 |
spark.kubernetes.scheduler.name | (没有任何) | 指定驱动程序和执行程序 pod 的调度程序名称。如果设置了“spark.kubernetes.driver.scheduler.name”或“spark.kubernetes.executor.scheduler.name”,则将覆盖此项。 | 3.3.0 |
spark.kubernetes.configMap.maxSize | 1572864 | 配置映射的最大大小限制。这可根据k8s 服务器端的 限制进行配置。 | 3.1.0 |
spark.kubernetes.executor.missingPodDetectDelta | 30s | 当已注册执行器的 POD 在 Kubernetes API 服务器的轮询 POD 列表中缺失时,此增量时间将被视为注册时间和轮询时间之间的可接受时间差。在此时间之后,该 POD 将被视为从集群中缺失,并且执行器将被删除。 | 3.1.1 |
spark.kubernetes.decommission.script | /opt/decom.sh | 用于正常退役的脚本的位置。 | 3.2.0 |
spark.kubernetes.driver.service.deleteOnTermination | true | 如果为 true,则驱动程序服务将在 Spark 应用程序终止时被删除。如果为 false,则驱动程序服务将在驱动程序 pod 被删除时被清理。 | 3.2.0 |
spark.kubernetes.driver.service.ipFamilyPolicy | SingleStack | 驱动服务的 K8s IP 系列策略。有效值为 SingleStack 、PreferDualStack 和RequireDualStack 。 | 3.4.0 |
spark.kubernetes.driver.service.ipFamilies | IPv4 | K8s 驱动服务的 IP 系列列表。有效值为 IPv4 和IPv6 。 | 3.4.0 |
spark.kubernetes.driver.ownPersistentVolumeClaim | true | 如果为 true,则驱动程序 pod 将成为按需持久卷声明的所有者,而不是执行程序 pod | 3.2.0 |
spark.kubernetes.driver.reusePersistentVolumeClaim | true | 如果为 true,则驱动程序 pod 会尝试重用已删除执行程序 pod 的驱动程序拥有的按需持久卷声明(如果存在)。这可以通过跳过持久卷创建来减少执行程序 pod 创建延迟。请注意,处于“Terminating”pod 状态的 pod 按照定义不是已删除的 pod,并且其资源(包括持久卷声明)尚不可重用。当不存在可重用的持久卷声明时,Spark 将创建新的持久卷声明。换句话说,持久卷声明的总数有时可能大于正在运行的执行程序的数量。此配置需要spark.kubernetes.driver.ownPersistentVolumeClaim=true. | 3.2.0 |
spark.kubernetes.driver.waitToReusePersistentVolumeClaim | false | 如果为 true,驱动程序 pod 将计算创建的按需持久卷声明的数量,并等待该数量大于或等于 Spark 作业能够拥有的总卷数。此配置 spark.kubernetes.driver.ownPersistentVolumeClaim=true 需要 spark.kubernetes.driver.reusePersistentVolumeClaim=true. | 3.4.0 |
spark.kubernetes.executor.disableConfigMap | false | 如果为真,则禁用执行器的 ConfigMap 创建。 | 3.2.0 |
spark.kubernetes.driver.pod.featureSteps | (没有任何) | 实现“KubernetesFeatureConfigStep”的额外驱动程序 pod 功能步骤的类名。这是一个开发人员 API。以逗号分隔。在所有 Spark 内部功能步骤之后运行。自 3.3.0 起,您的驱动程序功能步骤可以实现“KubernetesDriverCustomFeatureConfigStep”,其中驱动程序配置也可用。 | 3.2.0 |
spark.kubernetes.executor.pod.featureSteps | (没有任何) | 实现“KubernetesFeatureConfigStep”的额外执行器 pod 功能步骤的类名。这是一个开发人员 API。以逗号分隔。在所有 Spark 内部功能步骤之后运行。自 3.3.0 起,您的执行器功能步骤可以实现“KubernetesExecutorCustomFeatureConfigStep”,其中执行器配置也可用。 | 3.2.0 |
spark.kubernetes.allocation.maxPendingPods | Int.MaxValue | 此应用程序执行程序分配期间允许的最大待处理 POD 数量。那些 Kubernetes 尚未识别的新请求执行程序也计入此限制,因为它们会随着时间的推移变为待处理 POD。此限制与资源配置文件无关,因为它限制了所有已使用资源配置文件的所有分配总和。 | 3.2.0 |
spark.kubernetes.allocation.pods.allocator | direct | 用于 Pod 的分配器。可能的值是direct (默认值)和statefulset ,或实现“AbstractPodsAllocator”的类的完整类名。未来版本可能会添加作业或副本集。这是一个开发人员 API,可能随时更改或删除。 | 3.3.0 |
spark.kubernetes.allocation.executor.timeout | 600s | 新创建的执行器 POD 请求尚未达到 POD 待处理状态,则视为超时并将被删除。 | 3.1.0 |
spark.kubernetes.allocation.driver.readinessTimeout | 1s | 在创建执行器 pod 之前等待驱动程序 pod 准备就绪的时间。此等待仅在应用程序启动时发生。如果发生超时,仍将创建执行器 pod。 | 3.1.3 |
spark.kubernetes.executor.enablePollingWithResourceVersion | false | 如果为 true,则在调用 pod 列表 API 期间将 `resourceVersion` 设置为 `0`,以允许 API 服务器端缓存。应谨慎使用。 | 3.3.0 |
spark.kubernetes.executor.eventProcessingInterval | 1s | 从 Kubernetes API 发送的执行器事件的连续检查间隔。 | 2.4.0 |
spark.kubernetes.executor.rollInterval | 0s | 执行器滚动操作之间的间隔。默认情况下,它被禁用,值为“0s”。 | 3.3.0 |
spark.kubernetes.executor.minTasksPerExecutorBeforeRolling | 0 | 滚动前每个执行器的任务数的最小值。Spark 不会滚动任务总数小于此配置的执行器。默认值为零。 | 3.3.0 |
spark.kubernetes.executor.rollPolicy | OUTLIER | 执行器滚动策略:有效值为 ID、ADD_TIME、TOTAL_GC_TIME、TOTAL_DURATION、FAILED_TASKS 和 OUTLIER(默认)。当执行器滚动时,Spark 使用此策略选择一个执行器并将其停用。内置策略基于执行器摘要,新启动的执行器受 spark.kubernetes.executor.minTasksPerExecutorBeforeRolling 保护。ID 策略选择执行器 ID 最小的执行器。ADD_TIME 策略选择添加时间最小的执行器。TOTAL_GC_TIME 策略选择总任务 GC 时间最大的执行器。TOTAL_DURATION 策略选择总任务时间最大的执行器。AVERAGE_DURATION 策略选择平均任务时间最大的执行器。 FAILED_TASKS 策略选择失败任务数量最多的执行器。OUTLIER 策略选择具有未完成统计数据的执行器,该统计数据在平均任务时间、总任务时间、总任务 GC 时间和失败任务数量(如果存在)方面至少比平均值大两个标准差。如果没有异常值,则其工作原理与 TOTAL_DURATION 策略相同。 | 3.3.0 |
Pod 模板属性
请参阅下表,了解将被 spark 覆盖的 pod 规范的完整列表。
Pod 元数据
Pod 元数据键 | 修改值 | 描述 |
---|---|---|
姓名 | 值spark.kubernetes.driver.pod.name | 驱动程序 pod 名称将被配置值或默认值覆盖 spark.kubernetes.driver.pod.name 。执行器 pod 名称将不受影响。 |
命名空间 | 值spark.kubernetes.namespace | Spark 对驱动程序和执行程序命名空间做出了严格的假设。驱动程序和执行程序命名空间都将被配置的或默认的 spark conf 值替换。 |
标签 | 添加来自的标签spark.kubernetes.{driver,executor}.label.* | Spark 将添加 spark 配置指定的额外标签。 |
注释 | 添加注释spark.kubernetes.{driver,executor}.annotation.* | Spark 将添加 spark 配置指定的额外注释。 |
Pod 规范
Pod 规范密钥 | 修改值 | 描述 |
---|---|---|
镜像PullSecrets | 添加来自以下来源的镜像拉取机密spark.kubernetes.container.image.pullSecrets | 额外的拉取机密将从 spark 配置添加到两个执行器容器中。 |
节点选择器 | 添加节点选择器spark.kubernetes.node.selector.* | 附加节点选择器将从 spark 配置添加到两个执行器容器中。 |
重启策略 | "never" | Spark 假定驱动程序和执行器都不会重新启动。 |
服务帐号 | 值spark.kubernetes.authenticate.driver.serviceAccountName | Spark 将serviceAccount 仅使用 spark 配置的值覆盖驱动程序 pod,并且仅当指定了 spark 配置时才会覆盖。执行程序 pod 将不受影响。 |
服务账户名 | 值spark.kubernetes.authenticate.driver.serviceAccountName | Spark 将serviceAccountName 仅使用 spark 配置的值覆盖驱动程序 pod,并且仅当指定了 spark 配置时才会覆盖。执行程序 pod 将不受影响。 |
卷 | 添加卷spark.kubernetes.{driver,executor}.volumes.[VolumeType].[VolumeName].mount.path | Spark 将添加由 spark conf 指定的卷,以及传递 spark conf 和 pod 模板文件所需的附加卷。 |
容器规格
以下内容会影响驱动程序和执行程序容器。Pod 规范中的所有其他容器均不受影响。
容器规范键 | 修改值 | 描述 |
---|---|---|
环境 | 添加环境变量spark.kubernetes.driverEnv.[EnvironmentVariableName] | Spark 将从中添加驱动程序环境变量spark.kubernetes.driverEnv.[EnvironmentVariableName] ,并从中添加执行器环境变量spark.executorEnv.[EnvironmentVariableName] 。 |
图像 | 值spark.kubernetes.{driver,executor}.container.image | 图像将由火花配置定义。 |
镜像拉取策略 | 值spark.kubernetes.container.image.pullPolicy | Spark 将覆盖驱动程序和执行器的拉取策略。 |
姓名 | 查看描述 | 如果 pod 模板未定义容器名称,则 spark 将分配容器名称(驱动程序容器为“spark-kubernetes-driver”,每个执行器容器为“spark-kubernetes-executor”)。如果容器由模板定义,则将使用模板的名称。 |
资源 | 查看描述 | cpu 限制由 设定spark.kubernetes.{driver,executor}.limit.cores 。cpu 由 设定 。内存请求和限制由和spark.{driver,executor}.cores 的值相加设定 。其他资源限制由 configs 设定。 spark.{driver,executor}.memory spark.{driver,executor}.memoryOverhead spark.{driver,executor}.resources.{resourceName}.* |
体积挂载 | 添加卷来自spark.kubernetes.driver.volumes.[VolumeType].[VolumeName].mount.{path,readOnly} | Spark 将添加由 spark conf 指定的卷,以及传递 spark conf 和 pod 模板文件所需的附加卷。 |
资源分配和配置概述
请确保已阅读配置页面上的自定义资源调度和配置概述部分。本节仅讨论 Kubernetes 特定的资源调度方面。
用户负责正确配置 Kubernetes 集群,使资源可用,并最好将每个资源隔离到每个容器,以便资源不会在多个容器之间共享。如果资源未隔离,则用户负责编写发现脚本,以便资源不会在容器之间共享。有关使用自定义资源配置 Kubernetes 的详细信息,请参阅 Kubernetes 文档。
spark.{driver/executor}.resource.{resourceType}
只要 Kubernetes 资源类型遵循 Kubernetes 设备插件格式,Spark 就会自动将 Spark 配置转换为 Kubernetes 配置vendor-domain/resourcetype
。用户必须使用配置指定供应商spark.{driver/executor}.resource.{resourceType}.vendor
。如果您使用 Pod 模板,则用户无需明确添加任何内容。有关参考和示例,您可以查看 Kubernetes 文档中的GPU调度。Spark 仅支持设置资源限制。
Kubernetes 不会告诉 Spark 分配给每个容器的资源地址。因此,用户必须指定一个发现脚本,该脚本由执行器在启动时运行,以发现该执行器可用的资源。您可以在 中找到示例脚本examples/src/main/scripts/getGpusResources.sh
。该脚本必须设置执行权限,并且用户应设置权限以不允许恶意用户修改它。该脚本应以 ResourceInformation 类的格式将 JSON 字符串写入 STDOUT。它具有资源名称和仅供该执行器使用的资源地址数组。
资源级别调度概述
Spark on Kubernetes 支持多种资源级别调度功能。
优先级调度
Kubernetes默认支持Pod 优先级。
Kubernetes 上的 Spark 允许通过Pod template定义作业的优先级。用户可以priorityClassName
在 driver 或 executor Pod templatespec
部分中指定。下面是一个示例来说明如何指定它:
apiVersion: v1
Kind: Pod
metadata:
labels:
template-label-key: driver-template-label-value
spec:
# Specify the priority in here
priorityClassName: system-node-critical
containers:
- name: test-driver-container
image: will-be-overwritten
为 Kubernetes 上的 Spark 定制 Kubernetes 调度程序
Spark 允许用户指定自定义 Kubernetes 调度程序。
-
指定调度程序名称。
用户可以使用
spark.kubernetes.scheduler.name
或spark.kubernetes.{driver/executor}.scheduler.name
配置指定自定义调度程序。 -
指定调度程序相关配置。
要配置自定义调度程序,用户可以使用Pod 模板,添加标签(
spark.kubernetes.{driver,executor}.label.*
)、注释(spark.kubernetes.{driver/executor}.annotation.*
)或调度程序特定的配置(例如spark.kubernetes.scheduler.volcano.podGroupTemplateFile
)。 -
指定调度程序功能步骤。
用户还可以考虑使用
spark.kubernetes.{driver/executor}.pod.featureSteps
来支持更复杂的需求,包括但不限于:- 为驱动程序/执行器调度创建额外的 Kubernetes 自定义资源。
- 根据配置或现有的 Pod 信息动态设置调度程序提示。
使用 Volcano 作为 Kubernetes 上 Spark 的定制调度器
先决条件
-
自 Spark v3.3.0 和 Volcano v1.7.0 起,Kubernetes 上的 Spark已支持使用Volcano作为自定义调度程序。以下是安装 Volcano 1.7.0 的示例:
kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/v1.7.0/installer/volcano-development.yaml
建造
要创建一个 Spark 发行版以及与 Spark下载页面分发的版本类似的 Volcano 支持,还可以参阅“构建 Spark”中的更多内容:
./dev/make-distribution.sh --name custom-spark --pip --r --tgz -Psparkr -Phive -Phive-thriftserver -Pkubernetes -Pvolcano
用法
Kubernetes 上的 Spark 允许使用 Volcano 作为自定义调度器。用户可以使用 Volcano 支持更高级的资源调度:队列调度、资源预留、优先级调度等。
要使用 Volcano 作为自定义调度程序,用户需要指定以下配置选项:
# Specify volcano scheduler and PodGroup template
--conf spark.kubernetes.scheduler.name=volcano
--conf spark.kubernetes.scheduler.volcano.podGroupTemplateFile=/path/to/podgroup-template.yaml
# Specify driver/executor VolcanoFeatureStep
--conf spark.kubernetes.driver.pod.featureSteps=org.apache.spark.deploy.k8s.features.VolcanoFeatureStep
--conf spark.kubernetes.executor.pod.featureSteps=org.apache.spark.deploy.k8s.features.VolcanoFeatureStep
火山特征步骤
Volcano 功能步骤帮助用户创建 Volcano PodGroup 并设置驱动程序/执行器 pod 注释以与该PodGroup链接。
请注意,Volcano Feature Step 当前仅支持驱动程序/作业级别的 PodGroup。
火山 PodGroup 模板
Volcano 使用CRD yaml定义 PodGroup 规范。
与Pod 模板类似,Spark 用户可以使用 Volcano PodGroup 模板来定义 PodGroup 规范配置。为此,请指定 Spark 属性spark.kubernetes.scheduler.volcano.podGroupTemplateFile
以指向进程可访问的文件spark-submit
。以下是 PodGroup 模板的示例:
apiVersion: scheduling.volcano.sh/v1beta1
kind: PodGroup
spec:
# Specify minMember to 1 to make a driver pod
minMember: 1
# Specify minResources to support resource reservation (the driver pod resource and executors pod resource should be considered)
# It is useful for ensource the available resources meet the minimum requirements of the Spark job and avoiding the
# situation where drivers are scheduled, and then they are unable to schedule sufficient executors to progress.
minResources:
cpu: "2"
memory: "3Gi"
# Specify the priority, help users to specify job priority in the queue during scheduling.
priorityClassName: system-node-critical
# Specify the queue, indicates the resource queue which the job should be submitted to
queue: default
使用 Apache YuniKorn 作为 Kubernetes 上 Spark 的定制调度程序
Apache YuniKorn是 Kubernetes 的资源调度程序,提供高级批量调度功能,例如作业排队、资源公平性、最小/最大队列容量和灵活的作业排序策略。有关可用的 Apache YuniKorn 功能,请参阅核心功能。
先决条件
安装 Apache YuniKorn:
helm repo add yunikorn https://apache.github.io/yunikorn-release
helm repo update
helm install yunikorn yunikorn/yunikorn --namespace yunikorn --version 1.3.0 --create-namespace --set embedAdmissionController=false
上述步骤将在现有的 Kubernetes 集群上安装 YuniKorn v1.3.0。
开始使用
使用以下额外选项提交 Spark 作业:
--conf spark.kubernetes.scheduler.name=yunikorn
--conf spark.kubernetes.driver.label.queue=root.default
--conf spark.kubernetes.executor.label.queue=root.default
--conf spark.kubernetes.driver.annotation.yunikorn.apache.org/app-id={{APP_ID}}
--conf spark.kubernetes.executor.annotation.yunikorn.apache.org/app-id={{APP_ID}}
请注意,{{APP_ID}} 是内置变量,将自动替换为 Spark 作业 ID。通过上述配置,作业将由 YuniKorn 调度程序而不是默认的 Kubernetes 调度程序进行调度。
阶段级别调度概述
Kubernetes 支持阶段级别调度:
- 当动态分配被禁用时:它允许用户在阶段级别指定不同的任务资源需求,并将使用启动时请求的相同执行器。
- 启用动态分配时:它允许用户在阶段级别指定任务和执行器资源需求,并将请求额外的执行器。这也需要
spark.dynamicAllocation.shuffleTracking.enabled
启用,因为 Kubernetes 目前不支持外部 shuffle 服务。无法保证从 Kubernetes 请求不同配置文件的容器的顺序。请注意,由于 Kubernetes 上的动态分配需要 shuffle 跟踪功能,这意味着来自使用不同 ResourceProfile 的先前阶段的执行器可能不会因为其上有 shuffle 数据而空闲超时。这可能会导致使用更多的集群资源,在最坏的情况下,如果 Kubernetes 集群上没有剩余资源,那么 Spark 可能会挂起。您可以考虑查看配置spark.dynamicAllocation.shuffleTracking.timeout
以设置超时,但如果确实需要 shuffle 数据,这可能会导致必须重新计算数据。请注意,基本默认配置文件和自定义 ResourceProfile 之间处理 pod 模板资源的方式有所不同。pod 模板文件中指定的任何资源都只能与基本默认配置文件一起使用。如果您创建自定义 ResourceProfiles,请确保其中包含所有必要的资源,因为模板文件中的资源不会传播到自定义 ResourceProfiles。