按理说到这一步Calico网络插件应该可以正常工作了,但我这里有一个节点的容器一直 Error 和 CrashLoopBackOff,查看一下 Pod 状态 和 Pod 日志:
1662517111449.jpg
从上面日志报出的问题可以看出是访问 :
https://10.0.0.1:443/api/v1/namespaces/kube-system/pods/kube-flannel-ds-kw2bh 的时候超时了,然后我就切换到报错这个k8s-node01~02主机上,试着手动访问一下:
$ curl --connect-timeout 10 https://10.0.0.1:443/api/v1/namespaces/kube-system/pods/kube-flannel-ds-kw2bh
curl: (28) Connection timed out after 10002 milliseconds
可以看到的确是超时的。。所以现在要找一下超时的原因了。
试着 ping 一下 10.0.0.1:
$ ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.138 ms
^C
--- 10.0.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.138/0.138/0.138/0.000 ms
也是 OK 的,证明 ping
的 ICMP
数据包是可以正常来回的,但 curl HTTP
数据包就不知道了,但至少确定了不是 10.0.0.1 这个目标地址的问题。
现在只能抓一下包了,打开一个窗口,执行 tcpdump -i eth0 host 10.0.0.1 -n
进行监听,然后在另一个窗口执行 curl https://10.0.0.1:443/api/v1/namespaces/kube-system/pods/kube-flannel-ds-kw2bh,此时 tcpdump
抓取到的报文如下:
$ tcpdump -i eth0 host 10.0.0.1 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
18:04:36.404311 IP 10.0.0.1.45998 > 192.168.0.181.sun-sr-https: Flags [S], seq 479485038, win 65495, options [mss 65495,sackOK,TS val 3269988560 ecr 0,nop,wscale 7], length 0
18:04:37.440153 IP 10.0.0.1.45998 > 192.168.0.181.sun-sr-https: Flags [S], seq 479485038, win 65495, options [mss 65495,sackOK,TS val 3269989596 ecr 0,nop,wscale 7], length 0
...
现在就来分析一下这个报文了:
- 首先,我是通过 curl 访问 10.0.0.1;
- 由于 10.0.0.1 这个地址是对 kube-apiserver 地址的代理,所以报文会被转发到 kube-apiserver,即 192.168.0.181;
- 而在上面抓取到的报文可以看出,报文转到 192.168.0.181 时源地址为 10.0.0.1,这就说明 192.168.0.181 回报文时也是直接会给 10.0.0.1 了;
- 而显然,回给 10.0.0.1 是不可取的,因为现在每个 Kubernetes Node 上都有一个 kube-apiserver 的代理地址,并且 kube-apiserver 所在主机并没有正确到到达 10.0.0.1 的路由;
- 而现在有一个 Kubernetes Node 是正常的,说明当前网络就把 10.0.0.1 这个地址绑定到了这个 Kubernetes Node,所以也就只有一个 Kubernetes Node 能够正常访问;
- 所以这个报文对于 k8s-node01~02 来说是处于一个只能出不能进的状态,那就当然超时了;
知道问题所在之处后,就有解决办法了。只要将从 Kubernetes Node
出去的报文的源地址改为 Kubernetes Node
本身的地址,而不是 10.0.0.1
就行了,这样响应报文就能正确从 kube-apiserver
所在主机响应到 Kubernetes Node
主机了。
在所有 Kubernetes Node
机器上,添加如下 SNAT
的 iptables
规则即可:
$ iptables -t nat -A POSTROUTING -s 10.0.0.1/32 -j MASQUERADE
然后,将其添加到 /etc/rc.local (避免以后重启开机后不在自运行)
$ chmod +x /etc/rc.d/rc.local && echo 'iptables -t nat -A POSTROUTING -s 10.0.0.1/32 -j MASQUERADE' >> /etc/rc.d/rc.local
户外题:如果安装 Flannel 插件,pod状态出现了Error掉,该如何处理呢?
答:Flannel 运行时指定使用的网卡,如 --iface=eth0
,修改 Flannel 部署的 YAML 文件在 Flannel 容器部分运行参数列表加上就行,如下:
containers:
- name: kube-flannel
image: registry.cn-shenzhen.aliyuncs.com/zze/flannel:v0.13.0
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --iface=eth0
- --kube-subnet-mg
在网上查找是有这个解决方案,不过这个方案对二进制部署k8s的起不到什么效果。如果还是不行,需要手动添加 SNAT
的 iptables
的规则。
网友评论