将 Apache Spark 应用程序提交到容器化集群时出现问题

Trouble Submitting Apache Spark Application to Containerized Cluster

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

为此,我为 spark-master 和 spark-worker 创建了两个 Docker 容器。这方面的一切似乎都在工作,工作人员能够向主人注册,两个 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 可以下载它?

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

发布这篇文章后不久,我想出了一个解决问题的方法,但我想知道这是否理想,或者是否有更好的方法。作为作业脚本的一部分,我将 jar 复制到一个目录中,该目录作为主机卷安装在 Docker a la:

Docker文件

...
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,尽管我可能在研究中错过了它。