离在线混部背景介绍

随着云原生技术的蓬勃发展,在整个行业内都在探索大数据组件云原生化从而实现资源更精细化的使用,PS:关于云原生和大数据结合之后文章单独来写),在这其中就以大数据离在线混部技术为代表首先尝试将资源进行波峰波谷式的进行充分利用,因为在线服务比如订单服务、商品服务等等后端应用服务往往是在白天的时候是有负载高峰期的,而到了晚上基本都处于低负载的情况,根据埃森哲报告显示2021年公有云数据中心的机器利用率平台不到10%,日均的资源利用率在10%左右(这里通常指的CPU和内存负载)

简单混部的概念讲起

什么是混部:简单来讲,就是将多个应用服务部署在同一个节点中,提升节点的CPU和内存资源的利用率,将机器效能发挥到最大,帮助企业能够最大化的提升IT资源的利用率,从而减少IT资源成本投入,起到降本增效的作用。

在大数据场景下,现在主流的技术架构还是以Hadoop生态为主,其中yarn作为分布式资源调度系统,核心功能就在于如何合理的分配机器资源(这里的资源指的是CPU和内存)然后将资源分配给特定的计算作业,来满足各个计算作业的资源需求,那么这时候问题就来了,资源不够了怎么办?常规的做法一般是如下几种:

  1. 直接申请扩容机器,然后将新增机器加入到集群列表中,硬填充的方式来满足资源需求

  2. 做一些计算作业的调优,看看有哪些计算作业有优化的空间。

  3. 将任务执行时间做分段处理,比如零点-两点首先保障高优任务运行(BI报表之类)其它时间段选择性的运行其他任务

那么,其实上面做法中基本上都是治标不治本,第一:数据规模和计算规模是不断上涨的,我们不可能无限制的进行资源的扩容。第二:调优是能解决部分任务的性能损耗问题,但在大规模场景且数据规模不断上升的情况下,调优带来的收益往往不明显,第三:一旦有任务阻塞住了,那么运行时间太长将是很严重的问题。

大数据场景混部概念

这里讲的是大数据场景的混部,而不是离在线混部的原因在于,我们要明确一个概念,混部表示的是通过资源波峰波谷的时间差,实现不同进程的灵活资源占用,那么就包括如下三种大数据混部架构设计:

  1. 大数据离线作业和流式作业的资源混部

  2. 大数据离线作业和在线应用服务之间的资源混部

  3. 大数据集群实现动态资源弹性,通过虚拟化调度技术实现资源弹性伸缩

大数据离线作业和流式作业的资源混部

在以离线数据仓库架构为代表的大数据处理中通常是以Hive、MapReduce、SparkSQL、FlinkCore等批处理技术,来做一些ETL的处理和离线分析作业,通过数据采集器将数据导入到离线数据仓库中,然后在进行数仓分层和建模,来满足大批量数据的定期处理需求,通常架构图如下:

随着整个大数据技术的发展,以Sparkstream为中心的微批处理技术逐步满足了当时大部分的实时性场景需求,于是,大数据团队基本上都在将一些离线计算作业迁移到微批处理中,比如原来T+1(T代表当天)才能够看到的报表数据,通过微批处理之后,几秒钟就可以看到了,而且还能实时在大屏中滚动着用户付费金额等信息,那老板们看着是相当得意。

于是乎,在这个时候大数据架构发生了微妙的变化,当初由图一的纯离线计算架构,慢慢的延伸出一条以微批计算的

处理链路,同时在整个数据处理架构中通过分布式消息队列Kafka来做中间数据的传输,这种架构我们也称之为Lamda架构

在Lambda架构中,基本上对于准实时作业和离线作业都在混跑在同一套集群中的,当时一方面是没有拆分集群的诉求,因为大部分都是在原有集群上演变来的,不会有什么资源干扰,另一方面当时Hadoop Yarn功能还没那么丰富,还不支持联邦调度和标签队列的配置,这些基础功能不满足的话,上面计算任务很难做到拆分,当然单独拆分一套集群出来是一种做法。

既然提到了Lamda架构了,那就在简单介绍一下Kappa架构,Kappa架构应该是当下应用最广泛的一种架构模式,它的诞生主要是大家对实时性的需求越来越多,而且随着千人千面、万物推荐、广告营销类场景下这种架构可以满足80%以上的实时场景,与此同时,大数据团队就开始探索如果将离线数据仓库改为实时数据仓库那效率岂不是提升了一大截,于是,以Flink为代表的批流一体计算引擎结合以Kafka和Pulsar为代表的高性能分布式消息队列引擎,开始大规模的实行实时数仓,基本架构如下:

从上面两种架构图来对比,可以看到Lambda和Kappa架构的区别就在于流处理这块,Lambda是流处理+批处理,Kappa是完全流处理模式,同时,这两种架构在部分的场景下也可以混合来使用,比如说去掉了微批处理,由流处理结合批处理这时候就可以同时处理离线数仓和实时数仓的场景,基本的架构设计如下:

如果你懂的数据湖的概念的话,会发现这两个架构混合之后 接下来就会天然的会走向数据湖的方向进行延展,当然本文的重点不在于数据湖的内容,后续关于数据湖的内容我会通过单独几篇来输出,OK,抛开数据湖的设计实现,我们单从资源层面来看,会发现这时候其实已经不是独立的集群了,至少不再是一个全部任务耦合在一个资源队列里来同时运行,会涉及到队列的拆分后者集群的拆分(离线集群+实时集群或者离线队列+实时队列)

那么这里会涉及到一个问题:流处理的数据会一直占用资源额度吗?很明显是不会的,我们上面讲到Yarn是用来做资源调度的,它会根据任务资源用量来选择要当下给某个计算作业申请多大的CPU和内存,对于流处理作业来讲,一般都是白天是业务高峰期,晚上是业务低峰期,那么这时候对于整个实时集群资源会下降很多,比如下面这种情况:

那么这时候,聪明的工程师团队就会想到,既然公司预算申请不下来,离线的任务每天半夜就出现资源不足告警的情况,那我们就想想看看能不能把实时集群晚上这波空闲资源给到离线批处理来使用呢?对,反正都是大数据团队自己维护的集群,那就搞呗!本质上讲,这两个技术是互通的,因为底层都是基于Yarn来运行的,我们可以很容易将离线批处理调度到实时处理的集群中,比如以下几种方案:

  1. 检测实时集群的负载情况,观察近一个月周期的负载规律,然后将部分离线任务在这个负载低峰时调度到实时集群中运行

  2. 将一些配置较低,耗时较短的任务调度到实时集群中,但是要配置好Yarn的调度策略

  3. 做集群间节点的动态调度,也就是节点的弹性伸缩,这个可能有一些技术难度,把控不好的话会影响集群稳定性,如果你用的是云服务的话,那么这个就很容易做到的

上面用了大量篇幅讲解了单一混部、大数据离线和实时混部,同时也看到了大数据架构的演变过程,那么看明白了上面之后,对于下面内容就可能更容易理解一下,当下所有事物的发生都是有迹可循的,包括存算分离、湖仓一体、统一分析引擎、向量化分析等等,都是经过上面整个大数据架构演变而来的结果,这些在后面篇幅里我会逐一讲解。

大数据离线作业和在线应用服务之间的资源混部

大数据云原生的简单概述

大约在2014 年开始,以Docker和 Kubernetes为代表的云原生技术迅猛发展,云原生技术相关的社区也开始迅速壮大,现在,以Kubernetes为核心的云原生技术已经成为了当今服务部署和运维的事实标准。

现在大部分的互联网企业在最近的几年基本都完成了从虚拟化时代到容器化时代的转型,运维和部署工作也从之前的系统运维、平台运维、服务运维转为了CI/CD、DevOps、容器化运维工作,于此同时存储、网络、负载均衡、安全等等相关的技术栈也都对应开发了云原生化的实现

那么,大数据生态也正在进行新一轮的技术变革,新的技术应用往往是从单一的进程服务支撑演变为分布式应用的服务支撑,比如Kubernetes的调度机制,现在主流的大数据计算引擎(比如Flink、Spark)也适配了基于Kubernetes的资源调度机制,而且基于Kubernetes的资源调度相比Yarn来讲,资源隔离性更强、避免了CPU绑定、多租户隔离性更好、灵活的进行资源的弹性等等,简单罗列了如下几个优势:

本身大数据生态是一头大象,经过这么多年的发展和迭代整个生态组件越来越繁多,随着计算量和存储量越来越多,大数据集群作为一个重资源的环境,对于资源的耗费也越来越大,仅仅通过离线批处理+实时集群两个混部对于资源的耗费依旧是捉襟见肘,无法满足长期需求,那么这时候就凸显出在线离线混部对于提高集群利用率的意义,

无论是在学术界,还是各大厂商实际落地,都对混部做了深入的研究。学术界如google论文CPI、Heracles、Bubble-up等。各大厂商中最早做混部也是目前利用率最高的是google Borg,其在2015年和2019年分别推出了两篇相关文章。国内的一些云厂商也最先推出了混部相关的产品和开源项目,来助力行业内混部能力的发展

离线和在线的资源差异

在上面内容中,有提及到在线服务(一般指的是后端应用服务)往往是晚上处于业务低峰期,资源负载利用率也就比较低,而离线大数据集群恰恰相反,一般是白天利用率比较低,晚上的时候因为要处理大量的批处理作业,所以晚上资源利用力基本是打满的状态,如图所示:

从上面两张图可以很鲜明的看到在线集群的负载和离线集群的负载之间的差异,往往很多公司大数据集群需求扩容的原因之一是承载不了夜间离线作业的负载,但是,扩容完之后,白天就会有很大的空闲资源了。

大数据离在线混部常见的几种架构模式

架构方案一:大数据集群容器化改造

在我接触的一些真实企业客户里面,有一部分客户自身大数据团队能力比较强,同时又看到了云原生所带来的好处,所以整个架构的做法会“相对激进”一些,他们会选择将新业务完全容器化,同时兼容在线集群,这样离线和在线再根据分时调度的策略,来选择不同时间段内离线大数据运行在那些woker节点(worker是K8s中的节点概念),在线服务运行在那些worker节点中。架构设计图如下:

从架构图上,我们可以看到,在线业务和离线业务都是运行在Kubernetes集群中(不一定是一套集群环境),离线业务按照分时场景调度策略 来选择性的将一些计算作业调度到在线集群中,在此之前,调度服务会首先给几个worker节点打上一个Label标签(Kubernetes自身的标签机制),打上了Label:Offline之后,那么离线任务就只允许在这几个worker节点运行了,为什么要这么做呢?

  1. 为了保障在线服务的稳定性,有些核心服务不允许做一些高负载的计算任务在里面,以免引起故障

  2. 离线资源精准可控,离线场景如果只给1C1G的资源,对计算作业会有热点问题,所以要对离线任务调度的最小资源最好是1:4的比例,比如最小1C4G

  3. 计算作业会有大量的shuffle产生,对磁盘会有的吞吐和IO会比较高,如果不是云盘或者对象存储的话,要慎重考虑。

针对这种架构模式,我推荐是没有历史性包袱的业务场景可以尝试,也不一定非要非选择新业务,毕竟哪有那么多公司时常都会新的业务呢?我们也可以机动性的来选择轻量化、低优先级、自主可控的项目迁移到该架构模式下,然后在稳定运行一段时间之后,逐步迁移其它业务过来,根据本人的观察整个过程大概会经过3-6个月的时间。

这里面在不同客户的场景里面,唯一的区别就是存储介质的区分,有的是自建的模式,那么存储就会选择MinIO或者HDFS,有的客户,可能会选择公有云或者私有云,那么存储一般会选择对象存储或者块存储(ESSD),否则在存算耦合的情况下,计算层无法实现完全弹性。

架构方案二:Hadoop Yarn on Kubernetes集群模式

这种架构模式是大部分企业会择优选择的,毕竟它的改造成本更低、能够完全兼容现有大数据集群、可以快速看到效果,这种架构简单来说,就是计算任务还是运行在Yarn NodeManager中,整个计算资源的调度还是由Hadoop Yarn来调度,计算任务和Kubernetes的调度系统没有任何关系,后面我们也会讲到Kubernetes调度如何更好的进行大数据作业的资源隔离,架构设计图如下:

从上面架构图中,我们可以看到大数据集群和容器集群依旧是相对独立的,容器集群中会启动一个Yarn NodeManager(以下简称为Yarn NM)的Pod,这里的Yarn NM 会自动连接到大数据集群的ResourceManager服务,那么这样在Yarn的WebUI中就会看到一个容器集群中注册过来的Yarn NM地址,如图:

这样的话,我们所有的业务代码和提交方式都不需要改变,等同于单独扩容了几台Yarn NodeManager,这种架构模式的好处有哪些呢?

  1. 计算任务层无感知,不需要考虑兼容性问题,即刻可以看到效果

  2. 相当于给Hadoop Yarn集群扩展了资源,一切还要由来调度,对上和对下都可兼容

  3. 比较灵活可控,按需扩容,需要的时候直接启动一个Yarn NM Pod即可,基本就是秒级别的等待

当然,上面说的都是它的好处,简单明了,肉眼可见,快速出成绩,那么对应也有它不好的地方

  1. 离线集群可扩展差,因为Yarn镜像中需要绑定大数据集群的Host列表(NM和RM是通过Host地址来通信),如果大数据节点修改了HostName或者扩容/缩容了节点,需要重新打镜像

  2. 资源利用不充分,上面说到是运行在Yarn NM Pod中,因为本身NodeManager就是一个进程,它本身也会占用服务资源,会导致一部分浪费

  3. 对于Yarn版本有一定依赖性,低版本中Yarn不支持Liunx ContainerCGroup设置,可能会对在线资源有影响,需要考虑好CGroup目录划分和驱逐策略

  4. 需要配置Yarn 的标签,否则会导致所有任务都会占用在线集群的资源,有些高优的离线任务最好是在本集群内运行

当然,这个方案也有类似于架构方案二中Shuffle数据盘的问题,会对磁盘吞吐和IO有一定影响,这里一般推荐使用独立的RemoteShuffleService,当然这是另外一个话题了,在后面实践部分我们会讲到如何解决这种问题。

架构方案二:多集群统一资源池

这种方案适合业务规模和集群规模都比较大的企业中,在很多企业中大数据集群是按照业务线来拆分的,每个集群服务于不同的业务线来使用,比如业务A是做营销分析的大数据团队,那么可能是一个独立的集群,业务B是做基本报表BI分析的,可能是一个独立的集群,这样每个业务线之间的存储和计算都不互相耦合,在降本增效的当下,企业会极大的缩减开支,尽量复用一些过保的集群(通常服务器都有过保时间,过了过保时间一般就不推荐作为核心业务部署使用)。

那么你想,大规模的企业中其实过保集群数量也是很大的,这时候聪明的架构师们就会想到一个办法来充分的利用上这些机器资源,毕竟能扛一年就少一年的开支呢。

作为大数据从业者都知道,大数据诞生的初衷是什么?一方面是海量数据的处理,另一方面是可以运行在廉价的设备上,因为自身的多副本机制,即便是一两台机器挂掉了,对整个业务也没有什么影响,但是,在这种架构模式下,一般推荐只运行计算资源,不会存储大批量数据。

架构的设计图如下:

我们可以看到,属于业务的集群有A、B、C,下面有一个共享的Kubernetes集群,在Kubernetes集群中,会给不同的worker节点打上对应的业务线的标签,来标记是属于那个业务线的,相关的业务在执行计算任务时,就可以将这部分资源作为一个弹性混部的资源池,想什么时候用就什么时候用,想用多少就用多少,资源还是实在不够的情况, 也可以跟其它业务线说一下“Hi 老铁,接点~”,然后打上你的标签,这样又能安心跑任务了。

这种架构方案的有点在于:

  1. 充分利用企业内闲置资源,节省公司的成本

  2. 资源灵活统一,对在线业务没有任何影响,不用担心资源隔离和资源冲突问题

  3. 没有历史负担,类似于架构方案二中的好处

  4. 容错性更强,只跑计算资源,不存储实际数据,不用担心数据丢失

那么,这种方案有缺点吗? 肯定也有是的

  1. 需要一个统一的资源管控调度服务,来灵活分配标签、节点归属、调度执行等

  2. 也存在绑定Host列表的问题

  3. 过保机器如果和当下集群不在同一个机房中,那么会涉及到网络问题