Hadoop势微,云原生上位——传统大数据平台的云原生化改造

以Hadoop为中心的大数据生态系统从2006年开源以来,一直是大部分公司构建大数据平台的选择,但这种传统选择随着人们深入地使用,出现越来越多的问题,比如:数据开发迭代速度不够快,集群资源利用效率过低、新的开发工具集成非常复杂。这些问题已经成为了困扰企业数字化转型加速迭代和升级的主要障碍。另一方面,

 以Hadoop为中心的大数据生态系统从2006年开源以来,一直是大部分公司构建大数据平台的选择,但这种传统选择随着人们深入地使用,出现越来越多的问题,比如:数据开发迭代速度不够快,集群资源利用效率过低、新的开发工具集成非常复杂。这些问题已经成为了困扰企业数字化转型加速迭代和升级的主要障碍。另一方面,从2014年开始,以Docker和Kubernetes(K8s)为代表的云原生技术蓬勃发展,云原生的社区和机构迅速壮大,到现在,Kubernetes已经成为企业搭建容器云平台的标配。

那么,业界都在思考一个问题,高速发展的云原生技术能不能解决传统大数据平台的那些问题。答案是肯定的。而本文将从智领云科大数据平台产品云原生化的实践过程,阐述一下传统大数据平台迁移到Kubernetes上所要经过的技术改造过程。

数据时代,传统大数据平台遭遇四大窘迫问题

传统大数据平台,是指以Hadoop为中心的大数据生态技术。一个Hadoop集群包含HDFS分布式文件系统和以Yarn为调度系统的MapReduce计算框架。围绕Hadoop,有一系列的软件来帮助人们进行大数据的存储和计算,比如数据仓库Hive、计算框架Spark、实时消息队列Kafka等。

在大数据发展的初期,这样的大数据生态技术框架是能基本满足人们建设大数据平台的需要的。随着时代的发展,大数据技术使用逐步地深入,大数据开发需求变得越来越旺盛,人们对多租户环境下大数据开发的效率、大数据集群资源利用率、新(计算和存储)技术的集成速度提出了越来越高的要求,而传统大数据平台在面对这些需求时则显得有点束手无策,出现了无法克服的困难。我们仔细分析一下,就可以看到传统大数据平台的技术架构决定了依靠它本身的发展是无法克服这些困难的:

  1. 传统大数据平台难以实现资源的隔离。多租户环境下的数据开发效率提升,需要以资源隔离的方式来保证租户之间的计算作业互相不影响,特别是不能出现某一个或几个租户独占集群资源的情况。但Hadoop系统本身的出发点就不是为了多租户环境而设计的,其目前的资源隔离实现也不完善。在最近的Hadoop版本中,在一定程度上实现了内存资源和文件资源的隔离,但是不够完整,而磁盘I/O和网络I/O的隔离还在社区讨论的过程中,短期内看不到解决的希望。
  2. 传统大数据平台难以集成新的计算和存储技术。Hadoop系统在部署其他组件的时候,对这些组件与HDFS和Yarn的版本适配是有严格要求的。很多新的大数据组件是不适配老版本的Hadoop的,而升级Hadoop又会造成其他组件的失效。另外,部署新的组件还要考虑到Linux不同操作系统的兼容性所带来的额外复杂度。所以引入一个新的计算和存储组件的难度是非常高的,往往需要几天甚至是几周的时候。
  3. Hadoop存算合一的耦合架构决定了它的资源利用率无法提高。在一个Hadoop集群中,一个节点既是存储节点(datanode),也是计算节点。当存储资源不够的时候,增加节点可以进行存储扩容,但会造成计算资源的利用率下降;同样,当计算资源不够而进行扩容的时候,存储资源利用率就会下降。同时,因为对于Yarn的依赖,不使用Yarn调度的其它组件很难集成到Hadoop的计算框架中。所以Hadoop的这种耦合架构决定了它的资源利用率不可能很高。
  4. Hadoop集群资源无法做到快速的弹性扩容和缩容。弹性的扩容和缩容是提高集群资源利用率的有效方法。很遗憾,Hadoop的节点扩容和缩容流程,导致这个动作无法在很快的时间内完成,尤其是缩容过程,只有当一个datanode的所有数据块都在其他节点完成了备份以后,该节点才能被移出集群,而由于数据备份是以较小的传输率运行在后台,往往要持续几个小时以上。

总而言之,传统大数据平台因为其结构性的缺陷导致了多租户环境下数据开发效率低、集群资源利用率不高、以及集成新技术很复杂等问题,依靠Hadoop生态技术框架本身的发展是不可能解决这些问题的。

 

业界趋势大数据平台的云原生化

既然不能够依靠Hadoop生态技术本身的发展来解决传统大数据平台带来的难题,那么我们就应该把注意力放到当前最新的技术发展趋势之上,也就是以容器和Kubernetes为代表的云原生技术。云原生技术在2013年容器项目以及2014年Kubernetes项目正式发布以后,发展非常迅猛。现在,各大公有云厂商都支持K8s,还有上百家技术公司在持续投入K8s的迭代和更新工作。成立于2015年的云原生计算基金会(CNCF),将K8s作为其托管的第一个项目,到目前该基金会已经托管了123个项目,近200个国家的16万开发者在为这些项目开发代码。更令人兴奋的是,CNCF的生态全景图目前包含了1000多个云原生技术产品,覆盖了数据库、消息级流处理、调度和任务编排、存储系统等10多个技术领域。

2021年应该是云原生大数据技术发展的里程碑,在这一年,有两个重大的技术进展被公布。一个是2021年3月,Apache宣布Spark 3.1正式支持了kubernetes,另外在2021年5月,Apache Kafka背后的商业公司Confluent 也发布了Confluent on Kuberneters,一个能私有发布的在K8s之上运行的Kafka生产集群系统。

这两个重要事件表明,大数据平台的云原生化已是大势所趋。按照这个趋势,Hadoop也会逐渐迁移到K8s上。从技术角度来分析,常说的Hadoop三架马车中,计算框架MapReduce会被更高效的Spark所取代,资源调度组件Yarn正在被K8s取代,最坚挺的HDFS也有了云原生的对标方案。这意味着直接在K8s上运行所有现在的大数据工作负载已经成为了可能。

智领云建设实践,攻破8技术难题

虽然大数据平台的云原生化已经是大势所趋,但在落地实践的过程中还是有一些技术难题需求攻克。就拿Spark来说,虽然Apache Spark 3.1已经支持了K8s,但是有几个问题还没有解决,比如Hive SQL作业如何以Spark的方式在K8s运行?JupyterLab运行的PySpark和Spark程序怎么运行在K8s上?智领云科技作为国内云原生DataOps技术的领先者和倡导者,在大数据平台产品的云原生化方向做了许多的努力和尝试,通过自主研发和对开源系统的扩展构建了自己的核心产品,云原生数据应用开发平台。该产品实现了大数据平台在K8s上生产化稳定运行,并解决了多租户环境下的数据安全和资源隔离难题。接下来,我们可以看看智领云具体解决了哪些大数据平台云原生化的技术难题。

1. Hive SQL程序在K8s上运行

在传统大数据平台中,Hive被广泛用来进行数据仓库的建设。大数据平台的云原生化一个很重要的工作就是要保留对Hive SQL的支持,否则原有的大量的Hive SQL程序需要进行迁移,风险和成本都难以把控。从语法上看,Hive SQL和Spark SQL还是有很大差异的,所以我们不能简单地用Spark SQL来取代Hive SQL。另一个技术选择就是修改Hive的底层执行引擎,让Hive SQL程序以Spark作业的方式运行在K8s上。这个选择看上去不错,但也面临一些技术挑战。

首先,由于Spark对K8s的支持是2021年达到GA状态,不同的Hive版本、Spark版本、K8s版本、以及很多相关大数据组件(比如说授权组件Apache Ranger)之间的适配还没有成熟。 智领云研发团队经过生产集群的验证,确定了基于以下大数据组件版本的Hive执行引擎切换到Spark的解决方案。对于Spark,我们推荐使用最新的版本,因为新版本的Spark能增强对K8s的支持。 而Hive从4.0.0 版本开始,重构了spark-client 模块的代码结构,增加了 SparkClient 抽象类,通过对该抽象类的代码扩展,我们可以实现对 K8s 的支持。但是在Hive代码进行扩展的过程中,要注意避免Hive和Spark针对 Kryo库的版本冲突。

 

我们对Hive代码的改造主要是增加了抽象类SparkClient的一个K8s实现,KubernetesSubmitSparkClient类。这个类通过创建一个SparkSubmit实例向 K8s 提交 Spark 任务的各种参数。如下图所示,Hive SQL代码的执行经过了下面一系列的流程。

  1. Hive SQL程序是通过Beeline 来连接 HiveServer2,而Hive查询工具Hue 则是通过JDBC来连接HiveServer2;
  2. Hive SQL语句提交到HiveServer2后,被解析生成一系列的SQL 执行计划,并生成SQL任务;
  3. SQL任务会启动一个RPC server,然后KubernetesSubmitSparkClient会带上RPC server 参数,通过K8s的API server提交一个Spark作业;
  4. K8s的scheduler这时会启动一个Spark Driver Pod 来和 HiveServer2 的那个RPC server进行通信,这个 Spark Driver Pod的主要功能就是接收RPC server发送过来的Hive SQL作业进行计算,计算完成后,将结果返回给RPC server;
  5. Spark Driver Pod在启动完成后,会发送启动Spark Executor Pod请求给K8s APIServer, K8s再启动若干Spark Executor Pod,然后Spark Driver和Spark Executor建立连接,完成Hive SQL作业的计算。

 

2.Spark程序在K8s上运行

对于Spark程序和PySpark代码的执行,智领云研发团队采用的解决方案是基于Google开源的Spark on K8s Operator项目。这个开源项目更好地利用了K8s的一些特性,来增强在K8s上使用Spark计算引擎的易用性、灵活性、以及性能的提升。但该项目有一个缺陷,就是用户需要通过配置一个复杂的Yaml文件来运Spark作业。该Yaml文件需要声明Spark作业的所有信息,包括Driver/Executor的资源配置、Spark的容器镜像版本、以及调度算法等。对于一般用户而言,这些配置信息显得过于繁琐和复杂。

    为了简化Spark程序在K8s上运行的复杂配置流程,我们模仿 Apache Livy 的API开发了一个Spark Job Manager Server。该服务负责管理Spark On K8s Operator的作业,提供作业的创建、更新、删除、查询状态、日志获取等接口。提交Spark程序的时候,用户不需要配置任何Yaml文件,只需要配置少量Spark作业参数,跟用spark-submit脚本提交方式没有区别。Spark Job Manager Server服务会根据用户提交的参数完成 Spark作业的Yaml文件渲染,将作业提交到 K8s 集群。这一操作方式极大地简化用户在K8s上运行Spark程序的复杂度。Spark程序在K8s上运行的架构图可以参考下图。需要注意的是,第1、2、3步都是发生在Spark Job Manager Server,第4步是将Spark作业

以Yaml文件的方式提交给K8s API Server,之后的Spark作业执行就交给Spark on K8s Operator去执行了。在第11步,Spark Job Manager Server会通过API Server获取Spark Driver的状态信息,从而与Spark Driver进行通讯以获取Spark作业的执行结果。

3. JupyterLab代码在K8s上运行

在传统大数据平台,JupyterLab一直是数据科学家首选的交互式编程工具,广泛应用在数据的探索分析以及人工智能机器学习算法的开发上。因此,在K8s平台上支持JupyterLab交互式的Spark程序运行是必须要解决的问题。

 

    目前,JupyterLab是利用开源项目SparkMagic Kernel通过Apache Livy服务来和Spark集群进行通讯,实现Spark程序的交互式运行。但是,Apache Livy目前的版本并不支持K8s。针对这个问题,智领云研发团队采用了Hive模式类似的方式,对Apache Livy代码进行了扩展,在Livy服务端创建了一个RPC Server,然后通过SparkSubmit提交Spark任务。运行在K8s集群的Spark Driver Pod会和RPC Server通信,来完成SQL任务的交互执行。上图展示了整个流程的架构图。

4. Kafka集群在K8s上运行

     Kafka on K8s有不少开源的方案,智领云研发团队选择了Strimzi开源的Kafka Operator。 这个项目通过CRD抽象描述各种Kafka组件的配置,以Operator控制协调的原理去管理Kafka集群组件,相对完整地实现了Kafka集群在K8s上的部署。 我们对Strimzi Kafka Operator的改造主要是支持安全认证和权限管理,将Schema Registry组件集成到Kafka Operator,然后对开源的Kafka运维管理工具AKHQ进行改造,将其也集成到Kafka Operator。下图展示了Kafka在K8s运行的架构图。

5. HDFS在K8s上运行

目前开源社区有不少成熟的项目都支持HDFS集群在K8s上发布,但是对多租户和数据安全的支持却不是很完善。智领云研发团队对HDFS on K8s项目进行了扩展,首先是将Hadoop的版本升级到最新版本,并于最新的K8s版本进行适配。同时,我们集成了对Https访问、Kerberos安全认证和Apache Ranger权限授权等功能的支持。

6. 利用KubeVela简化大数据组件在K8s上的发布

在K8s这样的平台上发布应用并不是一件容易的事情,应用开发者要了解K8s复杂的应用资源配置,比如API 版本、资源类型、命名空间、标签、容器参数、存储参数、网络参数、重启配置等等一长串的配置。应用开发者为了掌握K8s基于Yaml文件的应用配置方式需要大量时间去学习和实践。在实践过程中,有不少开发者反映,他们90%的时间都在编写重复的应用配置,整个流程过于复杂。为了解决这一问题,智领云研发团队采用了KubeVela框架来简化K8s上应用发布和交付的复杂性。KubeVela作为K8s的一个插件,它利用Open Application Model模型和K8s的可扩展性,通过构建应用发布的一个抽象层,来解决在K8s上发布应用存在的一些复杂问题,比如Pod、端口暴露、权限、资源声明和管理、CRD等概念,都被抽象成了以应用为视角的配置SDK。智领云研发团队通过KubeVela框架,将应用发布的通用定义、监控告警定义、监控面板定义、日志采集定义、以及对外端口定义等都抽象成了一个个组件,极大地简化了应用发布的复杂性,也统一了智领云数据应用集成开发平台的应用发布规范。

7. 大数据组件可观测性在K8s上的实现

大数据组件的运行需要有统一的监控、报警、日志系统来高效地进行运行状态及性能的监控、失效报警、和故障跟踪等大数据运维工作,以保证大数据生产系统的平稳运行。在可观测性方面,智领云研发团队采用了开源的Prometheus来进行监控指标的采集,集成了Grafana来配置各组件的监控面板,利用轻量级的云原生日志系统Loki来收集各组件的日志,并自主研发了LogViewer服务来快速地搜索和获取日志。下图展示了Kafka集群的监控面板及日志检索大屏。

 

 

8. 数据安全和资源隔离在K8s上的实现

通常一个大数据平台要服务多个部门、业务人员、数据开发人员,是一个典型的多租户环境。 在这样的多租户环境下,我们首先要实现所有大数据(可视化)组件的单点登录,这样既能避免维护多套用户登录系统的麻烦,也能保证我们能在大数据计算和存储层能实现统一的安全认证和权限授权机制。而安全认证和权限授权机制,也必须是所有计算和存储引擎共用同一套机制。传统大数据平台在多租户环境下的一个难点就是资源隔离,它很难避免一个或少数几个租户独占资源的情况。在云原生架构下,这一问题就迎刃而解。那么,现在我们具体看看智领云的研发团队是怎么实现上述功能点的。

  1. 单点登录:我们基于OpenID Connect协议以及开源认证授权管理平台Keycloak,对主要的大数据可视化工具(Hue、Superset、JupyterLab等)的登录代码做了修改或扩展,实现了所有可视化工具的单点登录。
  2. 数据安全:对于数据安全,我们采用了Kerberos协议来实现安全认证,并基于开源授权框架的Apache Ranger实现了统一的大数据资源(HDFS、Hive和Kafka)的授权管理。对于Spark,我们扩展了Spark Authorizer开源插件的代码以支持最新版本的Spark。对于Hive,我们修改了大量的Apache Ranger的代码以完成对Hive 4.0.0的支持。而对于Kafka,开源的Strimzi Kafka Operator是不支持Kerberos安全认证和Apache Ranger的授权机制的,我们对Strimzi Kafka Operator的代码和配置进行了扩展,实现了Kafka集群的数据安全。
  3. 资源隔离:我们充分了利用了K8s的命名空间来实现多租户的资源管理,对于每一个机构,我们在K8s上分配了一个独立的命名空间,并对该命名空间进行了资源配额的管理,以确保每个机构都不会使用超过其分配份额的集群资源。

 

智领云数据应用开发平台的数据安全架构如上图所示。目前,每个用户在每台虚机上都创建了一个相同的账号,并且保存了一份该用户的Kerberos keytab,这样每个运行中K8s上的容器和大数据组件都可以使用这个用户ID和keytab进行安全认证。

未来发展,让云原生大数据平台借 K8s 发挥更大价值

这两年以来,智领云的技术团队在大数据平台云原生化这个方向做了大量尝试,实现了大数据组件在K8s的稳定运行以及统一的数据安全机制,使智领云数据应用开发平台实现了完整的云原生化。目前,智领云的基于K8s的云原生大数据平台已经在智算之道——2020全国大学生大数据应用挑战赛中,稳定地支持超过1000名学生同时并发在线;在北京医保局数据竞赛活动中,支撑了12支参赛队伍,600GB数据集量级以及每个用户48核/256G内存算力的Spark计算引擎的挑战;在武汉防疫两次战役期间,智领云的云原生大数据平台系统扛过超5000万次核酸查询、核酸采样量196万次/小时、小程序访问232万次/小时的严峻考验。同时,智领云研发的在线云原生大数据平台BDOS Online也平稳地支持了来自全国100所高校600多名教师参加的二期全国高校教师培训营, 以及参与人数超过1000多名学生的“AI赋能大学计划”高校学生大数据培训营,为这些高校的老师和学生提供了稳定、高效、灵活可扩展的云原生大数据实验平台。

接下来,我们将在以下几个方向继续探索,推动大数据平台更高效更稳定地运行在K8s之上。

  1. 取代HDFS:HDFS的主要问题是文件块元数据都在内存中,造成NameNode 经常消耗大量的内存而且容易出现内存故障,同时对小文件的不友好,运维也比较复杂。我们计划在未来采用开源的云原生分布式文件存储系统MinIO来取代HDFS。
  2. 统一Spark程序的运行方式:目前我们运行Hive SQL和Spark SQL采用了不同的模式,未来我们希望能用统一的Spark On K8s Operator模式来执行Hive SQL和Spark SQL的计算,使得Spark运行更稳定,也使Spark计算引擎的监控和运维更加高效。
  3. Flink等其他大数据组件的云原生化:未来我们将持续不断地将其他主要的大数据计算和存储引擎集成到K8s集群上,进一步提升智领云数据应用开发平台的大数据开发体验。
  4. Spark访问数据的局部性问题(也称为Data Locality问题):当Spark程序和HDFS 都运行在K8s之上的时候,我们需要保证Spark executor在读取HDFS文件的时候是从同一个节点上的datanode去读数据,而不是到其他节点的datanode上去读取数据。在其他节点上去读取数据有网络上的延迟,会造成计算作业大约10%的性能损耗。解决这个问题可能会需要引入新的Spark作业调度机制,或者对Spark Driver的源码进行修改。

开放实验系统共建开源生态系统

为了让广大的大数据开发者能体验一下云原生大数据平台的技术,我们将云原生大数据平台的基本版作为一个项目开放了出来。在这个开放项目中,我们将HDFS、Hive、Spark operator、和Kafka Operator这些大数据组件的部署方式共享出来,开发者可以基于这个项目部署一个实验的大数据集群来体验一下云原生大数据平台。需要注意的是,本项目只能作为一个实验系统来运行,因为它不支持高可用、Kerberos安全认证、以及基于Apache Ranger的鉴权机制。

Github地址:https://github.com/linktimecloud/big-data-on-k8s

Gitee 地址:https://gitee.com/linktimecloud/big-data-on-k8s

知秋君
上一篇 2024-07-18 15:36
下一篇 2024-07-18 15:02

相关推荐