k8s安装读取内核modules_K8S容器跨主机通信浅析

k8s集群有多台宿主机的情况下,不同宿主机上的容器如何通过 ip地址进行相互访问呢 ,下面就根据k8s的网络模型,分析一下k8s集群容器的跨主机通信是如何实现的。

Flannel

Flannel是CoreOS推出的,是k8s的一种简单的三层网络方案。在k8s中可以借助这个网络插件实现不同宿主机节点之前的跨主机通讯。

Flannel有三种实现,分别是:

  1. UDP
  2. VXLAN
  3. host-gw

UDP是Flannel最早采用的方法之一,但性能较差,因为其从用户态到内核态的切换次数较为频繁,所以现在主要用的是Linux内核本身就支持的VXLAN网络虚拟化技术,下面会通过k8s的flannel插件来看看是 如何实现跨主机通讯的。

K8S实例

当前分别创建了三个虚拟机master、k8s-node1、k8s-node2当做k8s的三个节点。添加flannel插件:

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

ae7d10b4f3fdd6ac13010dd1d2cd6dab.png

可以看到三个节点的ip:

  • master: 192.168.10.200
  • k8s-node1: 192.168.10.201
  • k8s-node2: 192.168.10.202

VXLAN 模块会在现有的三层网络之上覆盖一层由它负责维护一个二层网络,使得在这个二层网络中的设备可以像在同一个局域网中一样通信。VXLAN在宿主机上设置一个特殊的网络设备叫作 VTEP,即:VXLAN Tunnel End Point(虚拟隧道端点)。VTEP设备的作用是负责在Linux内核中对二层数据帧进行封装和解封。

每台宿主机上都会有一个名为flannel.1的设备,这个设备就是VXLAN的VTEP设备,如图所示,k8s-node1上有一个flannel.1设备,它既有ip地址,又有mac地址。

ba60e3501326bb8cb16ae642a5831fd5.png

在k8s集群中通过deployment_busybox.yml起了三个busybox的pod,一个在k8s-node1,两个在k8s-node2。

db3ec16771de9105972ea79dd5728d95.png

现在,通过k8s-node1上的pod中的容器(下面用container1代替)访问在k8s-node2上的pod中的容器(下面用container2代替),基于VXLAN的跨主机通信流程图如下所示。

1e2c941bff5711083b5f92cfa4aebc39.png

container1的ip是10.244.5.2/24,它要去访问container2的ip是10.244.6.4/24。

首先进入container1,通过route -n查看容器内部的路由表

c5134bb1d3af04ea31b05d13702eed48.png

请求的ip是10.244.6.4,匹配第二条路由规则,走etho设备,而etho设备以Veth Pair的方式连接在k8s-node1的cni0网桥上,同个宿主机中docker容器通信是走docker0网桥,在k8s集群中替换为cni0网桥,作用和docker0网桥类似,都是二层交换设备。请求会通过cni0网桥到达宿主机上,而k8s-node1节点的路由表如下所示

9df252e8c56e98a5cb8daa1a71aa7d7b.png

10.244.6.0这条记录是在节点加入Flannel网络的时候,flanneld这个进程在路由表中添加的,请求匹配到 10.244.6.0 这条规则,走到flannel.1这个VETP设备,经过flannel.1这个设备转发到地址是10.244.6.0的网关。而10.244.6.0恰恰就是k8s-node2上flannel.1设备的ip地址。

39d3f4ef0346277fe2be5c7eb8370e55.png

3cfe652ba96f426c5b4ae3f0f7f2f43d.png

既然是要组成二层网络,所以flannel.1 VETP设备接收到原始ip包后,要加上目的mac地址封装成二层数据帧。获取ip对应的mac地址就需要通过ARP,flanneld进程在节点加入Flannel的网络时已经帮我们在ARP表中插入了一条ARP记录。

7125c683a3aa05d4bf12a3af4091fe00.png

可以看到10.244.6.0这个ip对应的mac地址是6a:2f:7d:e5:3f:2e。获取目的mac地址之后,就可以得到一个二层数据帧。

7912a84c5eafeb7114486a8892c97beb.png

但现在得到的二层数据帧还无法在宿主机的网络中传输,因为现在只有目的VETP设备的mac地址,而源宿主机需要目的宿主机的ip和mac地址。所以Linux内核会把这个二层数据帧前面加一个VXLAN头,封装到一个UDP包中从宿主机中发送出去,VXLAN头的作用是标识这个被包裹的数据帧是供VXLAN使用的。那么如何获取目的宿主机的ip和mac地址呢。宿主机上会有一个FDB表,它和ARP表的区别是ARP表是三层转发,而FDB表用于二层转发,flannel.1在这里相当于起到一个二层网桥设备的作用。

c1b43dc0c13253b5d8d1617206f0891f.png

我们在k8s-node1上通过之前获取到的目的VETP设备的mac地址可以查询到目的宿主机的ip是192.168.10.202,而目的宿主机的mac地址可以通过k8s-node1的正常ARP学习得到,并不需要特意维护一份,所以最终得到在宿主机网络中传输的二层数据帧格式如下所示

a39bd019350200d77bce5acb104d807d.png

k8s-node2节点的ens33网卡接收到这个请求之后对数据帧进行解包,Linux内核会根据该数据帧携带的VXLAN Header中的信息将内层包裹的VETP设备的二层数据帧转到k8s-node2上的flannel.1设备,然后flannel.1会再次对数据帧进行解包,拿到k8s-node1节点容器要发送请求的内容,根据路由表把请求转到cni0网桥,最终到达container2容器。

以上就是个人对k8s容器跨主机通信实现的理解,如果有误,可以在评论区指出,谢谢~!

参考链接

flannel插件​github.com CentOS7中用kubeadm安装Kubernetes-云栖社区-阿里云​yq.aliyun.com K8S网络模型​time.geekbang.org
db5a014dfc2456c8f10b82daa0df2249.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值