如何在 Kubernetes 集群中用 Apache Spark 进行分布式计算

公众号关注 「奇妙的 Linux 世界」

设为「星标」,每天带你玩转 Linux !

dbe81ef50d79c87082498bacca114e17.png

概 述

Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎。Spark是UC Berkeley AMP lab (加州大学伯克利分校的AMP实验室)所开源的类Hadoop MapReduce的通用并行框架,Spark,拥有Hadoop MapReduce所具有的优点;但不同于MapReduce的是——Job中间输出结果可以保存在内存中,从而不再需要读写HDFS,因此Spark能更好地适用于数据挖掘与机器学习等需要迭代的MapReduce的算法。

e969ef7976b8acc3d0dba0703e56f96d.png

▍开始 Spark on K8s 运行原理

e1ba7ee63ea83a1b839b0133c2ae0c37.png

spark-submit 可以直接用于向Kubernetes集群提交spark应用程序。提交机制的工作原理如下:

  • Spark创建一个Spark driver 在Kubernetes pod 运行。

  • driver 程序创建也在Kubernetes pods中运行的执行器,并连接到它们,然后执行应用程序代码。

  • 当应用程序完成时,执行程序pod将终止并被清理,但驱动程序pod会保存日志并在Kubernetes API中保持“已完成”状态,直到最终进行垃圾收集或手动清理。

▍Spark 运行模式

  • Client :客户端进程,负责提交作业到Master。

  • Master :Standalone模式中主控节点,负责接收Client提交的作业,管理Worker,并命令Worker启动Driver和Executor。

  • Worker :Standalone模式中slave节点上的守护进程,负责管理本节点的资源,定期向Master汇报心跳,接收Master的命令,启动Driver和Executor。

  • Driver :一个Spark作业运行时包括一个Driver进程,也是作业的主进程,负责作业的解析、生成Stage并调度Task到Executor上。包括 DAGScheduler , TaskScheduler 。

1)cluster 模式

ee9268b20f91a17e9ba83e3014740455.png

  • Driver程序在某个worker节点,但是这个节点由Master指定;

  • Driver程序占据Worker的资源;

  • cluster mode下Master可以使用–supervise对Driver进行监控,如果Driver挂了可以自动重启;

  • cluster mode下Master节点和Worker节点一般不在同一局域网,因此就无法将Jar包分发到各个Worker,所以cluster mode要求必须提前把Jar包放到各个Worker节点对应的目录下面。

2)client 模式

78722cb3ca6716ba96e70c8b1ddbbbac.png

  • Driver进程就是开始执行你Spark程序的那个Main函数,它可以在任何节点(可以是spark集群内的节点,Master节点或Worker节点;也可以是有spark环境但不是spark集群内的某台机器);Worker就是Slave节点,Executor进程必然在Worker节点上,用来进行实际的计算;

  • client mode下Driver进程不运行在Worker节点上,所以相对于参与实际计算的Worker节点而言,Driver就相当于是一个第三方的“client”;

  • 正由于Driver进程不在Worker节点上,所以不会消耗Worker节点上的资源;

  • client mode下Master和Worker节点必须处于同一片局域网内,因为Drive要和Executor通信,例如Driver需要将Jar包通过Netty HTTP分发到Executor,Driver要给Executor分配任务等;

  • client mode下没有监督重启机制,Driver进程如果挂了,需要额外的程序重启。

▍开始Spark on K8s 编排

1)下载Spark包

wget https://dlcdn.apache.org/spark/spark-3.3.0/spark-3.3.0-bin-hadoop3.tgz
tar -xf spark-3.3.0-bin-hadoop3.tgz
export SPARK_HOME=/opt/bigdata/servers/spark/spark-3.3.0-bin-hadoop3

2)构建镜像

Spark(从2.3版开始)附带了一个Dockerfile,可以在kubernetes/dockerfiles/目录中找到它。

2443fc59897141c045945fcee3efdc1f.png

Spark还附带一个构建和push镜像的脚本 bin/docker-image-tool.sh。构建镜像命令如下:

cd $SPARK_HOME
# 构建镜像
# -p ./kubernetes/dockerfiles/spark/Dockerfile,-p 指定Dockerfile
$SPARK_HOME/bin/docker-image-tool.sh -r myharbor.com/bigdata -t 3.3.0-hadoop3 build  build
# push
$SPARK_HOME/bin/docker-image-tool.sh -r myharbor.com/bigdata -t 3.3.0-hadoop3 push

3)配置 spark 用户权限

kubectl create ns spark
kubectl create serviceaccount spark -n spark
kubectl create clusterrolebinding spark-role --clusterrole=edit --serviceaccount=spark:spark
##在spark-submit中添加
--conf spark.kubernetes.authenticate.driver.serviceAccountName=spark

4)提交 Spark 任务(cluster 模式)

# 查看k8s apiserverl:kubectl cluster-info
cd $SPARK_HOME
./bin/spark-submit \
    --master k8s://https://192.168.182.110:6443 \
    --deploy-mode cluster \
    --name spark-pi \
    --class org.apache.spark.examples.SparkPi \
    --conf spark.executor.instances=5 \
    --conf spark.kubernetes.namespace=spark \
    --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark \
    --conf spark.kubernetes.container.image=myharbor.com/bigdata/spark:3.3.0-hadoop3 \
    local:///opt/spark/examples/jars/spark-examples_2.12-3.3.0.jar

c330bdce09ab84836e46f111b5a63a85.png

【注意】这里的 local:///opt/spark/examples/jars/spark-examples_2.12-3.3.0.jar 指的是 容器的文件系统路径,不是执行 spark-submit 的机器的文件系统路径,如果不使用 local 的话,也可以用 HTTPHDFS 等系统,没指定的话默认是 local 模式

5)配置spark历史服务器

存储目录需要提前创建

kubectl exec -it hadoop-hadoop-hdfs-dn-0 -n hadoop -- bash
hdfs dfs -mkdir  hdfs://hadoop-hadoop-hdfs-nn.hadoop:9000/sparkhistory
hdfs dfs -chmod 777  hdfs://hadoop-hadoop-hdfs-nn.hadoop:9000/sparkhistory

spark-history.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: spark-history-server
spec:
  selector:
    matchLabels:
      run: spark-history-server
  replicas: 1
  template:
    metadata:
      labels:
        run: spark-history-server
    spec:
      containers:
        - image: myharbor.com/bigdata/spark:3.3.0-hadoop3
          name: spark-history-server
          args: ["/opt/spark/bin/spark-class", "org.apache.spark.deploy.history.HistoryServer"]
          ports:
            - containerPort: 18080
              name: http
          env:
          - name: SPARK_HISTORY_OPTS
            value: "-Dspark.history.fs.logDirectory=hdfs://hadoop-hadoop-hdfs-nn.hadoop:9000/sparkhistory"


---


apiVersion: v1
kind: Service
metadata:
  name: spark-hs-svc
spec:
  ports:
  - port: 18080
    protocol: TCP
    targetPort: 18080
    nodePort: 31180
  selector:
    run: spark-history-server
  type: NodePort
status:
  loadBalancer: {}

执行

kubectl apply -f spark-history.yaml -n spark

0e58e28397746ead4d12da662973720c.png

web:http://192.168.182.110:31180

a7995a3d96863fe854b8ecf4b6784d38.png

再提交任务

# 增加配置项:
# --conf spark.eventLog.enabled=true \
# --conf spark.eventLog.dir=hdfs://hadoop-hadoop-hdfs-nn.hadoop:9000/sparkhistory \
cd $SPARK_HOME
./bin/spark-submit \
    --master k8s://https://192.168.182.110:6443 \
    --deploy-mode cluster \
    --name spark-pi \
    --class org.apache.spark.examples.SparkPi \
    --conf spark.executor.instances=5 \
    --conf spark.kubernetes.namespace=spark \
    --conf spark.eventLog.enabled=true \
    --conf spark.eventLog.dir=hdfs://hadoop-hadoop-hdfs-nn.hadoop:9000/sparkhistory \
    --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark \
    --conf spark.kubernetes.container.image=myharbor.com/bigdata/spark:3.3.0-hadoop3 \
    local:///opt/spark/examples/jars/spark-examples_2.12-3.3.0.jar


### jar放在hdfs
kubectl cp examples/jars/spark-examples_2.12-3.3.0.jar hadoop/hadoop-hadoop-hdfs-dn-0:/tmp/ -n hadoop
kubectl exec -it hadoop-hadoop-hdfs-dn-0 -n hadoop -- bash
hdfs dfs -put /tmp/spark-examples_2.12-3.3.0.jar hdfs://hadoop-hadoop-hdfs-nn.hadoop:9000/sparkhistory/
cd $SPARK_HOME
./bin/spark-submit \
    --master k8s://https://192.168.182.110:6443 \
    --deploy-mode cluster \
    --name spark-pi \
    --class org.apache.spark.examples.SparkPi \
    --conf spark.executor.instances=5 \
    --conf spark.kubernetes.namespace=spark \
    --conf spark.eventLog.enabled=true \
    --conf spark.eventLog.dir=hdfs://hadoop-hadoop-hdfs-nn.hadoop:9000/sparkhistory \
    --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark \
    --conf spark.kubernetes.container.image=myharbor.com/bigdata/spark:3.3.0-hadoop3 \
    hdfs://hadoop-hadoop-hdfs-nn.hadoop:9000/sparkhistory/spark-examples_2.12-3.3.0.jar

6)提交 Spark 任务(client 模式)

从Spark 2.4.0开始,可以在客户端模式下在Kubernetes上运行Spark应用程序。当应用程序在客户端模式下运行时,驱动程序可以在k8s pod或物理主机上运行。

7c3d499e92b616e1e4ade348edeafa93.png

配置 spark 用户权限
# 上面已经配置,这里可以忽略
kubectl create ns spark
kubectl create serviceaccount spark -n spark
kubectl create clusterrolebinding spark-role --clusterrole=edit --serviceaccount=spark:spark
##在spark-submit中添加
--conf spark.kubernetes.authenticate.driver.serviceAccountName=spark
准备独立Pod

配置 spark 容器,会在这个容器里以 client 模式 submit spark 程序,所以这个容器也会作为 driver。spark-client-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: spark-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: spark-client
      component: spark-client
  template:
    metadata:
      labels:
        app: spark-client
        component: spark-client
    spec:
      containers:
      - name: spark-client
        image: myharbor.com/bigdata/spark:3.3.0-hadoop3
        workingDir: /opt/spark
        command: ["/bin/bash", "-c", "while true;do echo spark-client;sleep 6000;done"]
      serviceAccountName: spark
暴露service

我们任意指定一个端口暴露,后续client mode将通过去DNS去查找Driver Pod的位置,这也是Spark on k8s要求DNS的原因。spark-client-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: spark-client-service
spec:
  selector:
    app: spark-client
  ports:
    - protocol: TCP
      port: 7321
      targetPort: 7321
  clusterIP: None

执行

kubectl apply -f spark-client-deployment.yaml -n spark
kubectl apply -f spark-client-service.yaml -n spark
kubectl get pods -n spark
提交 spark 任务
cd $SPARK_HOME
./bin/spark-submit \
    --master k8s://https://192.168.182.110:6443 \
    --deploy-mode client \
    --name spark-pi \
    --class org.apache.spark.examples.SparkPi \
    --conf spark.executor.instances=3 \
    --conf spark.kubernetes.namespace=spark \
    --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark \
    --conf spark.kubernetes.container.image=myharbor.com/bigdata/spark:3.3.0-hadoop3 \
    --conf spark.driver.host=spark-client-service  \
    --conf spark.driver.port=7321 \
    file:///opt/bigdata/servers/spark/spark-3.3.0-bin-hadoop3/examples/jars/spark-examples_2.12-3.3.0.jar

Client 模式很少使用,稍微了解即可,Spark on K8s讲解与实战操作就先到这里了。

本文转载自:「博客园」,原文:https://url.hi-linux.com/vC9LE,版权归原作者所有。欢迎投稿,投稿邮箱: editor@hi-linux.com。

dd258ad6fa0cda25f1cc032e26c9bed6.gif

最近,我们建立了一个技术交流微信群。目前群里已加入了不少行业内的大神,有兴趣的同学可以加入和我们一起交流技术,在 「奇妙的 Linux 世界」 公众号直接回复 「加群」 邀请你入群。

1e7d2f6c863c7bd1776923bff6dc48a7.png

你可能还喜欢

点击下方图片即可阅读

94860257befc4376ee3b801898e2a310.png

保姆级 Kubernetes 多租户虚拟集群平台 vcluster 使用指南(全网最详中文教程)

877f62e4d979141989998959bc6e6202.png
点击上方图片,『美团|饿了么』外卖红包天天免费领

576b04307dac1f4bbc81328d330885c9.png

更多有趣的互联网新鲜事,关注「奇妙的互联网」视频号全了解!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值