DOCKSWARM服务网络原理

如图所示,我们将在 swarm 集群中部署 “client” 服务 和 “vote” 服务,其中 “vote” 服务部署多个副本。
客户端请求 “vote” 服务时,输出结果中包含服务端的容器 ID,这样就更方便演示网络请求。
docker node ls
使用如下命令,创建 overlay 网络:
docker network create --driver overlay overlay
一、基于 DNS 的负载均衡(DOCKER引擎内嵌了DNS服务器,创建容器时,在各个容器内设置nameserver,指向dns服务)--内部转发
dns服务内会配置overlay网络内的容器的IP和容器主机之间的映射
下图描述了基于 DNS 的负载均衡是如何工作的:DNS轮询

DNS server 内嵌于 Docker 引擎。
Docker DNS 解析服务名 “vote” 并返回容器 ID 地址列表(随机排序)。
客户端通常会挑第一个 IP 访问,因此负载均衡可能发生在服务器的不同实例之间。
- 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
可以看出 "client" 运行于 node2,在 node2 上进入 client 容器,使用 dig 来解析服务名 "vote",如下所示,"vote" 解析到 10.0.0.6 和 10.0.0.5
docker exec -it 436702b21a1c /bin/bash
dig vote;
使用 ping 解析 "vote" 服务,如下所示,交替解析到 10.0.0.6 和 10.0.0.5
基于 DNS 负载均衡存在如下问题:
某些应用程序将 DNS 主机名缓存到 IP 地址映射,这会导致应用程序在映射更改时超时
具有非零 DNS ttl 值会导致 DNS 条目反映最新的详细信息时发生延迟
二、基于 VIP 的负载均衡(IPVS)--内部转发
克服了基于 DNS 负载均衡的一些问题。
在这种方法中,每个服务都有一个 IP 地址,并且该 IP 地址映射到与该服务关联的多个容器的 IP 地址。
在这种情况下,与服务关联的服务 IP 不会改变,即使与该服务关联的容器死亡并重新启动。
下图描述了基于 VIP 的负载均衡是如何工作的:

DNS server 会将服务名 "vote" 解析到 VIP,使用 iptables 和 ipvs,VIP 实现 2 个服务端 "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}]
Service IP "10.0.0.9" 使用 Linux 内核的 iptables 和 IPVS 负载均衡到 2 个容器。
iptables 实现防火墙规则,IPVS 实现负载均衡。
为了证明这一点,我们需要使用 nsenter 进入容器的网络空间 (namespace)。为此,我们需要找到网络的命名空间。
[root@node2 ~]# cd /run/docker/netns/
[root@node2 netns]# ls 1-tetug0isdx 1-vyy22w04t6 be7330b99a27 d67fa9efb59e ingress_sbox
[root@node2 netns]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES43a789312e70 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
查看 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"
三、路由网格 (Routing mesh)--外部访问内部
使用路由网格,服务暴露的端口会暴露在 Swarm 集群中的所有工作节点上。
Docker 是通过创建 "ingress" overlay 网络来实现这一点的,所有节点默认使用内在的 sandbox 网络命名空间成为 "ingress" overlay 网络的一部分。
sandbox 网络命名空间:具有独立的网络栈,IPTABLE 路由转发规则,独立的IPVS内核负载均衡,会通过接入sandbox 网络命名空间的ingress网络,分发请求到接入这个网络的某个容器
具体过程:主机指定端口流量,,通过iptable,会通过接入这个sandbox 网络命名空间,导向到ngress_sbox(ls /run/docker/netns),进入IPvs
下图描述了 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 natChain 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 shsh-4.2# iptables -nvL -t mangleChain 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# ipvsadmIP 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 Speed100 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 Speed100 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 Speed100 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 Speed100 3162 100 3162 0 0 169k 0 --:--:-- --:--:-- --:--:-- 171k
- Processed by container ID b07e95c5c681
DOCKSWARM服务网络原理的更多相关文章
- istio的原理和功能介绍
目录 1 什么是Istio 2 架构和原理 2.1 Proxy代理 2.2 Mixer混合器 2.3 Pilot引导 2.4 Citadel堡垒 2.5 Galley 3 功能列表 4 性能评估 1 ...
- 奇异值分解(SVD)原理与在降维中的应用
奇异值分解(Singular Value Decomposition,以下简称SVD)是在机器学习领域广泛应用的算法,它不光可以用于降维算法中的特征分解,还可以用于推荐系统,以及自然语言处理等领域.是 ...
- node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理
一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...
- 线性判别分析LDA原理总结
在主成分分析(PCA)原理总结中,我们对降维算法PCA做了总结.这里我们就对另外一种经典的降维方法线性判别分析(Linear Discriminant Analysis, 以下简称LDA)做一个总结. ...
- [原] KVM 虚拟化原理探究(1)— overview
KVM 虚拟化原理探究- overview 标签(空格分隔): KVM 写在前面的话 本文不介绍kvm和qemu的基本安装操作,希望读者具有一定的KVM实践经验.同时希望借此系列博客,能够对KVM底层 ...
- H5单页面手势滑屏切换原理
H5单页面手势滑屏切换是采用HTML5 触摸事件(Touch) 和 CSS3动画(Transform,Transition)来实现的,效果图如下所示,本文简单说一下其实现原理和主要思路. 1.实现原理 ...
- .NET Core中间件的注册和管道的构建(1)---- 注册和构建原理
.NET Core中间件的注册和管道的构建(1)---- 注册和构建原理 0x00 问题的产生 管道是.NET Core中非常关键的一个概念,很多重要的组件都以中间件的形式存在,包括权限管理.会话管理 ...
- python自动化测试(2)-自动化基本技术原理
python自动化测试(2) 自动化基本技术原理 1 概述 在之前的文章里面提到过:做自动化的首要本领就是要会 透过现象看本质 ,落实到实际的IT工作中就是 透过界面看数据. 掌握上面的这样的本领 ...
- CRC、反码求和校验 原理分析
3月份开始从客户端转后台,算是幸运的进入全栈工程师的修炼阶段.这段时间一边是老项目的客户端加服务器两边的维护和交接,一边是新项目加加加班赶工,期间最长经历了连续工作三天只睡了四五个小时的煎熬,人生也算 ...
随机推荐
- 题解【POJ1160】Post Office
[POJ1160]Post Office Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 22362 Accepted: 1208 ...
- HTML学习(13)区块元素和内联元素
HTML 区块元素 大多数 HTML 元素被定义为块级元素或内联元素. 块级元素在浏览器显示时,通常会以新行来开始(和结束). 实例: <h1>, <p>, <ul> ...
- 【vue store的使用方法】(this.$store.state this.$store.getters this.$store.dispatch this.$store.commit)
vue 页面文件 <template> <div> {{this.$store.state.count}}<br/> {{count}}<br/> {{ ...
- WPF学习笔记一之布局
1.Canvas 布局控件Canvas主要用来画图,注意Canvas.Left/Right/Top/Bottom <Canvas Margin="10,10,10,10" B ...
- 免费天气API,天气JSON API,不限次数获取十五天的天气预报
紧急情况说明: 禁用IP列表: 39.104.69.*(原因39.104.69.6 在2018年10月的 17~20日 排行为top 1,每天几十万次.) 47.98.211.* (原因47.98.2 ...
- 百炼OJ - 1004 - 财务管理
题目链接:http://bailian.openjudge.cn/practice/1004/ 思路 求和取平均... #include <stdio.h> int main() { fl ...
- nmon +java nmon Alalizy agent 动态交互监控
下载地址:1. Download and install nmon. - for linux platform, you can download form: http://nmon.sourcefo ...
- noobSTL-1-配置器-2
noobSTL-1-配置器-2 第一级配置器 1. 功能分析 第一级配置器以malloc(),free(),realloc()等C语言函数来执行实际的内存配置. 使用C语言函数是因为C++并未直接提供 ...
- 【Python】字符串(String)
python中单引号和双引号使用完全相同. 使用三引号('''或""")可以指定一个多行字符串. 转义符 '\' 反斜杠可以用来转义,使用r可以让反斜杠不发生转义.. 如 ...
- maven的安装与使用(运行单元测试和打包等)
maven的下载与安装 maven是用于java的自动化构建工具. 1.下载: http://maven.apache.org/download.cgi 下载maven包,比如 apache-mave ...