背景
准备往docker容器中新增一个服务Z,但是服务Z对docker以及docker-compose版本要求较高,所以决定做一次升级。
升级
简单看了下系统参数:
$ 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到版本:
$ docker --version
# Docker version 20.10.11, build dea9396
按照教程升级了docker-compose到版本:
$ 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通另一个容器
解决问题
应该能够确定问题:docker 加载内核的bridge.ko 驱动异常,导致docker0 网卡无法转发数据包,也就是系统内核的网桥模块bridge.ko 加载失败导致的,一般情况下这种场景的确很少见。
根据网上的说法是升级内核解决,于是我打算升级内核,运行:yum update
,发现error:
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的配置文件里面禁止更新内核:
$ cat /etc/yum.conf
# 里面有这么一行:
exclude=centos-release*
于是我注释掉排除升级内核的那一行,继续更新yum源仓库yum update
就没有报错了:
...
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报错:
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”之间有一个空格。
最终结果
# 使用 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网段。
{
// "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的认识也更加深刻。
在排查问题期间发现了一些好问题好文章: