在之前的docker简介中介绍了一些docker基础的操作,在涉及到多台不同的宿主机上运行docker时应该如何使他们之间进行通信呢,这篇文章将会介绍几种常见的配置方法。

docker 可以使用多种集群的解决方案,如k8s,mesos等,这个将在后面的内容中一一介绍,这里我们将使用docker原生的组件进行连接。

环境准备

两台宿主机,都安装docker. 并下载官方的centos镜像(也可以下载alpine镜像)。

node-1: 10.0.0.1

node-2: 10.0.0.2

1.直接路由方式

网络配置

在宿主机node-1和node-2上分别查看默认的docker0网络:

node1:docker0:  mtu 1500 qdisc noqueue state DOWN 
    link/ether 02:42:c2:a4:d3:e0 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forevenode2:docker0:  mtu 1500 qdisc noqueue state DOWN 
    link/ether 02:42:2e:be:83:69 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever

两个内部的网段相同,如果创建容器,两个网络肯定无法互联,所以我们修改默认docker0网络,并且使这两个网络不会和外部的网络冲突。

在node-1和node-2上的 /usr/lib/systemd/system/docker.service 文件中 ExecStart=区域添加参数:

node-1:--bip=172.17.1.1/16 \node-2:--bip=172.16.2.1/16 \

重启docker服务。

创建容器

分别在node-1和node-2上创建容器:

node1:
docker run -it --name test1 centos  bashnode2:
docker run -it --name test2 centos  bash

这时test1的ip地址为172.17.1.2, test2的地址为172.16.2.2, 两个虚拟机都是走的宿主机的内部桥接网络,所以依然无法通信。 而容器到node-1和node-2宿主机都是可以正常通信的,由于我们都是设置的不同网段,所以可以在每个宿主机上单独添加一条静态路由,指定数据包的流向:

node1:

route add -net 172.16.0.0/16 gw 10.0.0.2

node2:

route add -net 172.17.0.0/16 gw 10.0.0.1

这样不同宿主机上的容器就可以互联了。

这种方式虽然简单高效,但是如果是大规模的docker集群,会难以维护,同时由于docker容器都在不同宿主机的不同网段,需要使用网络组播和广播交互的服务就无法跨主机通信了.

2.使用openvswitch

Open vSwitch是一个开源的虚拟交换机软件,类似Linux中的bridge,但是功能要更加复杂。 Open vSwitch的网桥可以直接建立多种通道(隧道),如Open vSwitch with GRE/VxLAN。在Kunernetes和Docker场景下,主要使用建立L3到L3的隧道。

网络配置

与上面类似,为了避免Docker0中的网络相互冲突,我们需要修改Docker0中的网络:

node-1:

docker0: 172.16.1.1/24

node-2:

docker0: 172.16.2.1/24

安装openvswitch

在node-1和node-2上分别安装openvswitch和brctl的管理工具:

yum install openvswitch -y
yum install bridge-utils -y

启动服务:

systemctl start openvswitch

配置GRE网络

在node-1上执行如下命令:

# 创建ovs网桥
[root@node-1 ~]# ovs-vsctl  add-br br0

# 创建GRE隧道连接对端,remote_ip为对端网卡地址
[root@node-1 ~]# ovs-vsctl  add-port br0 gre1 -- set interface gre1 type=gre option:remote_ip=10.0.0.2

# 添加br0到本地docker0,使得容器流量通过OVS流经tunnel
[root@node-1 ~]# brctl addif docker0 br0

# 启动br0和docker0网桥
[root@node-1 ~]# ip link set dev br0 up
[root@node-1 ~]# ip link set dev docker0 up

# 添加路由规则
[root@node-1 ~]# ip route add 172.16.0.0/16 dev docker0

同理,node-2上执行:

[root@node-2 ~]# ovs-vsctl  add-br br0
[root@node-2 ~]# ovs-vsctl  add-port br0 gre1 -- set interface gre1 type=gre option:remote_ip=10.0.0.1 
[root@node-2 ~]# brctl addif docker0 br0
[root@node-2 ~]# ip link set dev br0 up
[root@node-2 ~]# ip link set dev docker0 up
[root@node-2 ~]# ip route add 172.16.0.0/16 dev docker0

验证

在node-1或node-2上分别ping 对端docker0的ip,可以互通,说明配置成功:

[root@node-1 ~]# ping -c 2 172.16.2.1PING 172.16.2.1 (172.16.2.1) 56(84) bytes of data.
64 bytes from 172.16.2.1: icmp_seq=1 ttl=64 time=0.936 ms
64 bytes from 172.16.2.1: icmp_seq=2 ttl=64 time=1.04 ms


[root@node-2 ~]# ping -c 2 172.16.1.1PING 172.16.1.1 (172.16.1.1) 56(84) bytes of data.
64 bytes from 172.16.1.1: icmp_seq=1 ttl=64 time=0.897 ms
64 bytes from 172.16.1.1: icmp_seq=2 ttl=64 time=0.350 ms