Flannel是用于解决容器跨节点通信问题的解决方案,兼容CNI插件API,支持Kubernetes、OpenShift、Cloud Foundry、Mesos、Amazon ECS、Singularity和OpenSVC等平台。它使用“虚拟网桥和veth设备”的方式为Pod创建虚拟网络接口,通过可配置的“后端”定义Pod间的通信网络,支持基于VXLAN和UDP的Overlay网络,以及基于三层路由的Underlay网络

Flannel在每个主机上运行一个名为flanneld的二进制代理程序,它负责从预留的网络中按照指定或默认的掩码长度为当前节点申请分配一个子网,并将网络配置、已分配的子网和辅助数据(例如主机的公网IP等)存储在Kubernetes API或etcd之中。Flannel使用称为后端的容器网络机制转发跨节点的Pod报文。

vxlan:使用Linux内核中的vxlan模块封装隧道报文,以Overlay网络模型支持跨节点的Pod间互联互通;同时,该后端类型支持直接路由模式,在该模式下,位于同一二层网络内节点之上的Pod间通信可通过路由模式直接发送,而跨网络的节点之上的Pod间通信仍要使用VXLAN隧道协议转发;VXLAN隶属于Overlay网络模型,或混合网络模型;vxlan后端模式中,flanneld监听UDP的8472端口发送的封装数据包

host-gw:即Host GateWay,它类似于VXLAN中的直接路由模式,但不支持跨网络的节点,因此这种方式强制要求各节点本身必须在同一个二层网络中,不太适用于较大的网络规模;host-gw有着较好的转发性能,且易于设定,推荐对报文转发性能要求较高的场景使用

udp:使用常规UDP报文封装完成隧道转发,性能较前两种方式低很多,它仅在不支持前两种后端的环境中使用;UDP后端模式中,flanneld监听UDP的8285端口发送的封装报文

Flannel使用etcd来存储虚拟IP和主机IP之间的映射,每个节点上运行的flanneld守护进程负责监视etcd中的信息并完成报文路由。默认情况下,Flannel的配置信息保存在etcd存储系统的键名/coreos.com/network/config之下,我们可以使用etcd服务的客户端工具来设定或修改其可用的相关配置。config的值是一个JSON格式的字典数据结构

Flannel会在集群中每个运行flanneld的节点之上创建一个名为flannel.1的虚拟网桥作为本节点隧道出入口的VTEP设备,其中的1表示VNI,因而所有节点上的VTEP均属于同一VXLAN,或者属于同一个大二层域(BD),它们依赖于二层网关进行通信。Flannel采用了分布式的网关模型,它把每个节点都视为到达该节点Pod子网的二层网关,相应的路由信息由flanneld自动生成。

Flannel VXLAN后端

Flannel网络插件_Flannel

Flannel并非依赖ARP进行MAC地址学习,而是由节点上的flanneld进程启动时将本地flannel.1接口IP与MAC地址的映射信息上报到etcd中,并由其他各节点上的flanneld来动态生成相应的解析记录

VXLAN协议报文

Flannel网络插件_Flannel_02

Flannel把flannel.1接口也作为网桥设备使用,该设备上附加了一个同样由flanneld维护的、称为FDB(Forwarding Database)的转发数据库。该数据库指明了到达目标节点flannel.1接口需要经由的下一跳IP,该IP是目标Pod所在节点的IP地址,即外部IP头部中的目标IP

为了提升性能,Flannel的VXLAN后端还支持DirectRouting模式,即在集群中的各节点上添加必要的路由信息,让Pod间的IP报文通过节点的二层网络直接传送。若Kubernetes集群节点全部位于单个二层网络中,则DirectRouting模式下的Pod间通信流量基本接近于直接使用二层网络

Flannel的host-gw后端通过添加必要的路由信息,并使用节点的二层网络直接发送Pod间的通信报文,其工作方式类似于VXLAN后端中的直接路由功能,但不包括该后端支持的隧道转发能力,这意味着host-gw后端要求各节点必须位于同一个二层网络中