前言
swarm创建得应用网络模式均为overlay。
swarm得网络需要拆成两部分来说:
- 一部分为上层流量得完整路径。
- 另一部分为overlay实现原理。
环境
操作系统:centos7。
docker版本:18.09。
使用swarm启动一个应用(这里不再介绍如何启动,本文章提及得应用外部映射端口为31883)。
安装网络相关软件工具
yum install -y bridge-utils
yum install -y iptables
外部访问swarm应用得流量完整路径介绍
基础介绍:
docker得网络命名空间位于: /var/run/docker/netns/
下
使用方式为:
nsenter --net=/var/run/docker/netns/ingress_sbox ip a
与 ip netns除了进入命令不同,其它一致。
容器、ingress_sbox(docker swarm使用的网络命名空间)、ingress(docker swarm使用的网络命名空间)、以及创建的其它网络均在 netns 目录下。
注意 ingress网络命名空间的名称需要通过 docker network list
转换一下才能找到,如下图:
整体介绍:
-
流量首先到达宿主机
-
宿主机上得iptables将流量转发至 ingress_sbox网络命名空间。
-
ingress_sbox 又将流量导向 ingress网络命名空间
-
ingress 通过网桥、veth pair 与本机容器互联,通过vxlan 与其它物理主机的容器实现互联。
进一步介绍:
宿主机到ingress_box的流量路径。
在宿主机上执行:
iptables -t nat -S
image.png
上图可以看到,将流量转发至 172.18.0.2 。
查看路由信息:
route -n
image.png
上图可以看到,将流量发往 docker_gwbridge
查看网桥:
brctl show
image.png
上图可以看到,网桥中挂载了多个 veth pair。而这个 "veth2c615a1"与ingress_sbox中的某个网卡 是一组 veth pair。
至于其它的veth 开头的网卡,是容器直接使用这个网络时创建的。
ingress_sbox原理
ingress_sbox得eth0与ingress得veth0是一对veth pair。
ingress_sbox得iptables、ipvs、route结合将流量指向eth0,通过veth pair特性,流量进入ingress得veth0。
进入ingress_sbox 网络命名空间执行以下4个步骤:
- 在流量进入ingress_sbox,通过iptables的mangle表将报文打上mark。这里的mark是二进制,在ipvs中显示的十进制。
命令参考:
iptables -t mangle -S
- ipvs 根据mark(十进制显示)将流量指向私网地址。
命令参考(无此命令直接安装,包名: ipvsadm):
ipvsadm -Ln
- 结合路由可以看到将流量通过eth0发送出去。
命令参考:
route -n
- iptables 的nat表,在将流量发送出去的同时修改了源ip,这样的目的是让包可以回来。
命令参考:
iptables -t nat -S
ingress原理
ingress 中有一个网桥,网桥上连接着veth pair,而veth pair的另一端在容器中。
流量在到达ingress时,结合路由将流量发送到网桥上,流量到达网桥后,可以直接通过veth pair 特性进入到本机容器中。
如果容器不在本地机器上:
ingress中还有一个端口 vxlan0,vxlan0挂载在网桥上。在每一台物理机器上的ingress中都有一个vxlan0,通过此端口实现了不同物理主机的ingress上的网桥的互联,从而实现了overlay网络。
overlay具体实现原理
在ingress中实现了overlay,效果就是:在某台物理机的ingress中可以ping通其它物理上的容器overlay地址。也就是让所有overlay网络下的容器,即使不同物理机也能互相通信。
目前只知道是通过vxlan实现得overlay,具体实现原理还未清楚。TODO
扩展
1. 容器的网络命名空间在哪?
docker inspect 984 |grep SandboxID
通过此ID 可以在 /var/run/docker/netns/ 下找到对应的文件。
这就是此容器的网络命名空间。
注意事项
由于ingress_sbox会更改源ip为统一得源ip,因此一个swarm集群似乎只能承载60k tcp连接。
可能得解决方案:将源ip负载得形式更改为多个,成倍得提升tcp连接数。
网友评论