[TOC]
安装
kubenetes1.18.7
集群后,一次异常重启后, 在集群内访问ingress失败, 这篇文章仅记录处理问题过程。
kubernetes集群搭建
- 系统环境: Ubuntu 18.04.
主机名 | IP地址 |
---|---|
master0 | 192.168.0.118 |
master1 | 192.168.0.119 |
master2 | 192.168.0.26 |
server22 | 192.168.0.20 |
server500 | 192.168.0.24 |
我们生产环境, 采用sealos一键快速部署集群.
$ sealos init --master 192.168.0.118 \
--master 192.168.0.119 \
--master 192.168.0.26 \
--node 192.168.0.20 \
--node 192.168.0.24 \
--pkg-url /root/kube1.18.7.tar.gz \
--version v1.18.7 \
--passwd ubuntu --user root
ingress
是使用官方的nginx-ingress
, 默认是daemonst + hostnetwork
.
$ kubectl apply -f https://kuboard.cn/install-script/v1.15.2/nginx-ingress.yaml
问题发现,
查看ingress后, 发现server22上面的ingress pod始终无法访问 , 导致对于的宿主机也无法访问其80端口.
root@ubuntu:~# kubectl get pod -n nginx-ingress -owide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-ingress-ndxd9 1/1 Running 0 79m 10.1.117.216 server22
nginx-ingress-xw5bb 1/1 Running 0 25d 10.1.220.194 server500
在server22上, 发现一直hang在那里.
$ curl 127.0.0.1
在server500 上
root@ubuntu:~# curl 127.0.0.1
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.17.3</center>
</body>
</html>
排查思路
基于hostNetwork
网络实现的对外暴露端口, 其本质就是iptables
的DNAT
. 一开始业务人员反映是svc
访问不了, 导致整个排除进入ipvs
的排错. 经过定位, 才发现是宿主机到ingress的pod网络不通.
以下是简便的步骤.
ingress
主机是暴露80端口, 所以查找关键字80即可. 这里可以看到, 到pod的网段10.1.117.194
的流量全部到CNI-DN-a2617edac93cc96942325
这条自定义规则上, 而且生成了三类规则. 其中有两条是重复的, 一条是新的.
$ iptables-save |grep -w 80
-A CNI-DN-0405c966411786b4a6079 -s 10.1.117.194/32 -p tcp -m tcp --dport 80 -j CNI-HOSTPORT-SETMARK
-A CNI-DN-0405c966411786b4a6079 -s 127.0.0.1/32 -p tcp -m tcp --dport 80 -j CNI-HOSTPORT-SETMARK
-A CNI-DN-0405c966411786b4a6079 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.1.117.194:80
-A CNI-DN-9c176252e9af1b9ec0d79 -s 10.1.117.216/32 -p tcp -m tcp --dport 80 -j CNI-HOSTPORT-SETMARK
-A CNI-DN-9c176252e9af1b9ec0d79 -s 127.0.0.1/32 -p tcp -m tcp --dport 80 -j CNI-HOSTPORT-SETMARK
-A CNI-DN-9c176252e9af1b9ec0d79 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.1.117.216:80
: 也就是这三条规则. 10.1.117.194 这个ip的pod已经被销毁了, 所以访问注定就不成功
-A CNI-DN-a2617edac93cc96942325 -s 10.1.117.194/32 -p tcp -m tcp --dport 80 -j CNI-HOSTPORT-SETMARK
-A CNI-DN-a2617edac93cc96942325 -s 127.0.0.1/32 -p tcp -m tcp --dport 80 -j CNI-HOSTPORT-SETMARK
-A CNI-DN-a2617edac93cc96942325 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.1.117.194:80
: 其实真正生效的就是这个规则, iptables的优先匹配.
-A CNI-HOSTPORT-DNAT -p tcp -m comment --comment "dnat name: \"k8s-pod-network\" id: \"67a31caecdf4bd8f176f3935263e4a3b309f56b0f2b25bb05352dc67de463cea\"" -m multiport --dports 80,443 -j CNI-DN-a2617edac93cc96942325
-A CNI-HOSTPORT-DNAT -p tcp -m comment --comment "dnat name: \"k8s-pod-network\" id: \"1305c56a786475d02cec2ddea98d3445bf8329fe6de5ac5adcb203f5932f8bfd\"" -m multiport --dports 80,443 -j CNI-DN-0405c966411786b4a6079
-A CNI-HOSTPORT-DNAT -p tcp -m comment --comment "dnat name: \"k8s-pod-network\" id: \"8b83153a6c417bcf7f5a5f73d1725593c318b6afc807ff93b40f1caf76b21051\"" -m multiport --dports 80,443 -j CNI-DN-9c176252e9af1b9ec0d79
纵观其他主机server500
的规则. 只有一条CNI-HOSTPORT-DNAT
-A CNI-HOSTPORT-DNAT -p tcp -m comment --comment "dnat name: \"k8s-pod-network\" id: \"4d3b483f886a775ce60fc3482c308aea1a5ba0b876ca8126a02562cf29ade9a2\"" -m multiport --dports 80,443 -j CNI-DN-4d0339c362ca90c577adb
对比后, 很明显的发现, 10.1.117.194
这个是老pod的ip. 应该是这个pod生命周期消失后, iptables规则没有自动去除, 新生成的10.1.117.216
pod的iptables规则添加后, 又被覆盖.
解决
知道了问题所在, 那么解决方法也很简单
$ iptables-save > iptables.20201215
## 删除无用的规则.
$ sed -i '/CNI-DN-a2617edac93cc96942325/d' iptables.20201215
$ sed -i '/CNI-DN-0405c966411786b4a6079/d' iptables.20201215
$ iptables-restore < iptables.20201215