k8s CNI组件flannel 和calico 网络原理
flannel介绍:
flannel项目是在三层物理网络之上构建一个可跨节点通信容器网络,负责为节点下发子网和路由等信息,为容器分发唯一IP,flannel只实现简单的网络通信,不支持网络ACL。
flannel 支持vxlan、host-gw模式,udp模式已弃用。
在k8s中flannel作为标准CNI插件,每个节点都会运行一个flanneld的二进制代理程序,每个节点分配一个子网,集群网络状态通过apiserver直接存储在etcd当中。
假设pod网络是10.64.0.0/16,当前k8s有两个节点,下面研究一下这两节点上的pod是怎么通信的
vxlan:
node-01
网卡 | eth0 | vethxxx | cni0 | flannel.1 |
作用 | 物理网卡 | kubelet创建pod时分配的虚拟网卡 | pod共用的网桥 | vxlan的VTEP设备,处理非本节点pod网络通信 |
IP | 192.168.1.121 | 10.64.0.1/24 | 10.64.0.0/32 |
路由表:
node-02
网卡 | eth0 | vethxxx | cni0 | flannel.1 |
作用 | 物理网卡 | kubelet创建pod时分配的虚拟网卡 | pod共用的网桥 | vxlan的VTEP设备, 处理非本节点pod网络通信 |
IP | 192.168.1.122 | 10.64.1.1/24 | 10.64.1.0/32 |
路由表:
本地pod通信:
pod的vethxxx网卡都连接到了网桥cni0上面,实际cni0就是pod的交换机
pod跨节点通信 :
通信流程:
- pod-a访问pod-b 因为两者IP不在同一个子网,首先数据会先到默认网关也就是cni010.64.0.1
- 节点上面的静态路由可以看出来10.64.1.0/24 是指向flannel.1的
- flannel.1 会使用vxlan协议把原始IP包加上目的mac地址封装成二层数据帧
- 原始vxlan数据帧无法在物理二层网络中通信,flannel.1 (linux 内核支持vxlan,此步骤由内核完成)会把数据帧封装成UDP报文经过物理网络发送到node-02
- node-02收到UDP报文中带有vxlan头信息,会转交给flannel.1解封装得到原始数据
- flannel.1 根据直连路由转发到cni0 上面
- cni0 转发给pod-2
其实flannel的核心就是把已知的网络信息存储在etcd当中,并且在本地节点维护其他节点的网络信息,具体网络通信的实现依赖linux网桥、vxlan封装。
- 步骤2本机路由需要静态路由表由flanneld动态维护
- 步骤3vxlan协议封装数据帧组成VTEP二层网络,那么就必须知道对方VTEP设备 flannel.1的mac地址,ARP表也由flanneld动态维护,目的mac就是aa:93:00:62:7d:0f
- 步骤4封装UDP报文时已知目的mac地址aa:93:00:62:7d:0f,但是却不知道对方eth0的IP地址,FDB表也由flanneld动态维护
host-gw:
host-gw 相对vxlan模式相对比较简单,直接把节点作为一个网关,比如节点node-02上的pod子网是10.64.1.0/24,那么集群中所有节点上都会增加一条路由指向node-02
很显然host-gw模式对物理网络有严格的要求,中间不能有额外路由,宿主机要求能在二层网络下能直接通信
Calico介绍:
Calico是针对容器、虚拟机场景下提供跨宿主机互通的开源网络和安全解决方案,支持复杂的网络策略。
Calico的特点就是把每个宿主机当中一个虚拟路由器建立与物理网络对等的虚拟网络,该模式BGP协议在网络中通告路由信息,巧妙的把二层网络转换成三层路由网络,避免报文被二次封装数据转发效率很高,Pod IP可以在物理网络中全局路由
当然Calico除了路由模式还是支持Overlay Network网络模式比如vxlan
Calico的主要组件:
- Felix:每个节点都要运行的calico agent,负责配置节点上的路由信息和ACL;
- ETCD:配置中心,主要负责网络元数据一致性,确保Calico网络状态的准确性
- BGP Client(BIRD):主要负责把Felix配置的路由信息分发到当前Calico网络,确保节点间能够进行三层通信
BGP路由:
路由表:
本地pod通信:
本节点pod间通信不在像flannel一样使用网桥二层通信,而是每个pod的虚拟网卡都会有Pod IP的静态路由指向
pod跨节点通信 :
节点上有路由指向Pod子网所属的宿主机上,整个流程都是普通的三层路由转发