深色模式
集群网络故障定位
摘要:本文面向生产 SRE / 网络工程师,覆盖 Kubernetes 数据面最常见的四类故障:Service 无端点、CoreDNS 解析失败、NetworkPolicy 误阻断、kube-proxy/CNI 异常。给出从控制面(Service/Endpoint/Policy)到数据面(Pod/节点/抓包)的系统化定位步骤。覆盖版本:Kubernetes v1.28+(kube-proxy
nftables模式于 v1.33 stable,本文以iptables/ipvs通用行为说明)。
适用版本与前提
- Kubernetes:v1.28+。
- 工具:
kubectl、kubectl debug node/<node>、netshoot(nicolaka/netshoot)镜像、crictl、tcpdump/iptables。 - 前提:了解 CNI 厂商差异(Calico/Cilium/Flannel 行为不同,排障前先确认你的 CNI 与版本)。
背景与问题
Kubernetes 只定义网络模型、不自带实现,连通性由 CNI 提供(来源:Kubernetes 官方文档 - Cluster Networking)。这带来一个后果:「能通但说不清为什么」是网络排障的常态,必须同时检查控制面(Service/EndpointSlice/NetworkPolicy)与数据面(CNI/kube-proxy/节点路由/防火墙)。
厂商差异提醒
iptables/ipvs 模式由 kube-proxy 负责;Cilium/eBPF 模式由 CNI 直接接管,不依赖 kube-proxy 的 iptables 链。排障前先用 kubectl get configmap kube-proxy -n kube-system -o yaml | grep mode 确认模式,否则会查错对象。
排障决策树
清单 1:Service 无端点(EndpointSlice 为空)
- 现象:Pod
Running但其它 Pod 经 Service 访问超时;curl直连 Pod IP 却正常。 - 原因:Service 的
selector与 Podlabels不匹配(如app: apivsapp: api-server);Pod 未就绪(readiness 失败);targetPort与容器监听端口不一致。 - 定位:bash
kubectl get endpointslices -l kubernetes.io/service-name=my-svc -n app kubectl get svc my-svc -n app -o jsonpath='{.spec.selector}' kubectl get pods -n app --show-labels # 直连 Pod 绕过 Service 验证应用本身 kubectl port-forward pod/my-pod 8080:8080 -n app1
2
3
4
5 - 修复:修正 selector 拼写或
targetPort;确认 PodREADY列全为1/1。 - 回滚:改回原 Service 定义:
kubectl apply -f svc-prev.yaml。
清单 2:CoreDNS 解析失败
- 现象:
nslookup my-svc.app.svc.cluster.local返回NXDOMAIN/SERVFAIL/超时。 - 原因:CoreDNS Pod 崩溃、配置错误(如
loop插件检测到转发回自身)、上游 resolver 不可达、resolv.conf中nameserver非 kube-dns ClusterIP。 - 定位:bash
kubectl get pods -n kube-system -l k8s-app=kube-dns kubectl logs -n kube-system -l k8s-app=kube-dns --tail=50 kubectl get endpointslice -l kubernetes.io/service-name=kube-dns -n kube-system # 集群内起临时 Pod 测 DNS kubectl run dnsutils --rm -it --image=registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3 \ --restart=Never -- nslookup kubernetes.default kubectl exec dnsutils -- cat /etc/resolv.conf1
2
3
4
5
6
7 - 修复:CoreDNS 崩溃先
kubectl rollout restart deployment coredns -n kube-system;loop错误需改 Corefile 上游(来源:Kubernetes 官方文档 - Debugging DNS Resolution);外部域名失败查 Corefile 的forward上游。 - 回滚:Corefile 改动前
kubectl -n kube-system get configmap coredns -o yaml > coredns-cm.bak。
优化
Pod 默认 options ndots:5 会把短名当 FQDN 反复向上递归,造成 DNS 抖动。对 DNS 敏感服务可显式降 ndots:
yaml
spec:
dnsConfig:
options:
- name: ndots
value: "2"1
2
3
4
5
2
3
4
5
清单 3:NetworkPolicy 误阻断
- 现象:连通性时好时坏,或与某策略上线时间吻合。
- 原因:一旦命名空间存在 NetworkPolicy,CNI 即实施「默认拒绝」入向模型;一条
policyTypes: [Ingress]无规则即阻断全部入向。 - 定位:bash
kubectl get networkpolicies -A kubectl describe networkpolicy <name> -n <ns>1
2 - 修复:临时放宽策略验证,确认后补最小放行规则(如仅放行业务前端 Pod 的 8080)。
- 回滚:保留策略原 YAML,验证后
kubectl apply还原。
注意
Cilium 等 eBPF CNI 提供被阻断流量的可观测性,远比 iptables 模式易定位。若频繁因策略排障,建议启用 CNI 的 policy 审计/metrics。
清单 4:节点/数据面排查与抓包
- 现象:Pod 间直接 IP 不通,或 Service 有端点但仍不通。
- 定位:用
netshoot起调试 Pod 抓包:bashkubectl run netshoot --rm -it --image=nicolaka/netshoot --restart=Never -- \ tcpdump -i eth0 -n host 10.244.1.5 # 节点层查路由与 NAT 规则(需节点权限) kubectl debug node/<node> -it --image=busybox -- chroot /host sh # 在 /host 内: iptables -t nat -L KUBE-SERVICES -n -v1
2
3
4
5 - 修复:CNI 异常重启对应插件 DaemonSet;kube-proxy 异常
kubectl rollout restart -n kube-system daemonset/kube-proxy。 - 回滚:DaemonSet 重启可逆;CNI 配置变更前务必备份
/etc/cni/net.d/。
生产危险
节点层执行 iptables -F 或清空 CNI 规则会瞬间切断全节点网络,绝对禁止。任何 iptables/CNI 改动前先 iptables-save > iptables.bak 并确认可在节点控制台还原。