K8S容器OOM killed排查

背景

数据服务平台南海容器k8s设置的内存上限2GB,多次容器被OOM killed。

启动命令

shell 复制代码
java -XX:MaxRAMPercentage=70.0 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/apps/logs/ ***.jar

排查过程

1 当收到实例内存超过95%告警时,把jvm进程堆dump下来后,用visual vm分析堆内存,并未发现内存泄漏。推测进程就需要花较多的内存,是内存分配不够。遂将内存增加到4GB。继续观察

2 南海和顺德docker实例依然OOM killed。 当实例内存超过95%时,dump出堆内存并分析,依然没有发现内存泄漏,比较正常。

3 怀疑是容器内部除了java的其他进程耗用了容器内存。当实例内存超过95%时,对比top显示的的jvm进程内存和ps stats输出的docker实例内存信息,其余进程耗用的内存忽略不计。

4 由于堆内存没有的到达上限,但是整个jvm进程内存超出了容器的内存限制。因此推测是对外内存(本地内存,栈内存等,元数据空间等)耗用较大,执行命令

shell 复制代码
/****/jcmd 1 VM.native_memory

VM.native_memory特性并未开启。

5 观察到一个现象,docker进程被oom killed之前,java应用堆内存并没有被Full gc。并且堆内存没有用到上限值2.8GB(4 * 0.7)。docker是go语言编写,并没有GC的能力。docker耗用完内存前,堆内存并没有达到上限,于是没有触发老年代GC,内存没有降下去。当堆内存不够的时候,依然会找docker容器申请内存。

6 修改jvm配置,将南海的MaxRAMPercentage降到60, 南海分组的堆内存上限变成2.4GB(4 * 0.6),顺德分组不变。并增加-XX:NativeMemoryTracking=summary配置。8.18日重启所有实例使新增的配置生效。观察一段时间

发现南海分组的full gc更加频繁,继续观察

结论

如果容器OOM killed,容器里的jvm进程没有Full GC,那么肯定是MaxRAMPercentage参数太高,导致堆内存没有用到上限,无法触发堆内存(老年代)GC。这个情况下就需要把MaxRAMPercentage参数适当调低。

相关推荐
昌sit!1 小时前
K8S node节点没有相应的pod镜像运行故障处理办法
云原生·容器·kubernetes
Yaml42 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~2 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616882 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
aloha_7892 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
记录成长java3 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
睡觉谁叫~~~3 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust
程序媛小果3 小时前
基于java+SpringBoot+Vue的旅游管理系统设计与实现
java·vue.js·spring boot
小屁孩大帅-杨一凡4 小时前
java后端请求想接收多个对象入参的数据
java·开发语言
java1234_小锋4 小时前
使用 RabbitMQ 有什么好处?
java·开发语言