写点什么

Docker OOM Killer

发布于: 3 小时前
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 stats
复制代码



  • 方式二

#获取容器的id docker inspect 容器名|grep Id #当前容器的内存使用情况  cat /sys/fs/cgroup/memory/docker/907a8ac37dbc4f73a13ef1dbf93a951b0ed1c43ed5e2a7aa2893d87d9e8cc1d4/memory.usage_in_bytes #当前容器的内存使用最大值  cat /sys/fs/cgroup/memory/docker/907a8ac37dbc4f73a13ef1dbf93a951b0ed1c43ed5e2a7aa2893d87d9e8cc1d4/memory.max_usage_in_bytes 
复制代码


  • 查看 docker 容器管理的杀死进程的分数

  #!/bin/bash  for proc in $(find /proc -maxdepth 1 -regex '/proc/[0-9]+'); do      printf "%2d %5d %s\n" \          "$(cat $proc/oom_score)" \          "$(basename $proc)" \          "$(cat $proc/cmdline | tr '\0' ' ' | head -c 500)"  done 2>/dev/null | sort -nr | head -n 40
复制代码


图中第一列就是分数值

内核在选择要杀死的进程时会对所有的进程打分,直接杀死得分最高的进程,接着是下一个。当 docker daemon 的 OOM 优先级被降低后(注意容器进程的 OOM 优先级并没有被调整),docker daemon 进程的得分不仅会低于容器进程的得分,还会低于其它一些进程的得分。这样 docker daemon 进程就安全多了


  • 查看 killer 日志



docker OOM killer 查看杀死日志
egrep -i -r 'killed process' /var/log
复制代码



处理方式

  1. 不控制内存使用的措施(不建议使用),去除容器的内存 limit 限制

  2. 将 jvm 的堆内存预留更多的空间给 docker damon

  3. jvm 保留根据容器规范的内存,增加 jvm 启动参数,需要 jdk 版本要求(JDK 8u131+)


-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
复制代码


用户头像

还未添加个人签名 2018.05.03 加入

十年开发老兵,多年搜索及推荐领域技术和业务积累目前主要研究低代码平台设计及开发模式,关注三高架构设计方案及系统实现,微服务治理实践及DDD领域驱动设计方案

评论

发布
暂无评论
Docker OOM Killer