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 -lntp、curl 127.0.0.1 |
| Pod 内网络层 | DNS、路由、连通性是否正常 | nslookup、ping、nc |
| 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 个问题:
- 名字能不能解析
- 端口能不能连通
- 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是否正确port与targetPort是否匹配- 类型是不是你期望的
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 使用抓包、连通性测试与链路视角排查问题
当 get、describe、logs 还不能解释问题时,就要进入“验证现场”阶段。
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 注入调试容器
当业务镜像过于精简,没有 curl、dig、tcpdump、ss 等工具时,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、抓包与链路验证
把问题放回一整条请求路径里看,定位速度会比“看到超时就怀疑网络插件”快得多。
📝 版权声明:本文为原创技术博客,转载请注明出处。
如文章中存在错误或不准确之处,欢迎在评论区指正,感谢您的阅读与支持!