Docker问题排查-异常断电导致Docker启动卡住

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker问题排查-异常断电导致Docker启动卡住相关的知识,希望对你有一定的参考价值。

参考技术A Docker守护进程在异常断电后卡在 activating 状态,并且内存占用在无限增加。

首先,查看 docker 版本和 docker info 信息

版本还算比较新,查看 docker 日志:

日志中存在明显的异常堆栈打印,分析可知,启动过程中走到 Loading containers: start. 之后卡住,然后打印 fatal error: runtime: out of memory ,也就是内存爆了。根据堆栈信息,可以看出异常的调用路径如下:

拉取对应版本的代码,根据上述调用过程,找到指定的代码位置:

可以看出,这段是读取 boltdb 数据库(用于缓存网络配置),从之前了解看,这个数据库在异常断电时很容易损坏,所以怀疑是数据库损坏了,导致此处的遍历读取超出了预期的循环次数,而每次循环都会创建变量,分配内存,最终被内核 OOM 。

在 docker 社区查找相关 issue [1] [2],发现确实存在 boltdb 数据库损坏的现象,不过最终报错的现象不太一样。最后,在 docker 社区也提了个 issue [3],社区反馈也是怀疑 boltdb 数据库损坏,并建议可以把 local-kv.db 文件删除再重启来恢复。

个人觉得,上面报错的地方可以优化一下,对 db 文件做一次检查,如果检查到异常,提前抛异常,而不是不停地吃内存(由于异常的环境被破坏了,这个想法需要等复现后再考虑优化)。

Docker启动问题排查

当docker镜像被制作之后,通过sudo docker images命令可以查看到镜像已经被制作。正常情况下已经在Dockerfile中配置启动命令,因此container容器也已经被启动。但是当镜像内部发生问题时,容器是启动不成功的,可以通过sudo docker ps -a查看所有容器,其中失败容器的status是不正常的。


方式一:通过查看logs日志来排查问题

通过命令sudo docker logs $container_id来指定具体id号的日志信息。

当发现问题需要重新制作镜像时,通过以下步骤进行排查:
1. 需要删除之前已经创建的镜像和据此镜像未启动的容器。步骤是先删除对应的子容器,再删除父镜像。
+ 查看容器命令:sudo docker ps -a 找到失败容器ID
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
32928ee6451a longsl/chatproxy:1.0 “/usr/app/chatprox…” 33 hours ago Exited (1) 33 hours ago KP_CHAT_PROXY

  • 删除对应容器:sudo docker rm KP_CHAT_PROXY

  • 查看镜像命令:sudo docker images
    $ sudo docker images
    REPOSITORY TAG IMAGE ID CREATED SIZE
    longsl/chatproxy 1.0 9281da534c00 33 hours ago 723 MB
    longsl/chatserver 1.0 171344fa3b34 35 hours ago 579 MB

  • 删除对应镜像:sudo docker rmi longsl/chatproxy:1.0

当所有清除工作完成后,开始构建新的镜像及容器

  • 创建镜像:docker build -t longsl/chatproxy:1.0 .
  • 最后启动容器

方式二:通过用初始化命令启动容来排查问题

通过/usr/sbin/init命令替换原项目程序来启动容器命令:

sudo docker run -d \\
    --user=kpgame \\
    -m=512m \\
    -e "TZ=Asia/Singapore" \\
    -e 'XMXSIZE=409m' \\
    ...
    longsl/chatproxy:1.0 \\
      /usr/sbin/init

启动成功后,通过sudo docker container exec KP_CHAT_PROXY_90 ls -al /usr/app/chatproxy/log命令进入出错的目录进行查看,发现仍然报 ls: cannot open directory /usr/app/chatproxy/log: Permission denied

最后发现是centos77中的安全模块selinux把权限禁掉了,通过在运行容器的时候,给容器加特权,及加上 --privileged=true参数可以解决,在文章最后的参考链接中,有更详细的说明。修改docker 容器的启动命令如下:

sudo docker run -d \\
    --user=kpgame \\
    -m=512m \\
    -e "TZ=Asia/Singapore" \\
    -e 'XMXSIZE=409m' \\
    ...
    -v /data/kpdeploy/logs/KP_CHAT_PROXY_90:/usr/app/chatproxy/log \\
    --name KP_CHAT_PROXY_90 \\
      --privileged=true \\
    longsl/chatproxy:1.0 \\
      /usr/sbin/init

搞定! 挂载文件可以被访问了,排查完成。


参考链接
[1] https://blog.csdn.net/rznice/article/details/52170085

以上是关于Docker问题排查-异常断电导致Docker启动卡住的主要内容,如果未能解决你的问题,请参考以下文章

Docker 容器中部署项目后一直重启原因排查

Docker启动问题排查

docker环境hosts配置错误导致的tomcat无法正常启动

06 基于 docker 网关服务 启动耗时过长问题排查

06 基于 docker 网关服务 启动耗时过长问题排查

真实案例:异常断电导致虚拟机无法启动恢复成功