Docker容器不定时出现无法连接的问题

一、背景

生产环境与版本

主机:centos8     docker:20.0       mysql:5.7

一般需要对外提供服务的Docker容器,我们在启动时后使用-p命令将对外访问端口暴露给外部,例如启动Docker Mysql,我们将3306端口映射出来供外部访问:

docker run -it -d -p 3376:3306 docker.io/centos:latest /bin/bash

但最近碰到一个非常奇怪的情况:ECS主机中一个CentOS 8生产环境里部署有Docker Mysql,并对外暴露了端口。启动容器后一段时间内都是可以正常工作的,但在不定时间间隔后,外部主机就会出现无法从访问的情况:

 

二,问题排查

1、排查端口

碰到此问题问询开发、运维人员是不是有人重启过CentOS 8 自己的firewallD了。

查看防火墙的状态

systemctl status firewalld.service

然后排查对应的端口是否开放

iptables -nL

如果是防火墙问题:解决方案有两种:

1)关闭FirewallD服务:

如果您不需要防火墙,那直接关掉FirewallD服务就好了

systemctl stop firewalld.service

2)添加策略对外打开指定的端口:

比如我们现在要打开对外5000/tcp端口,可以使用下面的命令:

iptables -A INPUT -p tcp --dport 5000 -j ACCEPT

 

2、查看容器日志

命令格式:

$ docker logs [OPTIONS] CONTAINER
  Options:
        --details        显示更多的信息
    -f, --follow         跟踪实时日志
        --since string   显示自某个timestamp之后的日志,或相对时间,如42m(即42分钟)
        --tail string    从日志末尾显示多少行日志, 默认是all
    -t, --timestamps     显示时间戳
        --until string   显示自某个timestamp之前的日志,或相对时间,如42m(即42分钟)

例子:

查看指定时间后的日志,只显示最后100行:

$ docker logs -f -t --since="2022-04-08" --tail=100 CONTAINER_ID

查看某时间之后的日志:

$ docker logs -t --since="2022-04-08T13:23:37" CONTAINER_ID

经过日志排查,发现容器日志无错误日志

 

3、排查网络

 A:查看容器运行状态正常如图:

由上图可知,容器运行正常。

 

 B:查看容器对外网之间的网络:

由上图所知,容器对外网不通

 

C:查看容器与docker0网卡之间网络

 由上图所知容器与docker0网卡之间通信正常

 

D:查看容器与宿主机之间网络

 

 由上图所知,容器与宿主机之间的通信正常

. Docker容器实例中解析DNS的顺序

1) 首先,查找Docker daemon内置的DNS服务器127.0.0.11

2) 其次,查找docker run创建容器实例时通过--dns参数设置的DNS服务器

3) 再次,查找Docker daemon通过--dns参数,或/etc/docker/daemon.json文件设置的DNS服务器

4) 又次,查找Docker宿主机上/etc/resolv.conf文件中配置的DNS服务器

5) 最后,查找Google的DNS服务器,如8.8.8.8和8.8.4.4,2001:4860:4860::8888和2001:4860:4860::8844

4、没有启用IP_FORWARD

因为网络通正常,一直没法定位出问题的所在,发现不能正常访问容器时,手动登陆宿主机重启Docker daemon服务。如果宿主机没有启用IP_FORWARD功能,那Docker容器在启动时会输出一条警告消息:

WARNING: IPv4 forwarding is disabled. Networking will not work.

会不会是因为宿主机的IP_FORWARD功能没有启用所以才引起的这个故障呢?

sysctl net.ipv4.ip_forward

果然,输出表示当前系统的IP_FORWARD功能处于停用状态!

可是问题来了,当时启动容器的时候都是好的啊,什么都没有输出,怎么用着用着IP_FORWARD功能就被禁用了呢?Docker daemon服务在启动的时候会自动设置iptables设置,难不成它还会检查IP_FORWARD设置,并帮我临时启用吗?

带着这个假设,我手动重启了一下Docker daemon服务:

果然,Docker daemon服务在启动过程中会检查系统的IP_FORWARD配置项,如果当前系统的IP_FORWARD功能处于停用状态,会帮我们临时启用IP_FORWARD功能,然而临时启用的IP_FORWARD功能会因为其他各种各样的原因失效…

echo 'net.ipv4.ip_forward = 1' >> /usr/lib/sysctl.d/50-default.conf
or
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf

然后使配置生效

sysctl -p

至此,业务恢复正常。

posted @ 2022-04-11 16:43  启云  阅读(2987)  评论(0编辑  收藏  举报