1. 金融行业大数据需求
1.1 云原生相比 Hadoop 的优势
传统大数据集群通常基于 Hadoop 系统构建,传统大数据作业通常是以裸进程的形式运行在节点上,很容易受到节点上的其他进程或其他因素干扰,因此带来的作业稳定性问题经常困扰用户。
一个实际的例子,如果一个 Flink 作业发生了延迟,找不到业务上的原因,但是观测到节点的 CPU 使用率比较高。用户通常选择杀掉节点上的其他作业,使机器负载下降,这时作业很有可能恢复了正常。但是,最终也没有定位到延迟的具体原因,一段时间后很可能会再次出现相同的问题,而且每次杀掉其他作业的处理方式非常繁琐,并且代价比较高。
那么,在大数据场景下,云原生系统相比 Hadoop 系统,具备以下能力:
- 强制的容器化能力:可以屏蔽大数据作业的运行环境,提高运行时隔离能力;
- 可定制化的网络 / 存储能力:可以支持大数据作业使用复杂的容器化网络技术,以及云原生支持的任意存储系统;
- 便捷的运维能力:可以轻松地进行节点上下线,集群扩缩容,降低基础设施运维成本。
因此,大数据架构向云原生演进是全行业,特别是金融行业的重要趋势。
困扰用户的第二个问题是资源效率问题。
在实践中,通常存在独立的 K8s 集群和 Hadoop 集群。独立的 K8s 集群运行着在线服务,独立的 Hadoop 集群运行着大数据作业,这两个集群不仅不能彼此共享资源,而且资源利用率都非常低。
离线计算和在线业务的资源需求具有周期性变化,资源需求高峰时资源不足,低峰时资源冗余。而在线业务与离线计算的资源高低峰期往往是错开的,所以离线计算高峰时如何利用在线集群资源,在线业务高峰时如何利用离线集群资源,成为了降本增效的关键。
集群管理的总体目标是在硬件资源不增加的情况下承载更多业务,整体提升集群资源利用率。
因为在线服务部署在云原生系统已经成为行业规范。在这个前提下,如果大数据系统也部署在云原生系统,和在线服务部署在一起,那么就具有如下优点:
- 在线资源和大数据资源可以高效、灵活地相互转换;
- 整个集群的利用率可充分地提升,降本增效;
- 资源共池,统一的配额管控、机器运维、软件部署等,降低维护成本。
因此,资源的高效利用是金融行业特别关注的能力和需求。
1.2 大数据迁移云原生的难点
现在,云原生系统仍然存在很多不足,大数据集群难以直接基于云原生构建,这也是为什么大部分公司仍然还在使用 Hadoop 系统的原因。大数据场景下,迁移使用云原生系统存在以下不足:
- 一个运行在 Hadoop 系统上的传统大数据作业迁移到云原生系统,具有一定的改造成本;而一个大数据集群通常存在数百个、数千个,甚至数万个、数十万个作业,全部迁移到云原生系统上,改造成本巨大,难以实现;
- 传统的大数据引擎,比如 Flink、Spark,最初不是针对云原生系统设计,其 AM-Task 作业形态难以直接在云原生系统上部署;
- 云原生系统的原生调度器不具备与 Hadoop YARN 队列类似的多租户资源管控能力;
- 云原生系统的原生调度器不存在“作业”概念,不具备作业排队能力,不具备作业级调度策略;
- 云原生系统的原生调度器吞吐能力差,不适用于任务量大且运行时间较短的大数据作业,比如一个只需要运行 1 分钟的 Spark 作业,在调度阶段就花费三分钟,不仅使作业完成时间大幅增加,还造成了集群资源浪费。
因此,只有在云原生系统上补齐上述不足,才可以更好地支撑金融行业大数据场景。
2. 云原生大数据部署
为了满足业务的多种需求,火山引擎支持大数据作业在云原生系统上的两种部署方式:
- 基于 Serverless YARN 的 Hadoop 方式部署。
- 基于 Arcee Operator 的云原生方式部署。
2.1 基于云原生的 YARN 解决方案 —— Serverless YARN
Serverless YARN 是基于云原生的 YARN 解决方案,帮助大数据作业透明迁移到云原生系统。简单来说,在 K8s 系统上模拟实现了 YARN 系统,传统作业可以像往常一样提交和运行,不需要进行任何改造,完全感知不到 K8s 的存在。
Serverless YARN 保留了 YARN Client、YARN API,以及 YARN 原有的 AM 管理、Quota 管理、权限管理等功能。
作业提交流程如下图:
- 用户在计算引擎的基础上进行开发,调用 YarnClient SDK,提交作业到 Serverless YARN 的 Resource Manager 组件;
- RM 组件为作业创建 AM Pod(每个作业有一个 Master 实例,负责管控整个作业,全称为 Application Master);
- AM Pod 经过 K8s 的 API Server 和调度器调度到一个具体的节点,然后由节点上的 Kubelet 负责启动和管控;
- AM 启动后定期向 RM 发送心跳,心跳信息包括自身运行状态,以及资源申请请求;
- AM 向 RM 申请更多资源,RM 将这些资源请求转换为 K8s 上的 Pod,由 K8s 负责调度和启动;
- 作业的其他 Pod 启动,开始实际计算,受 AM 管控。
上述过程和 YARN 完全相同,唯一的区别在于所有作业实例都收敛到 K8s 上,通过 Kubelet 启动容器并运行。
但是,YARN 系统负责启动和管控作业实例的 NodeMananger 组件具有很多 Kubelet 不具备的大数据特有功能。所以,Serverless YARN 还在每个节点上部署了大数据辅助插件,以弥补 Kubelet 的功能不足,比如:
- 提供为作业提前下载 Jar 包的功能(在大数据体系中称为 Localization) ;
- 启动计算引擎的 Shuffle 服务 ;
- 为大数据作业提供日志服务 ;
- 为大数据作业提供监控能力 ,等等。
Serverless YARN 还提供作业迁移工具,新作业可以无缝提交到 Serverless YARN 集群上,旧的 YARN 集群等到没有任何作业运行后,可以被操作下线。
更重要的是,Serverless YARN 做了深度的性能优化,RM 切主时间控制在秒级以内,Pod 调度吞吐提高到每秒 2000 个以上。
2.2 基于云原生的大数据统一 Operator —— Arcee Operator
Arcee Operator 是基于云原生的大数据统一 Operator,统一管控多种计算引擎。
Arcee 借鉴了 YARN 的两级管理模式,管理大数据作业的 Application Master,再由 AM 管理计算 Worker。
这种管理模式能够有效管理和表达大数据作业状态,定制作业管理策略,确保计算引擎对计算作业运行有充分的掌握能力,有能力按需调整资源使用。
除两级管理外 , Arcee Operator 还具备以下特性:
- Arcee 定义了统一作业实例:Arcee Operator 利用 K8s 的自定义资源定义了统一作业实例,无论是 Spark 还是 Flink ,或者使其他类 YARN 的计算引擎,都可以使用统一的 CRD 描述作业,包括作业配置、作业规格等信息,而且可以收集并展示作业的统一且详细的运行状态,有利于业务的统一表达和处理;
- Arcee 实现了作业异常处理:Arcee Operator 可以实时监控所有作业状态,处理作业异常,持续保障作业正常运行;比如因为节点磁盘故障而导致 AM 运行异常,Arcee 检测到后在其他节点重新启动 AM,并接管之前启动的 Work Pod,使作业恢复正常运行;
- Arcee 屏蔽了底层调度器:Arcee Operator 封装了底层调度功能,降低了作业使用高级调度策略的门槛,比如优先级调度、Gang 调度等大数据作业的强需求;并且可以从调度器上收集作业调度信息,然后对外展示,用户可以轻松知道“作业为什么没有进行调度”。
Arcee Operator 与其他云原生部署方案相比具有诸多优势,以 Spark 为例:
- Spark 社区推荐的 K8s Native 方式,Spark Pod 没有统一资源描述,很难进行管理和描述;
- Google 的 Spark Operator 在 K8s Native 方式的基础上封装了 CRD,提供了统一的资源描述,但是它是以旁路的方式实现的,基本不存在管控策略,而且不支持 Spark Client 模式。
相比上述两种方案,Arcee Operator 在适配大数据计算引擎的原生运行模式的同时,提供了 :
- 统一的作业描述,以及详细、准确的状态信息;
- 丰富的作业异常处理策略;
- 快速接入高级调度功能的能力。
3. 云原生大数据调度
火山引擎的云原生大数据系统存在三层资源管理:
- 全局的多机房统一资源湖 —— ResLake,负责全局统一的资源管理、调度、分发和容灾;
- 每个集群上,GRO Scheduler 负责集群内的 Quota 管控和 Pod 调度;
- 每个节点上,GRO Agent 负责单机调度和隔离增强。
3.1 基于云原生的高性能资源管理调度器 —— GRO
GRO Scheduler 是基于云原生的高性能资源管理调度器,管控集群资源,并结合 GRO Agent 实现单机调度、隔离、和混部能力。
3.1.1 GRO Scheduler
云原生系统原生调度器的主要功能是 Pod 放置,也就是为 Pod 选择一个最优的节点,但是这完全不能满足大数据作业的需求。
GRO Scheduler 参考 YARN 等大数据调度器,在 Pod 放置的基础上,增加了 Quota 管控。
整个调度流程如图:
- Quota 管控:调度器首先将集群资源分配给各个队列,然后将队列资源分配给该队列的各个作业,最后将作业资源分配给该作业的各 Pod。不是所有 Pod 都可以获得资源,只有获得资源的 Pod 才可以进入后续的 Pod 放置流程;
- Pod 放置:和原生调度器一样,首先为 Pod 筛选符合条件的节点,然后对筛选出来的节点进行打分,最后将 Pod 绑定到分数最高的节点上。
大数据作业,特别是批式计算,只会占用资源一段时间,运行结束后归还资源。为了保证大数据作业可以充分利用集群资源,通常用户会提交多个作业,部分作业不能立刻获得资源,而是排队等待,直到有作业结束退出,才开始获得资源开始运行。这其中涉及两个重要的概念,“队列”和“作业”。
云原生系统原生调度器最初是针对在线服务设计,没有这两个概念。
没有“ 队列 ”的概念:一个集群包含多个节点,可以供多个租户同时使用集群资源。为了避免一个租户占用集群全部资源,而影响到其他租户,集群的运维人员或者资源的管理人员非常希望能够按照一定比例,或者按照指定数量将集群资源分配给不同租户。而云原生系统不支持这样的多租户资源管控能力。
没有“作业”的概念:在大数据集群里,一定存在作业排队的情况,对于这些不同的作业,哪些获得资源,哪些排队等待,是需要一个能够感知作业优先级、规格或其他信息的资源分配策略的。云原生系统只有 Pod 的概念,而不能感知作业,不具备作业级的调度策略。
因此,为了更好地支持大数据场景资源分配, GRO 使用 K8s 自定义资源能力新增这两个概念 :
- Queue CRD:描述了一个“队列”,即 Quota(资源配额)的抽象;
- PodGroup CRD:描述了一个“作业”,标识多个 Pod 属于同一个集合,从而可以把多个 Pod 看作整体进行调度。
GRO 的每个队列有两个资源配额属性:
- Min Quota,又称为保障资源量。调度器为该队列预留 Min Quota 的资源量,不允许其他队列占用,以保障该队列在需要使用时可以立刻获得资源;
- Max Quota,又称为资源使用上限。调度器限制该队列使用资源不超过 Max Quota 的资源量。
GRO 将根据所有队列的 Min-Max 属性,将集群资源公平地分配给各个队列,再根据不同的调度策略,将队列资源公平地分配给队列内的各个作业,再进一步分配各作业内的各个 Pod。
目前支持的几种常用调度策略:
- 优先级调度:所有作业按照定义的优先级排序,调度器优先分配高优先级的作业;
- Gang 调度:调度器一次性为作业的所有 Pod 分配资源,或者一个 Pod 也不分配,保证不出现一个作业的部分 Pod 启动,部分 Pod 排队等待的情况;一个作业只有部分 Pod 启动,有可能不能正常运行,这样不仅浪费了集群资源,还可能存在多个类似作业相互死锁,导致所有作业都不能正常运行;
- DRF 调度:调度器公平分配资源给各个作业的同时,兼顾多维度资源的比例,尽可能提升资源利用率;比如队列剩余大量 CPU 和少量内存时,优先分配 CPU 需求多、内存需求少的作业,避免队列的内存完全耗尽,大量 CPU 剩余,无法被利用的问题。
GRO 还支持其他 Quota 管控策略 :
- 队列间抢占:队列没有使用的 Quota 允许临时被其他队列占用,当队列有资源需求时,可以从其他队列将资源抢占回来;
- 队列内抢占:队列没有剩余 Quota,高优作业提交后可以将正在运行的低优作业占用的资源抢占回来;
- 大作业资源预留:资源需求较大的作业很有可能因为节点资源碎片一直无法调度,调度器支持预留节点资源,保证大作业调度成功。
GRO Scheduler 具有强大的 Pod 放置能力, 支持将一个 Pod 调度到具体节点的各种不同策略,支持大部分原生调度器功能,比如节点名称、节点 Label、节点污点、亲缘性、集中调度、均衡调度等策略;也支持大数场景的高级策略,比如真实负载平均、GPU 共享、微拓扑调度等策略。
GRO Scheduler 具有极高的调度吞吐,采用批式调度,在支持复杂调度策略的前提下,调度吞吐性能仍然可以达到每秒上千个 Pod。
GRO Scheduler 具有丰富的信息统计,支持队列的资源统计,作业的状态、资源、计量统计,作业的运行事件等信息的收集和展示等。
大数据作业部署在云原生系统上,在线服务也部署在云原生系统上,在离线业务可以同时部署到同一个集群上。GRO Scheduler 统一管控云原生集群资源,同时调度在线服务和大数据作业。
- 在线服务高峰时,离线计算尽量停止运行,在线服务使用集群大部分资源;
- 在线服务低谷时,在线服务让出大部分资源,离线计算开始运行。
以证券交易场景为例,每天交易时间是固定的,这期间在线服务承接大量流量,需要大量资源,离线计算作业全部停止,优先保证在线服务运行;当交易时间结束后,在线服务没有流量,资源闲置,离线计算作业开始运行。
以上,在离线资源可以高效且灵活地相互转换,整个集群利用率得到极大地提升,实现降本增效。
同时,面对在离线业务,基础组件运维人员只需要维护云原生集群,降低维护开销。
3.1.2 GRO Agent
在线服务和大数据作业可以运行在一个集群,不可避免地也会运行在一个节点上。但是大数据作业的运行特性是大幅利用机器资源,是有可能会影响到在线服务的。
云原生系统的资源隔离机制可以限制每个 Pod 的 CPU 时间片和内存使用量,但是这样的隔离程度是不够的。比如大数据作业导致节点 Load 升高,会影响到同一个节点上的在线服务。
因此,GRO Agent 部署到每个节点上,用于增强单机隔离性。
单机隔离手段包括 CPU(调度权重、核心隔离)、内存(独立内存水位)、磁盘(IOPS/带宽限制)、网络(网络打标流量限制)等多个层面。
GRO Agent 支持在线 SLA 保障机制,监控节点上在线服务的运行情况,结合业务指标、资源指标、基础指标等,在必要情况下,可以驱逐大数据 Pod,或者通知调度器重新迁移在线服务,以保障在线服务的稳定性。
3.1.3 闲置资源利用
GRO 支持闲置资源利用,实现资源超发,更进一步提高资源利用率,降低成本。
举例来说,一个 4 核的 Flink Pod,在高峰期资源使用率是 3.9 核,但是低谷期资源使用率只有 0.2 核。因此不能简单的减少 Flink Pod 的资源申请量,但是低谷期时会存在资源的大量浪费。因此 GRO 可以在低谷期时,调度一个低优的 Pod,利用空闲的 3.8 核资源。
运行流程简述:
- GRO Agent 监控所有 Pod 的资源使用情况,结合实时/历史资源变化曲线,实时计算出节点上可以被重复利用的闲置资源量(BestEffort 资源);
- GRO Agent 上报 BE 资源量到 GRO Scheduler;
- GRO Scheduler 调度有预期的低优作业到节点上使用 BE 资源;
- GRO Agent 通过单机隔离机制保障正常 Pod 的稳定性和性能;
- GRO Agent 根据 BE 资源变化情况压缩混部 Pod 资源或者驱逐混部 Pod。
3.2 基于云原生的多机房统一资源湖 —— ResLake
ResLake 是基于云原生的多机房统一资源湖,统一管理全局计算、存储、网络资源,并提供全局容灾能力。
数据中心通常存在多个机房,每个机房也存在多个集群,而每个集群上都存在不同队列。用户面对不同机房、不同集群的多个队列,存在一定使用成本。
ResLake 提供了全局虚拟队列。 每个虚拟队列对应不同机房或集群的多个队列。用户提交作业到虚拟队列,ResLake 考虑资源情况、存储亲和性等因素,自动分发到合适的机房、集群和队列。
另外,ResLake 还提供了全局 Quota 管控。 ResLake 在调度作业时,会考虑 Quota 约束、数据局部性、机房拓扑、自定义约束等条件。
ResLake 优先调度作业到和存储资源更“近”的计算队列。这里的“近”,包括同一个集群、同一个集群,或者网络通信开销较小的不同机房。
ResLake 还支持管理和调度存储资源:
- 针对周期性作业,ResLake 提交将存储资源搬迁到计算队列所在的机房;
- 针对临时查询,如果存在跨机房读取存储数据,ResLake 将存储资源缓存在目的机房一段时间。
全局的计算和存储资源调度,可以避免大规模跨机房网络通信,达成“最优化资源利用率。最小化作业完成时间”的最终调度目的。
ResLake 支持分发作业到具体的集群和队列 :
- 支持一个作业全部分发到同一个队列;
- 支持一个作业的不同实例按照指定比例或者指定数量分发到不同队列,包括同集群、同机房的不同集群、不同机房的队列等。
结合上述分发策略,ResLake 提供三种容灾能力:
- 迁移容灾 :
- 灾难发生后,自动重新提交作业到备用队列;
- 备用集群资源不足时,自动杀死低优作业以腾出资源;
- 多活容灾 : 基于多副本的输入/输出,在备用队列启动副本作业;
- 高可用容灾 : 基于作业自身 HA 能力,作业子实例被分发到两个队列同时运行。
4. 云原生大数据助力金融
火山引擎云原生大数据平台致力于金融行业云原生大数据解决方案 :
- Serverless YARN:基于云原生的 YARN 解决方案。
- Arcee Operator:基于云原生的大数据统一 Operator。
- GRO:基于云原生的高性能资源管理调度器。
- ResLake:基于云原生的多机房统一资源湖。
上述四个解决方案提供了精细强大的作业管理能力,高效极致的资源管理能力和跨机房作业容灾能力,帮助大数据作业平滑迁移到云原生系统。满足用户在硬件资源不增加的情况下承载更多业务,整体提升集群资源利用率。