目录

弹性计算平台-Spark计算

概述

TenC Spark 是我司根据 Spark 以及 Kubernetes 还有 Spark Operator 的使用情况需改的版本,本文简要说明一下使用的问题,虽然跟原生的 Spark 有一定区别,版本也有一定的差异了,但是不影响读者对 Spark 运行在 Kubernetes 上的体感。

Spark支持的spark3是什么意思?

在使用 Spark 的时候,会发现版本可以选择 spark3,这里的意思是后台是通过 Spark on k8s Operator 来管理用户提交的 Spark 作业的,并且默认是提供是 v3.0.0-preview-rc1,由于 Spark 3.0 对 Spark on Kubernetes 的支持比之前的版本 Spark 2.3.0/2.3.1/2.3.2/2.3.3/2.3.4/2.4.1/2.4.2/2.4.3/2.4.4 都有较大幅度的提升,所以我们建议用户可以选择已经比较稳定的 v3.0.0-preview-rc1 来执行任务,下面是 Spark 3.0 在 on Kubernetes 上的一些提升。

  1. 支持非 shuffle service 的动态资源分配,具体内容可以参考 KM 文章 Spark on Kubernetes 的动态资源分配
  2. Executor Pod 退出后支持通过 spark.kubernetes.executor.deleteOnTermination=false 来保留。
  3. 支持自定义 Pod。

作业jar包和资源文件如何上传

在 TenC Spark 弹性计算平台上,作业 jar 包指用户编写的 Spark 代码。资源文件是指运行 Spark 作业需要的文件。

Driver 和 Executor 启动,需要 Driver 和 Executor 的容器可以获得用户提交的作业 Jar 包和其他资源文件。TenC Spark 以往是通过 文件服务器来让用户上传 Spark 程序下载这些文件的,不过在新发布的弹性计算平台,目前只支持用户上传文件到 S3 存储,然后由弹性计算平台将这些文件卷挂载到 Driver/Executor 上,Driver/Executor 会像读取本地文件的方式读取到这些文件,所以 jar 包路径只要写挂载的路径就可以,例如 /data/xx.jar,具体如下图所示。

/%E5%BC%B9%E6%80%A7%E8%AE%A1%E7%AE%97%E5%B9%B3%E5%8F%B0-spark%E8%AE%A1%E7%AE%97/img.png

TenC Spark通过intiContainer来挂载依赖

用户可以通过 init-container 将作业 jar 包和资源文件挂载到 Driver/Executor Pod,在指定作业 jar 包的时候填写本地文件系统,在读取资源文件的时候直接指定挂载的地址即可,其实现的基本原理如下图所示。

/%E5%BC%B9%E6%80%A7%E8%AE%A1%E7%AE%97%E5%B9%B3%E5%8F%B0-spark%E8%AE%A1%E7%AE%97/img_1.png
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
+--------------------------------------------+
|                                            |
|                                            |
|                                            |
|                                            |
|              Spark Driver Pod              |
|                                            |
|                                            |
|                                            |
|                                            |
|  +--------------------------------------+  |
|  |                                      |  |
|  |         S3 Volume1 Init Container    +--------------> Mount /data
|  |                                      |  |
|  +------------------+-------------------+  |
|                     |                      |
|  +------------------v-------------------+  |
|  |                                      |  |
|  |         S3 Volume2 Init Container    +--------------> Mount /data1
|  |                                      |  |
|  +------------------+-------------------+  |
|                     |                      |
|                .....v.....                 |
|                ...........                 |
|                .....+.....                 |
|                     |                      |
|  +------------------v-------------------+  |
|  |                                      |  |
|  |         Spark Driver Container       |  |
|  |                                      |  |
|  +--------------------------------------+  |
|                                            |
+--------------------------------------------+

TenC Spark支持自定义Pod吗

TODO 需要在 spark-submit 的进程可以访问到的地方。

解答: 可以。

因为 Pod Template 属于 Master 分支上的特性,所以如果需要使用,有两种方案。

1. 用户可以请使用 TenC 默认的镜像,作为自定义镜像的基础镜像,里面已经打包了 Master 分支的 Spark 依赖包,然后将需要的 Pod Template 放到镜像文件夹里,通过下面的配置参数来指定使用的 Pod Template 的文件地址。

1
2
3
4
spark.kubernetes.driver.podTemplateFile=/path/to/driver-pod-template.yaml
spark.kubernetes.driver.podTemplateContainerName=spark-driver
spark.kubernetes.executor.podTemplateFile=/path/to/executor-pod-template.yaml
spark.kubernetes.executor.podTemplateContainerName=spark-executor

2. 使用 S3 上传用户的 Pod Template 并在上述的配置中指定 Pod Template 文件的地址

TenC Spark的示例程序哪里可以找到

TenC Spark 的示例程序是管理员预先配置好的,并且经过多次测试,主要是 Spark 官方的多个 Example 程序。用户只有只读和执行权限,为了了解 Spark 程序如何在 TenC 弹性计算运行起来,用户可以随意执行并且观察。

关于 Spark 官方的 Example 程序,可以在官方网址找到。

Spark任务出错了如何排除

Spark 任务出错,大概可以分为两个类型,一是提交任务出错,也就是 spark-submit,二是任务运行出错。

对于提交出错,一般会在前端页面中显示,如下图,出错原因是以为 jar 包路径有问题,解决方法就是确认 jar 是否在 S3 目录中。

/%E5%BC%B9%E6%80%A7%E8%AE%A1%E7%AE%97%E5%B9%B3%E5%8F%B0-spark%E8%AE%A1%E7%AE%97/img_2.png

对于第二种情况,任务过程中出错,则可以通过 Pod 列表中,找到出错的 Pod,并且点击日志查看即可(注意筛选合适的 Pod 等条件),操作可参考下面的示例。

Spark任务完整的提交过程是怎样的?

具体请查看下面的视频。

TenC提供Spark的默认镜像

TenC Spark 提供如下镜像,tag 中 TenC 表示是由计算资源组构建的镜像,2.x.x 表示是基于 Apache Spark 社区的 2.x.x 版本。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
hub.oa.com/public/spark:tenc-2.4.4
hub.oa.com/public/spark:tenc-2.4.3
hub.oa.com/public/spark:tenc-2.4.2
hub.oa.com/public/spark:tenc-2.4.1
hub.oa.com/public/spark:tenc-2.4.0
hub.oa.com/public/spark:tenc-2.3.4
hub.oa.com/public/spark:tenc-2.3.3
hub.oa.com/public/spark:tenc-2.3.2
hub.oa.com/public/spark:tenc-2.3.1
hub.oa.com/public/spark:tenc-2.3.0

如果用户需要自定义镜像并且同时使用 S3 挂载文件,那需要使用到上述镜像中的 jar 包(需要匹配基础镜像的 Spark 版本)。

1
spark-kubernetes_2.11-2.x.x.jar

用户可以运行自己构建的镜像吗

可以。

如果用户需要自行构建 Spark 镜像,需要注意,只支持 Spark 2.3 以上,所以切勿使用 Spark 2.2 的自定义镜像。如果需要使用 Spark 2.2,请按下面例子进行配置,将版本设置成 spark2.2

如果需要使用其他jar包应该如何配置?

有两种方法可以实现。

  1. 通过 S3 上传文件到目录 /data/xx.jar,然后根据 Driver/Executor 指定 spark.driver.extraClassPath=/data/xx.jar
  2. 自定义镜像,将用户的 jar 包放入 /opt/spark/jars 或者其他 CLASSPATH 目录。

关于Spark Operator

Spark Operator 依赖 Spark 的镜像,所以如果 Spark 镜像有调整,需要注意是否需要更新到 Spark Operator。

因为 spark-submit 是在 Spark Operator 的 Pod 里运行的,所以需要注意 Spark 镜像里的文件,如果有变化,就一定要更新 Spark Operator 的镜像,以最新的 Spark 镜像作为 base 镜像。

1
2
3
4
# 以最新的 Spark 镜像作为 base 镜像
docker build --build-arg SPARK_IMAGE=hub.oa.com/runzhliu/spark:v3.0.0-0.0.1 -t hub.oa.com/runzhliu/spark-operator:0.0.6 .
# push 镜像
docker push hub.oa.com/runzhliu/spark-operator:0.0.6

Spark Operator 的 Submit Event。

/%E5%BC%B9%E6%80%A7%E8%AE%A1%E7%AE%97%E5%B9%B3%E5%8F%B0-spark%E8%AE%A1%E7%AE%97/img_3.png

首先需要理解 Spark Operator 的基础镜像是 Spark 的镜像,主要原因是 Spark Operator 会在容器中调用 spark-submit 命令来执行 Spark 任务。所以所有的 Spark Jars 等依赖在部署了 Spark Operator 的时候就已经确定了。

那么在 Spark on Kubernetes 的架构里,spark-submit 具体做了什么呢?其实在 spark-submit 主要是根据用户提交的脚本,按照各种 conf,来配置了 Driver Pod,包括 Pod 需要挂载的 Volume 等等,最后通过 k8s 的 Java Client,向 Kubernetes 的 ApiServer 发送构建 Driver Pod 的请求,然后后面的事情,spark-submit 一般就不管了,然后如何装配 Executor Pod,就由 Driver 来控制了。

Spark Operator的版本

Spark Operator 也已经连续发布了多个版本了,而其中使用到的一些 API 也跟 Kubernetes 集群的版本有关,也就是说,不是所有版本的 Spark Operator 都适合所有的 Kubernetes 集群。以我们使用的其中一个 Kubernetes 集群为例。

1
2
3
# kubectl version
Client Version: version.Info{Major:"1", Minor:"8+", GitVersion:"v1.8.15-27+31187439c9b31f", GitCommit:"31187439c9b31f99c93c514462e4157497f6d299", GitTreeState:"clean", BuildDate:"2018-09-17T08:09:01Z", GoVersion:"go1.10.3", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"8+", GitVersion:"v1.8.15-27+31187439c9b31f", GitCommit:"31187439c9b31f99c93c514462e4157497f6d299", GitTreeState:"clean", BuildDate:"2018-09-17T08:09:01Z", GoVersion:"go1.10.3", Compiler:"gc", Platform:"linux/amd64"}

显然这个版本跟最新的 Spark Operator 是不完全兼容的,详细也可以看最新的 README

因此,为了满足部署 Spark Operator 在 1.8 的 Kubernetes 集群中,我们需要找到匹配版本的 Spark Operator,否则会有一些不可预见的问题。

Spark Operator Tag Kubernetes Version Other Infos
v1alpha1-0.1-2.3.0 >= 1.8
v1alpha1-0.2-2.3.x >= 1.8
v1alpha1-0.3-2.3.x >=1.8 >= 1.9 of Kubernetes if using the mutating admission webhook for Spark pod customization
v1alpha1-0.4-2.3.x >=1.8 >= 1.9 of Kubernetes if using the mutating admission webhook for Spark pod customization
v1alpha1-0.5-2.4.0 >=1.8 >= 1.9 of Kubernetes if using the mutating admission webhook for Spark pod customization
v1alpha1-0.6-2.4.0 >=1.8 >= 1.9 of Kubernetes if using the mutating admission webhook for Spark pod customization
v1beta1-0.7-2.4.0 >=1.8 >= 1.9 of Kubernetes if using the mutating admission webhook for Spark pod customization
v1beta1-0.7.1-2.4.0 >=1.8 >= 1.9 of Kubernetes if using the mutating admission webhook for Spark pod customization
v1beta1-0.8.0-2.4.0 >=1.8 >= 1.9 of Kubernetes if using the mutating admission webhook for Spark pod customization
v1beta1-0.8.1-2.4.0 >=1.8 >= 1.9 of Kubernetes if using the mutating admission webhook for Spark pod customization
v1beta1-0.8.2-2.4.0 >=1.8 >= 1.9 of Kubernetes if using the mutating admission webhook for Spark pod customization
v1beta1-0.9.0-2.4.0 >=1.8 >= 1.9 of Kubernetes if using the mutating admission webhook for Spark pod customization
v1beta2-1.0.0-2.4.4 >=1.8 >= 1.9 of Kubernetes if using the mutating admission webhook for Spark pod customization
v1beta2-1.0.1-2.4.4 >=1.13 subresource support for CustomResourceDefinitions

Spark Operator Chart

Spark Operator 的 Helm Chart 主要是 Lightbend 公司的团队在维护,下面目前发布的版本。因为 Helm Chart 中默认用的是 Lightbend 提供的 Spark 镜像,所以如果需要定制 Spark 的话,那么最好是自行编译。

1
2
# helm search 一下
helm search -l incubator/sparkoperator
NAME CHART VERSION APP VERSION
incubator/sparkoperator 0.4.2 v1beta2-1.0.1-2.4.4
incubator/sparkoperator 0.4.1 v1beta2-1.0.1-2.4.4
incubator/sparkoperator 0.4.0 v1beta2-1.0.0-2.4.4
incubator/sparkoperator 0.3.1 v2.4.0-v1beta1-0.9.0
incubator/sparkoperator 0.3.0 v2.4.0-v1beta1-0.9.0
incubator/sparkoperator 0.2.8 v2.4.0-v1beta1-0.9.0
incubator/sparkoperator 0.2.7 v2.4.0-v1beta1-0.9.0
incubator/sparkoperator 0.2.6 v2.4.0-v1beta1-0.9.0
incubator/sparkoperator 0.2.5 v2.4.0-v1beta1-0.9.0
incubator/sparkoperator 0.2.4 v2.4.0-v1beta1-0.8.2
incubator/sparkoperator 0.2.3 v2.4.0-v1beta1-0.8.2
incubator/sparkoperator 0.2.2 v2.4.0-v1beta1-0.8.2
incubator/sparkoperator 0.2.1 v2.4.0-v1beta1-0.8.2
incubator/sparkoperator 0.2.0 v1beta1-0.8.1-2.4.0
incubator/sparkoperator 0.1.13 v1beta1-0.8.1-2.4.0
incubator/sparkoperator 0.1.12 v1beta1-0.8.0-2.4.0
incubator/sparkoperator 0.1.11 v1beta1-0.7-2.4.0
incubator/sparkoperator 0.1.10 v1beta1-0.7-2.4.0
incubator/sparkoperator 0.1.9 v1beta1-0.7-2.4.0
incubator/sparkoperator 0.1.8 v1beta1-0.7-2.4.0
incubator/sparkoperator 0.1.7 v1beta1-0.7-2.4.0
incubator/sparkoperator 0.1.6 v1alpha1-0.5-2.4.0
incubator/sparkoperator 0.1.5 v1alpha1-0.5-2.4.0
incubator/sparkoperator 0.1.4 v1alpha1-0.5-2.4.0
incubator/sparkoperator 0.1.3 v1alpha1-0.4-2.3.x
incubator/sparkoperator 0.1.2 v1alpha1-0.4-2.3.x
incubator/sparkoperator 0.1.1 latest
incubator/sparkoperator 0.1.0 latest

构建部署Spark Operator

因为 Spark 在内部的计算平台上运行,我们对 Spark 进行了一些定制,主要是针对 spark-submit 过程的变化,所以我们需要打一个 K8S 1.8 集群可用的 Spark Operator 的镜像,基础镜像当然是内部版本 Spark 的镜像,假设为 spark:v3.0.0-0.0.1

然后在 Spark Operator 的项目目录下执行下面的命令,可以得到 Spark Operator 可执行镜像文件 spark-operator:alpha-0.0.1

1
docker build --build-arg SPARK_IMAGE=spark:v3.0.0-0.0.1 -t spark-operator:alpha-0.0.1 .

部署的话,仍然可以通过 helm install 来部署,但是需要仔细阅读可选的选项,具体可以看 Spark Operator Chart 的 README

1
helm install incubator/sparkoperator --name sparkoperator --set ingressUrlFormat=localhost --set operatorImageName=spark-operator --set operatorVersion=alpha-0.0.1

然后自定义的 Spark Operator 部署完毕了。

目前平台可供部署的 Spark Operator 镜像如下。

1
2
hub.oa.com/runzhliu/spark-operator:tenc-3.0.0-v1beta2-1.0.0-2.4.4
hub.oa.com/runzhliu/spark-operator:tenc-2.4.4-v1beta2-1.0.0-2.4.4

这个问题显然就是 task 重名了。

1
2
3
4
5
6
7
8
spark-e05675647a4e8a697p8sp-driver   1/1       Terminating   0         1m
spark-e05675647a4e8a697p8sp-f4ca506e0d4c9a6b-exec-1   1/1       Terminating   0         54s
spark-e05675647a4e8a69rkz4k-driver   1/1       Terminating   0         1m
spark-e05675647a4e8a69rkz4k-e953e66e0d4ca9fd-exec-1   1/1       Terminating   0         46s
spark-e05675647a4e8a697p8sp-f4ca506e0d4c9a6b-exec-1   0/1       Terminating   0         1m
spark-e05675647a4e8a69rkz4k-e953e66e0d4ca9fd-exec-1   0/1       Terminating   0         58s
spark-e05675647a4e8a697p8sp-driver   0/1       Terminating   0         1m
spark-e05675647a4e8a69rkz4k-driver   0/1       Terminating   0         1m
警告
本文最后更新于 2017年2月1日,文中内容可能已过时,请谨慎参考。