Docker 杀掉了容器?问题分析与解决过程全面复盘
欢迎访问我的 GitHub
这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
本篇概览
在执行 docker exec 命令时,报错信息为:rpc error: code = 2 desc = containerd: container not found
先抛出结果
如果您是通过搜索错误信息看到了此文,直接参考以下三点即可:
在执行 docker exec 命令时报错,报错信息为:rpc error: code = 2 desc = containerd: container not found
以上错误是因为系统内存不足,导致 OOM Killer 杀掉 elasticsearch 进程,该进程就是上一步中 docker exec 命令想作用到的容器;
请检查您的系统内存情况,建议使用 egrep -i -r 'killed process' /var/log 和 dmesg|grep memory 命令查看 OOM Killer 日志,确认是否存在进程被杀的情况;
接下来的内容,是我对整个问题过程的复盘;
问题复盘
收到同事反馈,说后台服务出现异常,定位后发现是应用连接 elasticsearch server 失败,于是用 eshead 去连接,还是失败;
我们的 elasticsearch 是运行在 docker 环境中的,用 docker ps 查看,看起来没什么问题,信息如下:
用命令 docker logs -f elasticsearch,没有发现什么异常,只是最后一条日志是 17:35 打印的,而此时已经 22:00 了,也就是说四个小时 es 没有输出日志到控制台了;
此时打算去容器内部看看有没有什么错误信息,执行命令 docker exec -it elasticsearch /bin/bash,控制台显示如下错误信息:
提示信息的大意是找不到容器,当时并没有什么好思路,由于使用了数据卷,容器挂了不怕数据丢失,就想删除容器再创建一个试试;
用 docker rm -f elasticsearch 删除容器,提示删除成功;
用 docker run --name elasticsearch 重建一个容器,此时控制台提示"名为 elasticsearch 的容器已经存在"(不好意思忘了把当时的错误信息存下来了,大致是这个意思吧)
此时没辙了,就用命令 systemctl restart docker 重启了 docker 服务;
再用 docker run --name elasticsearch 命令,创建 es 容器成功;
打开 eshead,连接 es 成功;
测试业务,操作成功,连接 es 正常;
此时是 23:00 左右;
至此,觉得问题已经解决了,在群里给大家说了下就回家了;
大写的尴尬
刚刚坐上回家的车,收到同事消息说问题又出现了,es 再次连接不上,状况和之前一样,这就尴尬了...
带着郁闷回到家,在梦中问题再次解决,还是那熟悉的 systemctl restart docker 命令。。。
以上就是问题的出现和第一轮处理的过程;
定位
第二天再次面对此问题;
去 google 搜索的 rpc error: code = 2 desc = containerd: container not found,发现有不少人遇到了类似问题;
搜到的结果中,有的说重启 docker 解决,有的说升级 docker,也有不少是抛出问题没有解决的;
这个文章提供了有价值的信息,如下图,地址是:https://forums.docker.com/t/container-not-found-error/32303/4
看来可能是内存系统内存不足,导致 OOM Killer 将 elasticsearch 进程杀掉,但是 docker 服务没有同步到这个信息,因此尽管进程不在了,但是 docker ps 可以看到,不过 docker exec 不会起作用,因为进程已经没了;
执行命令 egrep -i -r 'killed process' /var/log 看看 OOM Killer 日志,有新发现,两次 OOM 导致进程被系统杀掉,时间上和 es 问题也吻合:
执行命令 dmesg|grep memory 看也有记录,进程 ID 和 egrep 查到的是同一个,如下:
所以可以基本确定是内存不足导致 OOM Killer 杀掉了 elasticsearch 进程,用 top 看看当前内存情况,发现 128G 内存几乎已经耗尽:
接下来的事情就简单了,根据进程 ID 检查耗内存大的进程的身份,最终确定有 5 个 java 进程的启动参数配置不当,都是 10G,一下子用掉了 50G 内存,导致系统内存不足,于是调整它们的启动内存再依次重启,然后重启 docker,重建 es 容器,运行了一天时间,一切正常;
至此,问题已经修复,为什么系统内存耗尽后 OOM Killer 杀掉的是 elasticsearch 进程(连续两次都是),可以参考内核的源码 linux/mm/oom_kill.c,里面的 oom_badness 方法,方法注释中说了,调出最耗内存的进程杀掉,如下图,我们的机器上 elasticsearch 占用了 32G 内存,就是最耗内存的那个,所以次次都是它了:
以上就是整个问题的复盘过程,如果您也遇到类似问题,希望本文能给您提供一些参考;
欢迎关注 InfoQ:程序员欣宸
版权声明: 本文为 InfoQ 作者【程序员欣宸】的原创文章。
原文链接:【http://xie.infoq.cn/article/bab5253ee82f13edaf0f5bf7e】。文章转载请联系作者。
评论