(四)理解容器之间的连通性
通过前面小节的实践,当前 docker host 的网络拓扑结构如下图所示,今天我们将讨论这几个容器之间的连通性。
两个 busybox 容器都挂在 my_net2 上,应该能够互通,我们验证一下:
root@cuiyongchao:~# docker run -it --network my_net2 --ip 172.22.0.88 busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:16:00:58
inet addr:172.22.0.88 Bcast:172.22.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:656 (656.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # ping 172.22.0.1 -c 1
PING 172.22.0.1 (172.22.0.1): 56 data bytes
64 bytes from 172.22.0.1: seq=0 ttl=64 time=0.152 ms
--- 172.22.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.152/0.152/0.152 ms
/ # ping 172.22.0.2 -c 1
PING 172.22.0.2 (172.22.0.2): 56 data bytes
64 bytes from 172.22.0.2: seq=0 ttl=64 time=0.127 ms
--- 172.22.0.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.127/0.127/0.127 ms
/ #
可见同一网络中的容器、网关之间都是可以通信的。
my_net2
与默认 bridge 网络能通信吗?从拓扑图可知,两个网络属于不同的网桥,应该不能通信,我们通过实验验证一下,让 busybox 容器 ping httpd 容器:
/ # ping 172.17.0.2 -c 1
PING 172.17.0.2 (172.17.0.2): 56 data bytes
--- 172.17.0.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
/ #
确实 ping 不通,符合预期。“等等!不同的网络如果加上路由应该就可以通信了吧?”我已经听到有读者在建议了。
这是一个非常非常好的想法。确实,如果 host 上对每个网络的都有一条路由,同时操作系统上打开了 ip forwarding,host 就成了一个路由器,挂接在不同网桥上的网络就能够相互通信。下面我们来看看 docker host 满不满足这些条件呢?
ip r
查看 host 上的路由表
root@cuiyongchao:~# ip r
default via 10.0.0.254 dev ens33 proto static
10.0.0.0/24 dev ens33 proto kernel scope link src 10.0.0.20
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
172.22.0.0/16 dev br-ba21840c1713 proto kernel scope link src 172.22.0.1
172.17.0.0/16 和 172.22.16.0/24 两个网络的路由都定义好了。再看看 ip forwarding:
# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
ip forwarding 也已经启用了。
条件都满足,为什么不能通行呢?
我们还得看看 iptables-save:
-A DOCKER-ISOLATION-STAGE-1 -i br-ba21840c1713 ! -o br-ba21840c1713 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-283474cba87c ! -o br-283474cba87c -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o br-ba21840c1713 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o br-283474cba87c -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
原因就在这里了:iptables DROP 掉了网桥 docker0 与 br-ba21840c1713 之间双向的流量。
从规则的命名 DOCKER-ISOLATION
可知 docker 在设计上就是要隔离不同的 netwrok。
那么接下来的问题是:怎样才能让 busybox 与 httpd 通信呢?答案是:为 httpd 容器添加一块 net_my2 的网卡。这个可以通过docker network connect
命令实现。
root@cuiyongchao:~# docker network connect my_net2 631d88d3f0d9
root@cuiyongchao:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
631d88d3f0d9 httpd "bash" 23 seconds ago Up 22 seconds 80/tcp elated_volhard
我们在 httpd 容器中查看一下网络配置:
root@631d88d3f0d9:/usr/local/apache2# ip a
bash: ip: command not found
root@631d88d3f0d9:/usr/local/apache2# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 3969 bytes 8864961 (8.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3861 bytes 209797 (204.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.22.0.4 netmask 255.255.0.0 broadcast 172.22.255.255
ether 02:42:ac:16:00:04 txqueuelen 0 (Ethernet)
RX packets 12 bytes 936 (936.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 2 bytes 171 (171.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2 bytes 171 (171.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
容器中增加了一个网卡 eth1,分配了 my_net2 的 IP 172.22.0.4。现在 busybox 应该能够访问 httpd 了,验证一下:
/ # ping 172.22.0.4 -c 1
PING 172.22.0.4 (172.22.0.4): 56 data bytes
64 bytes from 172.22.0.4: seq=0 ttl=64 time=0.098 ms
--- 172.22.0.4 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.098/0.098/0.098 ms
/ #
busybox 能够 ping 到 httpd,并且可以访问 httpd 的 web 服务。当前网络结构如图所示: