一、背景
现有生产环境存在2个版本Flink(1.14.6与1.16.1),均采用flink on native k8s部署、Application模式提交运行作业。
Flink作业启动配置由基础配置(统一固定配置,Flink基础镜像+ pod-template.yaml)+应用配置(Flink参数配置)拼装而成,其中pod-template.yaml中配置了OBS挂载,用于存储公共的依赖jar与配置。
对于FLink作业的生产参数配置,根据实时处理的数据量与逻辑复杂度,主要配置合适的JM-cpu/内存、TM-cpu/内存、并行度、slot数,其他统一配置在基础配置为默认配置(如ckp模式与间隔、失败率重启策略、region恢复等)。
二、问题现象
生产环境下两个版本的FLink作业大概有10%的作业存在不定期因容器内存使用率100%触发容器重启的现象(JM与TM都有类似情况),同时有20%左右的作业容器内存使用率维持在85%以上的高水位,部分仍在缓增,影响生产稳定性。
三、问题排查
-
查看作业运行日志
不同作业容器在重启前会有各种不同的报错日志,如找不到jar、连接断开等,经过共性分析,在报错前大多会有容器退出码exitCode=133,exitcode=137,reason=OOMKilled等日志信息。
-
查看作业监控
容器内存使用率在100%
-
堆内存使用率正常
-
其他监控指标均无异常(直接内存、ckp、gc、反压、网络等)
四、问题分析
1.基于排查的日志信息与指标监控数据,将问题原因指向FLink作业进程容器的内存使用率过高。
2.分析FLink进程与容器的关系:每个JM/TM的pod都仅启动一个container,因配置了obs挂载,container中除了FLink进程,还有一个obs挂载进程(内存仅占用不到10M)。同时检查pod-template的资源配置,发现配置的容器资源参数的requests与limits保持一致,即TM的process内存配置4G,则容器内存为4G,Flink进程内存也同样为4G,存在内存波动触发容器oomkilled的风险较大。
3.分析Flink内存模型:Flink作业的进程内存主要分为FLink内存与JVM内存(JVM Metaspace/Overhead),JM与TM的Flink内存模型也因职能不同而存在差异,相对JM而言,TM大体上多出了Network与Managed内存区域(暂不考虑task/framework的影响)。从Java进程的视角看,FLink作业的占有内存分为堆内内存与堆外内存(包含直接内存等),而结合此问题的日志与监控信息,能分析推导出是FLink作业进程的堆外内存占用持续高水位,无法被GC回收,只能交由操作系统内存管理,不可控。
4.分析Flink进程堆外内存:主要包含Managed-memory、Direct-memory、JVM Metaspace/Overhead这几部分。查看prometheus-grafana监控与FlinkUI,能观测到的内存使用率也未达到高水位。(Managed-memory、Network-memory都属于内存预分配固定资源)
五、解决方案
1.调大JM/TM的process内存(简单粗暴,但实际上不能一直往上调)
2.进程与容器间增加内存缓冲buffer(适合批量通用场景)
-
- pod-template中资源配置limits大于requests(两个版本Flink尝试修改后无效)
- 增加kubernetes.jobmanager.memory.limit-factor与kubernetes.taskmanager.memory.limit-factor参数(1.15+后才有的参数,验证可用有效)
3.调整Flink进程堆内外内存比例(需精细化调优)
-
- 增加作业并行度(降低单实例的内存占用)
-
- 减少TM分配的slot数量(减少多slot内存消耗)
-
-
降低堆内存使用比例(不推荐,需精准掌控)
-
设置参数:env.java.opts.taskmanager=-Xms1G -Xmx1G 【此值建议设置
为: process内存配置 *0.4 *0.8】
- 0.4是基于Flink内存默认分配公式计算而来,代表TM的JVM堆内存分配值
- 0.8表示堆内存压降系数,需保障堆内存使用率在合理区间,避免gc影响
-
-
-
设置参数:env.java.opts.jobmanager=-Xms1G -Xmx1G【此值建议设置为:process内存配置 *0.8 *0.8】
- 0.8是基于Flink内存默认分配公式计算而来,代表JM的JVM堆内存分配值
- 0.8表示堆内存压降系数,需保障堆内存使用率在合理区间,避免gc影响
-
-
项目中实际结合上述三点进行优化调整,所有Flink作业的容器内存使用率最高不超过90%,因oomkilled导致容器重启的问题彻底解决,生产运行瞬间稳了。
六、总结
高内存使用率一直都是生产稳定的隐患,对于实时Flink作业的内存管理尤为重要。我们要在事前充分评估好作业的资源参数配置,并经过数据压测,提前准备应急预案;事中要做好作业运行指标监控与阈值预警,及时掌握运行情况与风险识别应急处置; 事后要做好复盘沉淀与健康治理,将生产风险扼杀于摇篮。