Libnetwork最初是由libcontainer和Docker Engine中的网络相关的代码合并而成的,是Docker容器网络库,最核心的内容是其定义的Container Network Model(CNM)。
Libnetwork CNM 定义了Docker容器的网络模型,按照该模型开发出的driver就能与docker daemon协同工作,实现容器网络。docker 原生的driver包括 none、bridge、overlay和macvlan,第三方driver包括flannel、weave、calico等。

CNM定义了如下三个组件:
Sandbox
Sandbox是Docker容器中一个网络配置的隔离环境,包含容器的interface、路由表和DNS设置。Linux Network Namespace是Sandbox的标准实现。Sandbox可以包含来自不同 Network的Endpoint。
Endpoint
Endpoint是一个在Network中进行网络通讯的接口(veth pair),用于将Sandbox接入Network。一个Endpoint只能属于一个Network,也只能属于一个Sandbox
Endpoint可以加入一个network,但多个Endpoint可以在一个Sandbox中共存。
Network
一个Network就是一个唯一的、可识别的endpoint组,组内endpoint可以相互通讯。Network的实现可以是linux Bridge、VLAN等。
通过<code>nsenter --net=&lt;SandboxKey&gt; ip add</code>可以直接进入容器的Sandbox,查询相关的网络信息
创建一个自定义的overlay网络:
只需在manager节点创建,当有Service连接该overlay网络时,将会自动在所分配的worker节点上自动创建该overlay网络。
创建一个连接到自定义的overlay网络的service(未指定"endpoint-mode"则默认为VIP模式)
Docker会为每个overlay网络创建一个独立的network namespace,其中会有一个linux bridge br0,endpoint还是由veth pair实现,一端连接到容器中的eth0,另一端连接到network namespace的br0上。
<code>br0除了连接所有的endpoint,还会连接一个vxlan设备,用于与其他host建立vxlan tunnel。容器之间的数据就是通过这个tunnel通信的。</code>
service-name将通过内置的DNS解析到VIP地址
Service IP:<code>192.168.10.2</code>在iptables的mangle表的OUTPUT链中被标记为0x112(274),IPVS通过该标记将Service IP转发到192.168.10.3和192.168.10.4的容器
VIP模式中,swarm mode为容器分配了一个连接到overlay网络(my-network)的网卡<code>"eth0@if103"</code>且生成了VIP,同时也分配了一个连接到docker_gwbridge网络的网卡<code>"eth1@if105"</code>用于连接外部网络。
所有连接到my-network网络中的容器可以通过service-name或者VIP来访问service,通过service-name访问时,将先通过内置的DNS服务解析获取到VIP。
创建一个连接到自定义的overlay网络的service,并指定endpoint-mode为dnsrr
service-name将通过内置的DNS解析到每个容器的overlay网络地址
创建一个连接到自定义的overlay网络的service,并将容器的80端口映射host的80端口
容器中除了lo,还创建了3个网卡:
eth0:连接到<code>ingress</code>的网络,通过routing mesh提供外部服务访问。
eth1:当service设置了端口映射时,swarm会为Service中的每个容器另外分配一块网卡,连接到<code>docker_gwbridge</code>网络。当容器内部主动往外发送数据时,由docker_gwbridge SNAT转发至外部网络。
eth2:连接到<code>my-network</code>的overlay网络。
如果在创建Service时映射了端口,swarm mode将会<code>通过routing mesh在所有节点上监听80端口,即使节点上未创建相应的容器</code>,并通过iptables做反向NAT,当客户端访问集群中的任意节点的80端口,swarm负载均衡会将请求路由到一个活动的容器。若不想在未创建容器的节点上监听published端口,则可在映射端口时通过<code>--publish mode=host,target=80,published=8080</code>进行指定。
创建完Service之后会发现Virtual IPs有两个入口,其中<code>10.255.0.5</code>连接到ingress网络,<code>192.168.10.7</code>是连接自定义的my-network网络。当外部客户端访问服务时,swarm负载均衡的流程如下:
1、用户访问swarm-node1上的Nginx服务(172.16.100.21:80)
2、iptables将根据<code>-A DOCKER-INGRESS -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.18.0.2:80</code>的规则将请求转发至<code>ingress sanbox</code>中的172.18.0.2:80。
3、ingress sanbox中的iptable根据不同的端口设置不同的mark(0x114/276)。
4、ipvs将根据不同的mark转发到对应的real server(容器namespace);
<code>-> 10.255.0.7:0 Masq 1 0 0</code>
<code></code>
<code>本文转自Vnimos51CTO博客,原文链接:</code>http://blog.51cto.com/vnimos/2053238,如需转载请自行联系原作者