使用Docker Swarm构建Overlay网络实现跨主机的容器网络互通(1.12) 2016-08-14 08:00

说明

Docker Swarm可以方便的在多个主机上创建容器,并且实际容器之间跨主机的网络互通。

Swarm有集群的概念。集群分为Manager节点和Worker节点。一般的操作会在Manager节点上执行。

Swarm有Service的概念。一个Service是指使用相同镜像、同时运行的多个容器,多个容器同时一起对外提供服务,多个容器之间负载均衡。每个Service会有一个浮动IP(VIP),各个容器还有自己的物理IP。

创建基于Swarm的Overlay网络,将Service挂载到此网络上。然后Service中的各个容器便可以通过Service名称(同时也是一个DNS名称)和IP地址实现网络互通。

同一个Service内,多个容器之间的负载均衡有两种方案:

  1. 基于浮动IP(VIP)进行均衡
  2. 基于DNS解析出不同的IP地址进行均衡

前提

Docker Swarn Cluster已经安装配置完毕。本例中Docker Swarm Cluster共三个节点,一个Manager节点和两个worker节点。

使用VIP进行负载均衡

创建Overlay网络

首先,创建一个Overlay网络,网络名称叫"my-swarm-network":

docker network create \
  --driver overlay \
  --subnet 172.70.1.0/24 \
  --opt encrypted \
  my-swarm-network

创建完后,可以查询到创建的network:

[root@docker1 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
4413b8a15f70        bridge              bridge              local
2d35fcc5d5e2        docker_gwbridge     bridge              local
09f3b63353d1        host                host                local
9i43cyau914b        ingress             overlay             swarm
de44b3670d6d        my-bridge-network   bridge              local
9pcv57dt5hhz        my-swarm-network    overlay             swarm
d1016bf6cdf0        none                null                local
[root@docker1 ~]#

创建一个Service,挂载到此网络上

创建一个负荷均衡模式的nginx服务,挂载到此网络上,服务的名字叫"my-web":

docker service create \
  --replicas 3 \
  --name my-web \
  --network my-swarm-network \
  nginx

创建完,可以看到Swarm已经在三个节点上,分别启动了一个容器:

[root@docker1 ~]# docker service ps my-web
ID                         NAME      IMAGE  NODE     DESIRED STATE  CURRENT STATE           ERROR
aty6uidtlcf2y12twuf2bvc0u  my-web.1  nginx  docker2  Running        Running 24 seconds ago
e37dixtdgztw7q0uveyra1pxg  my-web.2  nginx  docker3  Running        Running 24 seconds ago
9iu3r34ypx7nee6t2i9gonals  my-web.3  nginx  docker1  Running        Running 25 seconds ago
[root@docker1 ~]#

检查此服务,查看网络信息

查看my-web服务信息,可以看到分配了一个浮动IP,这个浮动是基于my-swarm-network子网的IP。

[root@docker1 ~]# docker service inspect my-web
[
……
        "Endpoint": {
            "Spec": {
                "Mode": "vip"
            },
            "VirtualIPs": [
                {
                    "NetworkID": "9pcv57dt5hhz7haw5psslvg24",
                    "Addr": "172.70.1.2/24"
                }
            ]
        },
……
]
[root@docker1 ~]#

如果此时进入三个容器中,可以查询到三个容器的物理IP分别是:172.70.1.3/24,172.70.1.4/24,172.70.1.5/24。

[root@docker2 ~]# docker exec -it 14821cb93d32 /bin/sh
# ip a
……
13: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1424 qdisc noqueue state UP group default
    link/ether 02:42:ac:46:01:03 brd ff:ff:ff:ff:ff:ff
    inet 172.70.1.3/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet 172.70.1.2/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe46:103/64 scope link
       valid_lft forever preferred_lft forever
……
#

创建另外一个Service,也挂载到此网络上

创建一个叫"my-busybox"的服务,也挂载到此网络上,这个服务只有一个Replica:

docker service create \
  --name my-busybox \
  --network my-swarm-network \
  busybox \
  sleep 3000

查看此服务:

[root@docker1 ~]# docker service ps my-busybox
ID                         NAME          IMAGE    NODE     DESIRED STATE  CURRENT STATE          ERROR
1pnh6a5qdnf13ubcl9quodrd0  my-busybox.1  busybox  docker1  Running        Running 4 seconds ago
[root@docker1 ~]#

登录到此服务的容器中,查看其IP是172.70.1.6:

/ # ip a
……
17: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1424 qdisc noqueue
    link/ether 02:42:ac:46:01:07 brd ff:ff:ff:ff:ff:ff
    inet 172.70.1.7/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet 172.70.1.6/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe46:107/64 scope link
       valid_lft forever preferred_lft forever
……
/ #

检查网络互通

登录到此服务的容器中,执行与my-web服务相关的网络操作,确认网络是否互通:

[root@docker1 ~]# docker exec -it b7cbb0413b35 /bin/sh
/ # nslookup my-web
Server:    127.0.0.11
Address 1: 127.0.0.11

Name:      my-web
Address 1: 172.70.1.2
/ #
/ # nslookup tasks.my-web
Server:    127.0.0.11
Address 1: 127.0.0.11

Name:      tasks.my-web
Address 1: 172.70.1.5 my-web.3.9iu3r34ypx7nee6t2i9gonals.my-swarm-network
Address 2: 172.70.1.4 my-web.2.e37dixtdgztw7q0uveyra1pxg.my-swarm-network
Address 3: 172.70.1.3 my-web.1.aty6uidtlcf2y12twuf2bvc0u.my-swarm-network
/ # ping my-web
PING my-web (172.70.1.2): 56 data bytes
64 bytes from 172.70.1.2: seq=0 ttl=64 time=0.084 ms
……
/ # wget -O- my-web
Connecting to my-web (172.70.1.2:80)
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
/ #

使用DNS解析进行负载均衡

整体与使用浮动IPO进行负载均衡差不多,差别在于,创建需要均衡的服务时,需要指定--endpoint-mode dnsrr

docker service create \
  --replicas 3 \
  --name my-dnsrr-service \
  --network my-swarm-network \
  --endpoint-mode dnsrr \
  nginx
Tags: #Docker    Post on Docker