跳到主要内容
版本:1.3.0

运行Spark作业

注意

本文档假设您已安装YuniKorn及其准入控制器。请参阅 开始 查看如何操作。

为Spark准备docker镜像

要在Kubernetes上运行Spark,您需要Spark的docker镜像。您可以 1)使用Spark团队提供的docker镜像 2)从头开始构建一个镜像。如果你想建立自己的Spark的docker镜像,您可以找到 完整说明 在 Spark 文档中。简化步骤:

./buid/mvn -Pkubernetes -DskipTests clean package

建议使用dockerhub中不同spark版本的官方镜像

为Spark作业创建一个命名空间

创建一个命名空间:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: spark-test
EOF

创建服务帐号和角色绑定

spark-test 命名空间下创建 service account 和 role bindings :

cat <<EOF | kubectl apply -n spark-test -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: spark
namespace: spark-test
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: spark-role
namespace: spark-test
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list", "create", "delete"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "create", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: spark-role-binding
namespace: spark-test
subjects:
- kind: ServiceAccount
name: spark
namespace: spark-test
roleRef:
kind: Role
name: spark-role
apiGroup: rbac.authorization.k8s.io
EOF

:::注意 不可以在生产环境使用 ClusterRoleClusterRoleBinding 去运行一个Spark作业! 请为运行Spark作业配置更细粒度的安全上下文。有关如何配置正确的RBAC规则的详细信息,请参见链接。 :::

提交一个Spark作业

如果这是从本地计算机运行的,您需要启动代理才能与api服务器通信。

kubectl proxy

dockerhub中有不同spark版本的官方镜像 运行一个简单的 SparkPi 作业,假设 Spark 二进制文件本地安装在 /usr/local 目录中。

export SPARK_HOME=/usr/local/spark/
${SPARK_HOME}/bin/spark-submit --master k8s://http://localhost:8001 --deploy-mode cluster --name spark-pi \
--master k8s://http://localhost:8001 --deploy-mode cluster --name spark-pi \
--class org.apache.spark.examples.SparkPi \
--conf spark.executor.instances=1 \
--conf spark.kubernetes.namespace=spark-test \
--conf spark.kubernetes.executor.request.cores=1 \
--conf spark.kubernetes.container.image=docker.io/apache/spark:v3.3.0 \
--conf spark.kubernetes.authenticate.driver.serviceAccountName=spark-test:spark \
local:///opt/spark/examples/jars/spark-examples_2.12-3.3.0.jar
备注

spark 中有更多设置驱动程序和执行程序的选项。 可以分配 applicationId 和队列路径。

--conf spark.kubernetes.executor.label.applicationId=application-spark-0001
--conf spark.kubernetes.driver.label.applicationId=application-spark-0001
--conf spark.kubernetes.executor.label.queue=root.default.sandbox
--conf spark.kubernetes.driver.label.queue=root.default.sandbox

您可以看见Spark的driver和executors在Kubernetes上创建:

spark-pods

spark-pi结果在 driver pod中。

spark-pods

幕后发生了什么?

当Spark作业提交到集群时,该作业将提交到 spark-test 命名空间。Spark的driver的pod将首先在此名称空间下创建。 由于该集群已启用YuniKorn准入控制器,当driver的pod创建后,准入控制器会修改pod的规范并注入 schedulerName=yunikorn, 通过这样做默认K8s调度程序将跳过此pod,而由YuniKorn调度。请查看这里在Kubernetes配置其他调度器来了解是如何完成的.

默认配置已启用放置规则,该规则会自动将 spark-test 命名空间映射到YuniKorn的队列 root.spark test。 提交到此命名空间的所有Spark作业将首先自动提交到该队列。 要了解有关放置规则如何工作的更多信息,请参阅文档应用放置规则。 到目前为止,名称空间定义pod的安全上下文,队列考虑到作业顺序、队列资源公平性等因素会确定如何调度作业和pod。 注意,这是最简单的设置,不强制执行队列容量。该队列被视为具有无限容量。

YuniKor在标签 spark-app-selector 中重复设置Spark的应用程序ID,并提交此作业去YuniKorn,同时被视为一份作业。 当集群中有足够的资源时,作业被调度并运行。 YuniKorn将driver的pod分配给一个节点,绑定pod并启动所有容器。 一旦driver的pod启动,它会请求一堆executor的pod来运行它的任务。这些pod也将在相同的名称空间中创建,并且被YuniKorn所调度。