基于 Spark 2.3.3 文档
Spark可以在Kubernetes管理的集群上部署运行。 此功能已集成到Spark的本地Kubernetes调度程序中。


1. 使用前提

  • Spark版本在2.3或者以上;
  • Kubernetes集群版本在1.6以上,并且使用 kubectl 命令配置了对他的访问权限。如果还未安装Kubernetes集群,则可以使用minikube在本地计算机上搭建测试集群:1. 建议使用配置了DNS插件的最新版本的minikube;2. 需要注意的是,默认的minikube配置不足以运行Spark应用程序。 建议修改为 3core 和 4g 内存,以便能够用一个执行程序来启动一个简单的Spark应用程序;
  • 创建、编辑和删除集群中的Pod需要一定的权限,可以使用 kubectl auth can-i <list | create | edit | delete> pods 命令查看是否具备这些权限;
  • 您必须在集群中配置Kubernetes DNS。

    2. 执行原理

    spark-submit可以直接将Spark应用程序提交到Kubernetes集群。 提交应用的工作原理如下:

  • spark会创建一个Driver程序运行在Pod中;

  • Driver程序会创建一个或以上的Executor程序,运行在Pod中并且和他们进行通讯,然后执行应用程序的代码;
  • 应用程序完成后,Executor Pod会被终止并被清理掉。但 Driver Pod会保留日志,并在Kubernetes API中保持“完成”状态,直到最终对其进行垃圾收集或手动清理为止。

需要注意的是:在完成状态下,Driver Pod不会使用任何计算和内存资源。Driver Pod 和 Executor Pod 的调度均由 Kubernetes 来完成
image.png

3. 提交App程序到K8S上

3.1 Docker 镜像

Kubernetes要求用户提供可以部署到Pod内的容器镜像。 构建后的镜像在Kubernetes支持的容器运行时环境中运行。 Docker是Kubernetes经常使用的容器运行时环境。 Spark(从2.3版开始)附带了一个Dockerfile,可用于此目的,也可对其进行自定义以匹配单个应用程序的需求。 可以在kubernetes / dockerfiles /目录中找到它。
Spark还附带了 bin/docker-image-tool.sh 脚本,可用于构建和发布Docker镜像,以便于和Kubernetes后台一起使用。

  1. # -r 仓库地址 -t 标记构建的镜像 build 构建命令 push 推送命令
  2. $ ./bin/docker-image-tool.sh -r <repo> -t my-tag build
  3. $ ./bin/docker-image-tool.sh -r <repo> -t my-tag push

3.2 Cluster 模式

以集群模式启动 Spark PI:

  1. $ bin/spark-submit \
  2. --master k8s://https://<k8s-apiserver-host>:<k8s-apiserver-port> \
  3. --deploy-mode cluster \
  4. --name spark-pi \
  5. --class org.apache.spark.examples.SparkPi \
  6. --conf spark.executor.instances=5 \
  7. --conf spark.kubernetes.container.image=<spark-image> \
  8. local:///path/to/examples.jar

通过在 spark-submit 命令行中指定 —master 参数或者在应用程序中配置 spark.master 参数来指定 Spark master 的格式:k8s://。前缀 k8s:// 表示在k8s集群上启动, api_server_url 是与API server服务通讯时的地址。如果未在URL地址中指定 http 协议,则默认使用 https 协议。比如:k8s://examplecom:443 表示 k8s://https://examplecom:443
在Kubernetes模式下,默认使用spark.app.name或spark-submit的—name参数指定的Spark应用程序名称来命名创建的Kubernetes资源,例如驱动程序和执行程序。 因此,应用程序名称必须由 小写字母数字字符- 组成。 并且必须以字母数字开头和结尾。
如果安装了 kubernetes 集群,可以执行 kubectl cluster-info 命令来发现 API server 服务的URL地址:

  1. $ kubectl cluster-info
  2. Kubernetes master is running at http://127.0.0.1:6443

在上面的示例中,通过指定 spark-submit 命令的—master 参数,可以将特定的Kubernetes集群与spark-submit一起使用。 此外,还可以使用身份验证代理,kubectl代理与Kubernetes API进行通信。
本地代理可以通过以下方式启动:

  1. $ kubectl proxy

如果本地代理在 localhost:8001 地址上运行,则可以将 --master k8s://http://127.0.0.1:8001 用作spark-submit的参数。 最后,请注意,在上面的示例中,我们使用 local:// 方案指定了具有特定URI的jar。 该URI是Docker映像中已经存在的示例jar的位置。

3.3 依赖管理

使用 —jars 或者 —files 引用远端的jar文件或者文本文件

3.4 加密管理

Kubernetes Secrets可用于为Spark应用程序提供凭据,以实现安全的访问服务。要将用户指定的秘钥挂载到驱动程序容器中,用户可以使用 spark.kubernetes.driver.secrets.[SecretName] = <安装路径> 形式的配置属性。同样的,可以使用配置 spark.kubernetes.executor.secrets.[SecretName] = <mount path> 挂载到执行器容器中。需要注意的是,驱动器和执行器的挂载路径需要在同一个命名空间下。
如下,将一个名为 spark-secret 的秘钥存放在 /etc/secrets 目录下,则在 spark-submit 命令中添加以下选项:

  1. --conf spark.kubernetes.driver.secrets.spark-secret=/etc/secrets
  2. --conf spark.kubernetes.executor.secrets.spark-secret=/etc/secrets

【注意】:如果使用了 init 容器的话,则执行器和驱动器的秘钥都会挂载到 init 容器目录下

3.5 内省机制和调试机制

以下是对运行中或者已完成的Spark应用程序,提供进度监测和解决方式的一些方法。

3.5.1 日志访问

可以使用Kubernetes API和kubectl CLI访问日志。当Spark应用程序运行时,可以使用以下方法从应用程序中流式输出日志:

  1. $ kubectl -n=<namespace> logs -f <driver-pod-name>

同样的,如果在集群中安装了 kubernetes仪表板,则可以通过他对日志进行访问。

3.5.2 访问Driver的UI页面

可以使用 kubectl port-forward 命令在本地访问与任何应用程序关联的UI。

  1. $ kubectl port-forward <driver-pod-name> 4040:4040

然后,就可以在 http://localhost:4040 上访问spark驱动程序的UI页面

3.5.3 调试机制

可能有以下几种异常。 如果Kubernetes API服务器拒绝来自spark-submit的请求,或者由于其他原因拒绝了连接,则提交逻辑应显示遇到的错误。 但是,如果在应用程序的运行过程中发生错误,则最好的调查方法是通过 Kubernetes CLI 命令行。

  1. 要想获得有关 Driver Pod 调度决策的基本信息,可以执行:

    1. $ kubectl describe pod <spark-driver-pod>
  2. 如果 Pod 遇到运行时异常,则可以执行以下方法进一步查看异常状态:

    1. $ kubectl logs <spark-driver-pod>

    Executor Pod 的状态信息查看同理。

    3.6 Kubernates 特性

    3.6.1 命名空间

  • Kubernetes 具有命名空间的概念。 命名空间是在多个用户之间(通过资源配额)划分群集资源的方法。 Kubernetes上的Spark可以使用命名空间来启动Spark应用程序。 可以通过 spark.kubernetes.namespace 配置来启用它。
  • Kubernetes允许使用ResourceQuota在单个名称空间上设置对资源,对象数量等的限制。 管理员可以结合使用命名空间和ResourceQuota,以便于在Spark应用程序运行时,对Kubernetes集群中的共享和资源分配进行控制。

    3.6.2 基于角色的权限控制

3.7 Client 模式

在 Spark 2.4 开始支持

3.8 未来的工作方向

Spark on Kubernetes上有几个功能目前正在apache-spark-on-k8s/spark的分支中进行孵化,有望在未来版本将其纳入spark-kubernetes体系。包括:

  • PySpark
  • R
  • 执行器动态资源管理
  • 本地文件依赖管理
  • Spark应用程序管理
  • 作业队列和资源管理

    4. Spark配置项

  • 详见文档