使用 spark-on-k8s-operator 在 Kubernetes 上运行的 Pyspark 的依赖性问题



我现在花了几天时间试图找出我在 Kubernetes 上运行的 (Py(Spark 遇到的依赖问题。我正在使用spark-on-k8s-operator和Spark的Google Cloud连接器。

当我尝试使用带有以下 .yaml 文件的sparkctl create sparkjob.yaml ...提交我的 Spark 作业时,它就像一个魅力。

apiVersion: "sparkoperator.k8s.io/v1beta2"
kind: SparkApplication
metadata:
name: spark-job
namespace: my-namespace
spec:
type: Python
pythonVersion: "3"
hadoopConf:
"fs.gs.impl": "com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystem"
"fs.AbstractFileSystem.gs.impl": "com.google.cloud.hadoop.fs.gcs.GoogleHadoopFS"
"fs.gs.project.id": "our-project-id"
"fs.gs.system.bucket": "gcs-bucket-name"
"google.cloud.auth.service.account.enable": "true"
"google.cloud.auth.service.account.json.keyfile": "/mnt/secrets/keyfile.json"
mode: cluster
image: "image-registry/spark-base-image"
imagePullPolicy: Always
mainApplicationFile: ./sparkjob.py
deps:
jars:
- https://repo1.maven.org/maven2/org/apache/spark/spark-sql-kafka-0-10_2.11/2.4.5/spark-sql-kafka-0-10_2.11-2.4.5.jar
sparkVersion: "2.4.5"
restartPolicy:
type: OnFailure
onFailureRetries: 3
onFailureRetryInterval: 10
onSubmissionFailureRetries: 5
onSubmissionFailureRetryInterval: 20
driver:
cores: 1
coreLimit: "1200m"
memory: "512m"
labels:
version: 2.4.5
serviceAccount: spark-operator-spark
secrets:
- name: "keyfile"
path: "/mnt/secrets"
secretType: GCPServiceAccount
envVars:
GCS_PROJECT_ID: our-project-id
executor:
cores: 1
instances: 1
memory: "512m"
labels:
version: 2.4.5
secrets:
- name: "keyfile"
path: "/mnt/secrets"
secretType: GCPServiceAccount
envVars:
GCS_PROJECT_ID: our-project-id

Docker 镜像spark-base-image是使用 Dockerfile 构建

FROM gcr.io/spark-operator/spark-py:v2.4.5
RUN rm $SPARK_HOME/jars/guava-14.0.1.jar
ADD https://repo1.maven.org/maven2/com/google/guava/guava/28.0-jre/guava-28.0-jre.jar $SPARK_HOME/jars
ADD https://repo1.maven.org/maven2/com/google/cloud/bigdataoss/gcs-connector/hadoop2-2.0.1/gcs-connector-hadoop2-2.0.1-shaded.jar $SPARK_HOME/jars
ENTRYPOINT [ "/opt/entrypoint.sh" ]

主应用程序文件在提交应用程序时上传到 GCS,随后从那里获取并在启动应用程序时复制到驱动程序 pod 中。每当我想提供自己的 Python 模块deps.zip作为依赖项以便能够在我的主应用程序文件sparkjob.py中使用它时,问题就开始了。

这是我到目前为止尝试过的:

1

在 sparkjob.yaml 中的 spark.deps 中添加了以下行

pyFiles:
- ./deps.zip

这导致操作员甚至无法提交带有错误的 Spark 应用程序

java.lang.RuntimeException: java.lang.ClassNotFoundException: Class com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystem not found

./deps.zip与主应用程序文件一起成功上传到 GCS 存储桶,但虽然主应用程序文件可以从 GCS 成功获取(我在上面定义的没有依赖项的作业日志中看到了这一点(,./deps.zip无法以某种方式从那里获取。我还尝试将 gcs-connector jar 显式添加到 spark.deps.jars 列表中 - 没有任何变化。

阿拉伯数字

我通过将COPY ./deps.zip /mnt/添加到上述 Dockerfile 并在 sparkjob.yaml 中添加依赖项,将./deps.zip添加到用于启动驱动程序和执行程序 pods 的基本 docker 映像中

,通过以下方式
pyFiles:
- local:///mnt/deps.zip

这次可以提交 Spark 作业并启动驱动程序 pod,但是在初始化 Spark 上下文时出现file:/mnt/deps.zip not found错误 我还尝试在 Dockerfile 中额外设置ENV SPARK_EXTRA_CLASSPATH=/mnt/,但没有任何成功。我什至尝试使用卷挂载将整个/mnt/目录显式挂载到驱动程序和执行器 pod 中,但这也没有奏效。

<小时 />

编辑:

我的解决方法 (2(,将依赖项添加到 Docker 映像并在 Dockerfile 中设置ENV SPARK_EXTRA_CLASSPATH=/mnt/实际上有效!事实证明标签没有更新,我一直在使用旧版本的 Docker 映像。咄。

我仍然不知道为什么通过 gcs 连接器的(更优雅的(解决方案 1 不起作用,但它可能与 MountVolume.安装卷"火花-会议卷"失败

如果 zip 文件包含您在运行 Spark 作业时始终需要的 jar,则面临我刚刚添加的类似问题

FROM gcr.io/spark-operator/spark-py:v2.4.5
COPY mydepjars/ /opt/spark/jars/

一切都在我的火花会话中加载。可能是一种方法。

我在使用s3a时遇到了同样的问题(org.apache.hadoop.fs.s3a.S3AFileSystem未找到(。当我尝试时:

deps:
files:
- "s3a://k8s-3c172e28d7da2e-bucket/test.jar"

甚至在映像中添加了jars文件:"image-registry/spark-base-image"不起作用。但是当我在火花操作员吊舱内添加必要的罐子时,我解决了这个问题。您可以通过添加 jar 来重建 Docker 映像。在 s3 的情况下,我重建它:

FROM ghcr.io/googlecloudplatform/spark-operator:v1beta2-1.3.7-3.1.1
ENV SPARK_HOME /opt/spark
RUN curl https://repo1.maven.org/maven2/org/apache/hadoop/hadoop-aws/2.7.4/hadoop-aws-2.7.4.jar -o ${SPARK_HOME}/jars/hadoop-aws-2.7.4.jar
RUN curl https://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk/1.7.4/aws-java-sdk-1.7.4.jar -o ${SPARK_HOME}/jars/aws-java-sdk-1.7.4.jar

在 spark-operator 中,里面有 hadoop 版本 2.7,我们需要在 https://mvnrepository.com/上完全使用此版本的所有依赖项

首先进行测试,我通过命令进入火花操作员吊舱内部

kubectl exec -it spark-operator-fb8f779cb-gt657 -n spark-operator -- bash 

其中 Pod 名称为

火花操作员-FB8F779CB-GT657

和 -n 火花运算符它是命名空间的名称

您可以获取所有豆荚并查找豆荚名称

kubectl get po -A

然后在我的火花操作员 pod 中,我转到/opt/spark/jars 并上传 jar(例如 curl https://repo1.maven.org/maven2/org/apache/hadoop/hadoop-aws/2.7.4/hadoop-aws-2.7.4.jar(

然后我尝试使用 deps.files 应用我的清单,它已经工作了。

使用 Python 依赖项的 Google Cloud Storage 路径,因为它们已上传到那里。

spec:
deps:
pyFiles:
- gs://gcs-bucket-name/deps.zip

最新更新