参考
k8s<=1.16版本,则安装:flannel/v0.11.0
yml下载地址:https://raw.githubusercontent.com/coreos/flannel/v0.11.0/Documentation/kube-flannel.yml
k8s>=1.17版本,则安装:flannel/v0.12.0
yml下载地址:https://raw.githubusercontent.com/coreos/flannel/v0.12.0/Documentation/kube-flannel.yml
支持3种实现:UDP、VXLAN、host-gw
-
udp模式:使用设备
flannel.0
进行封包解包,不是内核原生支持,上下文切换较大,性能非常差 -
vxlan模式:使用
flannel.1
进行封包解包,内核原生支持,性能较强 -
vxlan(Dirextrouting)模式:经过测试发现
感觉和host-gw模式差不多。不知道它们的区别是啥
。 -
host-gw模式:
无需flannel.1这样的中间设备
,直接宿主机当作子网的下一跳地址
,性能最强
host-gw
的性能损失大约在10%左右
,而其他所有基于VXLAN隧道
机制的网络方案,性能损失在20%~30%左右
使用kubernetes安装flannel
由于flannel没有master和slave之分,每个节点上都安装一个agent,即flanneld。我们可以使用kubernetes的DaemonSet部署flannel,以达到每个节点部署一个flanneld实例的目的。
1. 安装vxlan模式的flannel
1.1 安装
修改下载的kube-flannel.yml中的"Network": "10.244.0.0/16",与你k8s集群配置的Pod CIDR一致即可(注意不要和物理网卡的IP同网段,这样可能导致路由问题
)。
可以看到kube-flannel.yml中配置的Backend默认为vxlan。因此不用修改。
"Backend": {
"Type": "vxlan"
}
kubectl create -f kube-flannel.yml
flannel采用VxLan模式,使用8472
端口。在每个k8s集群中的节点都会监听8472端口,其它节点会用一个随机端口连接到目标主机的8472端口,采用UDP协议进行发布。如下面一条抓包数据所示:我们在192.168.19.166的pod(10.244.1.7)中去ping 192.168.19.167的pod ip(10.244.2.6),这时我们抓取192.168.19.166 的enp0s3设备的udp包,192.168.19.166.39338 > 192.168.19.167.otv
表示192.168.19.166发包的时候会的用39338(随机端口)连接到192.168.19.167的8472(otv)端口---这相当于隧道的包头(新的目的和源地址);后面的fe:0e:f2:75:aa:44 > 92:e5:0e:57:bd:72, ethertype IPv4 (0x0800), length 98: 10.244.1.7 > 10.244.2.6: ICMP echo request, id 3072, seq 0, length 64
表示隧道传输的原始数据。
1.1.1 安装好之后的网络架构图如下
1.1.2 以Node1为例详细说明
1.2 测试
1.2.1 创建测试pod
kubectl run busybox --image=busybox --generator=run-pod/v1 --command -- sleep 36000m
kubectl run busybox1 --image=busybox --generator=run-pod/v1 --command -- sleep 36000m
kubectl run busybox2 --image=busybox --generator=run-pod/v1 --command -- sleep 36000m
kubectl run busybox3 --image=busybox --generator=run-pod/v1 --command -- sleep 36000m
kubectl run busybox4 --image=busybox --generator=run-pod/v1 --command -- sleep 36000m
这里我创建好之后的拓扑架构如下图:
1.2.2 在node1的busybox3(10.244.1.7)pod中去ping node2的busybox(10.244.2.6)
# kubectl exec -ti busybox3 sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
# 这里看到eth0配对的网卡是if8(即veth1093090e)
3: eth0@if8: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue
link/ether d2:64:45:f9:14:d3 brd ff:ff:ff:ff:ff:ff
inet 10.244.1.7/24 scope global eth0
valid_lft forever preferred_lft forever
# 看到路由的网关是10.244.1.1(即网关是cni0设备)
/ # ip r
default via 10.244.1.1 dev eth0
10.244.0.0/16 via 10.244.1.1 dev eth0
10.244.1.0/24 dev eth0 scope link src 10.244.1.7
# 发起ping包
/ # ping 10.244.2.6 -c 1
1.2.2.1 node1的抓包结果
在ping的同时,对node1的veth1093090e、cni0、flannel.1、enp0s3设备抓包:
# tcpdump -i veth1093090e -ne icmp
15:00:44.493616 d2:64:45:f9:14:d3 > 42:e1:b2:c8:b5:24, ethertype IPv4 (0x0800), length 98: 10.244.1.7 > 10.244.2.6: ICMP echo request, id 9216, seq 0, length 64
15:00:44.494266 42:e1:b2:c8:b5:24 > d2:64:45:f9:14:d3, ethertype IPv4 (0x0800), length 98: 10.244.2.6 > 10.244.1.7: ICMP echo reply, id 9216, seq 0, length 64
#tcpdump -i cni0 -ne icmp
15:00:44.493616 d2:64:45:f9:14:d3 > 42:e1:b2:c8:b5:24, ethertype IPv4 (0x0800), length 98: 10.244.1.7 > 10.244.2.6: ICMP echo request, id 9216, seq 0, length 64
15:00:44.494257 42:e1:b2:c8:b5:24 > d2:64:45:f9:14:d3, ethertype IPv4 (0x0800), length 98: 10.244.2.6 > 10.244.1.7: ICMP echo reply, id 9216, seq 0, length 64
#tcpdump -i flannel.1 -ne icmp
15:00:44.493648 fe:0e:f2:75:aa:44 > 92:e5:0e:57:bd:72, ethertype IPv4 (0x0800), length 98: 10.244.1.7 > 10.244.2.6: ICMP echo request, id 9216, seq 0, length 64
15:00:44.494245 92:e5:0e:57:bd:72 > fe:0e:f2:75:aa:44, ethertype IPv4 (0x0800), length 98: 10.244.2.6 > 10.244.1.7: ICMP echo reply, id 9216, seq 0, length 64
# tcpdump -i enp0s3 -ne udp and 'host 192.168.19.167'
15:00:44.493668 08:00:27:69:22:80 > 08:00:27:f3:59:5b, ethertype IPv4 (0x0800), length 148: 192.168.19.166.39338 > 192.168.19.167.otv: OTV, flags [I] (0x08), overlay 0, instance 1
fe:0e:f2:75:aa:44 > 92:e5:0e:57:bd:72, ethertype IPv4 (0x0800), length 98: 10.244.1.7 > 10.244.2.6: ICMP echo request, id 9216, seq 0, length 64
15:00:44.494191 08:00:27:f3:59:5b > 08:00:27:69:22:80, ethertype IPv4 (0x0800), length 148: 192.168.19.167.59883 > 192.168.19.166.otv: OTV, flags [I] (0x08), overlay 0, instance 1
92:e5:0e:57:bd:72 > fe:0e:f2:75:aa:44, ethertype IPv4 (0x0800), length 98: 10.244.2.6 > 10.244.1.7: ICMP echo reply, id 9216, seq 0, length 64
经测试,数据包确实由 busybox3 pod 的eth0
发往 veth1093090e
再发往 cni0
再发往flannel.1
再发往enp0s3
,再发到node2。
且从enp0s3的抓包发现,enp0s3发送的是udp
的包,协议是OTV
协议。以隧道的方式发送,真实的数据包在隧道内部。
1.2.2.2 node2的抓包结果
在ping的同时,对node2的enp0s3、flannel.1、cni0、vethd7bb83ed设备抓包:
# tcpdump -i enp0s3 -ne udp and 'host 192.168.19.166'
15:00:44.492688 08:00:27:69:22:80 > 08:00:27:f3:59:5b, ethertype IPv4 (0x0800), length 148: 192.168.19.166.39338 > 192.168.19.167.otv: OTV, flags [I] (0x08), overlay 0, instance 1
fe:0e:f2:75:aa:44 > 92:e5:0e:57:bd:72, ethertype IPv4 (0x0800), length 98: 10.244.1.7 > 10.244.2.6: ICMP echo request, id 9216, seq 0, length 64
15:00:44.492926 08:00:27:f3:59:5b > 08:00:27:69:22:80, ethertype IPv4 (0x0800), length 148: 192.168.19.167.59883 > 192.168.19.166.otv: OTV, flags [I] (0x08), overlay 0, instance 1
92:e5:0e:57:bd:72 > fe:0e:f2:75:aa:44, ethertype IPv4 (0x0800), length 98: 10.244.2.6 > 10.244.1.7: ICMP echo reply, id 9216, seq 0, length 64
# tcpdump -i flannel.1 -ne icmp
15:00:44.492779 fe:0e:f2:75:aa:44 > 92:e5:0e:57:bd:72, ethertype IPv4 (0x0800), length 98: 10.244.1.7 > 10.244.2.6: ICMP echo request, id 9216, seq 0, length 64
15:00:44.492908 92:e5:0e:57:bd:72 > fe:0e:f2:75:aa:44, ethertype IPv4 (0x0800), length 98: 10.244.2.6 > 10.244.1.7: ICMP echo reply, id 9216, seq 0, length 64
# tcpdump -i cni0 -ne icmp
15:00:44.492812 3a:be:21:07:67:52 > 66:e9:bd:ae:22:49, ethertype IPv4 (0x0800), length 98: 10.244.1.7 > 10.244.2.6: ICMP echo request, id 9216, seq 0, length 64
15:00:44.492895 66:e9:bd:ae:22:49 > 3a:be:21:07:67:52, ethertype IPv4 (0x0800), length 98: 10.244.2.6 > 10.244.1.7: ICMP echo reply, id 9216, seq 0, length 64
# tcpdump -i vethd7bb83ed -ne icmp
15:00:44.492825 3a:be:21:07:67:52 > 66:e9:bd:ae:22:49, ethertype IPv4 (0x0800), length 98: 10.244.1.7 > 10.244.2.6: ICMP echo request, id 9216, seq 0, length 64
15:00:44.492895 66:e9:bd:ae:22:49 > 3a:be:21:07:67:52, ethertype IPv4 (0x0800), length 98: 10.244.2.6 > 10.244.1.7: ICMP echo reply, id 9216, seq 0, length 64
# busybox中eth0网卡的由于所在的namespace不好抓包,所以就没抓
经测试,node2收到ping包后,数据包的转发过程确实是由 enp0s3
发往 cni0
再发往 flannel.1
再发往vethd7bb83ed
,最好在发送到 busybox pod 的eth0
。
1.2.2.3 数据包的回路
数据包的原路返回。原理与前面类似。
2. 安装vxlan(Dirextrouting)模式flannel
2.1 安装
修改kube-flannel.yml中的"Network": "10.244.0.0/16",与你k8s集群配置的Pod CIDR一直即可。
修改kube-flannel.yml中配置的Backend,增加配置"Directrouting": true
:
"Backend": {
"Type": "vxlan",
"Directrouting": true
}
执行安装
kubectl create -f kube-flannel.yml
2.2 测试
创建测试pod
kubectl run busybox --image=busybox --generator=run-pod/v1 --command -- sleep 36000m
kubectl run busybox1 --image=busybox --generator=run-pod/v1 --command -- sleep 36000m
kubectl run busybox2 --image=busybox --generator=run-pod/v1 --command -- sleep 36000m
kubectl run busybox3 --image=busybox --generator=run-pod/v1 --command -- sleep 36000m
kubectl run busybox4 --image=busybox --generator=run-pod/v1 --command -- sleep 36000m
测试过程略....
2.3 测试结果
发现数据包的流向如下所示:
抓包发现,数据包直接由cni0转发给了enp0s3设备,少了flannel.1封版隧道包的过程。
通过抓包数据发现,该模式有点像Calico的BGP模式。
vxlan(Dirextrouting)模式的效率要比vxlan模式的效率高
。
3. 安装host-gw模式flannel
3.1 安装
修改kube-flannel.yml中的"Network": "10.244.0.0/16",与你k8s集群配置的Pod CIDR一直即可。 修改kube-flannel.yml中配置的Backend,配置Type的值为host-gw:
"Backend": {
"Type": "host-gw"
}
执行安装
kubectl create -f kube-flannel.yml
3.1.1 安装好之后的架构图
这里发现没有flannel.1
网络设备了。
数据包通过cni0网桥
,通过路由协议
由enp0s3网卡设备把数据包转发到其它节点pod。
3.2 测试
创建测试pod
kubectl run busybox --image=busybox --generator=run-pod/v1 --command -- sleep 36000m
kubectl run busybox1 --image=busybox --generator=run-pod/v1 --command -- sleep 36000m
kubectl run busybox2 --image=busybox --generator=run-pod/v1 --command -- sleep 36000m
kubectl run busybox3 --image=busybox --generator=run-pod/v1 --command -- sleep 36000m
kubectl run busybox4 --image=busybox --generator=run-pod/v1 --command -- sleep 36000m
测试过程略....