本文主要包括以下内容:
VXLAN(Virtual eXtensible LAN,虚拟可扩展的局域网),是一种虚拟化隧道通信技术。它是一种overlay(覆盖网络)技术,通过三层的网络搭建虚拟的二层网络。简单来讲,VXLAN是在底层物理网络(underlay)之上使用隧道技术,依托UDP层构建的overlay的逻辑网络,使逻辑网络与物理网络解耦,实现灵活的组网需求。它不仅能适配虚拟机环境,还能用于容器环境。
说明:我这里使用kubeadm安装的k8s,version为1.19,flannel的网络模式为vxlan,可以根据需要自己修改。
[root@master huazai]# kubectl version
Client Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.0", GitCommit:"e19964183377d0ec2052d1f1fa930c4d7575bd50", GitTreeState:"clean", BuildDate:"2020-08-26T14:30:33Z", GoVersion:"go1.15", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.0", GitCommit:"e19964183377d0ec2052d1f1fa930c4d7575bd50", GitTreeState:"clean", BuildDate:"2020-08-26T14:23:04Z", GoVersion:"go1.15", Compiler:"gc", Platform:"linux/amd64"}
参考:https://kubernetes.io/docs/concepts/cluster-administration/networking/#how-to-implement-the-kubernetes-networking-model
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl apply -f kube-flannel.yml
[root@master huazai]# kubectl get po -A |grep flannel
kube-system kube-flannel-ds-f4x7m 1/1 Running 0 15h
kube-system kube-flannel-ds-ltr8h 1/1 Running 0 15h
kube-system kube-flannel-ds-mp76x 1/1 Running 0 15h
[root@master huazai]# ip -d link show flannel.1
4: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group default
link/ether fe:be:87:93:06:e2 brd ff:ff:ff:ff:ff:ff promiscuity 0
vxlan id 1 local 192.168.0.39 dev eth0 srcport 0 0 dstport 8472 nolearning ageing 300 noudpcsum
可以看到mtu为1450(IP头、UDP头、MAC头、vxlan协议共占了50)。dstport为8472,local IP为节点IP,查看flannel.1的信息如下
[root@master huazai]# ifconfig flannel.1
flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450
inet 10.244.0.0 netmask 255.255.255.255 broadcast 10.244.0.0
inet6 fe80::fcbe:87ff:fe93:6e2 prefixlen 64 scopeid 0x20<link>
ether fe:be:87:93:06:e2 txqueuelen 0 (Ethernet)
RX packets 2622 bytes 465577 (454.6 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 4765 bytes 1081070 (1.0 MiB)
TX errors 0 dropped 8 overruns 0 carrier 0 collisions 0
[root@master huazai]# route -n
10.244.1.0 10.244.1.0 255.255.255.0 UG 0 0 0 flannel.1
10.244.2.0 10.244.2.0 255.255.255.0 UG 0 0 0 flannel.1
[root@master huazai]# arp -n
10.244.1.0 ether 0e:61:06:ff:7a:73 CM flannel.1
10.244.2.0 ether 0a:72:bf:3f:cd:40 CM flannel.1
[root@master huazai]# bridge fdb
0a:72:bf:3f:cd:40 dev flannel.1 dst 192.168.0.8 self permanent
0e:61:06:ff:7a:73 dev flannel.1 dst 192.168.0.22 self permanent
以上的mac地址均为对应节点上flannel.1设备的mac
以下面两个pod为例,两个pod都在node1,ip分别为10.244.1.8、10.244.1.9,假设在ip为10.244.1.8的pod中去ping ip为10.244.1.9的pod
[root@master huazai]# kubectl get po -o wide
nginx-deployment-66b6c48dd5-nzjgd 1/1 Running 0 35m 10.244.1.8 node1
nginx-deployment-66b6c48dd5-jcwc9 1/1 Running 0 35m 10.244.1.9 node1
进入pod ip为10.244.1.8的pod中
[root@master huazai]# kubectl exec -it nginx-deployment-66b6c48dd5-jcwc9 -- /bin/bash
root@nginx-deployment-66b6c48dd5-jcwc9:/#
查看其路由
root@nginx-deployment-66b6c48dd5-jcwc9:/# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.244.1.1 0.0.0.0 UG 0 0 0 eth0
10.244.0.0 10.244.1.1 255.255.0.0 UG 0 0 0 eth0
10.244.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
可以发现在同一个节点上的pod,直接进行访问了(在同一个网络段),没有经过转发。进入另外一个pod中查看路由,发现也是一样的
[root@master ~]# kubectl exec -it nginx-deployment-66b6c48dd5-nzjgd -- /bin/bash
root@nginx-deployment-66b6c48dd5-nzjgd:/#
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.244.1.1 0.0.0.0 UG 0 0 0 eth0
10.244.0.0 10.244.1.1 255.255.0.0 UG 0 0 0 eth0
10.244.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
以下面两个pod为例,其中一个pod在node1上,IP为10.244.1.8,另外一个pod在node2,IP为10.244.2.4
[root@master ~]# kubectl get po -o wide
nginx-deployment-66b6c48dd5-f7v9q 1/1 Running 0 60m 10.244.2.4 node2
nginx-deployment-66b6c48dd5-nzjgd 1/1 Running 0 60m 10.244.1.8 node1
进入pod ip为10.244.1.8的pod中
[root@master huazai]# kubectl exec -it nginx-deployment-66b6c48dd5-jcwc9 -- /bin/bash
root@nginx-deployment-66b6c48dd5-jcwc9:/#
查看其路由 root@nginx-deployment-66b6c48dd5-jcwc9:/# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 10.244.1.1 0.0.0.0 UG 0 0 0 eth0 10.244.0.0 10.244.1.1 255.255.0.0 UG 0 0 0 eth0 10.244.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 可以发现如果是执行ping 10.244.2.4则需要经过10.244.1.1,而10.244.1.1为node1上cn0的IP,cni0为flannel自己创建的网桥
[root@node1 net.d]# ifconfig
cni0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450
inet 10.244.1.1 netmask 255.255.255.0 broadcast 10.244.1.255
再查看node1上的路由
[root@node1 net.d]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.0.1 0.0.0.0 UG 0 0 0 eth0
10.244.0.0 10.244.0.0 255.255.255.0 UG 0 0 0 flannel.1
10.244.1.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0
10.244.2.0 10.244.2.0 255.255.255.0 UG 0 0 0 flannel.1
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.0.0 0.0.0.0 255.255.255.192 U 0 0 0 eth0
由路由发现,目标地址为10.244.2.0的数据包的下一跳为10.244.2.0,且要通过flannel.1,flannel.1作为一个VTEP设备,收到报文后将按照VTEP的配置进行封包。查看node1上的arp和fdb
[root@node1 net.d]# arp -n
10.244.0.0 ether fe:be:87:93:06:e2 CM flannel.1
10.244.2.0 ether 0a:72:bf:3f:cd:40 CM flannel.1
[root@node1 net.d]# bridge fdb
0a:72:bf:3f:cd:40 dev flannel.1 dst 192.168.0.8 self permanent
fe:be:87:93:06:e2 dev flannel.1 dst 192.168.0.39 self permanent
这里的话,通过etcd可以得知10.244.2.4在node2上,并且可以得到node2的IP,并且通过node1上转发表,可以知道node2上对应的VTEP的mac,然后根据flannel.1设备创建时的设置参数(VNI、local IP、Port)进行VXLAN封包。然后数据包通过node1跟node2之间的网络连接,VXLAN包到达node2,通过端口8472,VXLAN包被转发给VTEP设备flannel.1进行解包,解封装后的IP包匹配node2中的路由表(10.244.2.0),内核将IP包转发给cni0。
[root@node2 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.0.1 0.0.0.0 UG 0 0 0 eth0
10.244.0.0 10.244.0.0 255.255.255.0 UG 0 0 0 flannel.1
10.244.1.0 10.244.1.0 255.255.255.0 UG 0 0 0 flannel.1
10.244.2.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0
cni0将IP包转发给连接在cni0上的pod
通过以上发现,不同节点上的pod要互相进行访问时,需要通过主机路由,需要经过内核的封包解包操作,整个过程如下所示:
因此,在后续发现相关网络时,可通过tcpdump对节点上的cn0、flannel.1、eth0以及veth pair抓包进行判断和处理。同时,也要查看节点上的arp和fdb。
公众号:运维开发故事
github:https://github.com/orgs/sunsharing-note/dashboard
爱生活,爱运维
如果你觉得文章还不错,就请点击右上角选择发送给朋友或者转发到朋友圈。您的支持和鼓励是我最大的动力。喜欢就请关注我吧~