一次docker容器和宿主机网络不通问题记录

背景

准备往docker容器中新增一个服务Z,但是服务Z对docker以及docker-compose版本要求较高,所以决定做一次升级。

升级

简单看了下系统参数:

1
2
3
4
5
6
7
8
$ uname -r
# 3.10.0-327.22.2.el7.x86_64

$ uname -a
# Linux 10-42-1-77 3.10.0-327.22.2.el7.x86_64 #1 SMP Thu Jun 23 17:05:11 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/redhat-release
# CentOS Linux release 7.2.1511 (Core)

貌似可以支持升级docker。

于是我首先运行了yum update 或者 yum upgrade(具体是哪个,我不记得了。这中间可能有error,当时没在意,起初我也不知道update和upgrade的区别)。

yum update和yum upgrade的真正区别:“yum update和yum upgrade的功能都是一样的,都是将需要更新的package更新到源中的最新版。唯一不同的是,yum upgrade会删除旧版本的package,而yum update则会保留(obsoletes=0)。生产环境中建议使用yum update,防止因为替换,导致旧的软件包依赖出现问题。”

然后按照docker官网教程升级了docker到版本:

1
2
$ docker --version
# Docker version 20.10.11, build dea9396

按照教程升级了docker-compose到版本:

1
2
$ docker-compose --version
# docker-compose version 1.29.2, build 5becea4c

出现问题

一切顺利,兴高采烈的去将所有之前的docker服务运行起来,运行也一切正常,无任何报错。

但是,发现所有服务连不上了(我用的nginx做反向代理,转发请求道docker服务的),当时就很纳闷。

于是找运维帮忙排查,经过一阵子折腾,发现docker IP和宿主机IP有冲突了,于是就修改docker网段,改完之后现象和之前一样,服务能正常启动,就是连不上。于是一个一个排查:

  • 关闭防火墙systemctl stop firewalld
  • IP没有冲突
  • docker服务正常
  • nginx服务正常
  • 路由正常

最终发现几个问题:

  • 宿主机无法ping通容器IP
  • 容器也无法ping通宿主机IP
  • 容器无法ping通docker0(Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络)
  • 容器可以ping通另一个容器

解决问题

经过2天问题的排查,直到找到这篇文章,接着找到这篇文章

应该能够确定问题:docker 加载内核的bridge.ko 驱动异常,导致docker0 网卡无法转发数据包,也就是系统内核的网桥模块bridge.ko 加载失败导致的,一般情况下这种场景的确很少见。

根据网上的说法是升级内核解决,于是我打算升级内核,运行:yum update,发现error:

1
2
3
Error: initscripts conflicts with centos-release-7-2.1511.el7.centos.2.10.x86_64
You could try using --skip-broken to work around the problem
You could try running: rpm -Va --nofiles --nodigest

于是又网上查找答案,发现是yum的配置文件里面禁止更新内核:

1
2
3
$ cat /etc/yum.conf
# 里面有这么一行:
exclude=centos-release*

于是我注释掉排除升级内核的那一行,继续更新yum源仓库yum update就没有报错了:

1
2
3
4
5
6
7
8
9
10
11
...
Installed:
kernel.x86_64 0:3.10.0-1160.49.1.el7

Dependency Installed:
bc.x86_64 0:1.06.95-13.el7

Updated:
centos-release.x86_64 0:7-9.2009.1.el7.centos initscripts.x86_64 0:9.49.53-1.el7_9.1

Complete!

接下来就是按照这篇文章一步步操作升级内核。

升级完成,重启之后,发现yum报错:

1
2
3
Cannot open logfile /var/log/yum.log
...
[Errno 30] Read-only file system: '/var/cache/yum/x86_64/7/runner_gitlab-runner/repomd.xml.old.tmp'

解决方法将文件系统重新挂载为读/写mount -o remount, rw /,注意“,”和“rw”之间有一个空格。

最终结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 使用 alpine 镜像创建一个容器,并进入容器
docker run -it --name altest alpine sh

# 从容器内 ping 宿主机ip
ping 10.xx.xx.77 -c 3

PING 10.xx.xx.77 (10.xx.xx.77): 56 data bytes
64 bytes from 10.xx.xx.77: seq=0 ttl=64 time=0.102 ms
64 bytes from 10.xx.xx.77: seq=1 ttl=64 time=0.097 ms
64 bytes from 10.xx.xx.77: seq=2 ttl=64 time=0.119 ms

--- 10.xx.xx.77 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.097/0.106/0.119 ms

# docker0 ip
ifconfig docker0 | grep inet
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255

# ping docker0 也是ok的
ping 172.117.0.1 -c 1

PING 172.117.0.1 (172.117.0.1): 56 data bytes
64 bytes from 172.117.0.1: seq=0 ttl=236 time=173.943 ms

--- 172.117.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 173.943/173.943/173.943 ms

终于网络问题解决了😄。

最后

为了避免IP冲突,最后又重新参考这里修改了docker网段。

1
2
3
4
5
6
7
8
9
{
// "default-address-pools": [{
// "base": "192.169.0.1/16",
// "size": 24
// }],
"bip":"192.168.0.1/24",
"data-root": "/data/docker",
"registry-mirrors": ["https://xxxxx.mirror.aliyuncs.com"]
}

关于Docker的阿里云镜像加速,可以到这里查看(需登录账号),也可以看看这篇文章

总结

问题是解决了,但是作为一个前端的我来说,还是有太多知识盲区,期间遇到了太多阻碍,不过解决之后很踏实,对网络、子网掩码有了更深的认识;对docker的认识也更加深刻。

在排查问题期间发现了一些好问题好文章:

Cleam Lee wechat
欢迎扫一扫订阅!