docker swarm网络模式

docker swarm 网络模式

swarm的三个网络

名称 类型 注释
docker_gwbridge bridge none
ingress overlay none
overlay none
  • docker_gwbridge和ingress是swarm自动创建的,当用户执行了docker swarm init/connect之后。
  • docker_gwbridge是bridge类型的负责本机container和主机直接的连接
  • ingress负责service在多个主机container之间的路由。
  • 是用户自己创建的overlay网络,通常我们都需要创建自己的network并把service挂在上面。

swarm service的路由办法通常有两种,VIP和DSN

service路由之:虚拟IP

这是缺省情况设置,当用户创建service的时候,这个service会被分配一个VIP,然后每一个具体的container都有一个独立的IP,ingress会负责从VIP到各个container之间的路由。

举例来说:

  1. 创建网络
$ docker network create --driver overlay my-network
kw3iy5w8ws7l568fe2o0ntpgw
$ docker network inspect my-network
[
    {
        "Name": "my-network",
        "Id": "kw3iy5w8ws7l568fe2o0ntpgw",
        ...,
        "IPAM": {
            ...,
            "Config": [
                {
                    "Subnet": "10.0.1.0/24",
                    "Gateway": "10.0.1.1"
                }
            ]
        },

并且看到了它的属性。

创建两个service:

$ docker service create --replicas 2 --network my-network --name my-web nginx
$ docker service create --replicas 1 --network my-network --name my-box busybox sleep 3000

nslookup查看域名解析:

$ docker ps | grep my-box
d0c2c0c88e20        busybox:latest      "sleep 3000"             32 seconds ago       Up 30 seconds                           my-box.1.rbdxb9ta7uk0606u7qw25wypc
$ docker exec -it d0c2c0c88e20 sh

/ # nslookup my-web     # 查看service的虚IP
Server:     127.0.0.11
Address:    127.0.0.11:53

Non-authoritative answer:
Name:   my-web
Address: 10.0.1.2             # 10.0.1.2就是service my-web的虚IP


/ # nslookup tasks.my-web        # 这个命令查看所有的tasks,即containers
Server:     127.0.0.11
Address:    127.0.0.11:53

Non-authoritative answer:
Name:   tasks.my-web
Address: 10.0.1.4
Name:   tasks.my-web
Address: 10.0.1.3


/ # nslookup 10.0.1.2
Server:     127.0.0.11
Address:    127.0.0.11:53

** server can't find 2.1.0.10.in-addr.arpa: NXDOMAIN

/ # nslookup 10.0.1.3
Server:     127.0.0.11
Address:    127.0.0.11:53

Non-authoritative answer:
3.1.0.10.in-addr.arpa   name = my-web.1.61t2nfcofsh3sqxarydp1tobi.my-network

/ # nslookup 10.0.1.4
Server:     127.0.0.11
Address:    127.0.0.11:53

Non-authoritative answer:
4.1.0.10.in-addr.arpa   name = my-web.2.3ngpbetri2v6jb84wysud76ux.my-network

从这个例子我们可以看到:

  1. service my-web的虚拟IP是10.0.1.2
  2. 它有两个containers,IP分别是:10.0.1.3 和 10.0.1.4
  3. 127.0.0.11是swarm内置的DSN服务器,用来解析service名字到IP地址

我们再进入container看看:

$ docker exec -it my-web.1.61t2nfcofsh3sqxarydp1tobi bash
root@1a55df476e01:/tools/tools# ./ifconfig 
eth0: flags=4163  mtu 1450
        inet 10.0.1.3  netmask 255.255.255.0  broadcast 10.0.1.255
        ether 02:42:0a:00:01:03  txqueuelen 0  (Ethernet)
        ...
eth1: flags=4163  mtu 1500
        inet 172.18.0.4  netmask 255.255.0.0  broadcast 172.18.255.255
        ether 02:42:ac:12:00:04  txqueuelen 0  (Ethernet)
        ...
lo: flags=73  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        ...

每一个container有两块网卡:
eth0: 10.0.1.3 这就是我们前面看到的service container IP地址,是属于网络my-network的。
eth1: 172.18.0.4,这是另一个网络地址;是谁的呢, 是网络docker_gwbridge。(另外bridge网络使用的是172.17网段)
也就是说每一个container属于两个网络,my-network和docker_gwbridge,分别用来service路由,和连接主机网络。

补充一点网卡eth1: 172.18.0.4,对应的网关地址是172.18.0.1,那个这个网关地址172.18.0.1是谁呢,它就是主机网络上的docker_gwbridge,在主机上运行ifconfig可以看到:

$ ifconfig 
docker0: flags=4099  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:4bff:fe9a:8b9a  prefixlen 64  scopeid 0x20
        ether 02:42:4b:9a:8b:9a  txqueuelen 0  (Ethernet)
        ...
docker_gwbridge: flags=4163  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255
        inet6 fe80::42:cfff:fedc:ca8  prefixlen 64  scopeid 0x20
        ether 02:42:cf:dc:0c:a8  txqueuelen 0  (Ethernet)
        ...

bridge网络的网段地址从172.17.X.X/16开始,第一个内置的docker0使用了172.17.X.X,后面每新增一个bridge网络就新增一个网地址,172.18.X.X, 172.19.X.X,。。。

至此两个bridge网络都比较清楚了。

另外如果发布service的时候指定了主机端口映射,那么container里面会有三块网卡分别属于:

  1. docker_gwbridge
  2. ingress, 其网段是10.255.X.X,每一个service在ingress上也有一个VIP,例如VIP=10.255.0.2,对映两个container:10.255.0.3和10.255.0.4

做一个总结:

docker swarm网络模式_第1张图片
image.png

发布service的时候:

  1. 如果指定了--publish端口,那么会在ingress网络中创建接口,并产生路由信息。
  2. 如果指定了--network网络,那么会在指定网络里面创建接口,并产业路由信息。
  3. 如果都没有指定,实际上相当于没有通信,不和主机通信,互相之间也不通信。
  4. 如果两者都指定了,那么在两处均创建接口。
  5. 如果没有指定--network网络,那么无法通过service名字寻址,例如curl my-web:80将无法访问;所以通常来说创建swarm service都需要指定一个overlay网络。

注意swarm VIP使用的一个限制:

Swarm routes requests for the VIP in a round robin fashion at L4.
This means that the following Interlock features are incompatible with VIP mode:

* Sticky sessions

也就是说无法做到同一个client过来的请求保持路由到同一个container去。

service路由之:DSN轮询

适合使用自己的DSN Load-Balance算法,例如HAProxy。

创建使用DSN轮询的service。

$ docker service create --replicas 2 --network my-network --name my-dnsrr-web --endpoint-mode dnsrr nginx

由参数--endpoint-mode决定。

先看一下两个container的ip 地址:

# ifconfig  # container 1
eth0: flags=4163  mtu 1450
        inet 10.0.1.28  netmask 255.255.255.0  broadcast 10.0.1.255
        ether 02:42:0a:00:01:1c  txqueuelen 0  (Ethernet)
        ...
eth1: flags=4163  mtu 1500
        inet 172.18.0.7  netmask 255.255.0.0  broadcast 172.18.255.255
        ether 02:42:ac:12:00:07  txqueuelen 0  (Ethernet)
        ...
lo: flags=73  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 0  (Local Loopback)
        ...

# ifconfig  # container 2
eth0: flags=4163  mtu 1450
        inet 10.0.1.29  netmask 255.255.255.0  broadcast 10.0.1.255
        ether 02:42:0a:00:01:1d  txqueuelen 0  (Ethernet)
        ...
eth1: flags=4163  mtu 1500
        inet 172.18.0.6  netmask 255.255.0.0  broadcast 172.18.255.255
        ether 02:42:ac:12:00:06  txqueuelen 0  (Ethernet)
        ...
lo: flags=73  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 0  (Local Loopback)
        ...

两个contaienr的ip 地址分别是:

  1. my-dnsrr-web.1.6a1xknrmh8rxnlvwftuzytwxp: eth0 10.0.1.28, eth1 172.18.0.7
  2. my-dnsrr-web.2.i5sgozdgtj4vs6ahok9wxs1o3: eth0 10.0.1.29, eth1: 172.18.0.6

再看DSN解析结果:

# ping my-dnsrr-web
PING my-dnsrr-web (10.0.1.28) 56(84) bytes of data.
64 bytes from 0cd9f35e6082 (10.0.1.28): icmp_seq=1 ttl=64 time=0.043 ms
64 bytes from 0cd9f35e6082 (10.0.1.28): icmp_seq=2 ttl=64 time=0.040 ms

# ping my-dnsrr-web
PING my-dnsrr-web (10.0.1.29) 56(84) bytes of data.
64 bytes from my-dnsrr-web.2.i5sgozdgtj4vs6ahok9wxs1o3.my-network (10.0.1.29): icmp_seq=1 ttl=64 time=0.096 ms
64 bytes from cf75bccfbacd.my-network (10.0.1.29): icmp_seq=2 ttl=64 time=0.070 ms

# ping my-dnsrr-web
PING my-dnsrr-web (10.0.1.28) 56(84) bytes of data.
64 bytes from 0cd9f35e6082 (10.0.1.28): icmp_seq=1 ttl=64 time=0.024 ms
64 bytes from 0cd9f35e6082 (10.0.1.28): icmp_seq=2 ttl=64 time=0.041 ms

# ping my-dnsrr-web
PING my-dnsrr-web (10.0.1.29) 56(84) bytes of data.
64 bytes from my-dnsrr-web.2.i5sgozdgtj4vs6ahok9wxs1o3.my-network (10.0.1.29): icmp_seq=1 ttl=64 time=0.061 ms
64 bytes from my-dnsrr-web.2.i5sgozdgtj4vs6ahok9wxs1o3.my-network (10.0.1.29): icmp_seq=2 ttl=64 time=0.051 ms

# ping my-dnsrr-web
PING my-dnsrr-web (10.0.1.28) 56(84) bytes of data.
64 bytes from 0cd9f35e6082 (10.0.1.28): icmp_seq=1 ttl=64 time=0.022 ms
64 bytes from 0cd9f35e6082 (10.0.1.28): icmp_seq=2 ttl=64 time=0.022 ms

# ping my-dnsrr-web
PING my-dnsrr-web (10.0.1.29) 56(84) bytes of data.
64 bytes from cf75bccfbacd.my-network (10.0.1.29): icmp_seq=1 ttl=64 time=0.063 ms

每次运行ping解析出的IP地址在两个container之间轮换,也就没有虚IP概念了,而且swarm自动实现了DSN轮询的功能。

再看一个nslookup结果:

# nslookup my-dnsrr-web
Server:     127.0.0.11
Address:    127.0.0.11#53

Non-authoritative answer:
Name:   my-dnsrr-web
Address: 10.0.1.28
Name:   my-dnsrr-web
Address: 10.0.1.29

可见nslookup直接把两个container的地址都解析出来,说明一个域名(service name)对映有两个IP地址。对照前面使用VIP的,一个service name只对映一个IP地址,就是VIP地址,而不管具体有多少个container实例。

你可能感兴趣的:(docker swarm网络模式)