docker swarm mode的服务发现和LB详解

一、服务发现

docker Swarm mode下会为每个节点的docker engine内置一个DNS server,各个节点间的DNS server通过control plane的gossip协议互相交互信息。注:此处DNS server用于容器间的服务发现。

swarm mode会为每个--net=自定义网络的service分配一个DNS entry。注:目前必须是自定义网络,比如overaly。而bridge和routing mesh的service,是不会分配DNS的。

下图是dockercon 2016上关于swarm mode的服务发现的slide。

二、Load Balancing

docker swarm mode有两种LB模式:1. Internal Load Balancing 2. Ingress Load Balancing。
要理解swarm的LB,需要具备1. iptables,2. LVS,3.CNM网络模型等知识。

1. Internal Load Balancing

顾名思义,此模式的LB用于同一个Swarm集群中容器和容器之前的互访。

此模式下也分两种情况:

1.1 当service的endpoint-mode为dnsrr时,service的DNS entry对应一组具体服务IP,通过round-robin轮询各个IP来达到LB的效果。

此时的Traffic Flow如图:

1> 客户端容器通过service域名访问相应服务,节点docker的DNS server会round-robin各个后端容器的服务IP给Client container。
2> LB到各个服务的真实IP。

1.2 非dnsrr的自定义网络时,service的DNS entry对应一组服务的VIP,再由VIP+内核IPVS来做相应的LB。(当然也可以直接访问VIP)

此时的Traffic Flow如图:

Internal LB通过在同一个网络中每个容器的network sandbox中配置相应的iptables和IPVS来达到负载均衡(LB)的效果。
同一个网络中每增加一个服务,每个容器的network sandbox中就会相应添加对应的iptables和ipvs规则,从而使得服务在整个网络内可访问。

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

docker exec –it container_id/container_name sh

2> CNM网络模型中一个容器对应一个sandbox,也即容器的net namespace。容器的sandbox中设置iptables的mangle表,设置OUTPUT链,将dest IP==VIP的包标记fwmark。

进入该容器的net namespace(即sandbox):

docker inspect container_id/container_name | grep -i sandbox
nsenter --net=SandboxKey(/var/run/docker/netns/xxxxx)

Sandbox中iptables mangle表内容:
serviceA的VIP为192.168.10.7
Fwmark设置为0x107,即263

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

Sandbox中Ipvs规则:
FWM为263的包,LB到192.168.10.8和192.168.10.9

2. Ingress Load Balancing

注:此图Task1,Task1,Task1应该为Task1,Task2,Task3

Ingress LB可以将容器网络中的服务暴露到宿主机网络中,从而被外部所访问。

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都共用此空间。

Ingress LB分别在1)节点iptables,2)ingress_sbox的iptables和ipvs,3)service容器的iptables处设置相应规则,从而可以在宿主机网络上通过宿主机IP和published端口来访问容器网络的服务。

整体flow图:


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

2) Worker节点iptables中NAT表定义规则,对于匹配published的宿主机端口(8080)的数据,将其dstIP转换成ingress_sbox中的ip:172.18.0.2。

3) Ingress_sbox是swarm为每个worker节点默认创建的net namespace,用于连接ingress overlay network。此处会设置mangle表,将dst port为8080的数据做标记(fwmark)。

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

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

三、混合LB

非dnsrr的internal LB和ingress LB可以同时使用,但配置dnsrr时,不能使用ingress LB,即不能published port。

四、Reference:

l Docker Networking Deep Dive
youtube.com/watch?

l Ipvsadm
kb.linuxvirtualserver.org

l Service Discovery and Load balancing Internals in Docker 1.12
Service Discovery and Load balancing Internals in Docker 1.12

l docker的网络-Container network interface(CNI)与Container network model(CNM)
xuxinkun.github.io/2016

l What’s new in Docker 1.12.0 Load-Balancing feature?
Dockercon 2017

编辑于 2017-03-23 17:51