Spark & Hive 云原生改造在智领云的应用
阿程编辑 2022-05-23 16:48 星期一 34

引 言

随着 Kubernetes 越来越成熟,使用者越来越多,大数据应用上云的需求也越来越迫切。原有的大数据资源管理器 Yarn 很难做到所有应用资源统一控制,完全隔离,带来的主机应用和大数据计算应用互相抢占资源,由此导致的计算任务时间可能经常性抖动,多租户应用互相影响。而在 Kubernetes 上,此类问题天然解决。所有的应用都以 Pod 形式在 Kubernetes 平台上统一管理,在规范的 namespace 管理下,不存在不受控的应用来进行资源抢占。同时,我们可以轻松地实现多租户,资源配额,运行审计计费等功能。在此背景下,客户原有的大数据计算任务如何无缝迁移到 Kubernetes 上,大数据应用如何进行云原生改造,都成了我们最迫切要解决的问题。本篇文章主要针对这两类问题来进行探讨。

4abe5cb15305e0799f727cb87b0fef7f.png

Spark 和 Hive 在智领云业务场景中的使用
Spark 和 Hive 是大数据平台中很常用的两个计算引擎。Hive 本身是一个基于 HDFS 的类 SQL 数据库,其 HQL 语句的底层执行引擎可以使用基于 Yarn 的 MapReduce,也可以使用 Spark。Spark 在 2021 年 3 月推出的 3.1 版本中实现了对 Kubernetes 支持的 GA(general availability,意味着生产级的支持)。在这个版本中,Spark 允许用户从命令行(spark-submit)上提交 Spark 任务到 Kubernetes 集群中。但是目前的 Hive 版本中,如果底层使用 Spark,还只能提交任务到 Yarn,而不能支持将 Hive 查询提交到 Kubernetes。

除了从命令行提交 Spark 任务,智领云使用 Hive 和 Spark 相关的业务还有三个场景:第一个、用户创建 Hive 作业进行数据 ETL 任务开发或数仓分层计算工作流创建。第二个、用户应用程序(例如,批处理调度系统)提交 pySpark 文件或者 Spark jar 包到平台,进行数据计算。第三个、用户使用 Jupyterlab Spark kernel 来访问 Hive/Mysql/Hdfs/Glusterfs 等数据源文件进行数据探索、机器学习及人工智能算法开发。这三种场景下的共同点都是需要将计算任务转换成 Spark job 在集群中调度运行(Hive 的缺省引擎已经从 MR 变成了 Spark)。在每个场景下,我们都在 Spark on Kubernetes 的基础上提供了相应的解决方案:

在 Kubernetes 平台上使用 Hive,我们使用了 Hive on Spark on Kubernetes。

对于 Spark 作业,我们集成了 Spark On Kubernetes Operator。

JupyterLab 中使用 Spark, 我们集成了SparkMagicKernel 和 Livy。

每种集成方式,都有其独有的优势和缺陷及其适用场景,下面我们来一一讲解。

d1bbc6c3ea12e300af9a6bc2180b26f1.png

Hive On Spark On Kubernetes
在类 SQL 数据库中,Hive 是很多 Hadoop 生态系统缺省的选择。虽然 Spark 也提供了 SparkSQL 来支持 SQL 查询,但是 Hive 使用的 HQL 和 SparkSQL 在语法支持上还是存在比较大的差异,对于大型的数据仓库项目,用户可能积累了几千个 Hive 任务,如果此时想要快速地迁移到 Kubernetes 上,那么使用 SparkSQL 存在很大的迁移成本和风险。但是如果我们只更改 Hive 的底层执行引擎,改成 Spark on Kubernetes,那么,我们就能让客户的 Hive HQL 应用,无需修改地快速迁移到 Kubernetes 上。但是由于 Spark on Kubernetes 是最近才达到 GA 状态,和不同的 Hive 版本,Kubernetes 版本,以及很多相关大数据组件之间的适配还没有成熟,我们需要对现有的版本之间进行一些适配才能平滑运行 Hive On Spark On Kubernetes。

首先,我们必须要确定 Hive、Spark、Hadoop(HDFS)以及相关的 Kerberos、Ranger 的版本。对于 Spark 版本的选择,我们开发选型的时候最新版为 3.1.1,目前 Spark 最新版已经到了 3.2.1,Spark 选取最新版本即可,最新版本能够增强对 Kubernetes 的支持。而 Hive 版本选取的主要原则,即查看 Spark-client 模块的代码是否支持 Kubernetes,如果不支持是否容易改造以便支持。而 4.0.0 版本开始,spark-client 模块重构了代码结构,增加了 SparkClient 的抽象类,有该结构支持,增加对 Kubernetes 的支持就容易了很多。这里还有一种选择,就是 Hive 选用 3.1.2 的稳定版本,然后把最新的 master 分支的 spark-client 模块代码 cherry pick 到 3.1.2 版本即可。

217c2ad3f95e706ee0d7d3f2c96d9a9c.png

在 Hive 代码中主要改造内容是增加 KubernetesSubmitSparkClient,主要内容是构造 SparkSubmit 向 Kubernetes 提交 Spark 任务的各种参数,包括和 Hive 中 RPC server 通信的配置,提交 Spark 作业后,Spark driver pod 启动后会连接 HiveServer2 中的 RPC server,连接成功后,HiveServer2 会发送相应的 Spark job 到 Spark driver 来进行计算。而 Spark 代码的改动,主要是修改 Spark 中的 hiveShim 模块,增加对 Hive 4.0.0 的支持。

Hive On Spark 在智领云的数据平台,主要作为 Hive 作业/工作流以及 Hue 查询工具的底层执行引擎:调度系统通过 Beeline 来连接 HiveServer2,Hue 通过 JDBC 连接 HiveServer2,客户端发送用户的 SQL 语句到 HiveServer2。HiveServer2 解析完成 SQL 后,会生成一系列的 HQL taskplan,对于这些 HQL 的执行,HiveServer2 会启动一个 RPC server,SparkSubmit 会带上 RPC server 参数,启动一个 Spark Driver Pod 来和 HiveServer2 进行 RPC 通信,这个 Spark Driver Pod 的主要功能就是接收 HiveServer2 发送过来的 SQL Job 进行计算,计算完成后,将结果返回给 HiveServer2 中运行的 RPC server。

在 Kubernetes 平台,SparkSubmit 客户端和 Kubernetes APIServer 通信,Kubernetes 在接收到 Spark 任务请求后,会调用 Scheduler 组件启动 Spark Driver Pod, Spark Driver 在启动完成后,会发送启动 Executor 请求给 Kubernetes APIServer, Kubernetes 再启动 Spark Executor Pod, Spark Driver 和 Executor 建立连接,完成整个 Spark 集群的创建。

整体架构如下图所示:

e6abe9aa3969af14184969dddbfaff1e.png

权限控制方面,我们使用 Ranger 来完成授权和鉴权操作,使用 Kerberos 来完成认证操作。对于 Ranger 鉴权插件, Hive 和 Spark 都有相应的解决方案。Hive 直接通过 Hive Ranger 插件和 Ranger 服务来通信,完成鉴权操作,Spark 则通过 Spark Authorizer 插件再调用 Hive Ranger 插件来完成鉴权。在 Hive On Spark 模式下,我们使用 Spark 对 Kerberos 的支持来完成用户身份认证操作,通过 Hive Ranger 插件来完成鉴权操作。

4dbef492b4166a718d2c2732e1fb7d88.png

Spark on Kubernetes Operator
Spark on Kubernetes Operator 项目是 Google 非官方推出的 Spark On Kubernetes 解决方案。它的内部实现是基于 Spark 官方的 Spark On Kubernetes 解决方案之上,更多的利用了 Kubernetes 特性,来增强在 Kubernetes 上使用 Spark 计算引擎的易用性和灵活性以及性能的提升。

它本质上是一个 Kubernetes Operator,所以在该解决方案下,用户提交 Spark 作业只需要通过 Yaml 文件即可,并且可以定制 Kubernetes Schedule。比如,可以配置使用华为提供的针对大数据领域优化过的 Volcano 调度引擎。

在智领云平台上,Spark on Kubernetes Operator 承载了用户提交 Jar 包或者 pySpark 文件类型的所有 Spark/Spark-streaming 作业的底层调度引擎。在 Spark OnKubernetes Operator 成熟之后,Hive on Spark 底层未来也可以增加 Spark On Kubernetes Operator 运行模式的支持,仅仅只需要在 spark-client 模块中增加KubernetesOperatorSparkClient 抽象类的支持即可。

Spark Operator 方案也存在一个弊端,就是 Spark 作业配置 Yaml 的高度复杂化,该 Yaml 需要配置 Spark 作业的所有信息,包括Driver/Executor 的资源控制,包括 Spark 的镜像版本和调度算法。普通用户不需要关注这些配置。在此问题下,我们模仿 Apache Livy 的 API 增加了一个 Spark On Kubernetes Operator Server。该服务负责管理 Spark On Kubernetes Operator Job,提供创建/更新/删除 Job 接口,提供查询 Job 状态及日志请求。用户只需要配置少量Spark Job 参数,后台服务会根据参数完成 Spark Job Yaml 文件渲染,提交到 Kubernetes 集群。

5134d63ffff6ace055c9aaeaffa7a896.png

在权限控制这一块,我们可以使用 Spark 相关配置结合 Spark Operator 对 Kerberos 的支持来实现。对 Ranger Hive 插件的支持,我们可以使用 Spark Authorizer 插件来转接适配,不过该插件版本较老,我们需要修改其 POM 文件和相关代码来使其可以支持 Spark 3.1.1 版本。在 Spark Operator 模式下, Spark 作业的相关配置都在 Yaml 中配置,我们可以利用 Spark Operator 对 Sidecar 的支持来完成 Spark Operator 对 Ranger Hive 插件的支持。主要方法就是 Spark 3.1.1 版本的原生镜像不变,将 Ranger 相关的 Jars 通过 Sidecar 共享目录共享给 Spark 主 Container,并配置相关 ClassPath 参数,使 Spark 能够找到 Ranger 和 Spark Authorizer 相关 Jar 包。

18680c7651343fa9cdb209ccadb1b528.png

JupyterLab On Kubernetes
JupyterLab 作为数据科学家首选的 IDE,在数据及人工智能领域应用非常广泛。在智领云平台,我们的主要改造是打通JupyterLab 和我们的调度平台的互相访问,增加 Spark 读写 Hive / HDFS 的支持。这个场景和前两个场景的主要区别在于 JupyterLab Kernel 和 Spark Driver Pod 之间可能有持续的交互,而不是 run to finish。其次,在 UI 界面下的任务需要无需修改的在后台(测试或生产环境下)运行。在此需求之下,我们主要做了几点改动:

选取了 SparkMagic Kernel 支持了用户编写测试 Spark 代码。

改造 JupyterLab Server 代码,允许用户直接点击开启当前 Spark 任务的 4040 调试页面 UI。

改造 JupyterLab Client 代码,允许用户可以直接在 JupyterLab Notebook 内直接引用系统或者用户自定义变量,并能够在调度和调试时生效。

增加了 JupyterLab 调度 Worker,使调度平台可以直接调度运行用户的 ipynb 类型的 Notebook 文件。

增加 JupyterLab Python 环境管理,允许 JupyterLab 在重启后保持其之前设置的 Python 环境。

SparkMagic Kernel 执行 Spark 任务是利用 Apache Livy 服务来实现任务的提交以及交互Session 的维护。Apache Livy 目前版本对 Kubernetes 并不支持,我们需要添加 Kubernetes client 和状态查询的支持。Apache Livy 实现的对 Kubernetes 的支持实际上是和 Hive on Spark 模式类似,都是创建 RPC Server,然后调用 SparkSubmit 提交 Spark 任务和 RPC Server 通信,来完成 SQL 任务的交互。下图展示了整个流程的架构。

605dfefb80cd060e0f98d413e1586411.png

在此种模式下,Hive 的权限控制配置和 Spark Operator 类似,都是使用 Spark Authorizer 和 Hive Ranger 插件来实现。

155809eebeba2204d0a3cab76fc1ab11.png

未来
在智领云平台,我们使用了存储和计算分离的方案,在计算层使用 Spark on Kubernetes 作为主要的计算引擎,底层可以采用 HDFS 兼容现有系统,也可以采用其它支持 HDFS 接口的云原生存储。这样的架构,加上对 Hive 等传统 Hadoop 生态的云原生改造,可以在最大程度的支持现有系统的同时逐步迁移到纯云原生的体系架构下,无缝集成新的大数据和人工智能系统。而基础架构即代码(Infra as Code)方式的使用, CI / CD 全链路的支持,为类似 DataOps,DataMesh 的新型数据应用开发运维范式提供了清晰可行的技术架构支持。而由此带来的业务开发效率的提升,业务管理运维效能的提升,都是质的变化。未来可期。

谁在招聘
怿星科技是一家高速成长的智能网联汽车技术服务公司。公司依托全球顶尖的服务厂商,通过强强合作,面向国内有自主研发能力的汽车企业,提供研发工具、系统集成、工程咨询、软件方案和培训等多种产品与服务。 怿星科技总部位于上海漕河泾高科技开发区,并在北京和深圳设有分公司。公司创始团队来自汽车电子、互联网、通信等多个不同行业,符合当下智能网联汽车跨界融合的大趋势,核心成员平均具有10年以上的汽车电子及相关行业资历。
华为创立于1987年,是全球领先的ICT(信息与通信)基础设施和智能终端提供商,我们致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界:让无处不在的联接,成为人人平等的权利;为世界提供最强算力,让云无处不在,让智能无所不及;所有的行业和组织,因强大的数字平台而变得敏捷、高效、生机勃勃;通过AI重新定义体验,让消费者在家居、办公、出行等全场景获得极致的个性化体验。目前华为约有19.4万员工,业务遍及170多个国家和地区,服务30多亿人口。
滴滴出行是卓越的一站式移动出行平台;为5.5亿用户提供出租车、快车、专车、豪华车、公交、代驾、企业级、共享单车、共享电单车、共享汽车、外卖等多元化的出行和运输服务。在滴滴平台,超过3100万车主及司机获得灵活的工作和收入机会。
中科创达软件股份有限公司(股票代码:300496)是全球领先的智能平台技术提供商。自2008年成立以来,公司致力于提供卓越的智能终端操作系统平台技术及解决方案,助力并加速智能手机、智能物联网、智能汽车等领域的产品化与技术创新。作为一家技术驱动型企业,中科创达不但坚持自我创新,也注重扶持创新。一方面与高通、英特尔、微软等分别运营了多个联合实验室,为元器件适配和终端测试提供先进的资源和技术支持。
长城汽车股份有限公司是全球知名的SUV制造企业,于2003年、2011年分别在香港H股和国内A股上市,截止2017年底资产总计达1105.47亿元。目前,旗下拥有哈弗、长城、WEY和欧拉四个品牌,产品涵盖SUV、轿车、皮卡三大品类,拥有四个整车生产基地,具备发动机、变速器等核心零部件的自主配套能力,下属控股子公司40余家,员工7万余人。
北京云中融信网络科技有限公司(简称融云),是安全、可靠的全球互联网通信云服务商,向开发者和企业提供即时通讯和实时音视频通信云服务。iResearch 艾瑞权威数据报告显示,融云即时通讯云市场份额连续多年稳居头位。
头条
整理 | 梦依丹 出品 | CSDN(ID:CSDNnews) 一分钟速览新闻点! 腾讯宣布自研业务实现全面上 […]
1995年8月16日,Windows第一个默认浏览器——Internet Explorer(IE)首次亮相,由 […]
AI 领域,传来一个让人悲恸的消息。6 月 14 日,旷视官方发布讣告,旷视首席科学家、旷视研究院院长孙剑博士 […]
TIOBE 在更新了官网的设计之后,重磅带来了新一个月的编程语言榜单。 C++ 即将超越 Java 在最新的 […]
“网红”马斯克再现江湖。如果稍微留意一下,就会发现近段时间“马斯克”的名字似乎在各大科技网站的首页就没有下来过 […]
像苹果、微软、谷歌这样的巨头科技公司,公司的总部可谓是既具有科技感又非常的醒目,比如苹果的总部大楼外形酷似一艘 […]
数字时代下,随着企业向数字化、在线化、智能化高速演进,存储需求呈指数级增长,业务也面临着更多热点和突发流量带来 […]
在本篇文章中,曾在 Facebook、亚马逊工作 20 年余年,也经历过两家公司的低谷期,现任 Coatue( […]