Docker网桥导致网络故障分析
两台服务器为什么ping不通?Docker容器应用创建的网桥在搞鬼!
# 一、故事背景
VSS项目在使用FHTP自动化用例平台进行接口自动化用例编写,结果却发现一直在报错:

是一个熟悉的错误,网络连接超时了,原因很多,但是在PC环境执行此用例却是成功的,被测服务肯定是OK的,问题一定出在FHTP的测试用例执行环境上。
测开同学一通定位分析了解到,执行此测试用例的服务器ip为:172.17.xx.xx,登陆此服务器尝试ping被测接口服务的ip(172.16.24.3)发现网络不通:

由此开始了一次解谜游戏......
在开始解谜之前,我们先交代下被研究的对象
| 服务器角色 | 服务器IP |
|---|---|
| FHTP自动化用例平台测试执行节点(后续我们用worker代指) | 172.17.xx.xx |
| 被测对象VSS服务接口服务器 | 172.16.24.3 |
好了,记住这一点,我们出发了。
# 二、寻找蛛丝马迹
常规思路开始对172.16.24.3服务器进行问题分析排查:
- 把服务器防火墙关闭,依然不通;
- 网络连接信息检查,发现了问题的踪迹:

与Docker有关,有个172.17的IP出现了! 查看服务器网络配置,找到了一个网络,br-xxxxx
这是Docker容器应用创建的网桥,之前遇到过类似的问题:

# 三、真相大白
br-1fa4179c4771这是哪个容器应用创建的网络?

找到了,这个172.17.0.1的网桥是vss创建的,我们在这个网络的配置中看到了两个容器的名称:
- milvus-gpu-0.10.0
- rabbitmq
顺藤摸瓜我们继续找,这是哪个配置文件定义的容器名称。
我们在/home/vss目录下,我们找到了base_enviroment.yml这个配置文件,来看看其内容:
version: '3'
services:
rabbitmq:
image: rabbitmq:3.8.5-management
container_name: rabbitmq
privileged: true
environment:
RABBITMQ_DEFAULT_USER: "admin"
RABBITMQ_DEFAULT_PASS: "admin"
volumes:
- /home/vss/mqdata:/var/lib/rabbitmq
ports:
- 15672:15672
- 4369:4369
- 5672:5672
- 25672:25672
restart: always
milvus:
image: milvusdb/milvus:0.10.0-gpu-d061620-5f3c00
container_name: milvus-gpu-0.10.0
privileged: true
volumes:
- /home/vss/milvusdata:/var/lib/milvus/db
- /home/vss/conf:/var/lib/milvus/conf
- /home/vss/logs/milvus:/var/lib/milvus/logs
- /home/vss/wal:/var/lib/milvus/wal
ports:
- 19533:19530
- 19123:19121
restart: on-failure
nacos:
image: nacos-pg:1.0.0
container_name: nacos-server
network_mode: "host"
privileged: true
environment:
- PG_IP_PORT=172.16.24.3:5432
- PG_DB_NAME=nacos
- PG_USER_NAME=nacos
- PG_PWD=nacos
volumes:
- ./logs/nacos:/home/nacos/logs
ports:
- 8848:8848
- 9555:9555
restart: on-failure
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
嗯,就是这个了,证据确凿。

官方网站告诉我们一切:

我们在vss目录下,通过docker-compose编排启动了一组Docker容器,会默认创建一个vss_default的网络,一切都对上了。
# 四、分析复盘
通过docker-compose编排启动的一组容器,若没有声明网络配置,则会默认创建一个新的网桥(且IP网段是随机的,会选取一个没有使用的IP网段)。
我们通过试验证明下,现在新的网络IP网段为172.21.0.1了

此时若局域网内有一台服务器的IP为172.21.xx.xx,访问我们的测试服务器,则会出现上述的网络不通的情况!
基本情况我们已经知道了,但还有一个疑问,通过docker-compose,base_enviroment.yml明明编排了三个容器,为什么有nacos-server没有使用新创建vss_default的网络呢?
......
nacos:
image: nacos-pg:1.0.0
container_name: nacos-server
network_mode: "host"
......
2
3
4
5
6
因为配置了network_mode: "host",默认使用宿主机的IP,而不是新建网络。

# 五、总结反思
考虑到我们公司的产品,部署在客户环境,且当前基本没有提供DNS服务,我们务必重识这种容器IP网段与宿主机冲突导致网络故障的问题,这应该纳入我们的Docker应用测试标准规范中,在安装测试环节进行检查,增加测试用例。
解决这个问题有两种办法:
- 显示的为容器配置网桥
- 为容器绑定宿主机网段
上策为安装程序自动检测宿主机的IP网段和已经被其他容器使用的IP网段,自适应创建本容器的网桥网络的IP网段;
中策为在安装文档着重提示安装人员检查宿主机的IP地址,选择未被占用的合理的IP网段,配置本容器的网桥网络的IP网段;
下策为粗暴的绑定宿主机网段,这种最简单,但使用起来有诸多限制;
# (一)显示的为容器配置网桥
配置示例如下图所示,避免和宿主机在同一网段:
version: "3"
services:
py_env:
image: qguo/py_env:3.7.7-buster_v1
container_name: AITestDBManager-Release
stdin_open: true
tty: true
restart: unless-stopped
networks:
ait_release_net:
ipv4_address: 192.167.1.2
ports:
- "3344:5000"
- "2555:22"
volumes:
- /etc/localtime:/etc/localtime:ro
- ./AITestDBManager:/home/AITestDBManager
depends_on:
- db
- nginx
nginx:
image: nginx:latest
container_name: AITNginx-Release
ports:
- "12345:80"
restart: unless-stopped
networks:
ait_release_net:
ipv4_address: 192.167.1.3
volumes:
- /etc/localtime:/etc/localtime:ro
- ./AITNginx/nginx_conf/aitest_data.conf:/etc/nginx/nginx.conf
- ./AITNginx/logs:/var/log/nginx
- ./AITestDBManager/output_data/images:/store/images
- ./AITestDBManager/output_data/audios:/store/audios
networks:
ait_release_net:
driver: bridge
ipam:
config:
- subnet: 192.167.1.0/16
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# (二)为容器绑定宿主机网段
将每个容器的网络都配置为network_mode: "host",绑定到宿主机(但需要注意,这样的话,容器内部的端口在宿主机映射就不能自定义了)。
nacos:
image: nacos-pg:1.0.0
container_name: nacos-server
network_mode: "host"
2
3
4