21.3 构建跨主机容器网络
在这里,笔者将演示使用libnetwork自带的Overlay类型驱动来轻松实现跨主机的网络通信。Overlay驱动默认采用VXLAN协议,在IP地址可以互相访问的多个主机上之间搭建隧道,让容器可以互相访问。
1.配置网络信息管理数据库
我们知道,在现实世界中,要连通不同的主机需要交换机或路由器(跨子网时需要)这样的互联设备。这些设备一方面是在物理上起到连接作用,但更重要的是起到了网络管理的功能。例如,主机位置在什么地方,地址是多少等信息,都需要网络管理平面来维护。
在libnetwork的网络方案中,要实现跨主机容器网络也需要类似的一个网络信息管理机制,只不过这个机制简单得多,只是一个键值数据库而已,如Consul、Etcd、ZooKeeper等工具都可以满足需求如图21-3所示。

图21-3 跨主机的容器网络
以Consul为例,启动一个progrium/consul容器,并映射服务到本地的8500端口,用如下命令即可:
- $ docker run -d \
- -p "8500:8500" \
- -h "consul" \
- progrium/consul -server -bootstrap
- 1ad6b71cfdf83e1925d960b7c13f40294b7d84618828792a84069aea2e52770d
所在主机作为数据库节点。
2.配置Docker主机
启动两台Docker主机n1和n2,分别安装好最新的Docker-engine(1.7.0+)。确保这两台主机之间可以通过IP地址互相访问,另外,都能访问到数据库节点的8500端口。
配置主机的Docker服务启动选项如下所示:
- DOCKER_OPTS="$DOCKER_OPTS --cluster-store=consul://<CONSUL_NODE>:8500 --cluster-
- advertise=eth0:2376"
重新启动Docker服务如下所示:
- $ sudo service docker restart
3.创建网络
分别在n1和n2上查看现有的Docker网络,包括三个默认网络:分别为bridge、host和none类型。
- n1:$ docker network ls
- NETWORK ID NAME DRIVER
- dc581a3eab4c bridge bridge
- ee21a768c6f6 host host
- 8d1ee747b894 none null
- n2:$ docker network ls
- NETWORK ID NAME DRIVER
- e7f24593bada bridge bridge
- 5bfae3a62214 host host
- 4adc19ad9bc7 none null
在任意节点上创建网络multi,例如在n1上执行如下命令即可完成对跨主机网络的创建:
- n1:$ docker network create -d overlay multi
- eadd374a18434a14c6171b778600507f300d330f4622067d3078009a58506c2d
创建成功后,可以同时在n1和n2上查看到新的网络multi的信息:
- n1:$ docker network ls
- NETWORK ID NAME DRIVER
- dc581a3eab4c bridge bridge
- ee21a768c6f6 host host
- eadd374a1843 multi overlay
- 8d1ee747b894 none null
- n2:$ docker network ls
- NETWORK ID NAME DRIVER
- e7f24593bada bridge bridge
- 5bfae3a62214 host host
- eadd374a1843 multi overlay
- 4adc19ad9bc7 none null
此时,还可以通过docker network inspect命令查看网络的具体信息:
- $ docker network inspect multi
- [
- {
- "Name": "multi",
- "Id": "eadd374a18434a14c6171b778600507f300d330f4622067d3078009a58506c2d",
- "Scope": "global",
- "Driver": "overlay",
- "EnableIPv6": false,
- "IPAM": {
- "Driver": "default",
- "Options": {},
- "Config": [
- {
- "Subnet": "10.0.0.0/24",
- "Gateway": "10.0.0.1/24"
- }
- ]
- },
- "Internal": false,
- "Containers": {},
- "Options": {},
- "Labels": {}
- }
- ]
4.测试网络
在n1上启动一个容器c1,通过—net选项指定连接到multi网络上。查看网络信息,其中一个接口eth0已经连接到了multi网络上:
- n1:$ docker run -it --name=c1 --net=multi busybox
- / # ip a
- 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue
- link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
- inet 127.0.0.1/8 scope host lo
- valid_lft forever preferred_lft forever
- inet6 ::1/128 scope host
- valid_lft forever preferred_lft forever
- 72: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue
- link/ether 02:42:0a:00:00:02 brd ff:ff:ff:ff:ff:ff
- inet 10.0.0.2/24 scope global eth0
- valid_lft forever preferred_lft forever
- inet6 fe80::42:aff:fe00:2/64 scope link
- valid_lft forever preferred_lft forever
- 74: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
- link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
- inet 172.18.0.2/16 scope global eth1
- valid_lft forever preferred_lft forever
- inet6 fe80::42:acff:fe12:2/64 scope link
- valid_lft forever preferred_lft forever
在n2上启动一个容器c2,同样连接到multi网络上。
通过ping c1进行测试,可以访问到另外一台主机n1上的容器c1:
- n2:$ docker run -it --name=c2 --net=multi busybox
- / # ping c1
- PING c1 (10.0.0.2): 56 data bytes
- 64 bytes from 10.0.0.2: seq=0 ttl=64 time=0.705 ms
- 64 bytes from 10.0.0.2: seq=1 ttl=64 time=0.712 ms
- 64 bytes from 10.0.0.2: seq=2 ttl=64 time=0.629 ms
- ^C
- --- c1 ping statistics ---
- 3 packets transmitted, 3 packets received, 0% packet lossround-trip min/avg/max =
- 0.629/0.682/0.712 ms
