音效素材网提供各类素材,打造精品素材网站!

站内导航 站长工具 投稿中心 手机访问

音效素材

详解Docker Swarm服务发现和负载均衡原理
日期:2018-05-04 09:36:50   来源:脚本之家

本文将介绍基于 DNS 的负载均衡、基于 VIP 的负载均衡和路由网格(Routing Mesh)。

使用的技术

Docker 使用了 Linux 内核 iptables 和 IPVS 的功能来实现服务发现和负载均衡。

iptables 是 Linux 内核中可用的包过滤技术,它可用于根据数据包的内容进行分类、修改和转发决策。

IPVS 是 Linux 内核中可用的传输级负载均衡器。

准备工作

swarm 集群: 【Manager】node1、【Worker】node2

客户端镜像: registry.cn-hangzhou.aliyuncs.com/anoy/ubuntu

服务端镜像: registry.cn-hangzhou.aliyuncs.com/anoy/vote

如图所示,我们将在 swarm 集群中部署 “client” 服务 和 “vote” 服务,其中 “vote” 服务部署多个副本。客户端请求 “vote” 服务时,输出结果中包含服务端的容器 ID,这样就更方便演示网络请求。

集群状态

[root@node1 ~]# docker node ls
ID              HOSTNAME      STATUS       AVAILABILITY    MANAGER STATUS   ENGINE VERSION
rnr2i1y2of3n5vy2vzh2vkzq0 *  node1        Ready        Active       Leader       18.03.1-ce
qvik057dvphx5s06evmswahaf   node2        Ready        Active                 18.03.1-ce

使用如下命令,创建 overlay 网络:

docker network create --driver overlay overlay1

基于 DNS 的负载均衡

下图描述了基于 DNS 的负载均衡是如何工作的:

DNS server 内嵌于 Docker 引擎。Docker DNS 解析服务名 “vote” 并返回容器 ID 地址列表(随机排序)。客户端通常会挑第一个 IP 访问,因此负载均衡可能发生在服务器的不同实例之间。

使用如下命令创建 2 个基于 DNS 负载均衡的服务 “client” 、 “vote”:

docker service create --endpoint-mode dnsrr --replicas 1 --name client --network overlay1 registry.cn-hangzhou.aliyuncs.com/anoy/ubuntu ping anoyi.com

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

查看服务信息:

[root@node1 ~]# docker service ls
ID         NAME        MODE        REPLICAS      IMAGE                         PORTS
2mrj3pqyioc3    client       replicated     1/1         registry.cn-hangzhou.aliyuncs.com/anoy/ubuntu:latest
826s79tsixuh    vote        replicated     2/2         registry.cn-hangzhou.aliyuncs.com/anoy/vote:latest

[root@node1 ~]# docker service ps client
ID         NAME        IMAGE                         NODE        DESIRED STATE    CURRENT STATE      ERROR        PORTS
f74i688vbh12    client.1      registry.cn-hangzhou.aliyuncs.com/anoy/ubuntu:latest  node2        Running       Running 2 minutes ago

[root@node1 ~]# docker service ps vote
ID         NAME        IMAGE                        NODE        DESIRED STATE    CURRENT STATE        ERROR        PORTS
7iiuzl2a63hy    vote.1       registry.cn-hangzhou.aliyuncs.com/anoy/vote:latest  node1        Running       Running 47 seconds ago
uyhxxqfdima7    vote.2       registry.cn-hangzhou.aliyuncs.com/anoy/vote:latest  node2        Running       Running about a minute ago

可以看出 "client" 运行于 node2,在 node2 上进入 client 容器,使用 dig 来解析服务名 "vote",如下所示,"vote" 解析到 10.0.0.6 和 10.0.0.5

[root@node2 ~]# docker ps
CONTAINER ID    IMAGE                         COMMAND         CREATED       STATUS       PORTS        NAMES
1eed67d37cbb    registry.cn-hangzhou.aliyuncs.com/anoy/vote:latest   "gunicorn app:app -b…"  About a minute ago  Up About a minute  80/tcp       vote.2.uyhxxqfdima7smos5pki84wul
436702b21a1c    registry.cn-hangzhou.aliyuncs.com/anoy/ubuntu:latest  "ping anoyi.com"     3 minutes ago    Up 3 minutes              client.1.f74i688vbh12on8oniufht633

[root@node2 ~]# docker exec -it 436702b21a1c /bin/bash

root@436702b21a1c:/# dig vote

;; ANSWER SECTION:
vote.      600 IN A  10.0.0.5
vote.      600 IN A  10.0.0.6

使用 ping 解析 "vote" 服务,如下所示,交替解析到 10.0.0.6 和 10.0.0.5

root@436702b21a1c:/# ping -c1 vote
PING vote (10.0.0.6) 56(84) bytes of data.
64 bytes from vote.2.uyhxxqfdima7smos5pki84wul.overlay1 (10.0.0.6): icmp_seq=1 ttl=64 time=0.087 ms

root@436702b21a1c:/# ping -c1 vote
PING vote (10.0.0.5) 56(84) bytes of data.
64 bytes from vote.1.7iiuzl2a63hyj084qgufc175v.overlay1 (10.0.0.5): icmp_seq=1 ttl=64 time=0.767 ms

如果使用 curl,如下所示,请求也能解析到不同的容器

root@436702b21a1c:/# curl vote | grep -i "container id"
 % Total  % Received % Xferd Average Speed  Time  Time   Time Current
                 Dload Upload  Total  Spent  Left Speed
100 3162 100 3162  0   0  7542   0 --:--:-- --:--:-- --:--:-- 7546
     Processed by container ID 9b42319d4f13

root@436702b21a1c:/# curl vote | grep -i "container id"
 % Total  % Received % Xferd Average Speed  Time  Time   Time Current
                 Dload Upload  Total  Spent  Left Speed
100 3162 100 3162  0   0  452k   0 --:--:-- --:--:-- --:--:-- 514k
     Processed by container ID 1eed67d37cbb

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

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

基于 VIP 的负载均衡

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

下图描述了基于 VIP 的负载均衡是如何工作的:

DNS server 会将服务名 "vote" 解析到 VIP,使用 iptables 和 ipvs,VIP 实现 2 个服务端 "vote" 容器的负载均衡。

使用如下命令创建 2 个 VIP 模式的服务 “client” 、 “vote”:

docker service create --replicas 1 --name client --network overlay1 registry.cn-hangzhou.aliyuncs.com/anoy/ubuntu ping anoyi.com

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

查看这 2 个服务和它们的服务 IP:

[root@node1 ~]# docker service inspect --format {{.Endpoint.VirtualIPs}} vote
[{tetug0isdx1gri62g7cfm889i 10.0.0.9/24}]

[root@node1 ~]# docker service inspect --format {{.Endpoint.VirtualIPs}} client
[{tetug0isdx1gri62g7cfm889i 10.0.0.7/24}]

在 "client" 的容器中使用如下命令,可以看到服务名 "vote" 映射到 VIP "10.0.0.9"

[root@node2 ~]# docker exec -it f3d1c4ef53f8 /bin/bash

root@f3d1c4ef53f8:/# dig vote

;; ANSWER SECTION:
vote.      600 IN A  10.0.0.9

Service IP "10.0.0.9" 使用 Linux 内核的 iptables 和 IPVS 负载均衡到 2 个容器。iptables 实现防火墙规则,IPVS 实现负载均衡。为了证明这一点,我们需要使用 nsenter 进入容器的网络空间 ( namespace )。为此,我们需要找到网络的命名空间。

如下是 node2 上的网络命名空间:

[root@node2 ~]# cd /run/docker/netns/

[root@node2 netns]# ls
1-tetug0isdx 1-vyy22w04t6 be7330b99a27 d67fa9efb59e ingress_sbox

前 2 个命名空间是用于 overlay 网络,后面的用于容器。下面的命令用于找到 "client" 容器的网络命名空间:

[root@node2 netns]# docker ps
CONTAINER ID    IMAGE                         COMMAND         CREATED       STATUS       PORTS        NAMES
43a789312e70    registry.cn-hangzhou.aliyuncs.com/anoy/vote:latest   "gunicorn app:app -b…"  3 minutes ago    Up 3 minutes    80/tcp       vote.1.u46ms31e8zjdxtwrxvaec8zub
f3d1c4ef53f8    registry.cn-hangzhou.aliyuncs.com/anoy/ubuntu:latest  "ping anoyi.com"     4 minutes ago    Up 4 minutes              client.1.ycox088aek5ajejezubwsjqf2

[root@node2 netns]# docker inspect f3d1c4ef53f8 | grep -i sandbox
      "SandboxID": "be7330b99a274a03a7f58e9e991346dc6f048836a1682c7244a6068acbfb664c",
      "SandboxKey": "/var/run/docker/netns/be7330b99a27",

SandboxID 即为 "client" 容器的网络命名空间。

使用如下命令,我们就能够进入到 "client" 容器的网络命令空间:

nsenter --net=f3d1c4ef53f8 sh

下面,我们可以看到 iptables 的转发规则和 IPVS 输出:

sh-4.2# iptables -nvL -t mangle

Chain OUTPUT (policy ACCEPT 606 packets, 50867 bytes)
 pkts bytes target   prot opt in   out   source        destination
  0   0 MARK    all -- *   *    0.0.0.0/0      10.0.0.7       MARK set 0x102
  0   0 MARK    all -- *   *    0.0.0.0/0      10.0.0.9       MARK set 0x103

sh-4.2# ipvsadm
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
 -> RemoteAddress:Port      Forward Weight ActiveConn InActConn
FWM 258 rr
 -> node2:0           Masq  1   0     0
FWM 259 rr
 -> 10.0.0.10:0         Masq  1   0     0
 -> 10.0.0.11:0         Masq  1   0     0

Service IP "10.0.0.9" 使用 iptables OUTPUT 链获得标记 0x103 (十六进制 -> 十进制:259),然后 IPVS 使用此标记并将它负载均衡到 "10.0.0.10" 和 "10.0.0.11" 。

查看 vote 服务的 2 个容器的 IP 如下所示,即 VIP "10.0.0.9" 负载均衡到不同的容器实例:

[root@node2 netns]# docker inspect vote.1.u46ms31e8zjdxtwrxvaec8zub | grep IPv4
            "IPv4Address": "10.0.0.10"

[root@node1 ~]# docker inspect vote.2.tutj19i4iwu1xn7arsaq815cu | grep IPv4
            "IPv4Address": "10.0.0.11"

进入 client 服务的容器,使用 curl 请求 vote 服务,输出结果如下,即请求分发到不同的容器:

root@f3d1c4ef53f8:/# curl vote | grep -i "container id"
 % Total  % Received % Xferd Average Speed  Time  Time   Time Current
                 Dload Upload  Total  Spent  Left Speed
100 3162 100 3162  0   0 14409   0 --:--:-- --:--:-- --:--:-- 14438
     Processed by container ID c2af209c4e90

root@f3d1c4ef53f8:/# curl vote | grep -i "container id"
 % Total  % Received % Xferd Average Speed  Time  Time   Time Current
                 Dload Upload  Total  Spent  Left Speed
100 3162 100 3162  0   0  165k   0 --:--:-- --:--:-- --:--:-- 171k
     Processed by container ID 43a789312e70

路由网格 (Routing mesh)

使用路由网格,服务暴露的端口会暴露在 Swarm 集群中的所有工作节点。Docker 是通过创建 "ingress" overlay 网络来实现这一点的,所有节点默认使用内在的 sandbox 网络命名空间成为 "ingress" overlay 网络的一部分。

下图描述了 Routing mesh 如何实现负载均衡的:

首先,会将 Hostname 或 IP 映射到 Sandbox IP,Sandbox 中的 iptables 和 IPVS 负责将请求负载均衡到 2 个 vote 容器。Ingress sandbox 网络命名空间驻留在 swarm 集群中的所有工作节点,它通过将主机映射的端口负载均衡到后端容器来协助路由网格功能。

使用如下命令创建 vote 服务,使用路由网格暴露端口到所有节点:

复制代码 代码如下:
docker service create --name vote --network overlay1 --replicas 2 -p 8080:80 registry.cn-hangzhou.aliyuncs.com/anoy/vote

下图显示了 Sandbox、容器和每个节点的网络之间的映射关系:

如图所示,Sandbox 和 vote 容器是 "ingress" 网络的一部分,它有助于路由网格。client 容器和 vote 容器是 "overlay1" 网络的一部分,它有助于内部负载均衡。所有容器都是默认 "docker_gwbridge" 网络的一部分。

遵循 iptables 中的 NAT 规则显示,端口 8080 上的主机流量发送到 node1 里的 Sandbox:

[root@node1 ~]# iptables -nvL -t nat

Chain DOCKER-INGRESS (2 references)
 pkts bytes target   prot opt in   out   source        destination
  0   0 DNAT    tcp -- *   *    0.0.0.0/0      0.0.0.0/0      tcp dpt:8080 to:172.18.0.2:8080
 315 18876 RETURN   all -- *   *    0.0.0.0/0      0.0.0.0/0

进入 node1 上的 Sandbox 网络命名空间 (ingress_sbox),查看 iptables 的转发规则和 IPVS 输出:

[root@node1 netns]# nsenter --net=ingress_sbox sh

sh-4.2# iptables -nvL -t mangle
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target   prot opt in   out   source        destination
  0   0 MARK    tcp -- *   *    0.0.0.0/0      0.0.0.0/0      tcp dpt:8080 MARK set 0x105

sh-4.2# ipvsadm
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
 -> RemoteAddress:Port      Forward Weight ActiveConn InActConn
FWM 261 rr
 -> 10.255.0.5:0         Masq  1   0     0
 -> 10.255.0.6:0         Masq  1   0     0

端口 8080 标记为 0x105 (十六进制 -> 十进制:261),IPVS 使用此标记将它负载均衡到 "10.255.0.5" 和 "10.255.0.6" 。

查看 vote 服务的 2 个容器的 IP 如下所示,即主机端口 8080 的流量会负载均衡到不同的容器实例:

[root@node1 netns]# docker inspect 6173afd5fab8 | grep IPv4
            "IPv4Address": "10.255.0.6"
            "IPv4Address": "10.0.0.14"

[root@node2 ~]# docker inspect b07e95c5c681 | grep IPv4
            "IPv4Address": "10.255.0.5"
            "IPv4Address": "10.0.0.13"

验证负载均衡,在 node1 上通过 node2 的 IP 和 8080 端口请求 vote 服务:

[root@node1 netns]# curl node2:8080 | grep -i "container id"
 % Total  % Received % Xferd Average Speed  Time  Time   Time Current
                 Dload Upload  Total  Spent  Left Speed
100 3162 100 3162  0   0  199k   0 --:--:-- --:--:-- --:--:-- 192k
     Processed by container ID 6173afd5fab8

[root@node1 netns]# curl node2:8080 | grep -i "container id"
 % Total  % Received % Xferd Average Speed  Time  Time   Time Current
                 Dload Upload  Total  Spent  Left Speed
100 3162 100 3162  0   0  7551   0 --:--:-- --:--:-- --:--:-- 7546
     Processed by container ID b07e95c5c681

在 node2 上通过 node1 的 IP 和 8080 端口请求 vote 服务:

[root@node2 ~]# curl node1:8080 | grep -i "container id"
 % Total  % Received % Xferd Average Speed  Time  Time   Time Current
                 Dload Upload  Total  Spent  Left Speed
100 3162 100 3162  0   0  7531   0 --:--:-- --:--:-- --:--:-- 7546
     Processed by container ID 6173afd5fab8

[root@node2 ~]# curl node1:8080 | grep -i "container id"
 % Total  % Received % Xferd Average Speed  Time  Time   Time Current
                 Dload Upload  Total  Spent  Left Speed
100 3162 100 3162  0   0  169k   0 --:--:-- --:--:-- --:--:-- 171k
     Processed by container ID b07e95c5c681

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

    您感兴趣的教程

    在docker中安装mysql详解

    本篇文章主要介绍了在docker中安装mysql详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编...

    详解 安装 docker mysql

    win10中文输入法仅在桌面显示怎么办?

    win10中文输入法仅在桌面显示怎么办?

    win10系统使用搜狗,QQ输入法只有在显示桌面的时候才出来,在使用其他程序输入框里面却只能输入字母数字,win10中...

    win10 中文输入法

    一分钟掌握linux系统目录结构

    这篇文章主要介绍了linux系统目录结构,通过结构图和多张表格了解linux系统目录结构,感兴趣的小伙伴们可以参考一...

    结构 目录 系统 linux

    PHP程序员玩转Linux系列 Linux和Windows安装

    这篇文章主要为大家详细介绍了PHP程序员玩转Linux系列文章,Linux和Windows安装nginx教程,具有一定的参考价值,感兴趣...

    玩转 程序员 安装 系列 PHP

    win10怎么安装杜比音效Doby V4.1 win10安装杜

    第四代杜比®家庭影院®技术包含了一整套协同工作的技术,让PC 发出清晰的环绕声同时第四代杜比家庭影院技术...

    win10杜比音效

    纯CSS实现iOS风格打开关闭选择框功能

    这篇文章主要介绍了纯CSS实现iOS风格打开关闭选择框,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作...

    css ios c

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的办法

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的

    Win7给电脑C盘扩容的办法大家知道吗?当系统分区C盘空间不足时,就需要给它扩容了,如果不管,C盘没有足够的空间...

    Win7 C盘 扩容

    百度推广竞品词的投放策略

    SEM是基于关键词搜索的营销活动。作为推广人员,我们所做的工作,就是打理成千上万的关键词,关注它们的质量度...

    百度推广 竞品词

    Visual Studio Code(vscode) git的使用教程

    这篇文章主要介绍了详解Visual Studio Code(vscode) git的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...

    教程 Studio Visual Code git

    七牛云储存创始人分享七牛的创立故事与

    这篇文章主要介绍了七牛云储存创始人分享七牛的创立故事与对Go语言的应用,七牛选用Go语言这门新兴的编程语言进行...

    七牛 Go语言

    Win10预览版Mobile 10547即将发布 9月19日上午

    微软副总裁Gabriel Aul的Twitter透露了 Win10 Mobile预览版10536即将发布,他表示该版本已进入内部慢速版阶段,发布时间目...

    Win10 预览版

    HTML标签meta总结,HTML5 head meta 属性整理

    移动前端开发中添加一些webkit专属的HTML5头部标签,帮助浏览器更好解析HTML代码,更好地将移动web前端页面表现出来...

    移动端html5模拟长按事件的实现方法

    这篇文章主要介绍了移动端html5模拟长按事件的实现方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家...

    移动端 html5 长按

    HTML常用meta大全(推荐)

    这篇文章主要介绍了HTML常用meta大全(推荐),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参...

    cdr怎么把图片转换成位图? cdr图片转换为位图的教程

    cdr怎么把图片转换成位图? cdr图片转换为

    cdr怎么把图片转换成位图?cdr中插入的图片想要转换成位图,该怎么转换呢?下面我们就来看看cdr图片转换为位图的...

    cdr 图片 位图

    win10系统怎么录屏?win10系统自带录屏详细教程

    win10系统怎么录屏?win10系统自带录屏详细

    当我们是使用win10系统的时候,想要录制电脑上的画面,这时候有人会想到下个第三方软件,其实可以用电脑上的自带...

    win10 系统自带录屏 详细教程

    + 更多教程 +
    WIN服务器linux服务器FTP服务器DNS服务器其他