Docker OOM Killer
背景
压测环境下 docker 容器内的 java 进程莫名的被 killed 掉,没有 jvm 致命文件 hs_err_pid%p.log,也没有系统 Coredump 文件,利用 ulimit -a 检查 core dump 文件是 unlimit
分析
如果 java 程序放到物理机上运行是没有问题,所以初步怀疑和 docker 容器有关
Docker 限制容器不能过多的使用主机的内存是非常重要的。对于 linux 主机来说,一旦内核检测到没有足够的内存可以分配,就会扔出 OOME(Out Of Memmory Exception),并开始杀死一些进程用于释放内存空间。糟糕的是任何进程都可能成为内核猎杀的对象,包括 docker daemon 和其它一些重要的程序。更危险的是如果某个支持系统运行的重要进程被干掉了,整个系统也就宕掉了!这里我们考虑一个比较常见的场景,大量的容器把主机的内存消耗殆尽,OOME 被触发后系统内核立即开始杀进程释放内存
我们通过命令查询容器的内存限制值
方式一
方式二
查看 docker 容器管理的杀死进程的分数
图中第一列就是分数值
内核在选择要杀死的进程时会对所有的进程打分,直接杀死得分最高的进程,接着是下一个。当 docker daemon 的 OOM 优先级被降低后(注意容器进程的 OOM 优先级并没有被调整),docker daemon 进程的得分不仅会低于容器进程的得分,还会低于其它一些进程的得分。这样 docker daemon 进程就安全多了
查看 killer 日志
处理方式
不控制内存使用的措施(不建议使用),去除容器的内存 limit 限制
将 jvm 的堆内存预留更多的空间给 docker damon
jvm 保留根据容器规范的内存,增加 jvm 启动参数,需要 jdk 版本要求(JDK 8u131+)
评论