momo's Blog.

了解Docker的网络模型

字数统计: 2.6k阅读时长: 11 min
2019/09/26 Share

1. 前言

为了加深对docker网络的了解,本文将详细的介绍Docker网络模型

2. Docker 网络模型

  • bridge :默认的网络模型,通常创建容器时,使用 -p 选项则默认使用的是bridge网络模型。
  • host : 使用此网络模型,将删除容器与宿主机的net 名称空间的隔离,容器将直接占用宿主机端口,使用宿主机网络。
  • overlay : 叠加网络,通常为swram群集使用,创建后将借助两个Docker宿主机现存网络之上模拟出一条网络通道,使不同宿主机之间的容器可以通过叠加网络的网段相互通信。
  • macvlan : 此网络模型会将mac地址分配给容器,使其在网络中模拟出真实的物理设备。docker守护进程会通过mac地址,将流量路由至此容器。

2.1 网络模型的选择

  • 当一台宿主机运行多个容器时,为了保证容器间端口不冲突,建议使用bridge网络单独分配端口。
  • 当宿主机只为某一个容器工作,或者你不希望将容器的网络进行隔离,可以使用Host网络。
  • 当你Docker中采用集群模式时,或者你希望两台宿主机之间的容器之间通过IP地址即可访问时,可以使用overlay网络。
  • 当你想让容器在其他设备监控下像物理主机时,可以使用macvlan网络。

3. 使用 bridge 网络

如果使用过KVM虚拟化的小伙伴一定很清楚,KVM通过桥接网络来建立于虚拟机的通信。
桥接网络,顾名思义,是指在本地物理网卡模拟出一个虚拟网卡,这个虚拟网卡的流量实际上是通过物理网卡进行转发,所以称之为桥接网络。

docker默认网络则是桥接模式,会在宿主机新建出一个虚拟网卡:docker0
默认启动的容器,如果没有指定网络,将自动连接到此网络,并分配出一个IP地址

除此之外,用户也可以自己定义桥接网络,自定义的桥接网络会优于docker默认的桥接网络

3.1 用户自定义的bridge网络与默认的bridge区别

  • 使用用户自定义的网络docker将会提供DNS解析

我们可以测试一下:

1
2
3
4
5
6
[root@localhost ~]# docker run --rm --name test1 -it busybox /bin/sh
/ # ping test1
ping: bad address 'test1'
/ # ping test2
ping: bad address 'test2'
/ #

可以看到,ping本地以及ping其他主机并没有办法解析
下面我们自己创建网络测试一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@localhost ~]# docker network create my-net
[root@localhost ~]# docker run --rm --network=my-net --name test1 -it busybox /bin/sh
/ # ping test1
PING test1 (172.21.0.2): 56 data bytes
64 bytes from 172.21.0.2: seq=0 ttl=64 time=0.133 ms
^C
--- test1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.133/0.133/0.133 ms
/ # ping test2
PING test2 (172.21.0.3): 56 data bytes
64 bytes from 172.21.0.3: seq=0 ttl=64 time=0.165 ms
64 bytes from 172.21.0.3: seq=1 ttl=64 time=0.193 ms
^C
--- test2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.165/0.179/0.193 ms
/ #
  • 用户可以随时的将容器加入或断开自定义网络

断开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

[root@localhost ~]# docker network disconnect my-net test1
[root@localhost ~]#

# 进入容器查看
/ # ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:10 errors:0 dropped:0 overruns:0 frame:0
TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:618 (618.0 B) TX bytes:618 (618.0 B)

/ #

加入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@localhost ~]# docker network connect my-net test1
[root@localhost ~]#
/ # ifconfig
eth1 Link encap:Ethernet HWaddr 02:42:AC:15:00:02
inet addr:172.21.0.2 Bcast:172.21.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:648 (648.0 B) TX bytes:0 (0.0 B)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:10 errors:0 dropped:0 overruns:0 frame:0
TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:618 (618.0 B) TX bytes:618 (618.0 B)
  • 启动容器指定容器网络,并暴露端口
1
2
[root@localhost ~]# docker run --name my-nginx --network my-net -p 8888:80 nginx
Unable to find image 'nginx:latest' locally

3.1.1 总结

  1. Docker如果不通过 –network 指定网络,将使用默认网络。
  2. Docker 官方并不建议使用默认的网络。
  3. 使用默认网络的话,容器内部只能使用IP地址进行通信,不能使用容器名进行解析,而我们自定义的可以使用容器名解析。
  4. 我们可以随时的将容器从自定义的网络中断开和重连,断开后容器将没有IP地址
  5. 容器启动时,我们可以通过-p 或者 -P 来映射容器内的端口

4. 使用host网络

  • Host网络 除去了原本容器与宿主机之前的网络隔离,从而可以直接占用宿主机的网络
  • 使用Host网络,将无需映射端口,容器内监听的端口在宿主机直接使用netstat 命令即可看到
1
docker run --rm -d --network host --name my_nginx nginx

5. 使用overlay网络

要使用overlay网络,需要初始化或者加入群集,docker会新建两个网络

  • 一个是overlay网络ingress,用于处理与群体服务有关的控制和数据流量。创建群集服务并且不将其连接到用户定义的覆盖网络时,将默认使用此 ingress 网络。

  • 一个名为的桥接网络docker_gwbridge,它将连接docker的守护进程到各个节点。

你可以使用docker network create 来创建 overlay 网络,要注意的是,服务或者容器可以一次连接多个网络。但是容器之间只能在相同网络进行通信。

5.1 创建overlay的前提条件

提前说明,此部分很重要,有很多人创建玩overlay网络后,发现并没有时间应该有的效果,并且检查也一头雾水,所以需要详细的了解overlay的工作过程。

overlay网络进行通信时,需要占用3个网络端口

  • 用于群集管理通信的TCP端口2377

  • TCP和UDP端口7946,用于节点之间的通信

  • UDP端口4789,用于overlay网络流量,如果此端口没有监听,或者防火墙阻拦,overlay网络将无法做到跨宿主机通信

  • 在创建overlay网络前,需要激活swarm集群管理,分别在两台节点上执行, docker swarm init 以及 docker swarm join

这两个都将创建默认的ingress 叠加网络,默认情况下,群集服务会使用该 叠加网络。即使您从未计划使用群体服务,也需要这样做。之后,您可以创建其他用户定义的叠加网络。

  1. 在manager, 初始化集群。如果主机只有一个网络接口,则该–advertise-addr标志是可选的。
    1
    docker swarm init --advertise-addr=<IP-ADDRESS-OF-MANAGER>

保存下输出内容,方便以后加入集群时调用

  1. 在上worker-1,加入群体。如果主机只有一个网络接口,则该–advertise-addr标志是可选的。
1
2
3
docker swarm join --token <TOKEN> \
--advertise-addr <IP-ADDRESS-OF-WORKER-1> \
<IP-ADDRESS-OF-MANAGER>:2377
  1. 在上manager,列出所有节点。此命令只能由管理员执行。
    1
    2
    3
    4
    5
    [root@localhost ~]# docker node ls
    ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
    b3n0ugrgd2kc8s7pj0l028rt2 * localhost.localdomain Ready Active Leader 18.09.6
    uklmc8wr08vls7kehg0z6y8m9 localhost.localdomain Ready Active 18.09.6
    [root@localhost ~]#

您还可以使用该–filter标志按角色进行过滤:

1
2
3
4
5
6
7
[root@localhost ~]# docker node ls --filter role=manager
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
b3n0ugrgd2kc8s7pj0l028rt2 * localhost.localdomain Ready Active Leader 18.09.6
[root@localhost ~]# docker node ls --filter role=worker
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
uklmc8wr08vls7kehg0z6y8m9 localhost.localdomain Ready Active 18.09.6
[root@localhost ~]#

创建服务

  1. 在manager上,创建一个新的叠加网络,称为 nginx-net:
    1
    2
    3
    [root@localhost ~]# docker network create -d overlay nginx-net
    au4hqfopux7jzebsf7w1rr8i7
    [root@localhost ~]#

注意,创建集群的网络只需要在管理节点中创建即可,当其他节点被管理节点运行服务时,会自动创建该叠加网络。

  1. 在上manager,创建一个连接到的5副本Nginx服务nginx-net。该服务将向外部世界发布80端口。所有服务任务容器都可以彼此通信,而无需打开任何端口。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [root@localhost ~]# docker service create --name my-nginx -p 80:80 --replicas=5 --network nginx-net nginx
    Error response from daemon: rpc error: code = InvalidArgument desc = port '80' is already in use by service 'flask_web' (dplob4wwnrrgxf8rjmec13vn9) as an ingress port
    [root@localhost ~]# docker service create --name my-nginx -p 899:80 --replicas=5 --network nginx-net nginx
    af9iufr1fff3j2qwbruxef2q6
    overall progress: 5 out of 5 tasks
    1/5: running [==================================================>]
    2/5: running [==================================================>]
    3/5: running [==================================================>]
    4/5: running [==================================================>]
    5/5: running [==================================================>]
    verify: Service converged
    [root@localhost ~]#

因为调试其他服务,80端口已经被占用,所以改成899端口

默认的发布模式ingress,当你不指定所使用mode的–publish标志,意味着如果你浏览到端口80上manager,worker-1或者worker-2即使没有,你会被连接到端口80上的5项服务任务之一,任务当前正在您浏览到的节点上运行。如果要使用host模式发布端口 ,则可以将其添加mode=host到–publish输出中。但是,在这种情况下,也应该使用–mode global代替–replicas=5,因为只有一个服务任务可以绑定给定节点上的给定端口。

  1. 运行docker service ls以监视服务启动情况,并更改不同主机的html页面进行验证,观察跨主机负载均衡是否生效

  2. 创建其他容器可连接的overlay网络,并检查overlay网络是否生效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@localhost ~]# docker network create -d overlay --attachable my-attachable-overlay
j7qbhhc3t4o0w7a73lplimxyo
[root@localhost ~]#
# 如果需要允许独立的容器使用此网络,则需要在创建网络时,使用 --attachable 选项


# node1
[root@localhost ~]# docker run -it --name test1 --rm --network my-attachable-overlay busybox /bin/sh
/ #

# node2
[root@localhost ~]# docker run -it --name test2 --rm --network my-attachable-overlay busybox /bin/sh
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:fe301db49df08c384001ed752dff6d52b4305a73a7f608f21528048e8a08b51e
Status: Downloaded newer image for busybox:latest
/ # ping test1
PING test1 (10.0.3.2): 56 data bytes
64 bytes from 10.0.3.2: seq=0 ttl=64 time=1.717 ms
64 bytes from 10.0.3.2: seq=1 ttl=64 time=0.948 ms
64 bytes from 10.0.3.2: seq=2 ttl=64 time=0.896 ms

# 我们可以看到,容器是可以互相通信的
CATALOG
  1. 1. 1. 前言
  2. 2. 2. Docker 网络模型
    1. 2.1. 2.1 网络模型的选择
  3. 3. 3. 使用 bridge 网络
    1. 3.1. 3.1 用户自定义的bridge网络与默认的bridge区别
      1. 3.1.1. 3.1.1 总结
  4. 4. 4. 使用host网络
  5. 5. 5. 使用overlay网络
    1. 5.1. 5.1 创建overlay的前提条件