如何将应用程序打包到能够在 Kubernetes 中的 Spark 集群上运行的 docker 镜像中?
Posted
技术标签:
【中文标题】如何将应用程序打包到能够在 Kubernetes 中的 Spark 集群上运行的 docker 镜像中?【英文标题】:How to package an application in a docker image capable of running on a Spark cluster in Kubernetes? 【发布时间】:2020-12-29 11:21:05 【问题描述】:我是在 Kubernetes 上运行 Spark 的新手,我正在尝试打包一个非常简单的应用程序,以便在我设置的 K8s 集群上的 Spark 中运行。我面临的挑战是如何打包我的应用程序以在 Spark 中运行?我从Spark Operator 在 K8 上安装了 Spark,我注意到示例使用了图像 gcr.io/spark-operator/spark:v3.0.0
。
我注意到 Spark documentation 提到了这个 docker-image-tool.sh
脚本来生成应用程序。但这看起来像是用于定制环境。我想要一个我的应用程序可以用来在 Spark 集群上运行的轻量级图像。不知道如何将它们联系在一起。
所以我从文档中看到了 2 个选项
-
使用this docker file 作为基础镜像。
使用
docker-image-tool.sh
脚本。
但我不确定我需要选择哪个选项或何时使用其中一个选项?为什么要使用一个而不是另一个?还有其他选择吗?是否有一个预构建的映像,我可以将我的应用程序复制到其中并使用它来运行?
【问题讨论】:
【参考方案1】:Spark 的docker-image-tool.sh
是一个创建Spark 镜像的工具脚本。如果您想要一个轻量级的 docker 镜像,您可以调整项目附带的 Dockerfile 或编写自己的 - 不要忘记编辑 entrypoint.sh
脚本。
通常,将 Spark 应用程序导入 Kubernetes 的步骤如下:
-
创建一个基础 spark 图像供您使用。
将其推送到 docker 注册表 - 如果您使用 minikube,则可以使用
-m
标志将其移动到 minikube 环境。
编写一个 Spark 应用程序,将其打包,然后运行spark-submit
命令。
注意:
如果你没有在 Kubernetes 上投入太多,只是想快速试用整个平台,你可以通过运行以下命令来代理 kube-api-server
:
kubectl proxy
它将开始在localhost:8001
上为 api 服务器提供服务,然后您可以通过运行类似的命令来提交您的 spark 应用程序
bin/spark-submit \
--master k8s://http:localhost:8001 \ #If you don't specify the protocol here, it'd default to https
--deploy-mode client \ #if you want to go for `cluster mode` then you'd have to set up a service account
--name sparkle \
--class edu.girdharshubham \
--conf spark.executor.instances=1 \ #Number of pods
--conf spark.kubernetes.container.image=<your-spark-image>
--conf spark.kubernetes.driver.pod.name="sparkle"
--conf spark.kubernetes.hadoop.configMapName="HADOOP_CONF_DIR"
--conf spark.kubernetes.executor.deleteOnTermination
path/to/jar
在客户端模式下运行的注意事项:
确保您正在运行上述命令的节点 - VM - 可从 pod 进行网络寻址 executor(pod) 将运行一个 JAVA 进程 默认 Dockerfile 使用 tini - 微小但对容器有效的init
。
spark.kubernetes.executor.deleteOnTermination
- 如果你刚刚开始,这个 conf 应该是你的 conf,默认情况下,在失败或正常终止的情况下会删除 pod。这将帮助您快速调试 executor pod 的情况——无论它们是否失败。
【讨论】:
deleteOnTermination
标志非常有用,非常有用。
单独的问题 - 您打包应用程序的 docker 映像是否必须包含整个 spark 分发?看起来即使在docker-image-tool.sh
中也像示例一样打包了一些不必要的东西。我认为可能只有一些客户端库可以打包到 docker 映像中,而不是整个 spark 库。
我添加了一个关于使用基本 dockerfile 与 docker-image-tool.sh
脚本的附加问题 - 如果您对该问题有任何见解,请分享!谢谢
嗨 - 当您说“不要忘记编辑 entrypoint.sh
脚本时。” - 你什么意思?我们需要在该文件中编辑什么?【参考方案2】:
我想我让你有点困惑。准备 spark 发行版的镜像和打包你的应用程序是两件不同的事情。以下是使用 Kuberentes 作为调度程序部署应用程序的方法。
第 1 步:构建 Spark 的映像
./bin/docker-image-tool.sh -r asia.gcr.io/menace -t v3.0.0 build
第 2 步:将映像推送到 Docker 注册表
./bin/docker-image-tool.sh -r asia.gcr.io/menace -t v3.0.0 push
第 3 步:配置您的 Kubernetes 以能够拉取您的镜像,在大多数情况下,只需要设置 imagePullSecrets
。
Pull Images from a private registry
第 4 步:编写您的 Spark 应用
package edu.girdharshubham
import scala.math.random
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.SparkSession
object Solution
def main(args: Array[String])
val spark = SparkSession
.builder
.master("k8s://http://localhost:8001")
.config("spark.submit.deployMode","client")
.config("spark.executor.instances", "2")
.config("spark.kubernetes.container.image", "asia.gcr.io/menace/spark:v3.0.0")
.appName("sparkle")
.getOrCreate()
import spark.implicits._
val someDF = Seq(
(8, "bat"),
(64, "mouse"),
(-27, "horse")
).toDF("number", "word")
println("========================================================")
println(someDF.take(1).foreach(println))
println("========================================================")
spark.stop()
第 4 步:运行您的应用程序
sbt run
这将导致在您的集群上生成 executor pod。
第 5 步:打包您的应用程序
sbt package
第 6 步:使用 spark submit 命令运行您的应用 - 请参阅我的初始答案
现在来回答您关于打包 Spark 发行版的问题,请注意您打包的版本和您使用的依赖项。 Spark 对版本有点不确定。
【讨论】:
所以我的问题是关于打包我的应用程序,而不是 spark 分发。我从 spark-operator 安装了 Spark,并且需要我的应用程序是 docker 映像 哦!在这种情况下,您只需在清单中提供以下内容。基本图像将是您的火花分布。 ``` mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.12-2.3.0.jar mainClass: org.apache.spark.examples.SparkPi ``` 或者如果你只是测试它out atm,你可以打包你的应用程序。将您的代码放在 spark 目录中,并将 Dockerfile 更改为在 spark 映像中也复制该应用程序 好的,我想我明白了。所以我仍然需要构建一个包含所有 spark 依赖项的图像吗?我需要更改docker-image-tool.sh
脚本以将我的新代码复制到其中吗?还是更改其中一个 docker 文件?
是的,您仍然需要构建 spark 基础镜像 - 除非您计划使用社区提供的镜像。在 kubernetes/dockerfiles/spark/Dockerfile 的原始 dockerfile 中添加 COPY 指令。之后,使用构建标志运行 docker 映像工具,然后使用推送标志以上是关于如何将应用程序打包到能够在 Kubernetes 中的 Spark 集群上运行的 docker 镜像中?的主要内容,如果未能解决你的问题,请参考以下文章
如何在Kubernetes 上部署安装PHP + Nginx 多容器应用