Jusene's Blog

Kubernetes flannel网络解析

字数统计: 1.4k阅读时长: 6 min
2020/09/21 Share

Flannel网络

Flannel是CoreOS团队针对kubernetes设计的覆盖网络(Overlay Network)工具,Flannel通过给每台宿主机分配一个子网为容器提供虚拟网络,使用UDP封装IP包来创建overlay网络,并借助etcd维护网络的分配情况。

flannel网络backend解决方案:

  • hostgw 直接路由,适合局域网,性能好,仅适合二层可达的局域网
  • vxlan 是flannel推荐的方式,需要通信的网络设备支持vxlan,具备很好的跨局域网通信,但使用了隧道封装,性能较差
  • udp 改方式于vxlan很类似,对ip层网络进行封装,通常用于调试环境或者不支持vxlan协议的网络环境 Flannel vxlan原理图:

IP package解包:

  1. 头部TCP头部信息封装源宿主机到目的宿主机IP,MAC地址封装源MAC到下一跳MAC地址的网络信息
  2. 封装vxlan头部信息,指明改网络包是overlay网络包
  3. 内部封装容器源mac地址到目的mac地址,源容器IP到目的IP的信息

flannel的的大致工作原理:

  • 数据从源容器中发出后,经由所在主机的docker0虚拟网卡转发到flannel0虚拟网卡,flanneld服务监听在网卡的另外一端。
  • flannel通过etcd维护了一张节点间的路由表,该张表保存了各个节点主机的子网网段信息
  • 源主机的flanneld服务将原本的数据内容udp封装后根据自己的路由表投递给目的节点的flanneld服务,数据到达以后被解包,然后直接进入目的节点的flannel0虚拟网络,然后被转发到目的主机的docker0虚拟网卡,最后就像本机容器通信一样的由docker0路由到达目标容器

flannel网络实验可参考:https://jusene.github.io/2018/04/13/docker-flannel/

Kubernetes中flannel网络

  1. cni0: 网桥设备,每创建一个pod都会创建一对veth pair,其中一端是pod的eth0,另一端是cni0网桥中的端口,pod中从eth0的流量都会到cni端口
1
~]# brctl show
2
bridge name     bridge id               STP enabled     interfaces
3
cni0            8000.a2ed1ec1f6fa       no              veth382beee9
4
                                                        vethf1a85950
5
docker0         8000.0242b9ef22c0       no
1
~]# ifconfig cni0
2
cni0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
3
        inet 10.20.2.1  netmask 255.255.255.0  broadcast 10.20.2.255
4
        ether a2:ed:1e:c1:f6:fa  txqueuelen 1000  (Ethernet)
5
        RX packets 44921  bytes 3152070 (3.0 MiB)
6
        RX errors 0  dropped 0  overruns 0  frame 0
7
        TX packets 47841  bytes 17248924 (16.4 MiB)
8
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

cni0设备获取到的地址是分配到本机网络的第一个ip

  1. flannel.1 overlay网络设备,用来进行vxlan的报文处理(封包和解包);不同node之间的Pod数据流量都从overlay设备以隧道的形式发送到对端
1
~]# ifconfig flannel.1
2
flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
3
        inet 10.20.2.0  netmask 255.255.255.255  broadcast 0.0.0.0
4
        ether 32:5b:33:4e:42:50  txqueuelen 0  (Ethernet)
5
        RX packets 5  bytes 420 (420.0 B)
6
        RX errors 0  dropped 0  overruns 0  frame 0
7
        TX packets 5  bytes 420 (420.0 B)
8
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
  1. flanneld: flannel会在每个主机运营flanneld作为agent,它会会主机在集群网络地址空间中获取一个小网段,本机内所有容器的IP地址都从中分配;同时flanneld会监听etcd,为flannel.1设备提供封装时必要的mac、ip等网络数据信息

解析

1
~]# kubectl get pod --all-namespaces -o wide                  
2
NAMESPACE     NAME                            READY   STATUS    RESTARTS   AGE     IP             NODE          NOMINATED NODE   READINESS GATES
3
default       test-skaffold-6d8ff678d-ldhqm   1/1     Running   0          3m24s   10.20.1.5      k8s-node1     <none>           <none>
4
kube-system   coredns-85b4878f78-gtknx        1/1     Running   0          45s     10.20.2.4      k8s-node2     <none>           <none>

从10.20.1.5访问10.20.2.4

  1. 进入容器查看路由
1
/ # route -n
2
Kernel IP routing table
3
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
4
0.0.0.0         10.20.1.1       0.0.0.0         UG    0      0        0 eth0
5
10.20.0.0       10.20.1.1       255.255.0.0     UG    0      0        0 eth0
6
10.20.1.0       0.0.0.0         255.255.255.0   U     0      0        0 eth0

网关指向cni0的ip

  1. 在宿主机上查看路由表
1
~]# route -n
2
Kernel IP routing table
3
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
4
0.0.0.0         10.211.55.1     0.0.0.0         UG    100    0        0 eth0
5
10.20.0.0       10.20.0.0       255.255.255.0   UG    0      0        0 flannel.1
6
10.20.1.0       0.0.0.0         255.255.255.0   U     0      0        0 cni0
7
10.20.2.0       10.20.2.0       255.255.255.0   UG    0      0        0 flannel.1
8
10.211.55.0     0.0.0.0         255.255.255.0   U     100    0        0 eth0
9
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0

路由指向flannel.1

  1. flannel.1

flannel.1为vxlan设备,当数据包来到flannel.1时,需要将数据包封装起来,vxlan需要封装mac地址信息,flannel.1通过flanneld程序从etcd中获取mac地址,并用此信息封装vxlan数据包。

简单流程:

  • 数据包到达flannel.1通过查找路由表,知道数据包要通过flannel.1发往10.20.2.0
  • 通过arp cache表,知道目的的ip 10.20.2.4的mac地址(对端flannel.1的mac地址)
  1. 对端flannel.1

对端eth0接受vxlan数据包,拆开数据包,转给flannel.1设备

1
~]# route -n
2
Kernel IP routing table
3
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
4
0.0.0.0         10.211.55.1     0.0.0.0         UG    100    0        0 eth0
5
10.20.0.0       10.20.0.0       255.255.255.0   UG    0      0        0 flannel.1
6
10.20.1.0       10.20.1.0       255.255.255.0   UG    0      0        0 flannel.1
7
10.20.2.0       0.0.0.0         255.255.255.0   U     0      0        0 cni0
8
10.211.55.0     0.0.0.0         255.255.255.0   U     100    0        0 eth0
9
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0

通过路由表 10.20.2.0 的数据包发往cni0

  1. cni0发送到pod

cni0是一个网桥设备,通过peer veth将数据包发给pod

查看arp cache

1
ip n | grep 10.20.2.4
2
10.20.2.4 dev cni0 lladdr ea:ca:7c:a8:5b:60 REACHABLE
CATALOG
  1. 1. Flannel网络
  2. 2. Kubernetes中flannel网络
    1. 2.1. 解析