问题描述
某个服务无法通过节点 IP 访问,具体表现为:
curl 192.168.31.32:32642/metrics
- 连接失败curl 192.168.31.61:32642/metrics
- 连接失败
具体错误信息
shell
Failed to create pod sandbox: plugin type="flannel" failed (add):
failed to set bridge addr: "cni0" already has an IP address different from 10.244.1.1/24
验证服务
查看服务是否正常
shell
root@master-node1:~# kubectl get svc -A | grep dcgm
exporter dcgm-exporter ClusterIP 10.103.86.191 <none> 9400/TCP 21h
exporter dcgm-exporter-nodeport NodePort 10.103.10.199 <none> 9400:32642/TCP 4h17m
root@master-node1:~# kubectl get pods -n exporter -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dcgm-exporter-lxcch 1/1 Running 0 3h22m 10.244.0.8 edge-node1 <none> <none>
查看iptables路由规则是否创建
shell
root@edge-node1:~# iptables -t nat -L KUBE-NODEPORTS | grep 32642
KUBE-EXT-KESVHFWXM5EP343O tcp -- anywhere anywhere /* exporter/dcgm-exporter-nodeport:metrics */ tcp dpt:32642
这条规则表示接收来自任何地址、发往本机32642
端口的所有 TCP 流量转发到后端的 dcgm-exporter Pod。
但是明明有iptables规则连接却被拒绝
先排除法将service转发到本机,从本机发起请求,这样可以绕过nodeport的iptables规则,然后验证是否可以请求,port-forward使用apiserver代理直接与pod通信。
shell
root@master-node1:~# kubectl port-forward -n exporter svc/dcgm-exporter-nodeport 9400:9400
请求可以正常响应说明端口转发工作正常,服务本身没问题。问题还是在 NodePort 的路由。
查看iptables规则转发最终的位置
shell
root@edge-node1:~# iptables -t nat -L KUBE-SEP-2EUH5K5MZAUPM34C
Chain KUBE-SEP-2EUH5K5MZAUPM34C (1 references)
target prot opt source destination
KUBE-MARK-MASQ all -- 10.244.0.12 anywhere /* exporter/dcgm-exporter-nodeport:metrics */
DNAT tcp -- anywhere anywhere /* exporter/dcgm-exporter-nodeport:metrics */ tcp to:10.244.0.12:9400
可以看到最终是路由到10.244.0.12:9400
, 然后在node节点尝试 ping -c 2 10.244.0.12
发现无法ping通
shell
Error: PING 10.244.0.12 (10.244.0.12) 56(84) bytes of data.
From 10.244.0.1 icmp_seq=1 Destination Host Unreachable
From 10.244.0.1 icmp_seq=2 Destination Host Unreachable
--- 10.244.0.12 ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1005ms
pipe 2
这样来看就是cni出现了问题...我本地环境使用的是flannel, 接下来就是检查flannel的配置和状态
shell
root@edge-node1:~# ip addr show flannel.1
flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default
link/ether f6:8a:62:59:d7:4e brd ff:ff:ff:ff:ff:ff
inet 10.244.1.0/32 scope global flannel.1
查询节点的cidr范围
shell
root@master-node1:~# kubectl get nodes -o jsonpath='{.items[*].spec.podCIDR}'
10.244.1.0/24 10.244.0.0/24
这里就发现了问题
edge-node1 有 flannel.1 接口,IP 是 10.244.1.0/32,Pod CIDR 是 10.244.1.0/24
master-node1 的 Pod CIDR 是 10.244.0.0/24
dcgm-exporter Pod IP 是 10.244.0.12,运行在 edge-node1 上,但它应该获得 10.244.1.x 的 IP
这里出现问题的原因是 Pod IP 分配冲突导致的。
问题修复
bash
# 检查当前cni0网桥配置(子节点)
ip addr show cni0
# 删除冲突的网桥(子节点)
ip link del cni0
# 重启kubelet服务重新初始化网络(子节点)
systemctl restart kubelet
# 删除并重新创建Pod
kubectl delete pod dcgm-exporter-xxx -n exporter
步骤 3: 验证修复
bash
# 等待Pod重新创建并检查IP
kubectl get pods -n exporter -o wide
# 验证NodePort访问
curl http://192.168.31.32:32642/metrics
curl http://192.168.31.61:32642/metrics
修复结果
shell
# 查看 pod ip
root@master-node1:~# kubectl get pods -n exporter -o wide dcgm-exporter-lxcch
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dcgm-exporter-lxcch 1/1 Running 0 3h52m 10.244.1.8 edge-node1 <none> <none>
测试 api 从任意 node ip 都可以发起请求