Docker Swarm(三):集群服务间通信之RoutingMesh
前一小节通过service create 部署了wordpress,我们的这个wordpress有2个service组成一个wordpress,一个mysql。这2个service运行在不同的机器上边,并且他们之前是可以进行通信的,可以通过servicename的方式通信。先创建mysql,wordpress查找mysql就是通过servicename这种方式。懂网络的老铁应该就知道了,这里面肯定有DNS的功劳在里面。
实验的方式了解这个网络
- 必须创建overlay的network
sudo docker network create -d overlay demo
- 创建一个service,这个service 使用whoami,这个image,这个image的作用,就是访问后,返回当前访问的主机名称
docker service create --name whoami -p 8000:8000 --network demo jwilder/whoami
#查看service 里面的服务
docker service ls
#查看whoami的信息
docker service ps whoami
#因为service ps whoami 在manager上运行,直接在manager查看ps下
docker ps
#访问下本地swarm-worker3的whoami
curl 127.0.0.1:8000
- 创建一个service,这个service 使用busybox,之前创建过是一个比较简单的image,这个是为了当客户端service之间的访问。
docker service create --name client -d --network demo busybox sh -c "while true;do sleep 3600;done"
docker service ls
#在swam-work3上进行运行
docker exec -it busybox的容器ID sh
ping whoami
ping whoami ip地址是10.0.0.48
- 测试whoami的ip是否发生变化
在manager下进行scale 扩展为2个,查看到一个在worker2上边,并在worker2的ps上可以查看到whoami的运行,尝试继续ping whoami,结果ip不发生变化。
#manager机器上进行扩展
docker service scale whoami=2
#worker1 上运行 查看whoami 是否存在
docker ps
#worker3 上ping whoami发现ip没有发生变化10.0.0.48
ping whoami
为什么呢 ip不发生变化,其实我们ping的地址是一个虚拟的ip,docker 集群默认使用 Overlay 网络驱动,Overlay 驱动实现了跨主机集群内部虚拟网络。它的作用:将运行的多个容器(不同主机),附加(attach to)到一个网络默认情况下,服务发现为群集中的每个服务分配虚拟IP地址(VIP)和 动态 DNS,使其可以通过服务名称将其提供给同一网络上的容器。即在一个 Overlay 虚拟网络内,使用服务名称访问,将实现任务级别的负载均衡在群集中使用覆盖网络,需要在群集节点之间打开以下端口:
端口7946 TCP / UDP用于容器网络发现。
端口4789 UDP用于容器覆盖网络。
机器进行迁移的时候有一套map<k,v>关系,虚拟ip 和实际的ip 有个对应的关系
- 轮训的负载机制
wget whoami:8000
more index.html
#因为目前就有2个whoami,
#所以可以看到第三次执行wget获取的时候发现id重复了也变成了adc8b384a15b
Routing Mesh的体验
- Internal — Container 和Container 之间的访问通过overlay网络(通过VIP虚拟IP)
- Ingress---- 如果服务有绑定接口,则此服务可以通过任意swarm节点的响应接口访问
Load Balancing
现在有3台机器1个client,2个web,他们3个连通在同一个swam下,当client访问web的时候其实,其实是访问10.0.9.4,然后通过负载的方式映射到10.0.9.5或者10.0.9.6上面。
PS:内部负载均衡
当在docker swarm集群模式下创建一个服务时,会自动在服务所属的网络上给服务额外的分配一个虚拟IP,当解析服务名字时就会返回这个虚拟IP。对虚拟IP的请求会通过overlay网络自动的负载到这个服务所有的健康任务上。这个方式也避免了客户端的负载均衡,因为只有单独的一个虚拟IP会返回到客户端,docker会处理虚拟IP到具体任务的路由,并把请求平均的分配给所有的健康任务。
当创建或更新一个服务时,你可以利用–publish选项把一个服务暴露到外部,在docker swarm模式下发布一个端口意味着在集群中的所有节点都会监听这个端口,这时当访问一个监听了端口但是并没有对应服务运行在其上的节点会发生什么呢?
- 接下来就该我们的路由网(routing mesh)出场了,路由网时docker1.12引入的一个新特性,它结合了IPVS和iptables创建了一个强大的集群范围的L4层负载均衡,它使所有节点接收服务暴露端口的请求成为可能。当任意节点接收到针对某个服务暴露的TCP/UDP端口的请求时,这个节点会利用预先定义过的Ingress overlay网络,把请求转发给服务对应的虚拟IP。ingress网络和其他的overlay网络一样,只是它的目的是为了转换来自客户端到集群的请求,它也是利用介绍过的基于VIP的负载均衡技术。
- 当启动服务时,你可以为你的应用创建一个外部的DNS服务,并把它映射到你集群的任意节点或者是所有节点,你无需担心你的容器具体运行在那个节点上,因为有了路由网这个特性后,你的集群看起来就像是单独的一个节点一样。
上面这个图表明了路由网是怎么工作的:
- 服务(app)拥有两份复制,并把端口映射到外部端口的8000
- 路由网在集群中的所有节点上都暴露出8000
- 外部对服务app的请求可以是任意节点,在本例子中外部的负载均衡器将请求转发到了没有app服务的主机上
docker swarm的IPVS利用ingress overlay网路将请求重新转发到运行着app服务的节点的容器中
PS:负载均衡解决了单一入口负载到多个容器上问题, 但是由于容器调度之后可能落到多个机器上, 假如某些主机上面没有工作的容器,而对外服务时候又希望服务可以被访问, Routing Mesh概念引入是解决多个入口点负载到单个容器的问题。