⼀一、三种⽅方式:
1. 原⽣生kubernetes的调度⽅方式。官⽅方⽂文档《Running Spark on Kubernetes》;
2. 是由⾕谷歌发起维护的管理理Spark应⽤用程序⽣生命周期的Kubernetes插件,叫做SparkOperator。官⽅方⽂文档《spark-on-k8s-operator》;
3. 就是standalone的⽅方式,就是在Kubernetes集群⾥里里⾯面直接跑⼀一套Spark的集群。这个没有官⽅方⽂文档参考;
⼆二、分析:
第⼀一种:
1. 该项⽬目本来是由第三⽅方在⽀支持直到⼀一年年前被DEPRECATED,项⽬目地址《Apache Spark enhanced with native Kubernetes scheduler
back-end》。现在该项⽬目的后续⽀支持已经交由Spark官⽅方在集成,但是各项在被DEPRECATED的那个项⽬目中的功能还没完全集成官⽅方的Spark
应⽤用中,⽐比如:本地⽂文件依赖管理理的⽀支持等。
2. 该⽅方式的调度就没有master、worker的概念了了,通过spark submit提交应⽤用程序到kubernetes直接启动的是driver和excutor,具体启
动instance的数量量和要使⽤用的资源根据配置⽽而定。并且在也不不会在kubernetes集群中⼀一直运⾏行行着spark的进程,⽽而是每次提交应⽤用的时候才
启动driver和excutor,当计算应⽤用结束后excutor所在的pod⽴立⻢马被回收,⽽而driver会被留留下供查看⽇日志等并等待kubernetes⾃自动回收策
略略回收或者⼈人⼯工⼲干预删除pod。
3. 提交应⽤用和原⽣生spark提交唯⼀一参数区别就是master不不⼀一样,实例例如下:
bin/spark-submit \
--master k8s://https://10.0.10.197:6443 \
--deploy-mode cluster \
--name spark-SparkPi \
--class org.apache.spark.examples.SparkPi \
--conf spark.executor.instances=1 \
--conf spark.kubernetes.container.image=kubespark/spark:2.3.2 \
--conf spark.kubernetes.namespace=default \
--conf spark.kubernetes.authenticate.driver.serviceAccountName=spark \
--conf spark.kubernetes.submission.waitAppCompletion=false \
local:///opt/spark/examples/jars/spark-examples_2.11-2.3.2.java
4. 这⾥里里我们看到了了,提交Spark的应⽤用程序则需要我们在任何提交Spark应⽤用的机器器上要有⼀一个编译好的Spark⼆二进制包(不不需要运⾏行行,只是借助
它的spark-submit命令能⼒力力),并需要配置java环境供spark-submit运⾏行行。
5. 该⽅方式需要编译Spark来⽀支持kubernetes,当然官⽹网打包编译好的⽂文件是已经⽀支持了了的,如果⾃自⼰己编译就需要带上-Pkubernetes参数,可参
考如下命令:
./build/mvn -Pkubernetes -Phadoop-2.7 -Dhadoop.version=2.7.3 -Phive -Phive-thriftserver -DskipTests clean
packag
6. 当然该⽅方式也是需要我们打包⼀一个⽀支持Kubernetes的docker镜像的,并且需要将镜像分发到所有的Kubernetes机器器节点或者上传到我们的
私有镜像仓库中供kubernetes使⽤用,打包镜像命令官⽹网也提供了了,参考如下命令:
./bin/docker-image-tool.sh -r kubespark -t 2.3.2 buil
8. 应⽤用⽇日志查看⽅方式不不再出现Spark Master UI⻚页⾯面,也没有History Server存储运⾏行行后的⽇日志,⽽而且Driver UI只能在Driver运⾏行行期间才
能查看,⼀一旦Driver⽣生命周期结束也就不不能查看了了。但是我们可以通过Kubernetes来查看运⾏行行情况,⽐比如通过kubectl logs driver-
pod-name或者通过Kubernetes Dashboard从界⾯面去查看。
9. 资源的分配直接交由kubernetes管理理。
第⼆二种:
1. 该⽅方式需要在Kubernetes集群⾥里里⾯面部署SparkOperator以便便⽀支持直接通过部署常规应⽤用⼀一样来部署Spark应⽤用,这样我们就可以直接通过编
写yaml⽂文件来运⾏行行Spark应⽤用,也不不需要应⽤用程序提交客户机上要有⽀支持spark-submit的⽀支持,只需要⼀一个yaml⽂文件。运⾏行行⽂文件实例例:
apiVersion: "sparkoperator.k8s.io/v1beta1"
kind: SparkApplication
metadata:
name: spark-pi
namespace: default
spec:
type: Scala
mode: cluster
image: "kubespark/spark:2.4.2"
imagePullPolicy: IfNotPresent
mainClass: org.apache.spark.examples.SparkPi
mainApplicationFile: "http://10.0.10.197:30010/spark/spark-examples_2.12-2.4.2.jar"
sparkVersion: "2.4.2"
restartPolicy:
type: Never
driver:
cores: 0.1
coreLimit: "200m"
memory: "512m"
labels:
version: 2.4.2
serviceAccount: spark
executor:
cores: 1
instances: 1
memory: "512m"
labels:
version: 2.4.2
2. 但是该项⽬目还处于beta阶段还在不不断的完善。
3. 该⽅方式除了了需要再Kubernetes集群⾥里里⾯面部署SparkOperator以外,同样需要第⼀一种⽅方式中的⽀支持Kubernetes的Spark编译打包后的镜像,
打包⽅方式同第⼀一种⽅方式。
4. 该⽅方式和第⼀一种⼀一样,没有Spark进程实现运⾏行行着等待应⽤用提交,机制和第⼀一种⼀一样只运⾏行行driver和excutor,也没有master和worker的概
念。
5. 资源的使⽤用也是直接交由kubernetes管理理。
第三种:
1. 这种⽅方式和宿主机直接运⾏行行Spark集群⼏几乎没什什么⼤大得区别,唯⼀一⽅方便便的就是得⼒力力于Kubernetes的能⼒力力Worker可以很⽅方便便任性的伸缩。
2. 这种⽅方式就是在Kubernetes集群中部署⼀一套Spark的Standalone的集群,并且是⼀一直运⾏行行着Master和N份Worker等待应⽤用的提交。启动
yaml配置如下:
apiVersion: v1
kind: Namespace
metadata:
name: spark-cluster
labels:
name: spark-cluster
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: spark-master
namespace: spark-cluster
labels:
name: spark-master
spec:
replicas: 1
template:
metadata:
labels:
name: spark-master
spec:
hostname: spark-master
containers:
- name: spark-master
image: spark:2.3.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 7077
- containerPort: 8080
- containerPort: 6066
command:
- "/bin/bash"
- "-c"
args :
- './start-master.sh ; tail -f /dev/null'
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: spark-worker
namespace: spark-cluster
labels:
name: spark-worker
spec:
replicas: 3
template:
metadata:
labels:
name: spark-worker
spec:
containers:
- name: spark-worker
image: spark:2.3.2
imagePullPolicy : IfNotPresent
ports:
- containerPort: 8081
command:
- "/bin/bash"
- "-c"
args :
- './start-worker.sh ; tail -f /dev/null'
---
kind: ReplicationController
apiVersion: v1
metadata:
name: spark-ui-proxy
namespace: spark-cluster
spec:
replicas: 1
selector:
name: spark-ui-proxy
template:
metadata:
labels:
name: spark-ui-proxy
spec:
hostname: spark-ui-proxy
containers:
- name: spark-ui-proxy
image: spark-ui-proxy:1.0
imagePullPolicy : IfNotPresent
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
args:
- spark-master:8080
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 120
timeoutSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: spark-master
namespace: spark-cluster
labels:
name: spark-master
spec:
clusterIP: None
ports:
- name: webui
port: 8080
targetPort: 8080
- name: spark
port: 7077
targetPort: 7077
- name: rest
port: 6066
targetPort: 6066
selector:
name: spark-master
---
kind: Service
apiVersion: v1
metadata:
name: spark-worker
namespace: spark-cluster
spec:
ports:
- name: workerui
port: 8081
targetPort: 8081
selector:
name: spark-worker
---
kind: Service
apiVersion: v1
metadata:
name: spark-ui-proxy
namespace: spark-cluster
spec:
ports:
- port: 80
targetPort: 80
selector:
name: spark-ui-proxy
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: spark-ingress
namespace: spark-cluster
spec:
rules:
- http:
paths:
- path: /sparkui
backend:
serviceName: spark-ui-proxy
servicePort: 80
- path: /proxy
backend:
serviceName: spark-ui-proxy
servicePort: 80
- path: /app
backend:
serviceName: spark-ui-proxy
servicePort: 80
3. 该种⽅方式唯⼀一由Kubernetes接管的资源就是Master和Work可⽤用资源,就是启动Master和Worker的时候给它们配置的资源,但是我们提交的
应⽤用程序需要的资源仍然是由Master来管控的,当然Master能⽤用多少⼜又是Kubernetes来管控的。
4. 该种运⾏行行⽅方式在提交应⽤用程序在deploy-mode使⽤用cluster的时候由于Worker运⾏行行Excutor的时候使⽤用的计算机的hostname作为Driver
URL使⽤用,spark集群所在计算机的hostname需要事先配置好,但是搬到Kubernetes上后由于Worker节点是通过Kubernetes的pod启动的
多副本Deployment,hostname是随机⽣生成不不可预知不不能提前配置导致exceutor不不能启动。经多番折腾通过Kubernetes暂不不能解决该问
题,最后只能通过修改spark源码通过ip⽅方式可以解决。但是影响范围需要张奇确认(论对spark源码熟悉度⾮非张奇莫属了了)。
5. 提交应⽤用⽅方式也是通过spark-submit⽅方式,和宿主机部署集群提交⽅方式⼀一样。实例例:
./bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://spark-master:7077 \
--deploy-mode client \
--executor-memory 1G \
--total-executor-cores 2 \
/spark/examples/jars/spark-examples_2.11-2.3.2.jar \
1000
./bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://spark-master:6066 \
--deploy-mode cluster \
--executor-memory 1G \
--total-executor-cores 2 \
/spark/examples/jars/spark-examples_2.11-2.3.2.jar \
1000
6. 此⽅方式我们也需要将spark打包成docker镜像来运⾏行行,打包⽅方式和上两种⽅方式对kubernetes原始资源⽀支持需要的镜像包有所不不同,就是将宿
主机运⾏行行⽅方式的命令使⽤用在镜像⾥里里⾯面⽽而已。
7. ⽇日志的查看和宿主机运⾏行行也没缺别,不不管是Master UI还是History Server。
三、对⽐比:
1. 第⼀一种⽅方式有官⽅方⽀支持,应该会越来越好⽤用,且⽀支持原⽣生的Kubernetes资源调度;
2. 第⼆二种⽅方式也是⼤大⼚厂⽀支持,基于第⼀一种⽅方式和Kubernetes的深度集成(建议采⽤用这种⽅方式);
3. 第三种standalone⽅方式,只是把Spark集群部署搬到了了Kubernetes不不⽀支持Kubernetes原⽣生资源调度,只是和只是集群交由Kubernetes管
控⽽而已;