主要内容
简介
当我们在创建swarm集群的时候,默认有两个网络会同时被创建,它们是
- ingress 属于overlay网络,通过routing mesh的方式实现容器网络的负载均衡
- docker_gwbridge 用于连接不同Docker host上的docker进程
swarm模式中,如果容器没有显示指定网络,默认使用名为ingress的overlay网络,虽然它是一个overlay网络,但是ingress下的容器是不能互相通讯的,ingress的作用是把用户的请求分发给指定节点的容器之中,实现流量的负载。
routing mesh和VIP
ingress的特点是routing mesh,即容器内部的负载均衡。假设网络上部署了一个3副本的web服务器,用户向容器发送请求的时候,routing mesh负责选择节点响应用户的请求。
routing mesh的核心是VIP,每个容器除了自己原来真实的IP地址之外,还有一个VIP,routing mesh就是把请求转发VIP实现负载均衡的。
从上图可见,不管容器中是否提供服务(node 3),只要端口开放了,routing mesh就会转发该容器的流量。
从外界访问容器
和普通容器一样,swarm node中的容器要向外界提供服务,只需要使用--publish
选项开放指定的端口即可,例如http服务。
1 2 3 4 |
[root@centos7-server ~]# docker service create --name webapp \ --publish published=8080,target=80 \ #将外部8080端口映射到容器中的80端口 --replicas 2 nginx |
短语法:
1 2 |
[root@centos7-server ~]# docker service create --name webapp -p 8080:80 --replicas 2 nginx |
为已有容器添加开放端口
1 2 |
[root@centos7-server ~]# docker service update --publish-add 80:80 webapp |
容器之间互相访问
默认的ingress网络即使是相同的网络中的容器也不能互相访问。例如两个容器:webapp和mysql,如果它们都处于ingress网络,那么webapp是连不上mysql容器的。解决办法有两个:
- 开放mysql的访问端口
- 使用自定义overlay网络
第一种方法安全性差,一旦mysql的端口发布出来,外界就可以任意访问mysql服务,安全得不到保障。
第二种方法是推荐的,因为同一个自定义overlay网络中容器的任意端口是互相开放的,不需要publish任何一个端口,提供了可访问性的同时保证了安全性。
创建自定义overlay网络
swarm模式中的自定义overlay网络不需要使用key-value数据库保存网络信息。
该命令只能在manager node中执行。
1 2 |
[root@centos7-server ~]# docker network create --driver overlay ov_net |
创建后查看网络,它的范围是swarm
1 2 3 4 5 |
[root@centos7-server ~]# docker network ls NETWORK ID NAME DRIVER SCOPE ... zoh23lnwz1wb ov_net overlay swarm |
创建服务并加入自定义网络
首先创建web服务容器
1 2 |
[root@centos7-server ~]# docker service create --name webapp --network ov_net --publish 80:80 nginx |
其次是mysql容器
1 2 3 4 5 |
[root@centos7-server ~]# docker service create --name mysql \ --network ov_net \ -e MYSQL_ROOT_PASSWORD=your_password \ mysql:5.7.23 |
为了方便测试,直接在mysql容器中安装ping命令测试容器间的连通性
1 2 3 4 |
[root@centos74vm ~]# docker exec -it mysql.1.spqoq3476vh8g8poo8vjzqdtw /bin/bash root@f6a8e81a0d68:/# apt update #在容器中执行 root@f6a8e81a0d68:/# apt install iputils-ping #在容器中执行 |
完成后使用ping命令测试webapp
1 2 3 4 5 6 7 8 9 10 |
root@f6a8e81a0d68:/# ping webapp -c 3 PING webapp (10.0.1.8) 56(84) bytes of data. 64 bytes from 10.0.1.8 (10.0.1.8): icmp_seq=1 ttl=64 time=0.112 ms 64 bytes from 10.0.1.8 (10.0.1.8): icmp_seq=2 ttl=64 time=0.135 ms 64 bytes from 10.0.1.8 (10.0.1.8): icmp_seq=3 ttl=64 time=0.109 ms --- webapp ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2001ms rtt min/avg/max/mdev = 0.109/0.118/0.135/0.017 ms |
由于overlay网络提供了DNS解析,我们可以直接使用名称访问容器,现在证明webapp和mysql现在是可以通讯的,且webapp的ip地址是10.0.1.8。现在我们进入webapp内部安装net-tools
程序,这样就可以使用ifconfig
命令查看容器内部网络
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
root@nas-share:~# docker exec -it webapp.1.ip51dfx2m3wlm5hkitfpouuta /bin/bash root@07807a369336:/# apt update root@07807a369336:/# apt install net-tools root@07807a369336:/# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450 inet 10.255.0.24 netmask 255.255.0.0 broadcast 10.255.255.255 ether 02:42:0a:ff:00:18 txqueuelen 0 (Ethernet) RX packets 22 bytes 2224 (2.1 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 18 bytes 3988 (3.8 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450 inet 10.0.1.10 netmask 255.255.255.0 broadcast 10.0.1.255 ether 02:42:0a:00:01:0a txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 eth2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.18.0.3 netmask 255.255.0.0 broadcast 172.18.255.255 ether 02:42:ac:12:00:03 txqueuelen 0 (Ethernet) RX packets 5679 bytes 8485304 (8.0 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 3693 bytes 268810 (262.5 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ...... |
发现容器内部除了本地回环(lo)外还有3个ip地址,但是没有一个是10.0.1.8,实际上,10.0.1.8就是所谓的VIP,我们不需要知道容器的实际IP地址就可以容器网络,routing mesh就是通过这个地址进行流量分发。可以使用下面的命令查看容器的VIP
1 2 3 4 5 6 7 8 9 |
[root@centos7-server ~]# docker service inspect webapp ...... "VirtualIPs": [ { "NetorkID": "zoh23lnwz1wb96gastspqyxq1", "Addr": "10.0.1.8/24" }, ...... |
跳过routing mesh转发
有时候部分容器不需要routing mesh,通过把端口的开放模式设置为host
即可。
1 2 3 4 5 |
docker service create --name dns-cache \ --publish published=53,target=53,protocol=udp,mode=host \ --mode global \ dns-cache |
外部负载均衡器
routing mesh可以和外部负载均衡器混合使用,也可以禁用routing mesh,单独配置外部负载均衡,例如keepalived、haproxy等。
在这种情况下,端口8080必须能被HAProxy访问。
禁用routing mesh
如果我们只选择使用外部负载均衡,则可以关掉内部的routing mesh。禁用routing mesh很简单,创建的时候更改--endpoints-mode
为dnsrr即可,默认是vip。
1 2 3 4 5 6 |
[root@centos7-server ~]# docker service create --name web2 \ --network ov_net \ --endpoint-mode dnsrr \ #禁用routing mesh --replicas 2 \ nginx |
现在使用docker service inspect web2
,已经没有VIP的信息了。
转载请注明:Pure nonsense » Docker swarm网络