作者 | 火山引擎EMR团队
众所周知,基于 Hadoop 的 EMR 体系发展到现在,经历了很多个阶段。从基于 IDC 机房通过 CDH 去部署的 1. 0 阶段,演进到在公有云上面按照存算分离的办法去进行的 2. 0 阶段。
而在这些基础上,火山引擎数智平台 VeDI 的 EMR 团队又探索出了无状态的 EMR 3.0 演进阶段。上个月底,火山引擎 EMR 正式上线瞬态集群新功能,该能力基于业界领先的 EMR Stateless 理念,可以实现集群级别的弹性伸缩,即无业务需求时释放集群,有业务需求时再拉起集群,从而帮助企业大幅降低产品使用和平台运维成本。
什么是瞬态集群,什么是 Stateless 理念,本文从基础概念、架构体系、演进过程、实际运用场景&使用价值等多个角度全方位介绍 EMR Stateless 的创新理念以及应用。
什么是 Stateless?
Stateless——它的本质是一个瞬态集群的概念,但又不完全是瞬态集群,它属于一个轻量级交付的、无状态的瞬态集群。那无状态的瞬态集群又是什么意思呢?
首先,Stateless 的集群是在存算分离的基础上,进一步演化而得来的一个瞬态集群。普通的存算分离集群,像 Hadoop 体系里的相关内容都是绑定在集群中的,没有彻底将这些有状态的内容剥离出来成为一个独立的服务。而 Stateless 是把 Hive Metastore 以及 History Server 等进行了服务化,也就是从计算集群中把它们剥离出来了。
在 Stateless 的加持下,我们所指的 Hadoop 体系中的 Master、Core、Task 等节点就组成一个无状态的轻量级瞬态集群,可以被随时创建或释放,并拥有多个副本,这无疑可以让集群具备一个更好的扩展性。基于此,接下来就能够在云原生的基础上,以集群的视野,去更好的做能力的成长以及成本的优化。
接下来,为大家对比一下 Stateful 模式和 Stateless 模式,它们两个之间有什么典型的差异点?
左边这个流程图,是一个传统的 Stateful 模式。
在这个模式下,大家要提交一个任务的数据流程通常是这样的,首先必须要有一个长时间运行的集群,有了集群以后,再将任务提交上去,接下来无论是通过 IO 的直接返回,还是把数据写入到 HDFS 或是对象存储,执行结束后都将拿到历史结果。
站在大数据维护视角来看,在提交任务的流程结束以后,运维长时间运行的集群,无论是对它的运行状态进行监控,看看它是否出现了故障,还是对它存在的服务进行日志采集,这些动作都会产生一定量的运维成本。同时,在任务结束后,这些集群事实上变为了一个空置的集群。站在总成本承受的角度上来讲,这其实是一个不利的选项,以上就是典型的Stateful模式。
而在 Stateless 的模式下,这一切就会有所变化。
首先,操作的第一步直接变为了提交任务。在提交任务以后,集群会被及时地、按需地创建出来用于运行任务。当任务运行完成以后,集群将会被释放掉。在用户拿到计算结果之后,意味着整个的任务提交过程随之结束。
在这个过程中,由于 Stateless 已经把具有状态属性的,像日志服务之类的功能外置于集群。在集群释放以后,用户仍可以通过日志服务查询到任何一个时间段内,在 Stateless 集群模板下面的集群里执行过的任何一个任务结果。
在这样的流程中,用户是不需要去运维执行集群的。这就是 Stateful 和 Stateless 最大的不同点。
看了以上的内容,大家肯定会产生一些问题,有一些概念性的普遍问题,在这里可以先跟大家讲解一下。
1.Stateless 跟 Serverless 的区别?
首先,Serverless 相比于 Stateless,其实就是全托管和半托管的区别。在半托管的情况下,用户需要自我的去运维一些集群资源以及集群配置相关的内容,而在全托管的情况下,用户可以省去这部分的配置,但是也会失去了一些自定义配置集群的灵活性。
而 Stateless 其实是处于一个半托管的场景下面,基于 on cluster 形态的云原生优化体系,它和 Serverless 这种全托管的形态是没有什么本质联系的。它们相似之处,是在对资源的使用上面都比较充分,只有在执行任务时才会有计算资源存在。
2.Stateless 瞬态集群,瞬态怎么理解?
关于这个问题,更深层次的一个点就是瞬态,达到怎样一种时间粒度才叫瞬态?
首先,我们来对比一下瞬态集群和普通的云上 EMR 集群。普通 EMR 集群是长时间部署的,可能会部署一周两周,甚至一个月两个月的时间。而瞬态集群是当有任务到来时,我们为这些任务创建一个集群,任务运行完就把集群释放掉。
同样的,在第二次创建的时候,就可以直接进行一个类似复制的操作,集群的配置和规格和之前都是一致的。对用户来讲,做到这个程度是没有任何代价的。用户只需要去定义这个集群,Stateless 就能按需创建出这样的一个瞬态集群,并且这个瞬态集群的时间粒度是分钟级的,无需考虑间隔得太久会发生什么错误。
3.Stateless 它适合哪些业务场景?
基于我们的实践场景来谈,首先它适合需要存算分离的用户,并且更适合离线跑批的场景。计算量比较大,并且具有明显的潮汐性质特征时,在节约成本上面的体现是非常明显的。
4.Stateless是否需要用户改变使用习惯?
在用户使用方面,并不需要对流程进行改变。Stateless只是在云原生管控层面进行了优化,并且是在无状态服务剥离层面的优化。对于用户接口,无论是开源的 web UI还是开源引擎的对外接口,任务提交流程无任何变化,这些完全都是开源兼容的,大家可以一直享受开源社区版本迭代所带来的技术红利。
Stateless 大数据体系
了解完以上内容,大家应该对 Stateless 有一个初步的认识了,接下来再给大家介绍该体系是怎么实现的。
首先,在 Stateless 的架构体系里,用户集群包含了离线分析(Hadoop 体系)、实时计算( Flink 体系)、交互式分析、 NoSQL 数据库以及机器学习等相关内容。这个是带有计算特性的集群中,所有带有状态部分的内容都被剥离了。Stateless把 History Serverhe 和 UI 相关的内容都剥离成为独立服务,包含 Spark History Server, Presto History Server, YARN Timeline Server 等。不管集群是否存在,这些服务都在。
其次,通过 Open API 做了统一的调度和开发封装。同时将 EMR Studio服务化( EMR Studio可以理解成类似于 Oozie、Airflow、 DolphinScheduler 等的调度引擎)。用户可以在火山引擎 EMR 上面直接使用这些服务,而不需要通过提交机器来部署。
依托于火山引擎丰富的云上生态,Stateless 还可以无缝对接数据研发类产品。除此以外,EMR 元数据,包括 Hive Metastore 内置元数据库、外置的 RDS 等,也被抽取到统一的服务里。相信使用过 Hive Metastore 的小伙伴,肯定没有少被 Metastore 的 RDS 给坑过,RDS 有个风吹草动,那么 Hive Metastore 就会有问题,但这些问题现在都可以被云原生服务有效解决 。
同时,配置中心也对集群做了一层集群,如集群配置、所需组件等,都会以虚拟形式存储。同时,引擎的元数据做了服务化,包括权限管控、用户体系等。
最后,Stateless 解决了非常困扰运维的一个问题——日志把本地磁盘写满。在 Stateless 体系下面不会再有这样的问题,通过 TOS 对象存储,日志都是落在一个按需的对象存储上面。对象存储可以被认为是无限大的,所以无需为它所占的磁盘空间去担心,只需要去定义好它的生命周期,这个问题就能被解决。
上文提到了 Stateless 基础的大数据体系,现在就进入一个环节,在状态流上用一个 case 为大家讲解一下刚才的体系。
首先,从上图可以看到,虚线框框住的就是 Stateless 从实体集群里抽象出来的,像元数据服务、管控服务等一系列服务,有 Web UI,也有 Open API。这些 Open API 会作为控制集群创建和销毁的 trigger,相关指令会交到调度平台上,例如 Airflow, DolphinScheduler 等。调度平台在提交任务的时候,会通过接口对集群的生命周期做一些影响。
其次,再到 trigger 这一层,主要通过云原生提供的 Open API就能够去控制集群了。如果要提交任务,就会去新起一个集群,并且对集群做一个状态的恢复,这是指任务希望有一个什么样的集群配置。这个配置可能是版本参数,也有可能是一些机型的配置。无论是什么样的配置,Stateless 都能忠实地将集群恢复到初始化的样子。因为集群是无状态的,执行作业完成后, 就会释放掉实体的集群,它的生命周期也就结束了。
上面的这个 case,讲的是单独一个任务的提交。但在实践的过程中,往往集群可能会被提交多个任务上来,这种情况下直到所有任务执行完毕,实体集群就会被释放。当集群释放完以后,如果又有任务需要提交了,同理,只需要再去起一个配置相同的集群,再来做任务的执行,执行完了以后再释放。这就是Stateless 体系运转的大致流程。
Stateless 演进过程
理解完概念性和结构性的内容以后,接下来再分享一下 EMR Stateless 的演进过程。EMR Stateless,听上去是一个比较新的东西,我们为什么要这么去做这个呢?
在开篇中,跟大家分享了基于 Hadoop 的 EMR 体系的很多个阶段。
首先是基于 IDC 机房通过 CDH 去部署的 1. 0 阶段,到现在仍有不少的用户是基于1.0这个体系在做运营。它也有它的好处,无论加资源还是其他操作,是完全可控的。当然也存在很多问题,比如运维的复杂度很高,并且由于存算一体的架构,闲置了很大的计算资源,没有办法进行按需计算的场景。
基于这些问题,演进出了在公有云上按照存算分离的办法去建设的 2.0 阶段。通过把存储资源和计算资源分开,让计算资源尽量地做到按需分配。当然这也有限制和前提,它的计算资源是按照节点去做弹性的。所以在 2.0时代,它解决的最根本的问题还是一个计算和存储之间的解耦。
但是,火山引擎的 EMR 团队发现 2.0 时代的一些问题,影响到了日常的运维和集群的稳定性。基于这两点,我们首先考虑到了弹性的能力,对集群整体去做一个弹性的伸缩,而做这个的前提条件是要解耦集群和相关的集群元数据,在这些基础上做了集群无状态化,也就是集群服务的剥离。
谈到这里,Stateless的 优势其实就体现出来了。首先,Stateless 集群是百分之百不用去运维的,因为它只在运行时瞬态地出现。其次,集群的服务也无需用户去担心,并且它还保留了半托管模式的优点。在经过技术研判和综合判断后,相比起 EMR 1.0时代的IDC机房线下部署模式,使用 EMR Stateless 的资源成本能够达到百分之四十以上的优化。
以上就是EMR Stateless 演进的过程,以及火山引擎EMR团队关于Stateless的考虑思路和历程。
接下来,再跟大家详细地分享一下各个feature是怎么去演进的。
首先,存算分离其实是 EMR 2.0 时代的产物。到了Stateless的环境下,首先保留了所有EMR 2.0 里的一些 feature 。而在新的这一层上面,最主要的功能就是对负载进行了优化加速,这个可以认为是本地的 local shuffer,这样速度会更快。
并且进一步提供了冷热分层的管理,可以直接的去控制和定义冷热分层的行为,这也是成本节约的前提。计算资源已经做到极致优化,所以存储资源上面也需要及时优化。
首先平台会自动地去诊断用户的冷热分层,诊断的前提是什么?从上图中来看, 用户在火山 EMR 这一侧的所有读写行为,会经过 Metastore 服务,了解哪些是冷数据,哪些是热数据。
基于用户对表的定义,接下来再做自动化的诊断,并且把这些诊断以及预测,暴露给运维的人员,让他们看到诊断的结果,并且给出平台的建议。再由人工的判断,三位一体的来让冷数据找到自己最终的归宿。在这个话题上面,Stateless提供的冷数据分层层次也是比较多的,从标准到低频,再到归档,再到冷藏,再到最后的删除,能够给不同特点的数据找到最合适的存储点。这个也是Stateless为用户赋能的一个方面。
弹性伸缩,这也是演进 Stateless 产生出来的一个重大 feature。
对于弹性伸缩,主流分成两种,第一种是基于时间的弹性伸缩,比如运维人员知道几点到几点是高峰,几点到几点是低谷。第二种是基于负载指标的一个弹性伸缩,因为可能会有特殊情况出现,比如说在一个时间范围内,数值突然变大或者变小,或者是基于负载情况。
关于这一点,火山引擎 EMR 有独有的设定,可以把时间和负载混合起来用。并且,这样的混合弹性模式除了作用在 Hadoop 集群的节点上以外,它还可以作用在整个的瞬态集群上面。
Hive Metastore 服务上文也有提到过,无论是离线任务的元数据也好,或者是对实时以及实时离线混部,它的元数据其实都是可以托管至 Hive Metastore 。
目前,Stateless 已经实现了 Public History Server 一系列的服务。它是可以独立于集群实体而存在的,并且在集群运行的时候,这些作业就会上报数据到 Public History Server 服务。用户可以直接地通过域名去访问,不用进行绑定 IP 这些比较繁杂的一些环节。
依托于云上产品生态,Stateless 也升级了日志服务,它基于 OpenSearch,最终数据落地在 TOS 上面。面对数据的丢失,或者是数据磁盘的影响,这些用户都不需要去考虑和运维,但目前这部分功能还没有彻底的成熟,还需要一段时间完善。
关于调度服务,我们对 DolphinScheduler, Airflow 等这些具备调度能力的服务也做到了集成,为什么会去集成这些内容?是因为这些组件会去调创建集群的 API 任务,会随着调度系统里边的任务提交去触发,Stateless 把这些方法全部都集成服务化,用户无需自己去部署,可以直接做到一个开箱即用。
最后,把用户服务化以及鉴权服务化的内容合并分享给大家。第一是用户的服务化以及用户权限的服务化。用户的服务化,就是把 LDAP 集成为统一的用户管理服务。当然还是保留 LDAP 这一层级的,比如用户习惯用 LDAP 的 UI ,这些用户自己操作也没有任何问题,不用反复操作一个集群去导入用户的体系,这是收益最大的一件事。
同理,Stateless 鉴权服务使用 Ranger ,因为 Ranger是 RBAC 的概念,而在 RBAC 的概念上面,Stateless还抽象了 RBAC 的这一层概念,让用户可以去做更丰富的权限的一套配置。并且,这个权限和用户的系统是互通的,做到了一套用户系统加一套权限,可以覆盖所有的跟用户和角色权限相关的 RPC 模型,这也是Stateless演进过程中很重要的一个能力。
Stateless 业务价值
最后跟大家分享一下 Stateless 的业务价值。
首先介绍下体现业务价值的一个典型场景——
无状态集群是一些什么样的集群?如何把成本做到优化呢?
第一,为用户创建的无状态集群时,所选云服务器的机型可能会不一样。首先它是一个金字塔结构,在最下面一层,首先保证用户的计算资源。
第二,尽量满足用户的计算特性。比如 word count 或者 CPU 密集型的计算用不了多少内存,我们会尽量帮用户节约内存的资源,选择 CPU 和内存比例比较接近的机型。
第三,帮用户做成本优化。两种计价模型,一种是按需、一种是竞价。原则上来讲,竞价比按需便宜,且因为无状态集群时间短,我们会尽量地给用户选便宜机型。比如说用户倾向的一个机型无库存了,怎么办?我们尽量在价格以及配置上面选择跟用户定义类似的机型,以保证用户的计算任务是能够执行的。
最后,做一个简单的总结,Stateless 都有什么好处?
首先,其实就是很简单的按量付费。按需创建,自动销毁,用户无需关心集群的状态,因为它随着任务总会有的。其次,它永远处于一个迭代的状态,大家可以永远地去享受开源社区版本迭代带来的一个红利,因为我们是永远拥抱开源的,这也是我们火山引擎 EMR 不会放弃的一个初心。
然后就是存算分离和弹性扩展,弹性扩展具有一定先进性,可以在集群的力度上完成。日志是幂等的且上云的,随时都能看到,用户不用对日志有过多的运维。
最后,谈到运维,Stateless把有状态的服务抽取出来,用户无需再去关心跟集群服务相关的内容,只用关心运行计算、计算debug和计算诊断这些方面就足够了。