一、背景与问题
在生产环境下,Flink 作业长期稳定运行依赖状态存储与Checkpoint 机制保障容错与 Exactly-Once 语义。随着作业运行时间增长、作业数量逐渐增多、Key 数量膨胀、Checkpoint 持续生成,状态数据与元数据会不断累积。本文从一次Flink作业状态数据监控治理不及时引发的生产问题,深入分析Flink的元数据清理机制,并制定合适的应对策略,保障Flink作业的生产稳定运行。
公司内部的Flink集群是一个基于Native K8s部署的公共集群,面向用户提供namespace粒度的计算资源,用户将对应系统的Flink作业提交运行在制定的namespace。另外,Flink公共集群开启了Flink HA,HA元数据与Flink作业的Checkpoint/Savepoint数据统一存储在公共Hadoop集群的HDFS,路径为对应用户在HDFS上的app目录下。
在日常Flink集群与作业的运行维护中,除了用户因需求变更、性能优化等原因进行停启作业,也会经常遇到集群配置优化、漏洞修复等公共变更操作,需要所有作业配合重启来生效。有一次配合机房网络设备变更,将集群所有作业停止下来(做了Savepoint),等待机房网络设备完成变更后,再次启动所有Flink作业的过程中出现了问题,大批量作业启动运行一段时间后全失败停止了。
二、问题排查
随机挑选了几个Flink作业,查看运行日志(使用Fluent-operator采集日志存储在ES用于查询历史运行日志)发现所有作业都报错相同异常NSQuotaExceededException:the namespace quota(directories and files) of director xxx is exceeded : quota=xxx
接着找到负责Hadoop集群的同事排查HDFS quota情况,反馈结果如下:
1.公共Hadoop集群对外提供了公共app目录空间,供用户个性化使用;出于数据管控治理要求,对每个接入使用app空间的用户划分子目录,增加认证鉴权与配额管理(默认15000)。
2.报错的用户子目录下的文件配额确实已经用满达到15000了。
三、问题分析
报错的子目录下只有Flink配置的Checkpoint/Savepoint/HA目录,该用户总共有上百个Flink作业,所以目录配额满了是因为这三块元数据产生的文件与目录数达到HDFS的目录配置上限,经过排查分析,目录下存在很多过期、无用、残留的元数据(因异常重启、版本迭代等)。
Flink的Checkpoint目录主要存储由Flink自身定时(默认1min一次)触发的Checkpoint快照元数据,用于Flink容错恢复,目录结构大致如下:
/flink-checkpoints/jobid/chk-n/_metadata
/flink-checkpoints/jobid/chk-n/short-id
/flink-checkpoints/jobid/shared/short-id
/flink-checkpoints/jobid/taskowned/short-id
因为配置了num-retained(当前配置为3),正常情况下Flink作业运行仅保留3个最新版本的chk,过期会自动删除。结合实际情况发现,存在一些历史chk失败中断、异常停止退出等产生的过期残留文件。
Flink的Savepoint目录主要存储由用户主动触发Savepoint产生的快照数据,用于从指定状态点位重新启动作业,目录结构大致如下:
/flink-savepoints/savepoint-short-id/_metadata
/flink-savepoints/savepoint-short-id/short-id
Savepoint是用户手动触发(当前是作业停止会自动触发)的,Flink不会自动清理,需要人工干预,否则会不断积累。
Flink的HA目录主要存储JobManager leader 信息、JobGraph、Checkpoint 元数据、作业状态等,用于JM异常切换恢复,目录结构大致如下:
/k8s-ha/cluster-id/blob/job_jobid/blob_p-short-id
/k8s-ha/cluster-id/completedcheckpoint[n]
/k8s-ha/cluster-id/submittedJobGragh
Flink 不会自动清理 HA 元数据,官方也没有提供自动清理过期 / 废弃 HA 元数据的内置机制,Flink HA 只保证 “高可用切换”,不负责 “垃圾回收”,需要人工干预增加清理,否则也会日积月累,占用大量 HDFS 存储空间。
综上所述,此次问题是由于Checkpoint/Savepoint/HA目录数据日积月累而没有数据治理,直接导致目录下文件数超过配额限制引发作业异常。
四、解决方案
当前上游Kafka-topic的TTL为1-7天不等,状态元数据清理策略应与之契合。
1.Checkpoint 治理:增加定时脚本清理,清理7天未访问的 CP 目录、0KB / 不完整 CP 文件、无对应作业的孤儿 CP文件(Flink自身能清理运行中的过期chk)
2.Savepoint 治理:增加定时脚本清理,清理超过7天的历史 SP,只保留最近 1~2 个用于回滚
3.HA 元数据治理:增加定时脚本清理,清理K8s 中已不存在的作业对应的 HA 目录
4.孤儿作业及数据治理:排查期间发现存在作业已停止、但K8s后台仍运行的孤儿pod,对此类作业与元数据一并筛选清理
5.考虑作业的增长规模、维护频次等方面,调大HDFS的目录配额(最直接)
6.增加HDFS目录文件数的监控与预警,达到水位线及时人工干预
对于本次问题,优先采用调大HDFS目录配额的方案进行快速恢复生产作业,然后2周内完成Checkpoint/Savepoint/HA的数据治理配套建设与HDFS目录文件数的监控预警配置,多方位保证作业健康稳定运行。
五、总结
Flink的状态存储与HA机制保障了作业运行的高可用与高容错,对于技术人员来讲,每一次生产问题的排查都是对Flink运行机制的一次深入了解,更是对自身技术知识的沉淀与经验积累,会更从容地应对未来的问题与风险。