CNI学习系列2 Flannel

上篇我们介绍了一些CNI的细节,本篇我们将梳理下一个非常常见的CNI实现flannel。

如何部署flannel?

1
2
kubectl apply -f https://github.com/flannel-io/flannel/releases/
latest/download/kube-flannel.yml

这套配置的默认值有需要的话可以改下。

整体组件对比calico来说少得多。

1
2
3
4
5
6
namespace/kube-flannel created
serviceaccount/flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created

刨去namespace,sa,权限相关的,实际上也就一组守护进程DaemonSet和一个配置文件,不涉及任何CRD,可以说非常轻量了。

CNI配置也非常简洁:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@node1 ~]# cat /etc/cni/net.d/10-flannel.conflist 
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}

后端

flannel支持多种后端,目前最新的代码中支持:

  • alivpc 阿里云vpc做后端
  • awsvpc aws vpc做后端
  • gce google云做后端
  • hostgw 主机路由
  • tencentvpc 腾讯云vpc做后端
  • udp 用户态udp转发
  • vxlan vxlan内核态

抛开其中的绑定云供应商的方案:alivpc,awsvpc,gce,tencentvpc 。剩下的就剩三种常用的通用方案:

  1. udp
  2. vxlan
  3. hostgw

根据官方文档,这三种方案的定位是这样的:
vxlan是通用的,推荐的方案。host-gw是给那些需求更高的性能,且更有经验的用户的,并需要他们的基础架构能够支持。udp则仅用于debug或者那些非常老旧的,不支持vxlan的内核。

vxlan

首先守护进程集在每个节点启动好后会为每个节点配置对应的子网。

1
2
3
4
5
[root@node2 ~]# cat /run/flannel/subnet.env 
FLANNEL_NETWORK=10.233.64.0/18
FLANNEL_SUBNET=10.233.66.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true

在宿主机上查看路由会发现

1
2
3
4
5
6
7
8
9
10
[root@node2 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.31.1 0.0.0.0 UG 100 0 0 enp0s3
10.233.64.0 10.233.64.0 255.255.255.0 UG 0 0 0 flannel.1
10.233.65.0 10.233.65.0 255.255.255.0 UG 0 0 0 flannel.1
10.233.66.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.31.0 0.0.0.0 255.255.255.0 U 100 0 0 enp0s3

如果是本机的子网,则路由会走到cni0,如果不是本机的子网,则路由会走到flannel.1 这个设备。

1

flannel会配置Cni0 这样一个网桥。每个pod会配置一个veth到此网桥上

1
2
3
4
5
6
7
8
9
10
11
12
[root@node2 ~]# brctl show
bridge name bridge id STP enabled interfaces
cni0 8000.12db4b6540b9 no veth11915e9e
veth13da8459
veth68dfe2f4
vethb7e0fbb0
vethd8786cd9
vethe387ff6d
vethe8dfec1a
docker0 8000.0242684f69de no


根据是否为本机网段判断是否要走flannel.1

执行下面的命令我们可以看到 这是一个vxlan设备

1
2
3
4
5

[root@node1 node1]# ip -d link show flannel.1
10: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group default
link/ether 56:bc:93:2b:1a:4b brd ff:ff:ff:ff:ff:ff promiscuity 0
vxlan id 1 local 192.168.31.170 dev enp0s3 srcport 0 0 dstport 8472 nolearning ageing 300 noudpcsum noudp6zerocsumtx noudp6zerocsumrx addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535

vxlan 类似虚拟交换机将所有接入vxlan的设备组为虚拟大二层网络。每个节点的cni0像是接入了同一个物理交换机。由于vxlan是使用udp来封装了二层协议,所以比起raw网络有一些损耗,但是比起flannel的udp方案损耗还是小很多。

host-gw

这种就是纯路由的方案了

1
2
3
4
5
6
7
8
net-conf.json: |
{
"Network": "10.233.64.0/18",
"Backend": {
"Type": "host-gw"
}
}

这里配置host-gw 后apply即可。

部署好以后一看路由表

1
2
3
4
5
6
7
8
9
[root@node2 ~]# ip route
default via 192.168.31.1 dev enp0s3 proto static metric 100
10.233.64.0/24 via 192.168.31.170 dev enp0s3
10.233.65.0/24 via 192.168.31.172 dev enp0s3
10.233.66.0/24 dev cni0 proto kernel scope link src 10.233.66.1
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.31.0/24 dev enp0s3 proto kernel scope link src 192.168.31.171 metric 100


这次没有flannel.1这个设备了,这里flannel将根据网段直接路由到主机。这种方案整体来说损耗非常小,因为没有封装和解封的流程。

UDP

udp就是用户态中使用udp转发数据包,相当于用户态模拟vxlan效率较低,这里就不介绍了。

  • 本文作者: fenix
  • 本文链接: https://fenix0.com/cni-flannel/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC 许可协议。转载请注明出处!