【spark sedona k8s】spark(sedona) on kubernetes(k8s) 搭建,使用spark-operator提交任务

【spark sedona k8s】spark(sedona) on kubernetes(k8s) 搭建,使用spark-operator提交任务

引言

成功搭建 spark on yarn 后,总是觉得它与我们的服务之间不好联动。之前我们的服务都运行在 docker 之中,spark 又运行在 hadoop 中,我们要想通过服务控制集群执行任务,结合现在的情况,已有的解决方案十分麻烦,要么就是部署一个服务在 hadoopmaster 节点上,通过系统命令来控制,要么就是安装第三方工具。总之不管哪种办法我都觉得不够好,于是便想到在 k8s 上跑 spark

一、架构介绍

相较于之前的 sparkyarn 调度,使用 k8s 调度最大的好处是可以弹性伸缩,整个 k8s 集群中除了跑其他服务以外还能跑 spark 任务,其他服务不忙的时候,可以给 spark 的任务多一点资源。又因为 k8s 是自带 REST Api 的,所以我们在 k8s 上跑的服务可以通过访问 ApiServer 接口的方式直接向 k8s 提交 spark 任务。它的流程看起来像这样:

在这里插入图片描述

这样看起来就很优雅了,将 spark 的调度交给 k8sk8s 能动态管理我们的任务所需资源,我们与 spark 的交互也可以挪到 java 服务上,k8s 的健壮性、容错性我就不多提了,集群搭建起来也挺简单的。接下来我们就开始搭建 spark on k8s 并且开启 spark operator 管理任务。

二、搭建

在正式开始之前,你得有一个能正常运行的 k8s 集群,接下来的操作默认你有了一个能正常运行的 k8s 集群。如果你的集群还没搭建起来,参考我的 另外一篇帖子,先搭建集群。

1、安装 helm

我们可以通过很多方式将 Spark Operator 引入到集群中,可以手动下载源代码来安装,也可以使用 kustomize 来安装,哪种方式都可以,Spark Operator 官方 GitHub地址

我们用 helm,所以得先安装一个 helm,执行:

sudo apt update
sudo apt install -y curl apt-transport-https

curl https://baltocdn.com/helm/signing.asc | sudo apt-key add -
echo "deb https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list

sudo apt-get update
sudo apt-get install helm

2、添加 helm 仓库,安装 Spark Operator

需要将 Spark Operator 所在的仓库地址添加进去。Bitnami 提供了 Spark OperatorHelm chart。使用以下命令添加 Bitnami 仓库:

helm repo add spark-operator https://kubeflow.github.io/spark-operator
helm repo update

安装 Spark Operator

kubectl create namespace spark-operator # 创建一个命名空间

helm install spark-operator spark-operator/spark-operator \
  --namespace spark-operator \
  --set image.repository=docker.io/kubeflow/spark-operator \ # 在这里指定镜像所在的仓库
  --set image.tag=v1beta2-1.4.6-3.5.0 \ # 可以在这里指定要安装的版本,但是前提是镜像仓库要存在
  --set sparkJobNamespace=default

如果安装报错最后一句是这句:

ensure CRDs are installed first

执行这个安装 CRDs

kubectl create -f https://raw.githubusercontent.com/GoogleCloudPlatform/spark-on-k8s-operator/master/manifest/crds/sparkoperator.k8s.io_sparkapplications.yaml
kubectl create -f https://raw.githubusercontent.com/GoogleCloudPlatform/spark-on-k8s-operator/master/manifest/crds/sparkoperator.k8s.io_scheduledsparkapplications.yaml

这是一个在线地址,你也可以将源代码拉下来执行:

git clone https://github.com/GoogleCloudPlatform/spark-on-k8s-operator.git
cd spark-on-k8s-operator

kubectl apply -f manifest/crds/sparkoperator.k8s.io_sparkapplications.yaml
kubectl apply -f manifest/crds/sparkoperator.k8s.io_scheduledsparkapplications.yaml

在线地址执行和拉下来执行的效果是一样的,安装好 CRDs 后再执行上面的安装

执行完后去看看 Pod 的状态,要没有报错:

kubectl get pods -n spark-operator

在这里插入图片描述

3、配置账户信息

要想执行 Spark 任务,我们在提交任务的时候必需得指定一个 k8s 账户,它得绑定一个有权限的角色,才能有权限向 k8s 集群申请资源,创建一个账户:

vi spark-account.yaml

加入内容:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: spark-account
  namespace: spark-operator

创建一个角色绑定,我们将刚创建的账户绑定到集群管理员角色:

vi spark-role-binding.yaml

加入内容:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: spark-cluster-role-binding
subjects:
- kind: ServiceAccount
  name: spark-account
  namespace: spark-operator
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

分别执行两个文件,注意先后顺序:

kubectl apply -f spark-account.yaml
kubectl apply -f spark-role-binding.yaml

如果你觉得绑定管理员角色不妥,那么可以自定义一个角色,加入内容大概像:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: my-role
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log", "services", "configmaps", "secrets", "persistentvolumeclaims"]
  verbs: ["get", "list", "create", "delete", "watch"]
- apiGroups: ["batch"]
  resources: ["jobs"]
  verbs: ["get", "list", "create", "delete", "watch"]
- apiGroups: [""]
  resources: ["endpoints"]
  verbs: ["get", "create", "delete", "watch"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "create", "delete", "watch"]

4、测试

编写一个定义 Spark on K8s 任务的 yaml 文件,加入内容:

apiVersion: "sparkoperator.k8s.io/v1beta2"
kind: SparkApplication
metadata:
  name: spark-pi
  namespace: default
spec:
  type: Scala
  mode: cluster
  image: docker.io/spark:3.5.1 # 这里与我们安装的spark operator版本不一样,但是我使用没问题
  imagePullPolicy: Always
  mainClass: org.apache.spark.examples.SparkPi
  mainApplicationFile: "local:///opt/spark/examples/jars/spark-examples_2.12-3.5.1.jar"
  sparkVersion: "3.5.1"
  restartPolicy:
    type: Never
  driver:
    cores: 2
    memory: "2G"
    labels:
      version: 3.5.1
    serviceAccount: spark-account # 这里指定我们刚才创建的有权限的账户
    env:
      - name: SPARK_MODE
        value: "driver"
  executor:
    cores: 1
    instances: 4
    memory: "1G"
    labels:
      version: 3.5.1
  arguments:
    - "10000"

*** 特别注意的是,一定要指定有权限的账户来运行任务,不然会报各种各样的错,我就是报了很多错,干脆直接用集群管理员的角色来运行任务,就没再报错了。

查看是否开启了任务,执行:

kubectl get sparkapplications

在这里插入图片描述

我的已经执行完了,你的应该看到提交或者执行中

想看具体的日志,可以去看 Pod 的日志:

kubectl logs spark-pi-driver

我们在开启任务后,会发现多了一个 driverpodworkerpodworkerpod 数量取决于我们之前提交任务的配置文件中指定了几个,当然它也能动态的分配。例如我们的 spark-pi.yaml 任务就指定了四个 worker pod,我们查看一下:

kubectl get pods  # 不加 -n default 的话默认就是 -n default

在这里插入图片描述

果然就是启动了四个 pod 来运行任务,等它执行完,我们再看 driver 的日志:

kubectl logs spark-pi-driver

在这里插入图片描述

得到了结果,搭建成功

三、关于 Sedona

搭建 Sedona 就更简单了,我们只需要将上面用的 Spark 的镜像拉下来,写一个 Dockerfile ,将 Sedona 的插件 jar 包丢到对应的文件夹中去,重新构建镜像并上传到私有仓库或者公共仓库,只要 k8s 能拉取到就行,然后在 任务.yaml 中改一下镜像地址就行了,这里就不演示了,因为我也没弄,这个不难。

四、关于历史服务器

如果想用历史服务器,得将日志写到一个公共的持久化存储空间中,然后在 k8s 中跑一个历史服务器去读取日志文件,暴露一个 serviceingress 就能访问。

五、测试

我弄了四台机器,一台是 12C 64G,其他三台是 12C 16G,测试上面的 spark-pi 示例,计算 五十万次,开启8个 worker pod,结果是:

在这里插入图片描述

耗时 78s,将计算次数换为 一百万次,开启16个 worker pod,结果为:

在这里插入图片描述

耗时 142s,我记得之前使用 Spark on Yarn 的时候也是计算五十万次,结果是两分钟多一点,计算一百万次失败了,半个小时没结果。现在使用 Spark on Kubernetes,效率有所提升,不知道是我的实验变量没控制好还是怎么的,有点意外,不过除了效率之外,在 k8s 上跑 Spark 的优点我觉得还是灵活性强,跑任务的时候一堆 worker pod 就创建出来跑任务了,任务结束后 worker pod 就都没了,不会占用集群中其他服务的资源,这点挺好的。此外由于 k8s 是自带 REST Api 的,所以和我们自己写的服务交互起来就比较方便,我们可以通过 REST Api 提交任务,查看任务等等

写在最后

当然,我上面的这些办法可能不是最好的,我也在探索最好的实践,写到此处只是自己查找时方便,如果能顺道帮助你解决一些问题那再好不过。
学无止尽,瑞斯拜!

  • 27
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值