k8s网络原理之flannel

首先当你创建一个k8s集群后一般会存在三种IP分别是,Pod IP,Node IP,Cluster IP

其中一个Cluster IP之下包含多个Node IP,而一个Node IP之下又包含多个Pod IP,同一个Pod包含多个容器,这些容器的网络都在同一个命名空间,因此它们可以自由的通信,同一个Node包含多个Pod,这些Pod又通过veth pair技术与同一个cni网桥进行连接,通常这个cni网桥就是我们熟知的docker0网卡,这个是在你安装docker后就会创建在宿主机上的一个虚拟网卡,因此相同Node节点下的Pod又可以通过cni网桥进行通信。(这部分的知识我们在docker网络当中有详细的讲解,不了解的同学可以查看之前的微博。)

那么不同Node节点下的Pod又是如何进行通信的呢?本文重点要讲的flannel网络插件就是用来解决这个问题的。

一.在这里有必要先介绍一下flannel

Flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务,他的作用就是实现Pod资源跨主机进行网络通信。
我们知道在默认的Docker配置中,每个节点上的Docker服务会分别负责所在节点容器的IP分配。这样导致的一个问题是,不同节点上容器可能获得相同的内外IP地址。
那么flannel可以让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址,使得不同节点上的容器能够获得“同属一个内网”且”不重复的”IP地址,并让属于不同节点上的容器能够直接通过内网IP通信。

二.那么简单总结下flannel的作用有以下几点:

1.使集群中的不同Node主机创建的Docker容器都具有全集群唯一的虚拟IP地址。
2.建立一个覆盖网络(overlay network),通过这个覆盖网络,将数据包原封不动的传递到目标容器。覆盖网络是建立在另一个网络之上并由其基础设施支持的虚拟网络。覆盖网络通过将一个分组封装在另一个分组内来将网络服务与底层基础设施分离。在将封装的数据包转发到端点后,将其解封装。
3.创建一个新的虚拟网卡flannel0接收docker网桥的数据,通过维护路由表,对接收到的数据进行封包和转发(vxlan)。
4.etcd保证了所有node上flanned所看到的配置是一致的。同时每个node上的flanned监听etcd上的数据变化,实时感知集群中node的变化。

三.flannel网络架构的IP地址规划

flannel在每个主机中运行flanneld作为agent,它会为所在主机从集群的网络地址空间中,获取一个小的网段subnet,本主机内所有容器的IP地址都将从中分配。
如测试环境中ip分配:
1.master节点

2.node1

3.node2


在flannel network中,因为每个K8s node节点的subnet各不重叠,没有交集,因此各节点下的每个pod也都会被分配唯一的ip地址。

四.flannel网络架构原理图

这里借用官网的原理图讲解下各组件的功能:
1.Cni0:网桥设备,每创建一个pod都会创建一对 veth pair。其中一端是pod中的eth0,另一端是Cni0网桥中的端口(网卡)。Pod中从网卡eth0发出的流量都会发送到Cni0网桥设备的端口(网卡)上。

Cni0 设备获得的ip地址是该节点分配到的网段的第一个地址。

2.Flannel.1: overlay网络的设备,用来进行 vxlan 报文的处理(封包和解包)。不同node之间的pod数据流量都从overlay设备以隧道的形式发送到对端。

3.Flanneld:flannel在每个主机中运行flanneld作为agent,它会为所在主机从集群的网络地址空间中,获取一个小的网段subnet,本主机内所有容器的IP地址都将从中分配。同时Flanneld监听K8s集群数据库,为flannel.1设备提供封装数据时必要的mac,ip等网络数据信息。

不同node上的pod的通信流程:

pod中产生数据,根据pod的路由信息,将数据发送到Cni0虚拟网桥设备(非docker0)
Cni0虚拟网桥设备根据node节点的路由表,将数据发送到隧道设备flannel.1
Flannel.1查看数据包的目的ip,从flanneld获得对端隧道设备的必要信息(node节点对应的Mac地址),并对数据包进行封装。
Flannel.1将数据包发送到对端设备。对端节点的网卡接收到数据包,发现数据包为overlay数据包,解开外层封装,并发送内层封装到flannel.1设备。
Flannel.1设备查看数据包,根据目的node节点的路由表匹配规则,将数据发送给Cni0虚拟网桥设备。
Cni0虚拟网桥匹配Node节点路由表,将数据发送给网桥上对应的端口从而将数据传输给对应的目的pod。

不同node节点的pod的通信流程详解:

以不同node节点的Pod1 ping Pod3为例
1.pod1到cni0
首先Pod1与Pod3能够互相ping通

Ping包的dst ip 为192.20.1.43,根据路由匹配到最后一条路由表项,去往192.20.0.0/12的包都转发给192.20.0.1

192.20.0.1为cni0的ip地址

2.cni0到flannel1

根据最长匹配原则,匹配到图上的一条路由表项。去往192.20.1.0/24 网段的包,发送192.20.1.0网关,网关设备是flannel.1
3.源node节点flannel1对数据包进行封装处理并发到远端node节点的flannel1网络接口

VXLAN内层封装原理:

flannel.1为vxlan设备,当数据包来到flannel.1时,需要将数据包封装起来。此时的dst ip 为192.20.1.43,src ip为192.20.0.51。数据包继续封装需要知道192.20.1.43 ip地址对应的mac地址。此时,flannel.1不会发送arp请求去获得192.20.1.42的mac地址,而是由Linux kernel将一个“L3 Miss”事件请求发送给用户空间的flanned程序。Flanned程序收到内核的请求事件之后,从etcd查找能够匹配该目的地址的子网的flannel.1设备的mac地址,即发往的pod所在host中flannel.1设备的mac地址。Flannel在为Node节点分配ip网段时记录了所有的网段和mac等信息,所以能够知道。交互流程如下图所示:

flanned将查询到的信息放入master node host的arp cache表中:

到这里,vxlan的内层数据包就完成了封装。格式是这样的:

VXLAN外层封装原理:

简单总结这个流程:

  1. 数据包到达flannel.1,通过查找路由表,知道数据包要通过flannel.1发往192.20.1.0
  2. 通过arp cache表,知道了目的ip192.20.1.0的mac地址。
  3. kernel需要查看node上的fdb(forwarding database)以获得内层封包中目的vtep设备所在的node地址。因为已经从arp table中查到目的设备mac地址为52:77:71:e6:4f:58,同时在fdb中存在该mac地址对应的node节点的IP地址。如果fdb中没有这个信息,那么kernel会向用户空间的flanned程序发起”L2 MISS”事件。flanneld收到该事件后,会查询etcd,获取该vtep设备对应的node的”Public IP“,并将信息注册到fdb中。
    image

当内核获得了发往机器的ip地址后,arp得到mac地址,之后就能完成vxlan的外层封装
4.目的node节点flannel1接收到数据包之后

Node节点的eth0网卡接收到vxlan设备包,kernal将识别出这是一个vxlan包,将包拆开之后转给节点上的flannel.1设备。这样数据包就从发送节点到达目的节点,flannel.1设备将接收到一个如下的数据包:

目的地址为192.20.1.43,flannel.1查找自己的路由表,根据路由表完成转发。

根据最长匹配原则,flannel.1将去往192.20.1.0/24的流量转发到cni0上去。
5.cni0到pod
cni0是一个虚拟网桥设备。当cni0拿到数据包之后,通过veth pair,将数据包发送给pod。
在node节点上通过arp解析可以开出,192.20.1.43的mac地址为 66:57:8e:3d:00:85

该地址为pod的网卡eth0的地址

在获知目的pod mac地址后,cni0会通过veth pair将数据包发到pod eth0网卡veth pair接口,至此不同node 节点的通信圆满结束。

总结:本文详细介绍了K8s如何通过cni网络插件flannel完成了不同node节点也就是跨主机pod的通信,这部分的知识对于k8s集群来说十分重要,希望可以方便大家的理解,并在今后的使用和运维当中游刃有余。

posted @ 2020-11-06 10:34  渡边灬  阅读(4312)  评论(0编辑  收藏  举报
/* 看板娘 */