我们有以下场景,一个 docker 主机在两个子网中有两个 NIC,ens8: IP 192.168.100.74/24
并且ens9: IP 172.20.102.24/25
,默认网桥docker0 IP 172.17.0.1/16
和第二个网桥app_net IP 172.21.0.1/24
。192.168.100.1
是主机上的默认网关(互联网网关)。
Docker 容器使用 SNAT 有一个固定的传出 IP,请参阅将 docker 容器连接到本地网络的四种方法 - 使用 NAT。这通过两个命令完成,将目标地址分配给主机接口ip addr add 192.168.100.234/24 dev ens8
并添加 iptables 规则iptables -t nat -I POSTROUTING -s 172.21.0.4 -j SNAT --to-source 192.168.100.234
。使用来自网桥 app_net 的 IP 创建容器。
在主机上,我可以 ping/traceroute 子网192.168.100.x
和172.20.102.x
互联网中的 IP,例如 google.com。在容器内,我可以 ping/traceroute 子网中的 IP 192.168.100.x
,我也可以 ping 例如 google.com,但我无法 ping 中的任何内容172.20.102.x
,除了172.20.102.24
。请参阅以下输出。
# traceroute -I 192.168.100.10
traceroute to 192.168.100.10 (192.168.100.10), 30 hops max, 46 byte packets
1 172.21.0.1 (172.21.0.1) 0.004 ms 0.003 ms 0.002 ms
2 192.168.100.10 (192.168.100.10) 0.180 ms 0.158 ms 0.028 ms
# traceroute -I google.com
traceroute to google.com (216.58.214.46), 30 hops max, 46 byte packets
1 172.21.0.1 (172.21.0.1) 0.004 ms 0.013 ms 0.002 ms
2 fritz.box (192.168.100.1) 2.144 ms 3.114 ms 2.697 ms
3 server.provider.net (xx.yy.250.5) 6.947 ms 7.042 ms 4.305 ms
4 etc...
# traceroute -I 172.20.102.24
traceroute to 172.20.102.24 (172.20.102.24), 30 hops max, 46 byte packets
1 172.20.102.24 (172.20.102.24) 0.004 ms 0.003 ms 0.002 ms
# traceroute -I 172.20.102.9
traceroute to 172.20.102.9 (172.20.102.9), 30 hops max, 46 byte packets
1 172.21.0.1 (172.21.0.1) 0.004 ms 0.003 ms 0.002 ms
2 * * *
3 * * * (etc. no response)
如果我不添加 iptables SNAT 规则,容器可以 ping/traceroute 所有东西,包括子网上的机器172.20.102.x
。
我找到了一篇关于多个网卡和docker(#)的文章,精简解决方案在 serverFault 上,但是无论是这个,还是对高级 docker 网络的深入了解(#)都没有给我任何线索,为什么我无法访问 ens9 子网中的其他机器,除了 docker 容器内的网卡本身。
是我遗漏了什么,还是这个网络场景根本就不对?
(#) 由于声誉问题,不允许发布超过两个链接,但 serverFault 链接与 Google“跨多个网络接口的 Docker”一起应该有助于找到链接。