问题现场
自己的实验集群,使用的k3s v1.25.7+k3s1, 网络使用的默认flannel vxlan模式。
NAME STATUS ROLES AGE VERSION
whoops-home Ready <none> 253d v1.25.7+k3s1
whoops-k3s Ready control-plane,master 268d v1.25.7+k3s1
节点whoops-k3s是CentOS7.9,折腾网络,改了ifcfg-eth0配置,systemctl restart network重启网络,一开始没发现,第二天发现nginx到集群的访问504。
这个小集群是在家里NAS和软路由上跑的,whoops-home上有一个内网穿透了的nginx,集群流量都经过这个nginx转进来走traefik ingress controller。
链路大概这样:
域名流量->nginx(whoops-home)->traefik(nodeport)->pod
Nginx报504,那就是Nginx到traefik不通,现在nginx在whoops-home上,traefik在whoops-k3s上,查了下发现从whoops-home上ping不通whoops-k3s上的Pod,但是从whoops-k3s可以ping通whoops-home上的pod。
whoops-k3s上的flannel vxlan因为重启网络挂了?
原因分析
先来看看netfilter的FORWARD,没问题
iptables -t filter -nvL | grep FORWARD
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
看看路由, 也没问题,whoops-k3s是10.42.0.0/24网段,whoops-home是10.42.1.0/24网段。
default via 192.168.31.1 dev eth0
10.42.0.0/24 dev cni0 proto kernel scope link src 10.42.0.1
10.42.1.0/24 via 10.42.1.0 dev flannel.1 onlink
...
看看fdb? 不应该啊,whoops-k3s都能ping通whoops-home上的pod,arp要是有问题,咋ping出去的包,一看果然没问题。
sudo bridge fdb show | grep flannel.1
# 192.168.31.166 是 whoops-home
d6:f8:ec:13:3c:07 dev flannel.1 dst 192.168.31.166 self permanent
vxlan是走的flannel.1设备,这个设备是flanneld创建的,重启网络影响它了?但是如果配置不对,flanneld是不是应该自己感知调整回去呢?重启下k3s试试。
systemctl restart k3s
好了!重启k3s/flanneld,因为重配了flannel.1? 复现一下,特意检查flannel.1,网段配置、路由、arp、设备状态重启前后都没问题,重配重不配flannel.1应该不影响的啊,而且个人认为flanneld不应该这么不健壮,节点重启下network,整个节点的pod网络都挂掉了。
flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450
inet 10.42.0.0 netmask 255.255.255.255 broadcast 0.0.0.0
inet6 fe80::b45b:f1ff:fe24:82e4 prefixlen 64 scopeid 0x20<link>
ether b6:5b:f1:24:82:e4 txqueuelen 0 (Ethernet)
RX packets 237089 bytes 37524217 (35.7 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 174244 bytes 32444345 (30.9 MiB)
TX errors 29 dropped 5 overruns 0 carrier 29 collisions 0
抓包!
tcpdump -i flannel.1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on flannel.1, link-type EN10MB (Ethernet), capture size 262144 bytes
22:28:45.852513 IP 10.42.1.0 > 10.42.0.210: ICMP echo request, id 12, seq 48, length 64
22:28:46.872698 IP 10.42.1.0 > 10.42.0.210: ICMP echo request, id 12, seq 49, length 64
22:28:47.896618 IP 10.42.1.0 > 10.42.0.210: ICMP echo request, id 12, seq 50, length 64
22:28:49.851093 IP 10.42.1.0 > 10.42.0.210: ICMP echo request, id 13, seq 1, length 64
22:28:50.872665 IP 10.42.1.0 > 10.42.0.210: ICMP echo request, id 13, seq 2, length 64
22:28:51.896473 IP 10.42.1.0 > 10.42.0.210: ICMP echo request, id 13, seq 3, length 64
从whoops-home上的ping包到flannel.1了,但是没给到Pod网卡,丢哪了?重启网络操作到底干了啥?真的要研究kernel怎么实现的vxlan了么?debug flannel.1设备?
network.service
直接看/etc/rc.d/init.d/network脚本,看看重启网络做了哪些操作。
start)
apply_sysctl
...
stop)
sysctl -w net.ipv4.ip_forward=0 > /dev/null 2>&1
...
restart|force-reload)
cd "$CWD"
$0 stop
$0 start
...
好嘛,stop时候关了net.ipv4.ip_forward,flannel.1当然不把包往pod的网卡转了,重启k3s/flanneld,flanneld动态又把参数改回来了,所以就通了,复现验证一下,还真是。
搞不懂network.service stop为啥关这个,但是start时候也应该把之前的参数还回来吧?对不起,没有持久化的sysctl在start的apply_sysctl里还不回来。
修复搞定
echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf
验证一下,重启网络不影响Pod网络联通性了!
总结
之前特意研究了下flannel的vxlan模式,这次遇这么个case,又深刻了~