就目前 Docker 自身默认的网络来说,单台主机上的不同 Docker 容器可以借助 docker0 网桥直接通信,这没毛病,而不同主机上的 Docker 容器之间只能通过在主机上用映射端口的方法来进行通信,有时这种方式会很不方便,甚至达不到我们的要求,因此位于不同物理机上的 Docker 容器之间直接使用本身的 IP 地址进行通信很有必要。再者说,如果将 Docker 容器起在不同的物理主机上,我们不可避免的会遭遇到 Docker 容器的跨主机通信问题。本文就来尝试一下。
如下图所示,我们有两个物理主机 1 和主机 2,我们在各自宿主机上启动一个 centos 容器,启动成功之后,两个容器分别运行在两个宿主机之上,默认的 IP 地址分配如图所示,这也是 Docker 自身默认的网络。
此时两台主机上的 Docker 容器如何直接通过 IP 地址进行通信?
一种直接想到的方案便是通过分别在各自主机中 添加路由 来实现两个 centos 容器之间的直接通信。我们来试试吧
由于使用容器的 IP 进行路由,就需要避免不同主机上的容器使用了相同的 IP,为此我们应该为不同的主机分配不同的子网来保证。于是我们构造一下两个容器之间通信的路由方案,如下图所示。
各项配置如下:
这样配置之后,两个主机上的 Docker 容器就肯定不会使用相同的 IP 地址从而避免了 IP 冲突。
我们接下来 定义两条路由规则 即可:
综上所述,数据包在两个容器间的传递过程如下:
我们心里方案想的是这样,接下来实践一下看看是否可行。
编辑主机 1 上的 /etc/docker/daemon.json
文件,添加内容:"bip" : "ip/netmask"
{ "bip", "172.17.1.252/24" }
编辑主机 2 上的 /etc/docker/daemon.json
文件,添加内容:"bip" : "ip/netmask"
{ "bip", "172.17.2.252/24" }
主机 1 和主机 2 上均执行如下命令重启 docker 服务以使修改后的 docker0 网段生效
systemctl restart docker
主机 1 上添加路由规则如下:
route add -net 172.17.2.0 netmask 255.255.255.0 gw 192.168.145.129
主机 2 上添加路由规则如下:
route add -net 172.17.1.0 netmask 255.255.255.0 gw 192.168.145.128
主机 1 上添加如下规则:
iptables -t nat -F POSTROUTING
iptables -t nat -A POSTROUTING -s 172.17.1.0/24 ! -d 172.17.0.0/16 -j MASQUERADE
主机 2 上添加如下规则:
iptables -t nat -F POSTROUTING
iptables -t nat -A POSTROUTING -s 172.17.2.0/24 ! -d 172.17.0.0/16 -j MASQUERADE
主机 1 上启动 centos 容器:
docker run -it --name container1 centos /bin/bash
主机 2 上启动 centos 容器:
docker run -it --name container2 centos /bin/bash
好了,现在两容器可以互 ping 了
本文探讨了局域网中不同宿主机间 Docker 容器直接通信的一种可能方案。当然现在实现跨主机容器间通信的现成方案也很多,典型的比如 flannel 这种,我的 个人私有云 也用的是这种方案。
如果有兴趣,也可以抽点时间看看作者一些关于容器化、微服务化方面的文章:
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.