快手基于 Flink on K8s 的生产应用实践
1. 背景
2. 生产改造
3. 迁移实践
4. 未来改造出品社区|DataFun
01
背景
1.快手 Flink 发展历程
快手的Flink架构经过了五年的发展,整个过程大致可以分为三个阶段。
2018年到2020年,建设实时计算平台,助力公司各大部门向实时化转型,在 Flink runtime、 SQL、状态引擎三个方向达到生产可用。
2021年到2022年,主要在易用性、稳定性、功能性方面做深度优化,支持更大规模场景以及更稳定的服务,同时在流批一体和湖仓一体等方面进行了深入的探索。
2022年到2023年,在多个方面进行探索和落地:首先是 Flink 到 K8s 转型;其次是Runtime adaption 运行自适应;第三个是AI场景在快手大规模落地;最后是快手周边生态的建设和完善。
在实时数据流方面有广泛的应用,涵盖音视频、商业化推荐等核心业务;
基于Flink引擎进行流批一体、湖仓一体的建设;
在AI场景的大规模应用,涵盖特征工程,数据加工等场景;
当前Flink应用的规模,公司总的 CPU 核数是一百多万,Flink 作业数大概在1万到2 万之间,峰值处理能力超过 10 亿每秒,每天处理的数据量远远超过 100 万亿。
2018年到2021年,Flink 主要使用 Yarn。主要原因是,在初期 Yarn 和 Flink 结合的比较好,Yarn 的调度性能较好,可以支撑上万节点的调度,而 K8s 在早期不能支持这么大的节点。另外 Yarn 可以有效的整合 Hadoop 生态,方便使用 HDFS 和 Hive。
2022到2023年,Flink 切换到 K8s。主要因为 K8s 是一个统一的云生态,有丰富的应用,是云生态基础架构发展的大趋势;另外在 K8s 上可以做统一的资源管理、统一的应用管理以及在离线混部等架构规划;最后,K8s 有很好的隔离性,能够提供更稳定的生产保障。
4.Flink 当前整体架构
最底层是资源层和存储层,资源层使用 K8s 和 Yarn,存储采用 HDFS 和 Kwaistore; 计算层,基于 Flink Streaming&Batch 来提供统一的 runtime 层支持; 应用层,分为在线平台和离线平台; 最上层为业务层,涵盖公司的各大部门。
02
生产改造
为了适应云原生的大趋势,我们进行了 Flink on k8s 的开发和迁移。
1.核心痛点
设计:如何从 Yarn 平滑过渡到 K8s,兼顾用户体验和系统设计。在用户层面做最小改动,避免用户造成额外学习的成本。在系统层面,资源层做统一抽象,确保平滑过渡。
开发:快手当前使用的 Flink 是1.10版本,该版本下的 K8s 有较多的功能和 bug 需要重构和完善。
测试:需要完整全面的测试。
2.系统设计
3.功能开发
Flink client:主要负责定义 pod 模板,定义作业执行拓扑图,将作业提交到 K8s master 节点。
K8s master:分为控制和存储;控制层启动 Flink 任务 APP,做任务持久化操作,存储将信息存储到 ETCD,最终启动 Flink 的主节点。
Flink:
运行模式分为三种:
session 模式:常驻集群,做长轮询监听新任务,执行新任务。这种模式下一个session 会有多个作业,会存在隔离性安全问题.
perJob 模式:单作业模式,胖客户端模式,隔离性较好。在快手中,主要以这种模式为主。
application 模式:单作业模式,瘦客户端模式,将启动压力分散到集群上,客户端压力较小。在项目前期,功能不完善,比如一些自定义 UDF 和 jar 包的加载出现问题,后期逐渐完善。
实现方式:
对Flink进行改造,将1.10和1.17做封装。将使用 Flink 1.10的作业进行适配。同时也对 Flink 1.17进行封装。适配之后,用户看到的都是类似 perJob 的单作业模式。在此基础上,扩展资源管理能力,做到 native 的作业可以按需申请资源,以及资源快速分配;在性能方面,支持 K8s 上万 pod 快速启动;在稳定性方面,通过 metric 指标做到可观测性,同时提供日志服务,方便系统问题排查。
可观测性对系统至关重要,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 进行梳理,在搭建新环境之后,能做全量的测试,保障系统稳定。
Flink 自身指标,比如 Flink 延时,快照成功率;
性能指标,GC 实践,CPU 使用率,如果指标异常,需要用户进行资源调整;
反压率,在流式计算中出现背压,说明作业处理有问题;
数据倾斜率,水平差,综合反应作业健康程度;
提供接口,用户自定义接口指标。
4.资源收益
人力成本收益,将资源的底层配置统一化,减少了资源配置和迁移实践,降低了运维成本。
避免机器长时间闲置,提高了固定资产的使用效率。
未来工作主要包括以下几大部分:
存算分离:1.底层用 Kwaistore,目前支持存算分离,接下来会整合 flink,支持超大状态;2.去掉 Flink 的快照,由于 Kwaistore 已经具备持久化的功能,我们可以直接将 state 存储到上面,而不用周期性的往外部共享存储写快照。
资源管理:建设优先级抢占机制,不同的作业有不同的级别,比如 P0、P1 级别作业有 AZ 逃生能力, P2 是重要作业,P3 是低优先级作业,不同作业有不同的资源保障等级。在离线混部,将在线业务和离线任务混合混部到相同物理资源上,通过资源隔离、调度等控制手段 , 充分使用资源,同时保证服务的稳定性,提供资源利用,起到降本增效的效果。
Runtime adaption:提供动态扩容,以及算子的动态增删,实现运维更轻量级操作,降低成本和负担。
统一生态:将实时、近实时、批处理作业都统一到 K8s;另外与 Runtime adaption 结合,提高系统服务化能力。
以上就是本次分享的内容,谢谢大家。
分享嘉宾
INTRODUCTION
刘建刚
快手
技术专家
毕业于北航,先后任职于搜狗、百度,于2018年加入快手并推动 Flink 在快手的深度改造和生产可用。
资料领取
优质文章
往期推荐
点个在看你最好看