作者:刘海峰,IT行业资深码农,从事.net/java/go语言开发十余年,长期关注springcloud/k8s/linux网络相关的技术,现为滴普科技容器产品首席架构师。
前言
flannel一共有UDP、VXLAN、HOST-GW三种工作模式,如果开启了Directrouting的话,会使用VXLAN和HOST-GW组合,不跨网段就使用HOST-GW,跨网段就使用VXLAN。对于host-gw和vxlan我们在前面的文章中有过简单地介绍,在这篇文章我们来分析一下flannel的UDP模式,虽然这种模式现在基本上已经不在生产上用了,但通过对UDP模式的了解,可以让我们更好地理解linux中的虚拟网络设备tun,以及为我们提供一种在用户态干涉协议栈数据的思路。
udp模式
当flannel以udp模式运行的时候,每个节点会有两个守护进程以及一个binary文件:
- 以k8s的daemonset运行的kube-flannel,负责与ETCD交互,获取最新的节点与子网信息,通过unix domain socket 的方式把信息同步给相同节点的flanneld进程
- 一个名叫flanneld守护进程,负责监听UDP 8285端口(默认端口,可以修改)并打开/dev/net/tun设备,不管哪一端来的数据,都往另一端转;同时会打开一个unix domain socket,接收来自kube-flannel的指令,更新路由。
- binary文件,存放目录为:/opt/cni/bin/flannel,负责创建同主机容器的相互通信,但它不具体做创建bridge或veth的工作,它只是生成了一个配置文件,然后调用本机的其它cni插件(例如:bridge和host-local,通常cni插件都在/opt/cni/bin目录下)来完成同主机容器的通信。
另外,在每个节点还会:
- 创建一个名为flannel.1的tun设备
- 创建了一条到POD-CIDR的直连路由,流量全部引到flannel.1的tun设备,注意是pod-cidr,不是某个node-cidr,这就意味着这台机出的流量只要是去容器的(当然除了本机的容器),就会走这张网卡。
下面一步步地解释上面的部件是怎么联动起来并完成跨主机的POD之间的通信的,在下面我们创建的tun设备名为tun0。
环境介绍
首先介绍一下准备的环境:
host1:
物理网卡eth0 IP:10.57.4.20;linux veth设备veth1,没有设置IP地址;linux tun设备tun0,设置了IP为10.244.1.1
主机路由三条,一条是默认网关;另外两条直连路由,分别到pod1和去往10.244.0.0/16
有一个容器叫POD1,地址为10.244.1.3
host2:
物理网卡eth0 IP:10.57.4.21;linux veth设备veth1,没有设置IP地址;linux tun设备tun0,设置了IP为10.244.2.1
主机路由三条,一条是默认网关;另外两条直连路由,分别到pod2和去往10.244.0.0/16
有一个容器叫POD2,地址为10.244.2.3