21.3 构建跨主机容器网络

在这里,笔者将演示使用libnetwork自带的Overlay类型驱动来轻松实现跨主机的网络通信。Overlay驱动默认采用VXLAN协议,在IP地址可以互相访问的多个主机上之间搭建隧道,让容器可以互相访问。

1.配置网络信息管理数据库

我们知道,在现实世界中,要连通不同的主机需要交换机或路由器(跨子网时需要)这样的互联设备。这些设备一方面是在物理上起到连接作用,但更重要的是起到了网络管理的功能。例如,主机位置在什么地方,地址是多少等信息,都需要网络管理平面来维护。

在libnetwork的网络方案中,要实现跨主机容器网络也需要类似的一个网络信息管理机制,只不过这个机制简单得多,只是一个键值数据库而已,如Consul、Etcd、ZooKeeper等工具都可以满足需求如图21-3所示。

21.3 构建跨主机容器网络 - 图1

图21-3 跨主机的容器网络

以Consul为例,启动一个progrium/consul容器,并映射服务到本地的8500端口,用如下命令即可:


  1. $ docker run -d \
  2. -p "8500:8500" \
  3. -h "consul" \
  4. progrium/consul -server -bootstrap
  5. 1ad6b71cfdf83e1925d960b7c13f40294b7d84618828792a84069aea2e52770d

所在主机作为数据库节点。

2.配置Docker主机

启动两台Docker主机n1和n2,分别安装好最新的Docker-engine(1.7.0+)。确保这两台主机之间可以通过IP地址互相访问,另外,都能访问到数据库节点的8500端口。

配置主机的Docker服务启动选项如下所示:


  1. DOCKER_OPTS="$DOCKER_OPTS --cluster-store=consul://<CONSUL_NODE>:8500 --cluster-
  2. advertise=eth0:2376"

重新启动Docker服务如下所示:


  1. $ sudo service docker restart

3.创建网络

分别在n1和n2上查看现有的Docker网络,包括三个默认网络:分别为bridge、host和none类型。


  1. n1:$ docker network ls
  2. NETWORK ID NAME DRIVER
  3. dc581a3eab4c bridge bridge
  4. ee21a768c6f6 host host
  5. 8d1ee747b894 none null
  6. n2:$ docker network ls
  7. NETWORK ID NAME DRIVER
  8. e7f24593bada bridge bridge
  9. 5bfae3a62214 host host
  10. 4adc19ad9bc7 none null

在任意节点上创建网络multi,例如在n1上执行如下命令即可完成对跨主机网络的创建:


  1. n1:$ docker network create -d overlay multi
  2. eadd374a18434a14c6171b778600507f300d330f4622067d3078009a58506c2d

创建成功后,可以同时在n1和n2上查看到新的网络multi的信息:


  1. n1:$ docker network ls
  2. NETWORK ID NAME DRIVER
  3. dc581a3eab4c bridge bridge
  4. ee21a768c6f6 host host
  5. eadd374a1843 multi overlay
  6. 8d1ee747b894 none null
  7. n2:$ docker network ls
  8. NETWORK ID NAME DRIVER
  9. e7f24593bada bridge bridge
  10. 5bfae3a62214 host host
  11. eadd374a1843 multi overlay
  12. 4adc19ad9bc7 none null

此时,还可以通过docker network inspect命令查看网络的具体信息:


  1. $ docker network inspect multi
  2. [
  3. {
  4. "Name": "multi",
  5. "Id": "eadd374a18434a14c6171b778600507f300d330f4622067d3078009a58506c2d",
  6. "Scope": "global",
  7. "Driver": "overlay",
  8. "EnableIPv6": false,
  9. "IPAM": {
  10. "Driver": "default",
  11. "Options": {},
  12. "Config": [
  13. {
  14. "Subnet": "10.0.0.0/24",
  15. "Gateway": "10.0.0.1/24"
  16. }
  17. ]
  18. },
  19. "Internal": false,
  20. "Containers": {},
  21. "Options": {},
  22. "Labels": {}
  23. }
  24. ]

4.测试网络

在n1上启动一个容器c1,通过—net选项指定连接到multi网络上。查看网络信息,其中一个接口eth0已经连接到了multi网络上:


  1. n1:$ docker run -it --name=c1 --net=multi busybox
  2. / # ip a
  3. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue
  4. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  5. inet 127.0.0.1/8 scope host lo
  6. valid_lft forever preferred_lft forever
  7. inet6 ::1/128 scope host
  8. valid_lft forever preferred_lft forever
  9. 72: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue
  10. link/ether 02:42:0a:00:00:02 brd ff:ff:ff:ff:ff:ff
  11. inet 10.0.0.2/24 scope global eth0
  12. valid_lft forever preferred_lft forever
  13. inet6 fe80::42:aff:fe00:2/64 scope link
  14. valid_lft forever preferred_lft forever
  15. 74: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
  16. link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
  17. inet 172.18.0.2/16 scope global eth1
  18. valid_lft forever preferred_lft forever
  19. inet6 fe80::42:acff:fe12:2/64 scope link
  20. valid_lft forever preferred_lft forever

在n2上启动一个容器c2,同样连接到multi网络上。

通过ping c1进行测试,可以访问到另外一台主机n1上的容器c1:


  1. n2:$ docker run -it --name=c2 --net=multi busybox
  2. / # ping c1
  3. PING c1 (10.0.0.2): 56 data bytes
  4. 64 bytes from 10.0.0.2: seq=0 ttl=64 time=0.705 ms
  5. 64 bytes from 10.0.0.2: seq=1 ttl=64 time=0.712 ms
  6. 64 bytes from 10.0.0.2: seq=2 ttl=64 time=0.629 ms
  7. ^C
  8. --- c1 ping statistics ---
  9. 3 packets transmitted, 3 packets received, 0% packet lossround-trip min/avg/max =
  10. 0.629/0.682/0.712 ms