咱们知道docker官方并无提供多主机的容器通讯方案,单机网络的模式主要有host,container,brige,none。none这种模式,顾名思义就是docker自己不去管理网络模式,交由其余管理和分配,好比cni。Flannel是一个专为kubernetes定制的三层网络解决方案,主要用于解决容器的跨主机通讯问题。node
首先,flannel利用Kubernetes API或者etcd用于存储整个集群的网络配置,其中最主要的内容为设置集群的网络地址空间。例如,设定整个集群内全部容器的IP都取自网段“10.1.0.0/16”。
接着,flannel在每一个主机中运行flanneld做为agent,它会为所在主机从集群的网络地址空间中,获取一个小的网段subnet,本主机内全部容器的IP地址都将从中分配。
而后,flanneld再将本主机获取的subnet以及用于主机间通讯的Public IP,一样经过kubernetes API或者etcd存储起来。
最后,flannel利用各类backend ,例如udp,vxlan,host-gw等等,跨主机转发容器间的网络流量,完成容器间的跨主机通讯。docker
Flannel为每一个主机提供独立的子网,整个集群的网络信息存储在etcd上。对于跨主机的转发,目标容器的IP地址,须要从etcd获取。
先上图,比较直观:express
步骤:网络
在经常使用的vxlan模式中,涉及到上面步骤提到的封包和拆包,这也是Flannel网络传输效率相对低的缘由。并发
下面重点说一下host-gw模式。
hostgw是最简单的backend,它的原理很是简单,直接添加路由,将目的主机当作网关,直接路由原始封包。
例如,咱们从etcd中监听到一个EventAdded事件subnet为10.1.15.0/24被分配给主机Public IP 192.168.0.100,hostgw要作的工做就是在本主机上添加一条目的地址为10.1.15.0/24,网关地址为192.168.0.100,输出设备为上文中选择的集群间交互的网卡便可。对于EventRemoved事件,只需删除对应的路由。tcp
由于没有了封包和拆包,host-gw的性能是最好的。ide
不过host-gw 要求主机网络二层直接互联。因此每一个节点上有n-1个路由,而n个节点一共有n(n-1)/2个路由以保证flannel的flat网络能力。性能
为何host-gw 要求主机网络二层直接互联?
首先经过抓包分析,抓包结果以下图:this
能够看出host-gw在传输层走的是tcp。而后在网络层的源IP和目的IP均是容器的IP,虚拟IP。这就决定了二层互联,由于只有交换机是不关注源IP和目的IP。假如两台主机在两个lan中,二层不通,三层通,那么就须要路由器,而路由器是没法识别容器的这些ip。固然也能够配置路由规则,可是显然没有这么作的。spa
Openshift默认也是使用Flannel host-gw容器网络方案,其官网也清晰的画出了host-gw的data flow diagram。
示例配置:
{ "Network": "10.0.0.0/8", "SubnetLen": 20, "SubnetMin": "10.10.0.0", "SubnetMax": "10.99.0.0", "Backend": { "Type": "udp", "Port": 7890 } }
启动参数:
--public-ip="": IP accessible by other nodes for inter-host communication. Defaults to the IP of the interface being used for communication. --etcd-endpoints=http://127.0.0.1:4001: a comma-delimited list of etcd endpoints. --etcd-prefix=/coreos.com/network: etcd prefix. --etcd-keyfile="": SSL key file used to secure etcd communication. --etcd-certfile="": SSL certification file used to secure etcd communication. --etcd-cafile="": SSL Certificate Authority file used to secure etcd communication. --kube-subnet-mgr: Contact the Kubernetes API for subnet assignment instead of etcd. --iface="": interface to use (IP or name) for inter-host communication. Defaults to the interface for the default route on the machine. This can be specified multiple times to check each option in order. Returns the first match found. --iface-regex="": regex expression to match the first interface to use (IP or name) for inter-host communication. If unspecified, will default to the interface for the default route on the machine. This can be specified multiple times to check each regex in order. Returns the first match found. This option is superseded by the iface option and will only be used if nothing matches any option specified in the iface options. --iptables-resync=5: resync period for iptables rules, in seconds. Defaults to 5 seconds, if you see a large amount of contention for the iptables lock increasing this will probably help. --subnet-file=/run/flannel/subnet.env: filename where env variables (subnet and MTU values) will be written to. --subnet-lease-renew-margin=60: subnet lease renewal margin, in minutes. --ip-masq=false: setup IP masquerade for traffic destined for outside the flannel network. Flannel assumes that the default policy is ACCEPT in the NAT POSTROUTING chain. -v=0: log level for V logs. Set to 1 to see messages related to data path. --healthz-ip="0.0.0.0": The IP address for healthz server to listen (default "0.0.0.0") --healthz-port=0: The port for healthz server to listen(0 to disable) --version: print version and exit
接下来,会重点讲代码的实现部分。