Docker swarm中的LB和服务发现详解

Docker 提供了 overlay driver,使用户可以创建基于 VxLAN 的 overlay 网络。VxLAN 可将二层数据封装到 UDP 进行传输,VxLAN 提供与 VLAN 相同的以太网二层服务,但是拥有更强的扩展性和灵活性。linux下是使用了net namespace来隔离docker创建的overlay网络。

Docker 网络模型如下:

image.png

Sandbox

一个Sandbox包含了一个容器网络栈的配置。其中包括了对容器的网卡,路由表以及对DNS设置的管理。通常,一个Sandbox的实现可以是一个Linux Network Namespace,一个FreeBSD Jail或者其他类似的东西。一个Sandbox可以包含多个处于不同Network的Endpoint。

Endpoint

Endpoint将一个Sandbox加入一个Network。Endpoint的实现可以是一个veth对,一个Open vSwitch internal port或者其他类似的东西。一个Endpoint只能属于一个Network和一个Sandbox。

Network

Network是一个能够互相通信的Endpoint的集合。Network的实现可以是一个Linux网桥,一个VLAN等等。


Docker swarm中的服务发现:

每一个docker容器都有一个域名解析器,用来把域名查询请求转发到docker engine;docker engine内部dns的服务器收到请求后就会在发出请求的容器所在的所有网络中检查域名对应的是不是一个容器或者是服务,如果是,docker引擎就会从存储的key-value建值对中查找这个容器名、任务名、或者服务名对应的IP地址,并把这个IP地址或者是服务的虚拟IP地址返回给发起请求的域名解析器。如果目的容器或服务和源容器不在同一个网络里面,Docker引擎会把这个DNS查询转发到配置的默认DNS服务。

docker-dns.png

上图展示了task1.client请求两个不同资源dns返回的不同结果


Docker swarm 中的LB分为两种情况:

1. Ingress Load Balancing

2. Internal Load Balancing


简要介绍测试环境下docker swarm中的网络分布情况:

环境:
swarm-a(manager node):10.10.8.92

swarm-b(work node):10.10.8.93

swarm-c(work node):10.10.8.94

在docker swarm集群创建的开始,docker 会给每台host创建除了docker0以外的两个网络,分是bridge类型(docker_gwbridge网桥)和overlay类型(ingress)的网络,以及一个过度的命名空间ingress_sbox,我们可以使用如下命令自建overlay网络,结果如下:

docker network create --driver overlay mynet (后续会有用到)

1.png

  • ingress网络的IPAM( IP Address Management)分配如下:
ingress-net.png
  • mynet自建的overlay会使用docker自动分配的IPAM:
mynet.png
  • 建完的overlay网络的同时会在host本地创建对应的Net Namespace如下:
ns.png

注意1:要是想看到容器创建的两个Net Namespace需要执行
ln -s /var/run/docker/netns /var/run/netns


1. Ingress Load Balancing

1)、部署一个service使用默认的ingress网络:

docker service create --name web_ingress_lb --replicas=2 --publish 8090:80 httpd

  • 部署的两个容器分别处在a和b节点上:
ingress-1.png
  • service:web_ingress_lb的网络连接结构图如下:
image.png

Swarm mode下,docker会创建一个默认的overlay网络—ingress network。Docker也会为每个worker节点创建一个特殊的net namespace(sandbox)-- ingress_sbox。ingress_sbox有两个endpoint,一个用于连接ingress network,另一个用于连接local bridge network docker_gwbridge。Ingress network的IP空间为10.255.0.0/16,所有router mesh的service都共用此空间。

2)、Ingress Load Balancing实现方式:

swarm-ingress.jpg

1>宿主机网络通过worker节点IP和service published port来访问服务。比如:上面服务定义-p 8090:80,可以通过workerIP:8090 访问服务

2>每个节点iptables中NAT表定义规则,对于匹配published的宿主机端口(8090)的数据,将其dst IP转换成ingress_sbox中的ip:172.18.0.2。使数据包转发到ingress_sbox的ns中交给该ns处理做下一步的转发。

ingress-2.png

3>Ingress_sbox是swarm为每个节点默认创建的net namespace,用于连接ingress overlay network。此处会设置mangle表,将dst port为8090的数据做标记(fwmark)。同时做DNAT转换成vip地址使数据包能正常转发到ingress的ns中,该vip由ingress_sbox的ipvs做负载转发。

ingress-3.png

4>Ingress_sbox会设置kernel中的LVS模块,将标记fwmark的包LB到各个实际IP中,默认round-robin算法,forware为VS/NAT方式。容器底层间通过overlay网络互连通信。

ingress-4.png
  • 数据包在这一步进入ingress的ns后怎么实现到后端真实容器上呢?我们猜想下ingress想要转发就需要有各个节点容器对应的ingress veth pair网卡的mac地址才能做转发是吧,好的那我们来看下ingress的ns空间中的fdb(linux bridge forward db)信息。
ingress-5.png
  • 查看b节点上web_ingress_lb.1容器的mac地址信息
ingress-6.png

这样一来即使容器的副本没有落到host上我们仍可以通过这种转发方式来访问到服务。这应该就是routing mesh吧!

5>Service的各个容器会将dst port为8080的数据的dst port转换成80,从而访问到真实的服务。

ingress-7.png

可以看到一个请求到主机端口8090之后, 数据包的流向如下所示:
主机端口8090 => Ingress-sbox-VIP:8090 => 容器Ingress-sbox => IPVS分发到containers。
大家可以看到访问主机之后数据包流到了一个特殊的Sandbox容器里, 这个容器和我们的容器共享一个Ingress网络,通过Iptables和IPVS等重定向到了最终容器之上。 达到了服务在任何一台主机的8090端口都可达的目的。


2. Internal Load Balancing

1)、部署一个service使用我们自己创建的mynet网络:

docker service create --name web_mynet --replicas=2 --network=mynet --publish 8080:80 httpd
部署的两个容器分别处在a和c节点上:


mynet-1.png

--publish #--在这里的用意是将容器内部的服务暴露到host上这样我们就可以访问这个services,一般情况下我们在swarm中部署service后容器中的网络只有一张网卡使用的是docker0网络,当我们将服务发布出去后,swarm会做如下操作:

  • 给容器添加三块网卡eth0和eth1,eth2,eth0连接overlay类型网络名为ingress用于在不同主机间通信,eth1连接bridge类网络名为docker_gwbridge,用于让容器能访问外网。eth2连接到我们自己创建的mynet网络
    上,同样的作用也是用于容器之间的访问(区别于eth2网络存在dns解析即服务发现功能)。
  • swarm各节点会利用ingress overlay网络负载均衡将服务发布到集群之外。

结合例子如下:

2)、查看web_mynet.1容器和mynet网络命名空间的网卡情况:

mynet-2.png
$docker exec web_mynet.1.kammwchnoeend86w3e5pho88i ip add
上面的命令可以查看a节点上的容器的网络有四张网卡eth0和eth1,eth2和lo,eth2网卡可以看出其
对应的veth pair为mynet网络中的veth0,eth1的网卡比较容易找到在host上对应的veth pair

$ip netns exec 1-j6s2r8ahdh ip add
查看mynet网络命名空间下的网卡情况。

$ip netns exec 1-j6s2r8ahdh brctl show
查看mynet网络空间下网桥挂载情况可以看出veth0挂到了br0网桥上。

3)、查看web_mynet.1容器和ingress\ingress_sbox网络命名空间的网卡对应情况:

mynet-3.png
  • 获取mynet和ingress网络的vxlan-id:
## 执行如下命令查看mynet空间下vxlan0网卡所带的vlan-id:
$ip netns exec 1-j6s2r8ahdh ip -d l show vxlan0

可以看mynet网络下vlan-id 为4097,ingress网络空间同样操作可以得到vlan-id为4096

mynet-4.png

swarm-c节点上的情况也是差不多就不操作了,好了我们来画下网络连接的大致图:


image.png

可以看到这里ingress_sbox和创建容器的ns共用一个ingress网络空间。

4)、 Internal Load Balancing实现方式:

有两种实现方式dns rr和vip形式,在dns rr 的情况下可能会存在一定是的问题,当容器重启后dns的解析会存在一定时间的延迟。vip则是由vip+内核ipvs来实现。docker swarm默认使用的是vip,这里就以vip的形式来解析。(想要了解dns rr的可以看文章后面的参考链接都是大牛写的)

VIP形式下的流量路径:

swarm-vip.jpg

1> 同处于网络mynet中的容器可以通过service域名或者VIP来访问service;通过域名访问时,容器会访问docker engine中内置的DNS服务,从而获取VIP。

2> CNM网络模型中一个容器对应一个sandbox,也即容器的net namespace。我们查web_mynet.1容器的sandbox中iptables的mangle表的配置情况:mangle表中OUTPUT链,将destIP==VIP的包标记fwmark。

操作流程如下:
通过busybox服务做dns解析,可以发现该服务后端挂载的容器和该服务对应的
VIP地址。web_mynet服务对应的VIP为10.0.0.6。


mynet-5.png
  • 进入web_mynet.1容器的ns:
$docker inspect container_id/container_name | grep -i sandbox
$nsenter --net=SandboxKey(/var/run/docker/netns/xxxx) sh
mynet-6.png

3>web_mynet.1的 Sandbox中会设置kernel中的LVS模块,将标记fwmark的包LB到各个实际IP中,默认round-robin算法,VS/NAT方式。容器底层间通过overlay网络互连通信。在web_mynet.1的ns中执行如下获取LB信息:
$ipvsadm -L

mynet-7.png
  • 简单的来说就是在web_mynet.1容器中定义好了web_mynet服务的vip数据包的标签和LB,然后数据包通过容器本地路由从eth2接口出去,进入到mynet的ns中:
mynet-8.png
  • 带有具体目容器的MAC数据包进入mynet的ns后,由mynet网络中的fdb来进行转发:


    mynet-9.png
mynet-10.png

总结下:

在Internal Load Balancing也就是文中我们自建的mynet overlay网络中,我们会看到创
建的service会同时应用到两个网络环境里面去,为何要这样呢?

原因是swarm自带ingress不具备有服务发现的功能,而容器的生命周期又是不固定的,
service每次的消亡和启用都会改变容器内部的ip地址以及vip地址,那么集群中服务之间
的通信势必会造成问题,这里有人会说,要使多个service之间能够互相通信可以将所有
的service都publish出去,然后通过routing mesh 访问,这样是没错也能行得通,但是存
在一个缺点,那就是不安全,我们仅仅只需要的是将最终提供服务的端口publish即可。
那么不publish所有的service需要做到以下几点:

  • 让service通过简单的方法访问其他service

  • 当service副本的ip发生变化时,不会影响访问该service的其他service

  • 当service的副本数发生变化时,不会影响访问该service的其他service
    这其实就是服务发现,docker swarm提供了这些功能将LB和服务发现集成在一起,通过服务发现service,使用者不需要知道service运行在哪里,ip是多少有多少个副本,就能实现集群内service与service的通信以及LB。

这里我理解的是ingress是单单提供LB实现routing mesh而mynet是服务发现和LB的结合

所以上文中Internal Load Balancing中的数据流应该分成两种情景如下:

1、当一个外部请求到主机端口8080之后, 数据包的流向如下所示:
主机端口8080 => Ingress-sbox-VIP:8080 => 容器Ingress-sbox => IPVS分发到containers。

2、处于 同mynet网络的service内部通信时:
处于 同mynet网络的test service(busybox容器)发起访问web_mynet域名的请求=>请求转发到docker engine内置的DNS解析web_mynet的vip=>web_mynet(容器)在其ns中将
VIP数据包打上标签,并通过ipvs来负载到后端对应的容器=>数据包通过vip地址路由到
mynet的ns,由mynet中的fdb来做转发走tunnel出去。

文章中存在不足之处希望路过的大牛多踩踩^^!

参考:

https://zhuanlan.zhihu.com/p/25954203

https://www.jianshu.com/p/4433f4c70cf0

https://docs.docker.com/network/overlay/

http://julyerr.club/2018/03/20/docker-swarm/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容

  • 记事起,我便生活在桃庄,却从没见过自己的爹娘。 那日,一片片嫩绿的芳草探出了小脑瓜,几只燕子飞来飞去忙着筑巢。和煦...
    桃源渔歌阅读 599评论 32 15
  • 喜欢一个人静静地发呆到天荒地老 如果时候至始至终都没有那一个人的出现, 自己有什么理由不勇敢,坚强。 时光还是匆匆...
    哆啦的A梦阅读 112评论 0 0
  • 一、课堂的“教案剧” 中小学课堂的“教案剧”:备课时精心设问,课堂学生连续不断地匆忙紧张地应对教师提问 唱答式 猜...
    赵雪奎阅读 486评论 0 0
  • By:白忆 zero.花语 所以,你是小忆,亦是忆少。 单翼的你,拥有着一只翅膀。 往右天堂,化...
    忆少阅读 215评论 0 0
  • 随手一画。
    和果阅读 140评论 0 3