Kubernetes网络组件对比

Flannel网络

简介

flannel是CoreOS提供用于解决Dokcer集群跨主机通讯的覆盖网络工具。它的主要思路是:预先留出一个网段,每个主机使用其中一部分,然后每个容器被分配不同的ip;让所有的容器认为大家在同一个直连的网络,底层通过UDP/VxLAN等进行报文的封装和转发。

IP地址管理

flannel会利用Kubernetes API或者etcd用于存储整个集群的网络配置,flannel会在每个主机中运行flanneld作为agent,它会为所在主机从集群的网络地址空间中,获取一个小的网段subnet,本主机内所有容器的IP地址都将从中分配。然后,flanneld再将本主机获取的subnet以及用于主机间通信的Public IP,同样通过kubernetes API或者etcd存储起来。

最后,flannel利用各种backend mechanism,例如udp,vxlan等等,跨主机转发容器间的网络流量,完成容器间的跨主机通信。

支持的网络模式

UDP: 使用用户态udp封装,默认使用8285端口。由于是在用户态封装和解包,性能上有较大的损失。

VXLAN: vxlan封装,需要配置VNI,Port(默认8472)和GBP; 是Linux内核本身支持的一种网络虚拟化技术,是内核的一个模块,在内核态实现封装解封装,构建出覆盖网络,其实就是一个由各宿主机上的Flannel.1设备组成的虚拟二层网络,由于VXLAN由于额外的封包解包,导致其性能较差;VXLAN Directrouting模式也支持类似host-gw的玩法,如果两个节点在同一网段时使用host-gw通信,如果不在同一网段中,即 当前pod所在节点与目标pod所在节点中间有路由器,就使用VXLAN这种方式,使用叠加网络

Host-gw: 直接路由的方式,将容器网络的路由信息直接更新到主机的路由表中,仅适用于二层直接可达的网络 推荐使用,效率极高

不同网络模式下数据包流向

UDP模式

img

  1. 容器直接使用目标容器的ip访问,默认通过容器内部的eth0发送出去。

  2. 报文通过veth pair被发送到vethXXX。

  3. vethXXX是直接连接到虚拟交换机docker0的,报文通过虚拟bridge docker0发送出去。

  4. 根据路由表,外部容器ip的报文都会转发到flannel0虚拟网卡,这是一个P2P的虚拟网卡,然后报文就被转发到监听在另一端的flanneld。

  5. flanneld通过etcd维护了各个节点之间的路由表,把原来的报文UDP封装一层,通过配置的iface发送出去

  6. 报文通过主机之间的网络找到目标主机。

  7. 报文继续往上,到传输层,交给监听在8285端口的flanneld程序处理。

  8. 数据被解包,然后发送给flannel0虚拟网卡。

  9. 查找路由表,发现对应容器的报文要交给docker0。

  10. docker0找到连到自己的容器,把报文发送过去。

vxLan模式

img

  1. 源容器veth0向目标容器发送数据,根据容器内的默认路由,数据首先发送给宿主机的docker0网桥

  2. 宿主机docker0网桥接受到数据后,宿主机查询路由表,pod相关的路由都是交由flannel.1网卡,因此,将其转发给flannel.1虚拟网卡处理

  3. flannel.1接受到数据后,查询etcd数据库,获取目标pod网段对应的目标宿主机地址、目标宿主机的flannel网卡的mac地址、vxlan vnid等信息。然后对数据进行udp封装, 完成以上udp封装后,将数据转发给物理机的eth0网卡

  4. 宿主机eth0接收到来自flannel.1的udp包,还需要将其封装成正常的通信用的数据包,为它加上通用的ip头、二层头,这项工作在由linux内核来完成。通过此次封装,一个真正可用的数据包就封装完成,可以通过物理网络传输了

  5. 目标宿主机的eth0接收到数据后,对数据包进行拆封,拆到udp层后,将其转发给8427端口的flannel进程

  6. 目标宿主机端flannel拆除udp头、vxlan头,获取到内部的原始数据帧,在原始数据帧内部,解析出源容器ip、目标容器ip,重新封装成通用的数据包,查询路由表,转发给docker0网桥

  7. 最后,docker0网桥将数据送达目标容器内的veth0网卡,完成容器之间的数据通信

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事件,删除对应的路由即可。

img

  1. 源容器veth0向目标容器发送数据,根据容器内的默认路由,数据首先发送给宿主机的docker0网桥,并进入内核协议栈

  2. 经过netfilter的 PREROUTING,再进入到路由子系统,此时由于宿主机没有任何额外的设备,匹配到默认路由,从宿主机的eth0发出,数据包直接发送至目的节点所在的宿主机

  3. 数据帧通过宿主机的二层网络顺利到达节点目的节点

Calico网络

img

calico主要组件

  1. Felix:运行在每一台 Host 的 agent 进程,主要负责网络接口管理和监听、路由、ARP 管理、ACL 管理和同步、状态上报等。Felix会监听ECTD中心的存储,从它获取事件,比如说用户在这台机器上加了一个IP,或者是创建了一个容器等。用户创建pod后,Felix负责将其网卡、IP、MAC都设置好,然后在内核的路由表里面写一条,注明这个IP应该到这张网卡。同样如果用户制定了隔离策略,Felix同样会将该策略创建到ACL中,以实现隔离。

  2. etcd:分布式键值存储,主要负责网络元数据一致性,确保Calico网络状态的准确性,可以与kubernetes共用;

  3. BGP Client(BIRD):Calico 为每一台 Host 部署一个 BGP Client,使用 BIRD 实现,BIRD 是一个单独的持续发展的项目,实现了众多动态路由协议比如 BGP、OSPF、RIP 等。在 Calico 的角色是监听 Host 上由 Felix 注入的路由信息,然后通过 BGP 协议广播告诉剩余 Host 节点,从而实现网络互通。BIRD是一个标准的路由程序,它会从内核里面获取哪一些IP的路由发生了变化,然后通过标准BGP的路由协议扩散到整个其他的宿主机上,让外界都知道这个IP在这里,你们路由的时候得到这里来。

  4. BGP Route Reflector:在大型网络规模中,如果仅仅使用 BGP client 形成 mesh 全网互联的方案就会导致规模限制,因为所有节点之间俩俩互联,需要 N^2 个连接,为了解决这个规模问题,可以采用 BGP 的 Router Reflector 的方法,使所有 BGP Client 仅与特定 RR 节点互联并做路由同步,从而大大减少连接数。

网络管理过程

  1. k8s 下发pod

  2. kubelet 调用calico-cni 接口,然后calico守护进程Felix 创建veth-pair,一端连接pod,一端连接cali虚拟网卡,并写主机路由表。同时将数据(网卡,ip,mac)写入到etcd存储中。

  3. bird 检测到内核路由,bgp广播到集群内的所有节点

数据包流向

未完待续

Canel网络

Terway网络

posted @ 2022-01-20 10:50  梧桐花落  阅读(616)  评论(0编辑  收藏  举报