无法将 Apache Spark 应用程序提交到容器化集群

Posted

技术标签:

【中文标题】无法将 Apache Spark 应用程序提交到容器化集群【英文标题】:Trouble Submitting Apache Spark Application to Containerized Cluster 【发布时间】:2017-12-17 16:33:59 【问题描述】:

我在使用 spark-submit 和内部 REST API 运行 Spark 应用程序时遇到问题。我想演示的部署场景是 Spark 在我的本地笔记本电脑上作为集群运行。

为此,我为 spark-master 和 spark-worker 创建了两个 Docker 容器。这方面的一切似乎都在工作,worker 能够向 master 注册,两个 Web 控制台都可用,并且内部 REST(端口 6066)API 是响应式的。

我已经为我的应用程序创建了一个 uber jar,但是,在尝试执行它时,我在这两种情况下都遇到了同样的错误。

使用 spark-submit 时,我使用本地安装的本地 Spark 提交到容器:

$SPARK_HOME/bin/spark-submit \
    --class com.reynoldsm88.jobs.SparkApp \
    --master spark://localhost:7077 \
    --deploy-mode cluster \
    --supervise \
    /Users/reynoldsm88/workspace/spark-app/spark-app/target/scala-2.11/spark-app-assembly-0.0.1-SNAPSHOT.jar

使用 REST API 时,我的请求如下所示:

curl -X POST http://localhost:6066/v1/submissions/create --header "Content-Type:application/json;charset=UTF-8" --data '
    "action" : "CreateSubmissionRequest",
    "appArgs" : [ "myAppArgument1" ],
    "appResource" : "/Users/reynoldsm88/workspace/spark-app/spark-app/target/scala-2.11/spark-app-assembly-0.0.1-SNAPSHOT.jar",
    "clientSparkVersion" : "2.2.0",
      "environmentVariables" : 
        "SPARK_ENV_LOADED" : "1"
    ,
    "mainClass" : "com.reynoldsm88.jobs.SparkApp",
    "sparkProperties" : 
        "spark.master" : "spark://localhost:7077",
        "spark.jars" : "/Users/reynoldsm88/workspace/spark-app/spark-app/target/scala-2.11/spark-app-assembly-0.0.1-SNAPSHOT.jar",
        "spark.driver.supervise" : "false",
        "spark.app.name" : "MyJob",
        "spark.eventLog.enabled": "true",
        "spark.submit.deployMode" : "client"
    
'

两者的结果是一样的:

Spark Master(在 Docker 容器内)

17/12/17 16:08:23 INFO Master: Driver submitted org.apache.spark.deploy.worker.DriverWrapper
17/12/17 16:08:23 INFO Master: Launching driver driver-20171217160823-0001 on worker worker-20171217155536-172.17.0.5-7078
17/12/17 16:08:24 INFO Master: Removing driver: driver-20171217160823-0001

Spark Worker(在单独的 Docker 容器内)

17/12/17 16:08:24 INFO Worker: Asked to launch driver driver-20171217160823-0001
17/12/17 16:08:24 INFO DriverRunner: Copying user jar file:///Users/reynoldsm88/workspace/spark-app/spark-app/target/scala-2.11/spark-app-assembly-0.0.1-SNAPSHOT.jar to /spark-2.2.0-bin-hadoop2.7/work/driver-20171217160823-0001/spark-app-assembly-0.0.1-SNAPSHOT.jar
17/12/17 16:08:24 INFO Utils: Copying /Users/reynoldsm88/workspace/spark-app/spark-app/target/scala-2.11/spark-app-assembly-0.0.1-SNAPSHOT.jar to /spark-2.2.0-bin-hadoop2.7/work/driver-20171217160823-0001/spark-app-assembly-0.0.1-SNAPSHOT.jar
17/12/17 16:08:24 INFO DriverRunner: Killing driver process!
17/12/17 16:08:24 WARN Worker: Driver driver-20171217160823-0001 failed with unrecoverable exception: java.nio.file.NoSuchFileException: /Users/reynoldsm88/workspace/spark-app/spark-app/target/scala-2.11/spark-app-assembly-0.0.1-SNAPSHOT.jar

我可能被误解了,但我认为在这两种情况下,本地 JAR 文件都将提交给 Spark master,以便分发到工作节点。但是,由于某种原因,工作节点似乎正在尝试从我的本地文件系统加载它,这是有问题的,因为 Spark Worker 正在运行的 Docker 容器不知道该文件。

也许我弄错了这是如何工作的?如果我真的想将笔记本电脑上的应用程序提交到容器化集群,是否需要将该目录挂载为卷或在某处托管 JAR 以便 Worker 可以下载它?

任何帮助或见解将不胜感激。

【问题讨论】:

【参考方案1】:

发布后不久,我想出了一个解决我的问题的方法,但我想知道这是理想的还是有更好的方法。作为作业脚本的一部分,我将 jar 复制到一个目录中,该目录在 Docker 中作为主机卷挂载:

Dockerfile

...
VOLUME /etc/spark/apps
...

启动脚本

docker run -v /Users/reynoldsm88/spark/apps/:/etc/spark/apps --name spark-master -p 8080:8080 -p 7077:7077 -p 6066:6066 -t reynoldsm88/spark-master

这似乎有效并且符合我目前的需求。我确实希望有一种方法可以通过 API 将 JAR 部署到 Spark,尽管我可能在研究中错过了这一点。

【讨论】:

以上是关于无法将 Apache Spark 应用程序提交到容器化集群的主要内容,如果未能解决你的问题,请参考以下文章

Oozie Spark 操作工作流无法启动

无法使用 SSO 钱包将 Oracle 与 Apache Spark 连接

Apache Spark:CentOS7下的提交和执行一个官方的jar项目包

将 Spark 作业提交到 Spark 集群

《Apache Spark源码剖析》学习笔记之Spark作业提交

Apache Spark s3a 提交者 - 线程堆栈 - 内存不足问题