事故前言
有一个k8s的node节点上面的pod全部无法请求k8s集群以外的IP地址。只有一个节点上的pod全部有问题,其他节点的都是正常的。
排查过程
kubectl exec -it -n sc-microservice analysis-service-7cccbd6744-z6qqs -- curl -v https://www.baidu.com
kubectl exec -it -n sc-microservice analysis-service-7cccbd6744-z6qqs -- nslookup www.baidu.com通过curl得知dns解析是正常的。
kubectl logs -n kube-system kube-proxy-ddr22
kubectl logs -n kube-flannel kube-flannel-ds-sz9gt
通过日志发现Flannel网络组件日志dial tcp 10.96.0.1:443: i/o timeout发现存在连接问题。
kubectl delete pod -n kube-flannel kube-flannel-ds-sz9gt
kubectl delete pod -n kube-system kube-proxy-ddr22通过删除重建节点上面的kube-proxy 和flannel 解决了访问http://www.baidu.com的故障。发现更奇怪的问题,该节点的pod可以请求外网地址的http80请求,无法请求https443请求。
iptables -t nat -L -n | grep 443
[root@k8s-node01 ~]# iptables -t filter -L -n | grep 443
# Warning: iptables-legacy tables present, use iptables-legacy to see them
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443过通iptables -t filter -L -n | grep 443 发现一条其他node节点都没有的iptables请求,猜测应该是iptables规则污染导致的。
# 备份当前规则
mkdir -p /root/iptables_backup
iptables-save > /root/iptables_backup/iptables_rules_$(date +%Y%m%d_%H%M%S).bak
iptables-legacy-save > /root/iptables_backup/iptables_legacy_rules_$(date +%Y%m%d_%H%M%S).bak
# 清理常规iptables
iptables -F # 清空所有链的规则
iptables -X # 删除所有自定义链
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -t raw -F
iptables -t raw -X
iptables -t filter -F
iptables -t filter -X
# 清理legacy iptables
iptables-legacy -F
iptables-legacy -X
iptables-legacy -t nat -F
iptables-legacy -t nat -X
iptables-legacy -t mangle -F
iptables-legacy -t mangle -X
iptables-legacy -t raw -F
iptables-legacy -t raw -X
iptables-legacy -t filter -F
iptables-legacy -t filter -X
# 重启containerd(可能会导致容器短暂中断)
systemctl restart containerd
# 重启kubelet
systemctl restart kubelet
# 在控制节点上执行(或者有kubectl权限的任何机器上)
# 重启kube-proxy
kubectl delete pod -n kube-system $(kubectl get pods -n kube-system -o wide | grep kube-proxy|grep node01| awk '{print $1}')
# 重启flannel
kubectl delete pod -n kube-flannel $(kubectl get pods -n kube-flannel -o wide | grep flannel | grep node01 | awk '{print $1}')通过清理iptables规则和重启containerd、kubelet、kube-proxy、kube-flannel完成之后。测试curl恢复正常,问题修复。
总结
问题有两个:
kube-flannel出现网络问题导致无法请求外网。
iptables规则污染导致无法请求所有外部地址的443端口。