Docker 容器跨主机通信之:直接路由方式

2018-06-14 07:06:02 +08:00
 hansonwang99



概述

就目前 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 这种,我的 个人私有云 也用的是这种方案。

如果有兴趣,也可以抽点时间看看作者一些关于容器化、微服务化方面的文章:



3337 次点击
所在节点    程序员
9 条回复
AllOfMe
2018-06-14 07:52:25 +08:00
谢谢,收藏了
xenme
2018-06-14 08:10:14 +08:00
正规不应该是 overlay network 么
新一点的支持 macvlan 可以直用

最后才是楼主这。
renothing
2018-06-14 08:17:53 +08:00
手动去添加路由这显然不 docker。
楼主干的事儿,实际上就是 Flannel 干的活儿
hansonwang99
2018-06-14 08:55:30 +08:00
@renothing 可以
jinhan13789991
2018-06-14 09:38:25 +08:00
这不就是基本的路由规则嘛~ 其实和 docker 没什么关系吧。
我还以为在 docker 内部实现的~
rrfeng
2018-06-14 09:41:53 +08:00
直接路由为啥还有 nat ?你不是在逗我?
zhengxiaowai
2018-06-14 10:08:26 +08:00
一直以来都是自由两种方法:
一种是通过宿主机,就是你这种,这行方式性能好。
还有一种就是通过虚拟网桥实现,这种方式功能多。
hansonwang99
2018-06-14 10:38:13 +08:00
向列为大拿致敬
alexsunxl
2018-06-14 16:17:09 +08:00
@rrfeng 默认模式,docker 和宿主机有一层 nat 不是正常的吗?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/462947

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX