Fork me on GitHub

Flink on K8s在快手的实践

以下文章来源于 https://zhuanlan.zhihu.com/p/662925927

导读 本文将分享 Flink on K8s 在快手的实践。今天的介绍会围绕下面四点展开:

  1. 背景

  2. 生产改造

  3. 迁移实践

  4. 未来改造分享嘉宾|刘建刚 快手 技术专家编辑整理|戴志敏内容校对|李瑶

出品社区|DataFun

01背景

首先来简要介绍一下Flink在快手应用的背景。

1.快手 Flink 发展历程

快手的Flink架构经过了五年的发展,整个过程大致可以分为三个阶段。



  • 2018年到2020年,建设实时计算平台,助力公司各大部门向实时化转型,在 Flink runtime、 SQL、状态引擎三个方向达到生产可用。
  • 2021年到2022年,主要在易用性、稳定性、功能性方面做深度优化,支持更大规模场景以及更稳定的服务,同时在流批一体和湖仓一体等方面进行了深入的探索。
  • 2022年到2023年,在多个方面进行探索和落地:首先是 Flink 到 K8s 转型;其次是Runtime adaption 运行自适应;第三个是AI场景在快手大规模落地;最后是快手周边生态的建设和完善。

2.Flink 在快手的应用场景



  • 在实时数据流方面有广泛的应用,涵盖音视频、商业化推荐等核心业务;
  • 基于Flink引擎进行流批一体、湖仓一体的建设;
  • 在AI场景的大规模应用,涵盖特征工程,数据加工等场景;
    当前Flink应用的规模,公司总的 CPU 核数是一百多万,Flink 作业数大概在1万到2 万之间,峰值处理能力超过 10 亿每秒,每天处理的数据量远远超过 100 万亿。

3.Flink 架构演进



  • 2018年到2021年,Flink 主要使用 Yarn。主要原因是,在初期 Yarn 和 Flink 结合的比较好,Yarn 的调度性能较好,可以支撑上万节点的调度,而 K8s 在早期不能支持这么大的节点。另外 Yarn 可以有效的整合 Hadoop 生态,方便使用 HDFS 和 Hive。
  • 2022到2023年,Flink 切换到 K8s。主要因为 K8s 是一个统一的云生态,有丰富的应用,是云生态基础架构发展的大趋势;另外在 K8s 上可以做统一的资源管理、统一的应用管理以及在离线混部等架构规划;最后,K8s 有很好的隔离性,能够提供更稳定的生产保障。

4.Flink 当前整体架构

快手当前的 Flink 架构如下图所示:



整体分为以下几层:

  • 最底层是资源层和存储层,资源层使用 K8s 和 Yarn,存储采用 HDFS 和 Kwaistore;
  • 计算层,基于 Flink Streaming&Batch 来提供统一的 runtime 层支持;
  • 应用层,分为在线平台和离线平台;
  • 最上层为业务层,涵盖公司的各大部门。

02生产改造

为了适应云原生的大趋势,我们进行了 Flink on k8s 的开发和迁移。

1.核心痛点



  • 设计:如何从 Yarn 平滑过渡到 K8s,兼顾用户体验和系统设计。在用户层面做最小改动,避免用户造成额外学习的成本。在系统层面,资源层做统一抽象,确保平滑过渡。
  • 开发:快手当前使用的 Flink 是1.10版本,该版本下的 K8s 有较多的功能和 bug 需要重构和完善。
  • 测试:需要完整全面的测试。

2.系统设计



用户接口层,核心交互分为 Flink 作业管理平台和资源管理系统,接口对用户不变,客户只需要在使用的时候选择 yarn 或者 k8s 集群,就可以使用对应的平台。在底层的实现上,通过将 K8s 和 Yarn 做统一的封装,将 K8s 中的 AZ 和 Cluster 对齐,在 K8s 通过 CRD 自定义队列,映射到 Yarn 的队列,从而将 K8s 和 Yarn 做完全的映射。通过以上方式,实现了 Yarn 和 K8s 组件最大程度的复用,以此实现统一接口。

3.功能开发

(1)整体架构



整体架构分为3个部分:

  • Flink client:主要负责定义 pod 模板,定义作业执行拓扑图,将作业提交到 K8s master 节点。
  • K8s master:分为控制和存储;控制层启动 Flink 任务 APP,做任务持久化操作,存储将信息存储到 ETCD,最终启动 Flink 的主节点。
  • Flink:

Dispatcher:提交作业,实现 rest 服务;Resource Manager:作为统一资源调度,分为 Yarn 的 Resoure Manager 和 K8s 的 Resource Manager,负责实现不同资源的调度管理;JobMaster:负责 job 的具体执行,同时向 Resource Manager 申请资源,并将作业部署到 Flink 的 task Manager上,然后通过 task Executor 执行节点任务;LogService: 提供日志采集与查询服务;MeticReporter:系统指标实时监控;Ingress&service: 对外提供 Flink 服务;Kwaistore:负责存储作业状态和数据。(2)运行模式



运行模式分为三种:

  • session 模式:常驻集群,做长轮询监听新任务,执行新任务。这种模式下一个session 会有多个作业,会存在隔离性安全问题.
  • perJob 模式:单作业模式,胖客户端模式,隔离性较好。在快手中,主要以这种模式为主。
  • application 模式:单作业模式,瘦客户端模式,将启动压力分散到集群上,客户端压力较小。在项目前期,功能不完善,比如一些自定义 UDF 和 jar 包的加载出现问题,后期逐渐完善。

实现方式:

对Flink进行改造,将1.10和1.17做封装。将使用 Flink 1.10的作业进行适配。同时也对 Flink 1.17进行封装。适配之后,用户看到的都是类似 perJob 的单作业模式。在此基础上,扩展资源管理能力,做到 native 的作业可以按需申请资源,以及资源快速分配;在性能方面,支持 K8s 上万 pod 快速启动;在稳定性方面,通过 metric 指标做到可观测性,同时提供日志服务,方便系统问题排查。

(3)可观察测性



可观测性对系统至关重要,Flink 通过 metric 获取 Flink 吞吐量、内存、CPU 和checkpoint 等信息,但是 K8s metric 存在以下问题:

  • Flink on K8s 以 pod 为粒度汇报 metric 资源,连接数过多,容易把 metric 系统打爆。
  • K8s Prometheus 监控在海量 metric 存在性能问题,扩展性差。
  • 另外还需要考虑如何跟之前的 metric 处理保持兼容。在当前的系统中既有 Yarn 又有 K8s,在为用户提供统一视图的情况下,保持两者兼容。

具体实现如下:

Flink on k8s 通过 KafkaGateWay 服务来进行局部的 metric 汇总,从而减少与 Kafka 的连接总数。那么 yarn 和 k8s 这二者的 metric 是如何做到统一的呢?Yarn 的监控视图是以机器为粒度做了 local 的聚合,然后发到 Kafka。K8s 在 kafka 和 flink 之间做了一层缓冲和聚合,然后再将 metric 发送给 Kafka。至此,metric 都统一汇总到了kafka,后面再去接统一的 OLAP 引擎和 grafana 进行分析和展示。

(4)问题排查



问题排查最重要的一环是查看日志,在 K8s 中,存在以下几个问题:1.pod 结束之后,日志也会随着 pod 消失,导致作业结束之后无法查看日志;2.pod 自身问题的诊断,比如 pod 没有启动起来。

我们的解决方法为:

在每台机器上面部署一个日志服务,将日志和 pod 解绑,将日志写到 hostPath,然后由 K8s 统一进行管理。通过搭建的 webservice 访问机器上的日志。对于用户高优或者个性化的需求,采集到 ES 上。另外对 K8s 的 event 进行简化,通过日志服务暴露给用户。通过以上方式,用户自己可以查看日志,定位问题。

(5)测试



  • 集成测试:各个组件集成,进行端到端测试,保障整体功能完善。
  • 故障测试:分成3个方面:1. Flink 自身测试,包括 Flink job master 的 failover,Flink slave 的 failover,Flink task 的 failover,确保这些在 K8s 环境下能正常恢复;2. K8s 发生异常对系统的影响,包括 ETCD 存储异常,Kubelet 异常,master 节点异常等;3. 集群硬件异常,包括机器假死,磁盘故障,网络异常,确保在这些情况下,Flink 能正常恢复。
  • 性能测试:1. Flink 自身性能测试,确保在K8s虚拟化环境下,与在主机环境下的性能基本持平;2. K8s 的 apiserver 的性能问题,在大集群环境下,K8s 主节点会有较大的负载出现,确保在高负荷情况下,对系统的影响最小;3. K8s 调度优化,确保服务具有 AZ 逃生能力,在分钟级别情况下能调度起上10万的 pod。
  • 回归测试:将日常使用的 case 进行梳理,在搭建新环境之后,能做全量的测试,保障系统稳定。

03迁移实践

接下来介绍迁移的工作。主要包括四大痛点,在用户层面,针对单 job 要做到无缝迁移;作业量比较多的场景下,要为用户提供批量迁移工具,做到批量迁移;在迁移的过程中,做作业健康的检查,对于不健康的作业实现一键回滚;资源这块,需要做到资源的快速置换和调配。

1.用户迁移

将用户的配置做拆分,分为常规配置和集群配置。集群的配置在作业启动的时候自动生成,用户只需要指定是 Yarn 或者 K8s,在提交的时候自动生成相适应的配置,提交到相应的集群。做到 Yarn 和 K8s 的无缝迁移,屏蔽底层集群配置,使得用户学习成本最小。

2.批量迁移

将 Flink 队列作为批量迁移基本单位,迁移过程优先选择低优先级或者拓扑结构简单的作业,等这些作业没有问题之后,再选择高优和拓扑比较复杂的作业。然后给用户提供批量迁移工具,用户只需要指定目标集群是 k8s 即可,Flink 平台会在 Yarn 上生成快照,并从 k8s 上恢复,做到状态不丢不重。之后对作业进行健康监控,如果作业有问题,可以实现一键回滚操作。确保整个迁移过程全自动化,用户不需要介入。



3.作业健康度

对 Flink 每个作业指标建模,将关键指标汇总,然后按照0-10分对这些指标进行打分,对于不健康的作业,可以使用一键回滚,也可能通过指标分析出作业的问题所在。



  • Flink 自身指标,比如 Flink 延时,快照成功率;
  • 性能指标,GC 实践,CPU 使用率,如果指标异常,需要用户进行资源调整;
  • 反压率,在流式计算中出现背压,说明作业处理有问题;
  • 数据倾斜率,水平差,综合反应作业健康程度;
  • 提供接口,用户自定义接口指标。

4.资源收益

  • 人力成本收益,将资源的底层配置统一化,减少了资源配置和迁移实践,降低了运维成本。
  • 避免机器长时间闲置,提高了固定资产的使用效率。


04未来改造

未来工作主要包括以下几大部分:



  • 存算分离:1.底层用 Kwaistore,目前支持存算分离,接下来会整合 flink,支持超大状态;2.去掉 Flink 的快照,由于 Kwaistore 已经具备持久化的功能,我们可以直接将 state 存储到上面,而不用周期性的往外部共享存储写快照。
  • 资源管理:建设优先级抢占机制,不同的作业有不同的级别,比如 P0、P1 级别作业有 AZ 逃生能力, P2 是重要作业,P3 是低优先级作业,不同作业有不同的资源保障等级。在离线混部,将在线业务和离线任务混合混部到相同物理资源上,通过资源隔离、调度等控制手段 , 充分使用资源,同时保证服务的稳定性,提供资源利用,起到降本增效的效果。
  • Runtime adaption:提供动态扩容,以及算子的动态增删,实现运维更轻量级操作,降低成本和负担。
  • 统一生态:将实时、近实时、批处理作业都统一到 K8s;另外与 Runtime adaption 结合,提高系统服务化能力。

以上就是本次分享的内容,谢谢大家。



本文地址:https://www.6aiq.com/article/1698109231654
本文版权归作者和AIQ共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出