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 | [root@localhost ~] |
可以看到,ping本地以及ping其他主机并没有办法解析
下面我们自己创建网络测试一下
1 | [root@localhost ~]# docker network create my-net |
- 用户可以随时的将容器加入或断开自定义网络
断开
1 |
|
加入
1 | [root@localhost ~]# docker network connect my-net test1 |
- 启动容器指定容器网络,并暴露端口
1 | [root@localhost ~] |
3.1.1 总结
- Docker如果不通过 –network 指定网络,将使用默认网络。
- Docker 官方并不建议使用默认的网络。
- 使用默认网络的话,容器内部只能使用IP地址进行通信,不能使用容器名进行解析,而我们自定义的可以使用容器名解析。
- 我们可以随时的将容器从自定义的网络中断开和重连,断开后容器将没有IP地址
- 容器启动时,我们可以通过-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 叠加网络,默认情况下,群集服务会使用该 叠加网络。即使您从未计划使用群体服务,也需要这样做。之后,您可以创建其他用户定义的叠加网络。
- 在manager, 初始化集群。如果主机只有一个网络接口,则该–advertise-addr标志是可选的。
1
docker swarm init --advertise-addr=<IP-ADDRESS-OF-MANAGER>
保存下输出内容,方便以后加入集群时调用
- 在上worker-1,加入群体。如果主机只有一个网络接口,则该–advertise-addr标志是可选的。
1 | docker swarm join --token <TOKEN> \ |
- 在上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 | [root ~]# docker node ls --filter role=manager |
创建服务
- 在manager上,创建一个新的叠加网络,称为 nginx-net:
1
2
3[root@localhost ~]# docker network create -d overlay nginx-net
au4hqfopux7jzebsf7w1rr8i7
[root@localhost ~]#
注意,创建集群的网络只需要在管理节点中创建即可,当其他节点被管理节点运行服务时,会自动创建该叠加网络。
- 在上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,因为只有一个服务任务可以绑定给定节点上的给定端口。
运行docker service ls以监视服务启动情况,并更改不同主机的html页面进行验证,观察跨主机负载均衡是否生效
创建其他容器可连接的overlay网络,并检查overlay网络是否生效
1 | [] |