Spark提交到kubernetes:执行程序未拉取的包

Posted

技术标签:

【中文标题】Spark提交到kubernetes:执行程序未拉取的包【英文标题】:Spark submit to kubernetes: packages not pulled by executors 【发布时间】:2021-05-27 04:48:06 【问题描述】:

我正在尝试使用 spark-submit 将我的 Pyspark 应用程序提交到 Kubernetes 集群 (Minikube):

./bin/spark-submit \
   --master k8s://https://192.168.64.4:8443 \
   --deploy-mode cluster \
   --packages org.apache.spark:spark-sql-kafka-0-10_2.12:3.0.1 \
   --conf spark.kubernetes.container.image='pyspark:dev' \
   --conf spark.kubernetes.container.image.pullPolicy='Never' \
   local:///main.py

应用程序尝试访问集群内部署的Kafka实例,因此我指定了jar依赖:

--packages org.apache.spark:spark-sql-kafka-0-10_2.12:3.0.1

我使用的容器映像基于我使用实用程序脚本构建的容器映像。我已经在其中打包了我的应用程序需要的所有 python 依赖项。

驱动程序正确部署并获取 Kafka 包(如果需要,我可以提供日志)并在新 pod 中启动执行程序。

但随后 executor pod 崩溃:

ERROR Executor: Exception in task 0.0 in stage 1.0 (TID 1)
java.lang.ClassNotFoundException: org.apache.spark.sql.kafka010.KafkaBatchInputPartition
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at org.apache.spark.serializer.JavaDeserializationStream$$anon$1.resolveClass(JavaSerializer.scala:68)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1986)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1850)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2160)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1667)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2405)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2329)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2187)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1667)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2405)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2329)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2187)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1667)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:503)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:461)
at org.apache.spark.serializer.JavaDeserializationStream.readObject(JavaSerializer.scala:76)
at org.apache.spark.serializer.JavaSerializerInstance.deserialize(JavaSerializer.scala:115)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:407)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

所以我对执行程序 pod 进行了调查,发现 $SPARK_CLASSPATH 文件夹(设置为 ':/opt/spark/jars/*')中不存在 jar(如堆栈跟踪中所述)

在构建 docker 映像时,我是否还需要在 spark jars 文件夹中获取并包含依赖项? (我认为'--packages'选项也会让执行器检索指定的jar)

【问题讨论】:

刚刚尝试从 maven 添加所有 jar 依赖项并将它们放在 docker 中并且它可以工作。但我很困惑为什么我必须检索它们,因为 --package 标志似乎表明它将在驱动程序和执行程序 pod 中检索它们 嗨,Alexandre,您是如何在 Docker 映像中包含依赖项的?我做了完全相同的事情,如果我在构建映像中运行该作业,它可以正常工作,但当我将它部署到 Kubernetes 时就不行了。 【参考方案1】:

您是否从文档Docker images section 中描述的官方 Dockerfile (kubernetes/dockerfiles/spark/bindings/python/Dockerfile) 开始? 您还需要在与 Hadoop 兼容的文件系统上指定上传位置,并确保指定的 Ivy 主目录和缓存目录具有正确的权限,如Dependency Management section 中所述。

文档中的示例:

...
--packages com.amazonaws:aws-java-sdk:1.7.4,org.apache.hadoop:hadoop-aws:2.7.6
--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"
...

【讨论】:

是的,我从“官方 Docker”镜像开始(它只是调用给定的脚本来构建一个)。我确实遇到过(在这篇文章之后),我实际上需要创建一个共享卷,常春藤可以在其中放置所有依赖项以使其工作。现在我明白了,我只是坚持使用所有内置的 docker 映像,正如我在评论中所说的那样,因为它在我的情况下很好(deps 小于 2Mb)。感谢任何发现这篇文章并且确实错过了文档中的这一部分的人的澄清。 如果我创建到 docker 图像中它可以工作,你能检查一下它是否有效.. 但是传递 jar 文件以提取数据***.com/questions/69902575/…

以上是关于Spark提交到kubernetes:执行程序未拉取的包的主要内容,如果未能解决你的问题,请参考以下文章

spark任务运行过程的源码分析

查询未拉入选择框值,oracle

如何将应用程序打包到能够在 Kubernetes 中的 Spark 集群上运行的 docker 镜像中?

Python开发Spark步骤以及如何提交Spark应用,PythonOnSpark原理

spark任务的提交流程(yarn)

.Spark基于Standalone提交任务两种方式