首页 > 其他分享 >Docker Swarm 内部服务发现和负载均衡原理

Docker Swarm 内部服务发现和负载均衡原理

时间:2022-12-02 17:38:37浏览次数:45  
标签:10.0 负载 -- IP Swarm VIP vote Docker docker


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 内部服务发现和负载均衡原理_docker


其中上图打印的:​​​docker swarm join --token SWMTKN-1-32t98682uh3p0cvwe3c0t48a9nj9vzytiglcv1qgaz6em39920-1j4km76o6b3ze2blcppfqtt5y 192.168.104.79:2377​​ 即为其他服务器加入当前集群环境的命令。依次在docker-80,docker-81 服务器上执行上面的命令。提示当前节点作为worker角色,加入集群环境。

Docker Swarm 内部服务发现和负载均衡原理_IP_02


之后就可以在 79 机器上看到该集群环境的信息了:​​docker node ls​

Docker Swarm 内部服务发现和负载均衡原理_docker_03


其中 docker-79 为Leader节点,其他为work节点。

2. 基于 DNS 的负载均衡

DNS server 内嵌于Docker 引擎。下面创建两个基于DNS负载均衡服务:客户端​​client​​​和服务端​​vote​​​, 服务间通过服务名进行调用通信。 Docker DNS 解析服务名“​​vote​​” 并返回容器ID地址列表(随机排序)。客户端通常会挑第一个IP访问,因此负载均衡可能发生在不同实例之间。

Docker Swarm 内部服务发现和负载均衡原理_IP_04

  • 2.1 创建network : ​​docker network create --driver overlay overlay1​
  • Docker Swarm 内部服务发现和负载均衡原理_负载均衡_05


  • 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

Docker Swarm 内部服务发现和负载均衡原理_服务发现_06


会自动拉取镜像 ​​registry.cn-hangzhou.aliyuncs.com/anoy/ubuntu​​​ ,然后自动启动。查看服务日志:​​docker service logs 服务ID​

Docker Swarm 内部服务发现和负载均衡原理_服务发现_07


看下启动痕迹:​​docker service ps 服务ID​

Docker Swarm 内部服务发现和负载均衡原理_docker_08


可以看到,在docker-80机器上运行两次后失败了,最终是运行在docker-79机器上的。去80机器上看下:​​docker ps -a​​​ 可以看到有两次启动痕迹,状态都为​​Exist​

Docker Swarm 内部服务发现和负载均衡原理_服务发现_09

  • 2.2 创建 ​​vote​​ 服务
docker service create --endpoint-mode dnsrr --name vote --network overlay1 --replicas 2 registry.cn-hangzhou.aliyuncs.com/anoy/vote

Docker Swarm 内部服务发现和负载均衡原理_服务发现_10


可以看到创建了两个服务实例,并且自动分配,运行在80和81机器上,如下图 ​​NODE​​ 列所示。

Docker Swarm 内部服务发现和负载均衡原理_服务发现_11

  • 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

Docker Swarm 内部服务发现和负载均衡原理_IP_12


如果直接执行 ​​ping vote​​,则一直解析到 同一个IP上。

Docker Swarm 内部服务发现和负载均衡原理_服务发现_13


接着使用curl测试,可以看到也是可以随机解析到不同的容器上的。

Docker Swarm 内部服务发现和负载均衡原理_docker_14


基于DNS负载均衡存在如下问题:

  • 某些应用程序将DNS主机名缓存 到IP地址映射,这会导致应用程序在映射更改时超时。
  • 具有非零DNS ttl值 会导致DNS条目反映最新的详细信息时,发生延迟。

3. 基于VIP(Virtual IP)的负载均衡

基于VIP的负载均衡克服了基于DNS负载均衡的一些问题。在这种方法中,每个服务都有一个虚拟IP地址,并且该IP地址映射到与该服务关联的多个容器的IP地址。在这种情况下,与服务关联的服务IP不会改变,即使与改服务关联的容器死亡并重新启动。

Docker Swarm 内部服务发现和负载均衡原理_IP_15


使用如下命令创建两个新的服务:​​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 Swarm 内部服务发现和负载均衡原理_IP_16

docker service create --name vote_VIP --network overlay1 --replicas 2 registry.cn-hangzhou.aliyuncs.com/anoy/vote

Docker Swarm 内部服务发现和负载均衡原理_服务发现_17


查看这两个服务和他们的IP:​​docker service inspect --format {{.Endpoint.VirtualIPs}} 服务名称​

Docker Swarm 内部服务发现和负载均衡原理_docker_18


在 ​​client_VIP​​的容器中,使用 ​​dig vote​​可以看到 ​​vote​​ 映射同上面一样,映射到到 ​​10.0.1.9​​ 和 ​​10.0.1.8​

Docker Swarm 内部服务发现和负载均衡原理_IP_19


使用 ​​dig vote​​可以看到 ​​vote_VIP​​ 映射到到 ​​10.0.1.14​

Docker Swarm 内部服务发现和负载均衡原理_docker_20


接着使用 curl 请求 ​​vote_VIP​​ 服务:​​curl vote_VIP | grep -i "container id"​​,输出结果如下,可以看到时一种​​轮训分发​​请求到不同的容器:

Docker Swarm 内部服务发现和负载均衡原理_服务发现_21


这就有点神奇了,对比之前DNS负载均衡的结果,​​dig vote;​​ 是两个IP,curl 请求的时候,是随机返回的,而 ​​dig vote_VIP;​​ 返回一个IP,curl的时候,是轮训机制分发的。

Docker Swarm 内部服务发现和负载均衡原理_负载均衡_22


那这个Service IP ​​10.0.1.14​​ 是怎么分发到两个容器的呢?

实质是使用Linux内核的iptables 和 IPVS 负载均衡到2个容器。IPtables 实现防火墙机制,IPVS 实现负载均衡。这句话是重点,圈起来要考的。

下面带着这个猜想,看下能不能证明一下。

使用nsenter 进入容器网络空间(namespace)。为此我们需要找到网络命名空间。

如下是docker-79上面的网络命名空间:

Docker Swarm 内部服务发现和负载均衡原理_负载均衡_23


进入 ​​/run/docker/netns​​ 目录,可以看到有6个网络命名空间,前两个用于overlay网络,后面用于容器。

接着进去 client_VIP 容器内的网络空间。使用:​​docker inspect 4664834de94b | grep -i sandbox​​​ ,其中 ​​SandboxID​​ 即为 client_VIP 容器的网络空间

同理可以看到 如下是docker-80上面的网络命名空间:

Docker Swarm 内部服务发现和负载均衡原理_IP_24

最后对比下结果:

​client_VIP​​​ 解析​​vote_VIP​​​ 返回的IP是 ​​10.0.1.14​​​,多次执行仍然是​​10.0.1.14​

Docker Swarm 内部服务发现和负载均衡原理_负载均衡_25


其中 ​​curl vote_VIP | grep "container id"​​ 可以看到轮训到两个不同的容器上去。

Docker Swarm 内部服务发现和负载均衡原理_负载均衡_26


两个容器的IP分别为:​​10.0.1.15​​ 、​​10.0.1.16​

Docker Swarm 内部服务发现和负载均衡原理_负载均衡_27

Docker Swarm 内部服务发现和负载均衡原理_docker_28


至此,可以看到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网络的一部分。

Docker Swarm 内部服务发现和负载均衡原理_IP_29

首先,会将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

Docker Swarm 内部服务发现和负载均衡原理_IP_30


创建服务后,可以看到,服务​​vote_Routing​​​ 分别运行在 ​​docker-80​​​ 和 ​​docker-79​​ 两台服务器上。在 docker-80 服务器上可以正常请求的通,并且是轮训的机制负载均衡到两台服务器的容器上。

Docker Swarm 内部服务发现和负载均衡原理_IP_31


但是尝试在​​docker-79​​​机器上请求:​​curl 192.168.104.80:8080 | grep -i "container id"​​ 却一直没有响应回来。。。。。。。

Docker Swarm 内部服务发现和负载均衡原理_IP_32


也不报错,其中上图的Time列 开始计时,计时能一直走下去,直到提示连接超时。。。。。。。。。。

Docker Swarm 内部服务发现和负载均衡原理_IP_33


此时确保防火墙也是关闭状态的,连接超时这个就很坑。。。。。。。。

后面换成别的镜像测试后再补充。

 

标签:10.0,负载,--,IP,Swarm,VIP,vote,Docker,docker
From: https://blog.51cto.com/linmengmeng/5907320

相关文章

  • Docker 使用PXC搭建MySQL集群(MySQL:5.7.24)
    关于MySQL集群,常用的有两种模式:​​Replication集群架构(主从复制)​​​和​​PXC集群架构​​PXC集群方案所有节点都是可读可写的,Replication从节点不能写入,因为主从同步......
  • 【FastDfs】Docker自定义构建ARM架构的FastDfs镜像
    由于服务器环境为ARM架构,在部署fastdfs时,发现网上的镜像几乎都是X86_64的,不同架构的镜像还不能通用,这个就有点烦了。。。。。由于之前没有从头编译制作过镜像,步步都是坑,在......
  • Docker swarm 安装MySQL集群
    这里直接采用的是5.7.24版本的MySQL初始化dockerswarm:dockerswarminit正常会显示当前服务器作为leader,然后打印出来加入此dockerswarm的token。我这里执行过了,使用d......
  • docker从容器里面拷文件到宿主机或从宿主机拷文件到docker容器里面
    1、从容器里面拷文件到宿主机?在宿主机里面执行如下命令:dockercp容器名:要拷贝的文件在容器里面的路径要拷贝到宿主机的相应路径假设容器名为testtomcat,要从容器里面......
  • 内网服务器搭建docker环境
    1.x86_64服务器安装docker1.下载docker安装包下载地址:https://download.docker.com/linux/static/stable/x86_64/这里可以看到很多docker版本的压缩包。我这里下......
  • 如何使用 Docker 私有化部署 GitLab 教程 All In One
    如何使用Docker私有化部署GitLab教程AllInOneCI/CDGitLabInstallself-managedGitLabSelf-managed–installonyourowninfrastructurehttps://abou......
  • Deepin系统安装docker
    docker安装Deepin软件仓库有Docker,可以通过一键脚本安装1.安装dockersudoapt-getupdatesudoapt-getinstalldocker-cedocker-v2.授权普通用户运行dockersudo......
  • Deepin系统安装Java、maven、svn、git、eclipse svn插件、docker
    目录jdk、Maven安装svn、git安装eclipse、IDEA安装docker安装jdk、Maven安装下载jdk、Mavenjdk下载地址|maven下载安装配置对下载好的jdk、maven压缩包解压,移动到......
  • JAVA面试题--Docker
    Docker1.什么Docker2.Docker与虚拟机有何不同3.什么是Docker镜像4.什么是Docker容器5.Docker容器有几种状态6.DockerFile中最常见的指定是什么?7.DockerFile中的命......
  • Docker Swarm 安装 Redis 集群(bitnami/redis-cluster:latest)
    准备集群环境:​​docker-79​​​、​​docker-80​​​、​​docker-81​​拉取镜像:dockerpullbitnami/redis-cluster:latest3.在任意文件夹下新建compose.yml脚本:​......