返回首页

9.3 网络故障排查

Kubernetes 网络问题之所以难排查,是因为同一个“访问失败”现象,可能落在完全不同的层面:Pod 自身没有监听端口、Service 没选到后端、DNS 解析异常、NetworkPolicy 拦截、Ingress 转发错误,甚至 kube-proxy 或节点网络插件异常。Kubernetes 网络模型要求 Pod 之间通常可以直接通信,Service 负责提供稳定的访问入口,而后端 Pod 的实际端点信息则通过 EndpointSlice 进行表达::cite[391]。

9.3.1 Pod 间通信失败如何分层定位

遇到“Pod A 无法访问 Pod B”时,建议不要一上来就怀疑 CNI,而是按照从内到外、从应用到链路的顺序分层检查。

推荐的五层排查法

层次 重点问题 典型命令
应用层 服务是否真的监听端口 ss -lntpcurl 127.0.0.1
Pod 内网络层 DNS、路由、连通性是否正常 nslookuppingnc
Service / 发现层 Service 与 EndpointSlice 是否正确 kubectl get svc,endpointslices
节点代理层 kube-proxy / iptables / IPVS 是否工作 kubectl logs、节点侧检查
集群网络层 CNI、跨节点路由、NetworkPolicy CNI 日志、抓包、策略检查

第一步:确认目标 Pod 自己是否正常

很多“网络问题”其实并不是网络故障,而是目标应用根本没监听端口,或者 readiness 没通过。

kubectl get pods -n prod -o wide
kubectl describe pod payment-abcde -n prod
kubectl logs payment-abcde -n prod
kubectl exec -it payment-abcde -n prod -- ss -lntp

如果目标进程没有监听 8080,那么后面的 Service、DNS、策略排查都没有意义。

第二步:从源 Pod 内做最小化验证

kubectl exec -it client-pod -n prod -- nslookup payment
kubectl exec -it client-pod -n prod -- nc -vz payment 8080
kubectl exec -it client-pod -n prod -- wget -S -O- http://payment:8080/healthz

这里要回答 3 个问题:

  1. 名字能不能解析
  2. 端口能不能连通
  3. HTTP 请求有没有响应

如果 nslookup 失败,优先去 DNS;如果能解析但连不上,优先去 Service / Endpoint / NetworkPolicy;如果能连上但返回 5xx,就更像应用问题。

第三步:必要时直接访问 Pod IP

kubectl get pod payment-abcde -n prod -o wide
kubectl exec -it client-pod -n prod -- nc -vz 10.244.1.25 8080

这一步非常有价值:

  • Pod IP 能通,Service 不通:优先检查 Service、EndpointSlice、kube-proxy
  • Pod IP 也不通:优先检查 NetworkPolicy、CNI、节点路由、目标应用监听

9.3.2 Service 不通时应该检查什么

Kubernetes 官方的 Service 调试文档给出的核心思路很清晰:先确认 Pod 是否健康,再确认 Service 是否选择到了正确后端,最后检查代理链路是否把流量真正送到了 Pod::cite[298]。

标准检查顺序

1)看 Service 定义本身

kubectl get svc payment -n prod -o yaml
kubectl describe svc payment -n prod

重点检查:

  • selector 是否正确
  • porttargetPort 是否匹配
  • 类型是不是你期望的 ClusterIP / NodePort / LoadBalancer

2)看后端端点是否存在

Kubernetes v1.32 中,Service 的后端主要通过 EndpointSlice 表达,因此 Service 不通时,必须检查是否真的生成了对应端点::cite[455]。

kubectl get endpointslices -n prod -l kubernetes.io/service-name=payment
kubectl describe endpointslices -n prod -l kubernetes.io/service-name=payment

常见异常包括:

  • 没有任何 EndpointSlice
  • EndpointSlice 有对象,但没有 endpoint
  • 端点 IP 正常,但端口号错误
  • 端点存在但 Pod 没 Ready

3)核对 Pod 标签与 readiness

kubectl get pods -n prod -l app=payment --show-labels
kubectl describe pod payment-abcde -n prod

如果标签选不中,Service 就没有后端;如果 readiness probe 失败,Pod 即使在运行,也不会加入可用后端集合。

4)怀疑 kube-proxy 时要看代理层

Service 的虚拟 IP 背后,本质上依赖 kube-proxy 或等价实现去把流量转到真实端点。官方文档指出,在 iptables 模式下,kube-proxy 会为 Service 与其后端端点生成相应的内核规则表项::cite[456]。

这时你可以先做 Kubernetes 侧检查:

kubectl get pods -n kube-system -o wide
kubectl logs -n kube-system -l k8s-app=kube-proxy

如果问题集中在某一个节点,往往要进一步进入节点侧检查 kube-proxy 与数据面规则。

9.3.3 DNS 异常、网络策略冲突与入口流量问题

一、DNS 异常怎么查

官方 DNS 调试文档建议先创建或使用一个测试 Pod,验证集群内常见域名能否解析,然后再检查 DNS Pod、DNS Service 以及容器内的 /etc/resolv.conf::cite[285]。

kubectl exec -it client-pod -n prod -- cat /etc/resolv.conf
kubectl exec -it client-pod -n prod -- nslookup kubernetes.default
kubectl exec -it client-pod -n prod -- nslookup payment.prod.svc.cluster.local
kubectl get pods -n kube-system
kubectl logs -n kube-system -l k8s-app=kube-dns

重点看:

  • nameserver 是否指向集群 DNS
  • search domain 是否包含 <ns>.svc.cluster.local
  • CoreDNS Pod 是否重启异常
  • DNS Service 是否存在

二、NetworkPolicy 冲突怎么查

Kubernetes v1.32 的 NetworkPolicy 语义有一个非常关键的点:策略之间不是互相覆盖,而是叠加求并集。也就是说,只要某个方向上有策略开始生效,允许的流量就是所有匹配策略共同允许的那部分,而不是“最后一条规则覆盖前面规则”::cite[390]。

这意味着排查策略问题时,不能只看一条 YAML,要看:

  • 目标 Pod 是否被某些策略选中
  • 来源 Pod 是否满足 podSelector / namespaceSelector
  • 目标端口是否在允许范围内
  • 是入口方向被拦,还是出口方向被拦

推荐命令:

kubectl get networkpolicy -A
kubectl describe networkpolicy allow-payment -n prod
kubectl get pod client-pod -n prod --show-labels
kubectl get pod payment-abcde -n prod --show-labels

三、入口流量问题怎么查

当集群内直接访问 Pod 或 Service 正常,但从 Ingress / LoadBalancer 访问异常时,排查焦点应该切到入口层:

  • 域名是否正确解析到入口地址
  • Ingress 规则的 host / path 是否匹配
  • TLS 证书是否有效
  • Ingress Controller 是否能转发到正确 Service
  • Service 后端是否真的 Ready

可以先从 Kubernetes 对象侧入手:

kubectl get ingress -A
kubectl describe ingress payment-gateway -n prod
kubectl get svc payment -n prod
kubectl get endpointslices -n prod -l kubernetes.io/service-name=payment

一个很常见的现象是:

  • Ingress 规则存在
  • Service 也存在
  • 但后端 Pod readiness 失败

最终用户看到的只是 502/504,但真正根因仍在后端可用性。

9.3.4 使用抓包、连通性测试与链路视角排查问题

getdescribelogs 还不能解释问题时,就要进入“验证现场”阶段。

1)连通性测试:先做最小闭环

kubectl exec -it client-pod -n prod -- nc -vz payment 8080
kubectl exec -it client-pod -n prod -- wget -S -O- http://payment:8080/healthz
kubectl exec -it client-pod -n prod -- curl -v http://10.244.1.25:8080/healthz

通过不同目标做测试:

  • 测 Service 名称
  • 测 Service ClusterIP
  • 测 Pod IP
  • 测域名入口

这样可以快速判断故障卡在服务发现、虚拟 IP、真实 Pod,还是入口网关。

2)用 kubectl debug 注入调试容器

当业务镜像过于精简,没有 curldigtcpdumpss 等工具时,Kubernetes v1.32 推荐通过 kubectl debug 补充交互式调试能力::cite[403]。

kubectl debug pod/client-pod -n prod -it --image=nicolaka/netshoot --target=app

进入后可执行:

dig payment.prod.svc.cluster.local
curl -v http://payment:8080/healthz
ip route
ss -lntp
tcpdump -ni any port 53 or port 8080

3)用“链路视角”替代“点状视角”

网络排障最容易犯的错误,是只盯一个对象,比如只盯 Service YAML,或者只看某个 Pod 日志。更高效的方式,是把一次请求拆成完整链路:

客户端 Pod
  -> DNS 解析
  -> Service VIP
  -> kube-proxy / 数据面规则
  -> EndpointSlice
  -> 目标 Pod IP:Port
  -> 应用进程

然后逐段问自己:

  • 这一段是否有证据证明它正常?
  • 这一段的输入和输出是否一致?
  • 问题第一次出现在哪一跳?

一个排查示例

假设 frontend 调用 payment 超时,可以按下面顺序走:

kubectl exec -it frontend-abcde -n prod -- nslookup payment
kubectl exec -it frontend-abcde -n prod -- nc -vz payment 8080
kubectl get svc payment -n prod
kubectl get endpointslices -n prod -l kubernetes.io/service-name=payment
kubectl get pods -n prod -l app=payment -o wide
kubectl logs -n prod -l app=payment --all-containers=true

如果发现:

  • DNS 正常
  • Service 正常
  • EndpointSlice 为空

那么根因大概率就在:

  • selector 没选到 Pod
  • Pod 没 Ready
  • Pod 标签被改错

这就是典型的“表面是网络问题,实际是工作负载状态问题”。

本章小结

网络问题排查,核心不是去背某个 CNI 插件命令,而是掌握分层定位思路:

  • 先看目标应用是否真在监听
  • 再看 Pod 内解析与连通性
  • 再看 Service 与 EndpointSlice
  • 再看 NetworkPolicy、DNS、Ingress
  • 必要时升级到 kubectl debug、抓包与链路验证

把问题放回一整条请求路径里看,定位速度会比“看到超时就怀疑网络插件”快得多。


📝 版权声明:本文为原创技术博客,转载请注明出处。

如文章中存在错误或不准确之处,欢迎在评论区指正,感谢您的阅读与支持!

上一篇

9.2 常见 Pod 异常排查

下一篇

4.2 CNI 插件选型