swarm 模式可以使 overlay 网络只能被 swarm 中需要服务的节点所使用。当创建使用 overlay 网络的服务时,swarm 中的管理器节点就会自动扩展 overlay 网络到运行服务任务的节点上。下面的示例演示如何创建网络并在 swarm 中的管理器节点中为服务使用它:
# Create an overlay network `my-multi-host-network`. $ docker network create \ --driver overlay \ --subnet 10.0.9.0/24 \ my-multi-host-network 400g6bwzd68jizzdx5pgyoe95 # Create an nginx service and extend the my-multi-host-network to nodes where # the service's tasks run. $ docker service create --replicas 2 --network my-multi-host-network --name my-web nginx 716thylsndqma81j6kkkb5aus
要使用拥有键值存储区的 Docker 引擎,需要几个条件:
1、能够访问键值存储区。
2、一个能连接到该键值存储区的主机群。
3、主机群中的每台主机都有一个配置正确的引擎 daemon。
4、群中的主机必须拥有唯一的主机名,因为键值存储区使用主机名来区分群中的成员。
条件满足后就可以建立键值存储区了,它里面包含了很多网络状态信息,比如网络、发现及 IP 地址等。Docker 支持 Consul、Etcd 和 ZooKeeper 等键值存储区,本例中使用 Consul。
1、首先创建一个名为 mh-keystore 的 VirtualBox 机器:
$ docker-machine create -d virtualbox mh-keystore
在创建一台新机器后,进程会自动为该主机添加 Docker 引擎。这意味着可以利用 Docker 仓库中的 Consul 镜像来创建其实例,而无需手动安装 Consul(见第 3 步)。
2、设置本地环境为 mh-keyhost(相当于切换到该机器):
$ eval "$(docker-machine env mh-keystore)"
3、在 mh-keystore 主机上运行 progrium/consul 容器:
$ docker run -d \ -p "8500:8500" \ -h "consul" \ progrium/consul -server -bootstrap
在建立好键值存储区后,就可以创建 swarm 群了。在此使用“docker-machine create”来创建多台主机,并把其中之一作为 swarm 的管理器。
1、创建 swarm 管理器:
$ docker-machine create \ -d virtualbox \ --swarm --swarm-master \ --swarm-discovery="consul://$(docker-machine ip mh-keystore):8500" \ --engine-opt="cluster-store=consul://$(docker-machine ip mh-keystore):8500" \ --engine-opt="cluster-advertise=eth1:2376" \ mhs-demo0
在创建时,我们为引擎后台程序提供了“cluster-store”选项,该选项会将用于 overlay 网络的键值存储区的位置告知引擎。而“cluster-advertise”选项则是用来在网络上通告该机器。
2、创建另一台机器并将其添加到 swarm 中:
$ docker-machine create \ -d virtualbox \ --swarm \ --swarm-discovery="consul://$(docker-machine ip mh-keystore):8500" \ --engine-opt="cluster-store=consul://$(docker-machine ip mh-keystore):8500" \ --engine-opt="cluster-advertise=eth1:2376" \ mhs-demo1
3、查看已创建的机器运行情况:
$ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM default - virtualbox Running tcp://192.168.99.100:2376 mh-keystore * virtualbox Running tcp://192.168.99.103:2376 mhs-demo0 - virtualbox Running tcp://192.168.99.104:2376 mhs-demo0 (master) mhs-demo1 - virtualbox Running tcp://192.168.99.105:2376 mhs-demo0
现在主机群已准备就绪,接下来就可以为运行在这些主机上的容器创建多主机的 overlay 网络了。
1、切换 Docker 环境到 swarm 管理器:
$ eval $(docker-machine env --swarm mhs-demo0)
此处使用了“--swarm”标记将 Docker 命令限制为仅 swarm 信息。
2、查看 swarm 信息:
$ docker info Containers: 3 Images: 2 Role: primary Strategy: spread Filters: affinity, health, constraint, port, dependency Nodes: 2 mhs-demo0: 192.168.99.104:2376 └ Containers: 2 └ Reserved CPUs: 0 / 1 └ Reserved Memory: 0 B / 1.021 GiB └ Labels: executiondriver=native-0.2, kernelversion=4.1.10-boot2docker, operatingsystem=Boot2Docker 1.9.0 (TCL 6.4); master : 4187d2c - Wed Oct 14 14:00:28 UTC 2015, provider=virtualbox, storagedriver=aufs mhs-demo1: 192.168.99.105:2376 └ Containers: 1 └ Reserved CPUs: 0 / 1 └ Reserved Memory: 0 B / 1.021 GiB └ Labels: executiondriver=native-0.2, kernelversion=4.1.10-boot2docker, operatingsystem=Boot2Docker 1.9.0 (TCL 6.4); master : 4187d2c - Wed Oct 14 14:00:28 UTC 2015, provider=virtualbox, storagedriver=aufs CPUs: 2 Total Memory: 2.043 GiB Name: 30438ece0915
由此可看出在管理器上运行着三个容器和两个镜像。
3、创建 overlay 网络(只需在 swarm 中的任一机器上创建即可):
$ docker network create --driver overlay --subnet=10.0.9.0/24 my-net
4、查看运行的网络:
$ docker network ls NETWORK ID NAME DRIVER 412c2496d0eb mhs-demo1/host host dd51763e6dd2 mhs-demo0/bridge bridge 6b07d0be843f my-net overlay b4234109bd9b mhs-demo0/none null 1aeead6dd890 mhs-demo0/host host d0bb78cbe7bd mhs-demo1/bridge bridge 1c0eb8f69ebb mhs-demo1/none null
因为是在 swarm 管理器上,所以在此能看到所有位于 swarm 代理上的网络,包括了每个引擎的默认网络和新创建的 overlay 网络。如果切换到其他 swarm 代理,就只能看到该代理的默认网络以及此处作为多主机的 overlay 网络。
到此,我们的多主机网络就已经创建完成。接下来就可以在其中任意一台主机上启动一个容器,它会自动成为网络的一部分。下面咱们就来测试一下。
1、把上下文环境切换到 swarm 管理器:
$ eval $(docker-machine env --swarm mhs-demo0)
2、在 mhs-demo0 实例上启动 Nginx 服务:
$ docker run -itd --name=web --network=my-net --env="constraint:node==mhs-demo0" nginx
3、在 mhs-demo1 实例上运行 BusyBox 容器,并获取 Nginx 服务器主页内容:
$ docker run -it --rm --network=my-net --env="constraint:node==mhs-demo1" busybox wget -O- http://web ### 省略输出
还有一点需要注意的是,连接到多主机网络的容器会自动连接到 docker_gwbridge 网络,此网络允许容器在其群集之外进行外部连接。在任一 swarm 代理上使用“docker network ls”命令均可看到该网络:
$ eval $(docker-machine env mhs-demo0) $ docker network ls NETWORK ID NAME DRIVER 6b07d0be843f my-net overlay d0bb78cbe7bd bridge bridge 1c0eb8f69ebb none null 412c2496d0eb host host 97102a22e8d2 docker_gwbridge bridge
此时如果查看 Nginx 容器的网络接口将会看到如下情况:
$ docker exec web ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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 22: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default link/ether 02:42:0a:00:09:03 brd ff:ff:ff:ff:ff:ff inet 10.0.9.3/24 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::42:aff:fe00:903/64 scope link valid_lft forever preferred_lft forever 24: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 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
可看出 eth0 接口代表的是连接到 my-net overlay 网络的容器接口,而 eth1 则代表的是连接到 docker_gwbridge 网络的容器接口。