Skip to main content

Command Palette

Search for a command to run...

大数据容器化-K8s+Spark

Updated
2 min read

Apache Spark

在大数据处理与分析领域,Apache Spark无疑占据着重要地位。它的特点是基于内存计算,支持各类资源管理平台,其中以YARN最为常见,同时又与Hadoop平台集成,在集群节点以HDFS作为分布式文件存储系统。

我们可以先看一下搭建一个常见的Apache Spark大数据平台需要哪些步骤:

  1. 安装Hadoop集群

  2. 配置HDFS

  3. 配置YARN

  4. 安装Spark

  5. 配置Spark与YARN集成

事实上如果参阅官方文档,还有更多细节检查与配置,有过大数据相关领域从业经验的人都知道,要搭建一套可用的大数据环境并不容易,再加上后期维护,就更吃力了,而一套稳定的大数据平台正是进行大数据应用开发的基础。根据笔者了解,有不少公司正是因为大数据平台搭建及配置的复杂性等原因,不得不在多个测试环境中,共用一套大数据平台,这种方式长期看维护成本较高,也可能存在安全隐患。

大数据领域需要一些变化,而Kubernetes的出现则提供了契机。

Kubernete(以下简称k8s)是容器集群管理系统,是一个开源的平台,可以实现容器集群的自动化部署、自动扩缩容、维护等功能。通过Kubernetes你可以:

  • 快速部署应用

  • 快速扩展应用

  • 无缝对接新的应用功能

  • 节省资源,优化硬件资源的使用

大数据社区

随着K8s社区的发展壮大,微服务及容器化被越来越多的公司应用到生产环境。与此同时,K8s也成为容器编排的首选平台。大数据社区在容器化进程中当然也是不甘落后的。

Spark

自2.3开始官方支持K8s

Flink

自1.9开始官方支持K8s

Hue

官方Helm chart包

Hive

以MR3为执行引擎支持K8s

Airflow

自1.10开始支持K8s

Presto

支持K8s

……

 

可以看到整个大数据社区也在积极支持容器化,但大数据的容器化并不是生硬地将各个组件搬到K8s上,以Spark on YARN为例,核心组件YARN作为资源调度器,其结构如下图所示

下图讲述了Apache Spark on YARN的工作方式:

YARN ResourceManager的功能为:

负责集群中所有资源的统一管理和分配,它接收来自各个节点(NodeManager)的资源汇报信息,并把这些信息按照一定的策略分配给各个应用程序

了解K8s的同学可以看出YARN的功能其实与K8s Scheduler的功能非常类似

Kubernetes 调度器是一个策略丰富、拓扑感知、工作负载特定的功能,调度器显著影响可用性、性能和容量。调度器需要考虑个人和集体的资源要求、服务质量要求、硬件/软件/政策约束、亲和力和反亲和力规范、数据局部性、负载间干扰、完成期限等。

所以与其将YARN生搬到K8s中(早期确实是这样做的),何不用K8s调度器替换掉YARN,使得Spark适应K8s呢? 事实上社区确实是在这个方向努力尝试,并且自Spark 2.3开始,实验性支持使用K8s原生Scheduler替代YARN。

spark on k8s:

在该方案中

  1. 客户端通过`spark-submit`将任务提交到K8s集群中,并在集群中启动一个Spark Driver Pod;

  2. Spark Driver启动相应的Executor Pod, 组成一个Spark Application集群并执行作业任务;

  3. 任务执行完成后,Executor Pod会被销毁, 而Driver Pod会持久化相关日志,并保持在'completed'状态,直到用户手清理或被K8s集群的垃圾回收机制回收.

Spark原生支持K8s的好处也是很明显的:可以更好的利用K8s的集群资源,通过K8s赋能,更好的进行资源的隔离。这个方案不太友好的地方在于:`spark-submit`在K8s集群之外,使用非声明式的提交接口,实际使用起来不够友好。

将Spark应用迁移到K8s环境中

Spark Operator是Google基于Operator模式开发的一款的工具, 用于通过声明式的方式向K8s集群提交Spark作业,并且负责管理Spark任务在K8s中的整个生命周期,其工作模式如下图所示:

我们可通过Hem安装`spark-operator`

$ helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator
$ helm install incubator/sparkoperator --namespace spark-operator

创建服务用户及绑定权限

$ kubectl create serviceaccount spark 
$ kubectl create clusterrolebinding spark-role --clusterrole=edit --serviceaccount=default:spark --namespace=default

一个典型的Spark应用在K8s中的资源描述文件`spark-pi.yaml`如下所示

apiVersion: "sparkoperator.k8s.io/v1beta2"
kind: SparkApplication
metadata:
  name: spark-pi
  namespace: default
spec:
  type: Scala
  mode: cluster
  image: "gcr.io/spark-operator/spark:v2.4.4"
  imagePullPolicy: Always
  mainClass: org.apache.spark.examples.SparkPi
  mainApplicationFile: "local:///opt/spark/examples/jars/spark-examples_2.11-2.4.4.jar"
  sparkVersion: "2.4.4"
  restartPolicy:
    type: Never
  volumes:
    - name: "test-volume"
      hostPath:
        path: "/tmp"
        type: Directory
  driver:
    cores: 1
    coreLimit: "1200m"
    memory: "512m"
    labels:
      version: 2.4.4
    serviceAccount: spark
    volumeMounts:
      - name: "test-volume"
        mountPath: "/tmp"
  executor:
    cores: 1
    instances: 1
    memory: "512m"
    labels:
      version: 2.4.4
    volumeMounts:
      - name: "test-volume"
        mountPath: "/tmp"

部署运行

$ kubectl apply -f spark-pi.yaml

查看运行结果

计算与存储分离

计算与存储耦合存在的问题:

  1. 当存储或计算其中一方资源不足时,只能同时对两者进行扩容,导致扩容的经济效率比较低(另一种扩容的资源被浪费了);

  2. 在云计算场景下,不能实现真正的弹性计算,因为计算集群中也有数据,关闭闲置的计算集群会丢失数据。

因为耦合导致的以上这些问题,导致很多公司不得不考虑这种耦合的必要性。而Hadoop的架构设计正是计算与存储耦合,这种设计并不适合云原生架构。而作为大数据存储的基石-HDFS,目前并无官方的K8s解决方案,不过在K8s社区本身就有许多优秀的存储解决方案-MINIO

MinIO 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。而且实验数据表明,其性能丝毫不逊色于HDFS

安装MINIO也非常容易

$ helm install stable/minio

我们以WordCount,数据读写使用minio存储系统(兼容亚马逊S3云存储服务接口)

JavaRDD<String> textFile = sc.textFile("s3a://...");
JavaPairRDD<String, Integer> counts = textFile
    .flatMap(s -> Arrays.asList(s.split(" ")).iterator())
    .mapToPair(word -> new Tuple2<>(word, 1))
    .reduceByKey((a, b) -> a + b);
counts.saveAsTextFile("s3a://...");

由于兼容亚马逊S3云存储服务接口这一优势,minio也同样可以作为Hive数据仓库的可选存储系统。

<property>
<name>fs.s3a.path.style.access</name>
<value>true</value>
<description>Enable S3 path style access.</description>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>s3a://hive/warehouse</value>
</property>

总结

通过以上论述,在K8s集群上搭建Spark大数据平台,相比传统YARN调度方式而言更为简洁,MINIO可作为大数据的存储系统,在保证数据的持久性的同时,也实现了大数据计算系统与存储系统的解耦。

参考

More from this blog

2025: 祛魅 灰度 念头通达

今天是2025年的最后一天,当大家都在准备下班的时候,好巧不巧的,我刚好发现了一个不大不小的问题,大胆猜想,小心求证,向上反馈,暴露风险,作为2025年工作注解,实在是再有趣不过了。 今年的工作,从结果上看,还算平稳,至于过程,有太多不可言说的部分。厂里打镙丝的牛马,有工资可拿,理应知足了,至于其它的,与己无关,也没那么重要了。 祛魅 近距离观察大厂,才发现一些违背常识/直觉的事实:路人以为的高大

Feb 28, 20261 min read21

大厂祛魅:破碎的专注力

毁掉一个人最直接的方法,就是毁掉ta的专注力。 这句话的出处已然模糊,但放在大厂环境中,却显得格外深刻。 围城 大厂宛如一座围城。城外的人满怀憧憬,目之所及皆是光鲜;城内的人却如困笼之鸟,翅膀日渐退化,每日挣扎求生。 高大上 不可否认,大厂的硬件设施确实令人艳羡:宽敞的独立园区内,来往穿梭的人群中,几乎人人手握智能设备。这看似现代化的景象背后,却藏着一个无奈的事实:在工作时段,每台电脑都被严密监控,连听音乐都成奢望。于是,工作之余玩手机,成了许多人难得的解压方式。 大厂的品牌效应确实强大。外界对...

Jul 29, 20251 min read138

Black Swan

黑天鹅理论 是指极不可能发生,实际上却又发生的事件 来到大厂打工已经满一个月了,从一开始的手足无措,到逐渐度过不适期,也算是适应了吧。 不适应 刚入职时,不适应的地方还是挺多的。 第一次只使用台式机工作,这就限制了我一天中的绝大部分时间,都必须呆在自己的工位上,好在工位足够大。只是人与人的沟通少了很多,有问题只能在工位上通过 IM 呼对方,有种魔幻又现实的感觉 第一次只能用 Windows,也不能 WSL,这给我的工作效率带来了很大影响,不能用熟悉的软件,就连写代码用的 VSCode 的...

Jan 24, 20251 min read74

2024年: 逐渐平静

这个世界是一面镜子,会把你的感受反射给你 2024 开端: 相由心生 那时,还带着一着愤懑,因为拿到了低绩效,虽然内心知道这是公司经营困难,想让我离开的一种策略,但仍然感受到自己那可笑的自尊受到了践踏。自那之后,非必要不加班,只做份内事,尽可能地不去涉及份外之事。 2024 年中: 与人为善 组里的项目眼见不行了,我被迫去支援 AI 项目,久违地写起了 python,项目接近完成时,意外收到通知:我拿到大礼包了。在这之前,架构师因故裸辞。在我离开之后不到两周,我的 TL 也裸辞了,直到同事告诉...

Jan 9, 20251 min read92

企业软件之殇

殇 动词 未成年而死。 名词 战死者。 笔者经历了两家打着云原生旗号的企业软件/解决方案公司,都是中途加入,项目都以解(失)散(败)告终。 云原生解决方案 NB 公司:一个传统的 IDC 小厂,想着借云原生的热度,进军企业软件市场。 在加入这个项目之前,笔者考取了 CKAD 认证,彼时对 K8s 相当着迷。先简要介绍一下这个项目背景: 基于 Rancher (换皮肤)的二次开发项目,名字叫:HCaaS ,在笔者加入这个团队之前,项目已经开发近两年了,除了 TL 之外,其它人之前都...

Jul 1, 20241 min read103

just for fun

57 posts

I'm a Software Engineer