1. 集群环境准备
搭建三台服务器,并安装docker环境,并保证能正常连接互联网,后面会使用其他镜像做负载均衡测试。
- 192.168.104.79
- 192.168.104.80
- 192.168.104.81
首先修改hostname,便于后面区分当前操作所在机器: - 使用
hostname
可以查看当前hostname -
hostnamectl set-hostname 主机名
修改hostname 打开新的窗口,即可生效,重启仍然有效。
其中计划 192.168.104.79
作为集群的 Leader 节点,首先在 79 服务器上执行 docker swarm init
初始化manager节点。
其中上图打印的:docker swarm join --token SWMTKN-1-32t98682uh3p0cvwe3c0t48a9nj9vzytiglcv1qgaz6em39920-1j4km76o6b3ze2blcppfqtt5y 192.168.104.79:2377
即为其他服务器加入当前集群环境的命令。依次在docker-80,docker-81 服务器上执行上面的命令。提示当前节点作为worker角色,加入集群环境。
之后就可以在 79 机器上看到该集群环境的信息了:docker node ls
其中 docker-79 为Leader节点,其他为work节点。
2. 基于 DNS 的负载均衡
DNS server 内嵌于Docker 引擎。下面创建两个基于DNS负载均衡服务:客户端client
和服务端vote
, 服务间通过服务名进行调用通信。 Docker DNS 解析服务名“vote
” 并返回容器ID地址列表(随机排序)。客户端通常会挑第一个IP访问,因此负载均衡可能发生在不同实例之间。
- 2.1 创建network :
docker network create --driver overlay overlay1
- 2.2 创建一个名为
client
的服务
docker service create --endpoint-mode dnsrr --replicas 1 --name client --network overlay1 registry.cn-hangzhou.aliyuncs.com/anoy/ubuntu ping anoyi.com
会自动拉取镜像 registry.cn-hangzhou.aliyuncs.com/anoy/ubuntu
,然后自动启动。查看服务日志:docker service logs 服务ID
看下启动痕迹:docker service ps 服务ID
可以看到,在docker-80机器上运行两次后失败了,最终是运行在docker-79机器上的。去80机器上看下:docker ps -a
可以看到有两次启动痕迹,状态都为Exist
- 2.2 创建
vote
服务
docker service create --endpoint-mode dnsrr --name vote --network overlay1 --replicas 2 registry.cn-hangzhou.aliyuncs.com/anoy/vote
可以看到创建了两个服务实例,并且自动分配,运行在80和81机器上,如下图 NODE
列所示。
- 2.3 进入
client
服务内部,查看vote 解析规则
从上面的服务运行情况,可以看到client 服务是运行在79机器上的,所以需要从79机器上执行 docker ps
,拿到容器ID,然后进入服务内部,使用 dig 来解析服务名 “vote”, 可以看到 vote 会解析到 10.0.1.9
和 10.0.1.8
,这两个地址是集群内部的网络通信IP。
接着,使用 ping 解析 “vote” 服务,多次执行 ping -c1 vote
如下所示,随机交替解析到 10.0.1.9 和 10.0.1.8
如果直接执行 ping vote
,则一直解析到 同一个IP上。
接着使用curl测试,可以看到也是可以随机解析到不同的容器上的。
基于DNS负载均衡存在如下问题:
- 某些应用程序将DNS主机名缓存 到IP地址映射,这会导致应用程序在映射更改时超时。
- 具有非零DNS ttl值 会导致DNS条目反映最新的详细信息时,发生延迟。
3. 基于VIP(Virtual IP)的负载均衡
基于VIP的负载均衡克服了基于DNS负载均衡的一些问题。在这种方法中,每个服务都有一个虚拟IP地址,并且该IP地址映射到与该服务关联的多个容器的IP地址。在这种情况下,与服务关联的服务IP不会改变,即使与改服务关联的容器死亡并重新启动。
使用如下命令创建两个新的服务:client_VIP
和 vote_VIP
docker service create --replicas 1 --name client_VIP --network overlay1 registry.cn-hangzhou.aliyuncs.com/anoy/ubuntu ping anoyi.com
docker service create --name vote_VIP --network overlay1 --replicas 2 registry.cn-hangzhou.aliyuncs.com/anoy/vote
查看这两个服务和他们的IP:docker service inspect --format {{.Endpoint.VirtualIPs}} 服务名称
在 client_VIP
的容器中,使用 dig vote
可以看到 vote
映射同上面一样,映射到到 10.0.1.9
和 10.0.1.8
使用 dig vote
可以看到 vote_VIP
映射到到 10.0.1.14
接着使用 curl 请求 vote_VIP
服务:curl vote_VIP | grep -i "container id"
,输出结果如下,可以看到时一种轮训分发
请求到不同的容器:
这就有点神奇了,对比之前DNS负载均衡的结果,dig vote;
是两个IP,curl 请求的时候,是随机返回的,而 dig vote_VIP;
返回一个IP,curl的时候,是轮训机制分发的。
那这个Service IP 10.0.1.14
是怎么分发到两个容器的呢?
实质是使用Linux内核的iptables 和 IPVS 负载均衡到2个容器。IPtables 实现防火墙机制,IPVS 实现负载均衡。这句话是重点,圈起来要考的。
下面带着这个猜想,看下能不能证明一下。
使用nsenter 进入容器网络空间(namespace)。为此我们需要找到网络命名空间。
如下是docker-79上面的网络命名空间:
进入 /run/docker/netns
目录,可以看到有6个网络命名空间,前两个用于overlay网络,后面用于容器。
接着进去 client_VIP 容器内的网络空间。使用:docker inspect 4664834de94b | grep -i sandbox
,其中 SandboxID
即为 client_VIP 容器的网络空间
同理可以看到 如下是docker-80上面的网络命名空间:
最后对比下结果:
client_VIP
解析vote_VIP
返回的IP是 10.0.1.14
,多次执行仍然是10.0.1.14
其中 curl vote_VIP | grep "container id"
可以看到轮训到两个不同的容器上去。
两个容器的IP分别为:10.0.1.15
、10.0.1.16
至此,可以看到DNS Server 会将服务名 vote_VIP
解析到 Service IP 10.0.1.14
,使用iptables和ipvs,实现两个服务端 vote_VIP
容器10.0.1.15
、10.0.1.16
的负载均衡。
4. 路由网格(Routing mesh)
使用路由网络,服务暴露的端口会暴露在集群中的所有的工作节点。Docker 是通过创建“ingress overlay”网络来实现这一点的,所有节点默认使用内在sandbox 网络命名空间成为“ingress” overlay网络的一部分。
首先,会将Hostname或IP映射到Sandbox
IP,Sandbox中的 iptables 和 IPVS 负责将请求负载均衡到2个vote_Routing
容器,Ingress Sandbox网络命名空间驻留在 Docker Swarm 集群中的所有工作节点,它通过主机映射的端口负载均衡到后端容器来协助路由网格功能。
但是我这里测试后发现,只能访问主节点IP才能请求通,其他节点上的容器请求不通。这就很迷。。。。。。
创建服务:vote_Routing
docker service create --name vote_Routing --network overlay1 --replicas 2 -p 8080:80 registry.cn-hangzhou.aliyuncs.com/anoy/vote
创建服务后,可以看到,服务vote_Routing
分别运行在 docker-80
和 docker-79
两台服务器上。在 docker-80 服务器上可以正常请求的通,并且是轮训的机制负载均衡到两台服务器的容器上。
但是尝试在docker-79
机器上请求:curl 192.168.104.80:8080 | grep -i "container id"
却一直没有响应回来。。。。。。。
也不报错,其中上图的Time列 开始计时,计时能一直走下去,直到提示连接超时。。。。。。。。。。
此时确保防火墙也是关闭状态的,连接超时这个就很坑。。。。。。。。
后面换成别的镜像测试后再补充。
标签:10.0,负载,--,IP,Swarm,VIP,vote,Docker,docker From: https://blog.51cto.com/linmengmeng/5907320