• K8S Flannel容器跨主机通信浅析


    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

    可以看到三个节点的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地址。

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

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

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

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

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

    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地址。

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

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

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

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

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

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

    参考链接

    转发于网络

  • 相关阅读:
    TeamWork#3,Week5,Scrum Meeting 11.16
    TeamWork#3,Week5,Scrum Meeting 11.6, 11.7, 11.11, 11.12
    TeamWork#3,Week5,Scrum Meeting 11.15
    TeamWork#3,Week5,Scrum Meeting 11.14
    TeamWork#3,Week5,Scrum Meeting 11.13
    TeamWork#3,Week5,Scrum Meeting 11.9
    TeamWork#3,Week5,Bing Input Method vs Sogou Input Method
    TeamWork#3,Week5,Scrum Meeting 11.4
    Daily Scrum10 11.14
    Daily Scrum9 11.13
  • 原文地址:https://www.cnblogs.com/cheyunhua/p/15064651.html
Copyright © 2020-2023  润新知