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参数适当调低。

相关推荐
尘浮生5 分钟前
Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
Code_Artist17 分钟前
使用Portainer来管理并编排Docker容器
docker·云原生·容器
Eternal-Student26 分钟前
【docker 保存】将Docker镜像保存为一个离线的tar归档文件
运维·docker·容器
不是二师兄的八戒28 分钟前
本地 PHP 和 Java 开发环境 Docker 化与配置开机自启
java·docker·php
码农小丘34 分钟前
一篇保姆式centos/ubuntu安装docker
运维·docker·容器
爱编程的小生40 分钟前
Easyexcel(2-文件读取)
java·excel
带多刺的玫瑰1 小时前
Leecode刷题C语言之统计不是特殊数字的数字数量
java·c语言·算法
计算机毕设指导62 小时前
基于 SpringBoot 的作业管理系统【附源码】
java·vue.js·spring boot·后端·mysql·spring·intellij-idea
Gu Gu Study2 小时前
枚举与lambda表达式,枚举实现单例模式为什么是安全的,lambda表达式与函数式接口的小九九~
java·开发语言
Chris _data2 小时前
二叉树oj题解析
java·数据结构