设为首页 收藏本站
查看: 1648|回复: 0

[经验分享] 基于Kubernetes的Spark集群部署实践

[复制链接]

尚未签到

发表于 2018-9-16 08:00:47 | 显示全部楼层 |阅读模式
  Spark是新一代分布式内存计算框架,Apache开源的顶级项目。相比于Hadoop Map-Reduce计算框架,Spark将中间计算结果保留在内存中,速度提升10~100倍;同时它还提供更丰富的算子,采用弹性分布式数据集(RDD)实现迭代计算,更好地适用于数据挖掘、机器学习算法,极大提升开发效率。
  Docker是轻量级虚拟化容器技术,具有轻便性、隔离性、一致性等特点,可以极大简化开发者的部署运维流程,降低服务器成本。
  Kubernetes是Google开源的容器集群管理系统,提供应用部署、维护、 扩展等功能,能够方便地管理大规模跨主机的容器应用。
  相比于在物理机上部署,在Kubernetes集群上部署Spark集群,具有以下优势:

  •   快速部署:安装1000台级别的Spark集群,在Kubernetes集群上只需设定worker副本数目replicas=1000,即可一键部署。
  •   快速升级:升级Spark版本,只需替换Spark镜像,一键升级。
  •   弹性伸缩:需要扩容、缩容时,自动修改worker副本数目replicas即可。
  •   高一致性:各个Kubernetes节点上运行的Spark环境一致、版本一致
  •   高可用性:如果Spark所在的某些node或pod死掉,Kubernetes会自动将计算任务,转移到其他node或创建新pod。
  •   强隔离性:通过设定资源配额等方式,可与WebService应用部署在同一集群,提升机器资源使用效率,从而降低服务器成本。
  接下来我们将介绍,如何使用 Docker和Kubernetes创建Spark集群(其中包含1个Spark-master和N个Spark-worker)。
  参考文档:https://github.com/kubernetes/kubernetes/tree/master/examples/spark
  首先需要准备以下工具:
  ● 安装并运行 kubernetes 集群
  ● 安装 kubectl 命令行工具
  一、构建Docker镜像
  1. 从源码build:
  下载:https://github.com/kubernetes/application-images/blob/master/spark
docker build -t index.caicloud.io/spark:1.5.2 .  
docker build -t index.caicloud.io/zeppelin:0.5.6 zeppelin/
  连接国外网络较慢,构建镜像的时间有些长,请耐心等待……
  2. 从镜像仓库pull:
  a)  才云科技的镜像仓库(index.caicloud.io)
docker login index.caicloud.io  
docker pull index.caicloud.io/spark:1.5.2
  
docker pull index.caicloud.io/zeppelin:0.5.6
  b) DockerHub的镜像仓库(index.docker.io)
docker login index.docker.io  
docker pull index.docker.io/caicloud/spark:1.5.2
  
docker pull index.docker.io/caicloud/zeppelin:0.5.6
  二、在Kubernetes上创建Spark集群
  首先下载创建Kubernetes应用所需的Yaml文件: https://github.com/caicloud/public/tree/master/spark
  第一步:创建命名空间namespace
  Kubernetes通过命名空间,将底层的物理资源划分成若干个逻辑的“分区”,而后续所有的应用、容器都是被部署在一个具体的命名空间里。每个命名空间可以设置独立的资源配额,保证不同命名空间中的应用不会相互抢占资源。此外,命名空间对命名域实现了隔离,因此两个不同命名空间里的应用可以起同样的名字。创建命名空间需要编写一个yaml文件:
# namespace/namespace-spark-cluster.yaml  
apiVersion: v1
  
kind: Namespace
  
metadata:
  
  name: "spark-cluster"
  
  labels:
  
    name: "spark-cluster"
创建Namespace:  
$ kubectl create -f namespace/namespace-spark-cluster.yaml
  

  
查看Namespace:
  
$ kubectl get ns
  
NAME          LABELS             STATUS
  
default                    Active
  
spark-cluster name=spark-cluster Active
  

  
使用Namespace: (${CLUSTER_NAME}和${USER_NAME}可在kubeconfig文件中查看)
  
$ kubectl config set-context spark --namespace=spark-cluster --cluster=${CLUSTER_NAME} --user=${USER_NAME}
  
$ kubectl config use-context spark
  第二步:启动master服务
  先创建Spark-master的ReplicationController,然后创建spark所提供的两个Service(spark-master-service,spark-webui)。让Spark-workers使用spark-master-service来连接Spark-master,并且通过spark-webui来查看集群和任务运行状态。
  1) 创建ReplicationController:
  Kubernetes追求高可用设计,通过Replication Controller来保证每个应用时时刻刻会有指定数量的副本在运行。例如我们通过编写一个Replication Controller来运行一个nginx应用,就可以在yaml中指定5个默认副本。Kubernetes会自动运行5个nginx副本,并在后期时时对每一个副本进行健康检查(可以支持自定义的检查策略)。当发现有副本不健康时,Kubernetes会通过自动重启、迁移等方法,保证nginx会时刻有5个健康的副本在运行。对于spark-master,目前我们指定其副本数为1 (replicas: 1);对于spark-worker,我们指定其副本数为N (replicas: N,N >= 1)。
  spark-master-controller.yaml可参考如下:
# replication-controller/spark-master-controller.yaml  
kind: ReplicationController
  
apiVersion: v1
  
metadata:
  
  name: spark-master-controller
  
spec:
  
  replicas: 1
  
  selector:
  
    component: spark-master
  
  template:
  
    metadata:
  
      labels:
  
        component: spark-master
  
    spec:
  
      containers:
  
        - name: spark-master
  
          image: index.caicloud.io/spark:1.5.2
  
          command: ["/start-master"]
  
          ports:
  
            - containerPort: 7077
  
            - containerPort: 8080
  
          resources:
  
            requests:
  
              cpu: 100m
创建Master-ReplicationController:  
$ kubectl create -f replication-controller/spark-master-controller.yaml
  
replicationcontroller "spark-master-controller" created
  2) 创建Master-Service:
  Kubernetes追求以服务为中心,并推荐为系统中的应用创建对应的Service。以nginx应用为例,当通过Replication Controller创建了多个nginx的实例(容器)后,这些不同的实例可能运行在不同的节点上,并且随着故障和自动修复,其IP可能会动态变化。为了保证其他应用可以稳定地访问到nginx服务,我们可以通过编写yaml文件为nginx创建一个Service,并指定该Service的名称(如nginx-service);此时,Kubernetes会自动在其内部一个DNS系统中(基于SkyDNS 和etcd实现)为其添加一个A Record, 名字就是 “nginx-service”。随后,其他的应用可以通过 nginx-service来自动寻址到nginx的一个实例(用户可以配置负载均衡策略)。
  spark-master-service.yaml可参考如下:
# service/spark-master-service.yaml  
kind: Service
  
apiVersion: v1
  
metadata:
  
  name: spark-master
  
spec:
  
  ports:
  
    - port: 7077
  
      targetPort: 7077
  
  selector:
  
    component: spark-master
创建Master-Service:  
$ kubectl create -f service/spark-master-service.yaml
  
service "spark-master"created
  3) 创建WebUI-Service:
  如上所述,Service会被映射到后端的实际容器应用上,而这个映射是通过Kubernetes的标签以及Service的标签选择器实现的。例如我们可以通过如下的spark-web-ui.yaml来创建一个WebUI的Service, 而这个Service会通过 “selector: component: spark-master”来把WebUI的实际业务映射到master节点上:
# service/spark-webui.yaml  
kind: Service
  
apiVersion: v1
  
metadata:
  
  name: spark-webui
  
  namespace: spark-cluster
  
spec:
  
  ports:
  
    - port: 8080
  
      targetPort: 8080
  
  selector:
  
    component: spark-master
创建spark-webui-service:  
$ kubectl create -f service/spark-webui.yaml
  
service "spark-webui" created
  完成创建ReplicationController(rc)、Service(svc)后,检查 Master 是否能运行和访问:
$ kubectl get rc  
NAME                      DESIRED   CURRENT   AGE
  
spark-master-controller   1         1         23h
  

  
$ kubectl get svc
  
NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
  
spark-master   10.254.106.29           7077/TCP   1d
  
spark-webui    10.254.66.138           8080/TCP   18h
  

  
$ kubectl get pods
  
NAME                            READY     STATUS    RESTARTS   AGE
  
spark-master-controller-b3gbf   1/1       Running   0          23h
  确认master正常运行后,再使用Kubernetes proxy连接Spark WebUI:
kubectl proxy --port=8001  然后通过http://localhost:8001/api/v1/proxy/namespaces/spark-cluster/services/spark-webui/查看spark的任务运行状态。
  第三步:启动 Spark workers
  Spark workers 启动时需要 Master service处于运行状态,我们可以通过修改replicas来设定worker数目(比如设定 replicas: 4,即可建立4个Spark Worker)。注意我们可以为每一个worker节点设置了CPU和内存的配额,保证Spark的worker应用不会过度抢占集群中其他应用的资源。
  spark-worker-controller.yaml可参考如下:
# replication-controller/spark-worker-controller.yaml  
kind: ReplicationController
  
apiVersion: v1
  
metadata:
  
  name: spark-worker-controller
  
spec:
  
  replicas: 4
  
  selector:
  
    component: spark-worker
  
  template:
  
    metadata:
  
      labels:
  
        component: spark-worker
  
    spec:
  
      containers:
  
        - name: spark-worker
  
          image: index.caicloud.io/spark:1.5.2
  
          command: ["/start-worker"]
  
          ports:
  
            - containerPort: 8081
  
          resources:
  
            requests:
  
              cpu: 100m
  创建spark-worker的ReplicationController:
$ kubectl create -f replication-controller/spark-worker-controller.yaml  
replicationcontroller"spark-worker-controller" created
  查看 workers是否正常运行
  1.     通过WebUI查看: worker就绪后应该出现在UI中。(这可能需要一些时间来拉取镜像并启动pods)

  2.   通过kubectl查询状态(可看到spark-worker都已经正常运行):
$ kubectl get pods  
NAME                            READY     STATUS              RESTARTS   AGE
  
spark-master-controller-b3gbf   1/1       Running             0          1d
  
spark-worker-controller-ill4z   1/1       Running             1          2h
  
spark-worker-controller-j29sc   1/1       Running             0          2h
  
spark-worker-controller-siue2   1/1       Running             0          2h
  
spark-worker-controller-zd5kb   1/1       Running             0          2h
  第四步:提交Spark任务
  两种方式:Spark-client或Zeppelin。
  通过Spark-client,可以利用spark-submit来提交复杂的Python脚本、Java/Scala的jar包代码;
  通过Zeppelin,可以直接在命令行或UI编写简单的spark代码。
  1.     通过Spark-client提交任务
$ kubectl get pods | grep workerNAME                            READY     STATUS    RESTARTS   AGE  
spark-worker-controller-1h0l7   1/1       Running   0          4h
  
spark-worker-controller-d43wa   1/1       Running   0          4h
  
spark-worker-controller-ka78h   1/1       Running   0          4h
  
spark-worker-controller-sucl7   1/1       Running   0          4h
$ kubectl exec spark-worker-controller-1h0l7 -it bash  
$ cd /opt/spark
# 提交python spark任务  
./bin/spark-submit \
  
    --executor-memory 4G \
  
    --master spark://spark-master:7077 \
  
    examples/src/main/python/wordcount.py \
  
    "hdfs://hadoop-namenode:9000/caicloud/spark/data"
# 提交scala spark任务  
./bin/spark-submit
  
    --executor-memory 4G
  
    --master spark://spark-master:7077
  
    --class io.caicloud.LinearRegression
  
    /nfs/caicloud/spark-mllib-1.0-SNAPSHOT.jar
  
    "hdfs://hadoop-namenode:9000/caicloud/spark/data"
  2.   通过Zeppelin提交任务
  使用Zeppelin提交时有两种方式:pod exec 和 zeppelin-UI。我们先创建zeppelin的ReplicationController:
$ kubectl create -f replication-controller/zeppelin-controller.yaml  
replicationcontroller "zeppelin-controller"created
查看zeppelin:  
$ kubectl get pods -l component=zeppelin
  
NAME                        READY     STATUS    RESTARTS   AGE
  
zeppelin-controller-5g25x   1/1       Running   0          5h
  a) 通过zeppelin exec pods方式提交
  $ kubectl exec zeppelin-controller-5g25x -it pyspark

  b) 通过zeppelin UI方式提交
  使用已创建的Zeppelin pod,设置WebUI的映射端口:
$ kubectl port-forward zeppelin-controller-5g25x 8080:8080  访问 http://localhost:8080/,并提交测试代码:

  使用Spark的问题
  ●  Spark的master与worker无法通信
  解决办法:查看Spark Master Service是否正常
  ●  Spark资源与调度问题
  a) worker数量不要超过kubernetes集群的节点数量(如果超过,spark性能会下降)
  b) executor-memory不要超过机单台器最大内存,executor-cores不要超过单台机器的CPU核数
  c) 如果遇到insufficient resources问题,检查是否有其他任务在运行并kill
  d) 同一个kubernetes节点上,可能会分配多个worker,导致性能下降(这时最好重新创建worker)
  e) 内存、磁盘IO、网络IO、CPU都可能成为Spark的性能瓶颈
  ●  任务运行时的问题
  SocketTimeoutException: Accept timeout —— spark版本为1.5.2时,试试将jdk版本由1.8降低至1.7
  使用Zeppelin的问题
  ●  Zeppelin pod很大,拉取镜像可能会消耗一段时间,取决于你的网络条件
  ● 第一次运行Zeppelin时, pipeline可能会花费很多时间(约一分钟),需要比较多的时间来初始化。
  ● kubectl port-forward可能不会长时间保持稳定状态。如果发现Zeppelin变成断开(disconnected),port-forward很可能出现故障,这时需要重启
  ● 从ZeppelinUI提交任务,运行时间不稳定(波动较大)
  为了测试Spark性能,我们需要使用大量数据,但kubernetes节点所在的机器磁盘空间有限(20G)。通过为每台机器挂载NFS/GlusterFS大网盘,解决大数据存储的问题。
  接下来我们将介绍,如何使用Spark从NFS中读取数据,以及其中遇到的问题。
  1. 首先为每个kubernetes节点安装nfs-client,挂载nfs网盘(假设NFS-server为10.57.*.33,数据存于/data1T5目录下)
$ sudo apt-get install nfs-common  
$ sudo mkdir -p /data1T5
  
$ sudo mount -t nfs 10.57.*.33:/data1T5 /data1T5
  2. 声明PersistentVolumes(pv)和PersistentVolumeClaims(pvc),使得Kubernetes能连接NFS数据网盘:
$ kubectl create -f nfs/nfs_pv.yaml  
$ kubectl create -f nfs/nfs_pvc.yaml
# nfs/nfs_pv.yaml  
apiVersion: v1
  
kind: PersistentVolume
  
metadata:
  
    name: spark-cluster
  
spec:
  
    capacity:
  
        storage: 1535Gi
  
    accessModes:
  
        - ReadWriteMany
  
    nfs:
  
        server: 10.57.*.33
  
        path: "/data1T5"
# nfs/nfs_pvc.yaml  
apiVersion: v1
  
kind: PersistentVolumeClaim
  
metadata:
  
  name: spark-cluster
  
spec:
  
  accessModes:
  
    - ReadWriteMany
  
  resources:
  
    requests:
  
      storage: 1535Gi
  3. 为Spark的ReplicationController增加volumeMounts和volumes两项,并重新create,使得Spark容器能访问NFS数据。
  修改spark-master-controller.yaml和spark-worker-controller.yaml,存为nfs/spark-master-controller.nfs.yaml 和 nfs/spark-worker-controller.nfs.yaml
$ kubectl delete rc spark-master-controller  
$ kubectl create -f nfs/spark-master-controller.nfs.yaml
  
$ kubectl delete rc spark-worker-controller
  
$ kubectl create -f nfs/spark-worker-controller.nfs.yaml
  4. 使用exec方式进入master/worker所在的pod,可以看到nfs挂载的/data1T5目录:
$ kubectl exec spark-worker-controller-1h0l7 -it bash  
root@spark-worker-controller-1h0l7:/# ls -al /data1T5/
  成功挂载后,即可在Spark程序中,使用sc.textFile()读取NFS数据。
  注意事项:
  a) 如果希望使用spark从nfs中读取数据,必须事先在kubernetes集群的所有节点上安装nfs-client
  b) 使用spark从多台nfs-client读取一台nfs-server数据时,遇到IO瓶颈,读取速率只有30MB~40MB/s



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-584324-1-1.html 上篇帖子: centos7 kubernetes安装手册 下篇帖子: centos7 安装kubernetes1.4(kubeadm版)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表