Go应用K8s网络不通时,先确认Pod是否真正联网:查IP、验回环、看默认路由;再验证Service是否关联Pod(用endpoints检查);接着排查NetworkPolicy是否拦截入站;最后tcpdump抓包定位TCP层问题。

Go 应用在 Kubernetes 中跑不通网络,不是代码写错了,大概率是 Pod 没拿到 IP、Service 没关联上 Pod、或者被 NetworkPolicy 拦住了——先别改 Go 代码,按层查。
确认 Go Pod 是否真的“联网成功”
很多人一看到 curl http://my-go-service 失败,就去翻 Go 的 HTTP 客户端配置。但更常见的问题是:Pod 根本没分配到 IP,或者连本地回环都不通。
进容器里直接验:
-
kubectl exec -it <go-pod-name> -- sh,然后执行ip addr—— 看eth0有没有 IPv4 地址;没有?kubectl describe pod里看 Events 是否有FailedCreatePodSandBox或 CNI 相关报错 - 执行
ping 127.0.0.1—— 不通?说明容器 runtime 层或镜像基础有问题(比如 distroless 镜像没ping,但cat /proc/sys/net/ipv4/ip_forward应该是 1) - 执行
ip route | grep default—— 默认路由必须指向eth0,否则出不去;如果指向了lo或空,基本是 CNI 配置漏了routes字段
验证 Service 到 Go Pod 的链路是否打通
Go 应用监听 :8080,但 Service 指向的 targetPort 写成 80,或者 selector 标签根本没打在 Pod 上,是最常踩的坑。
两步快速确认:
-
kubectl get endpoints <go-service-name>—— 如果输出里ENDPOINTS列为空,说明 Service 没匹配到任何 Pod;检查kubectl get pods -l <your-selector-key>=<value>是否真有 Pod -
kubectl port-forward service/<go-service-name> 8080:80(注意端口要对齐service.spec.ports[0].port),然后本地curl http://localhost:8080/healthz—— 成功?说明 Service → Pod 通,问题在 DNS 或跨命名空间访问;失败?看kubectl logs -n kube-system -l k8s-app=kube-proxy是否有no endpoints类日志
排查 NetworkPolicy 是否静默拦截
NetworkPolicy 默认放行所有流量,但一旦命名空间里部署了任意一条策略,就会变成“默认拒绝”。Go Pod 能连 DB,但连不了另一个 Go Service?很可能只开了出站,没开入站。
检查命令和关键点:
-
kubectl get networkpolicy -n <namespace>—— 有输出就要逐条看;特别注意spec.podSelector是否意外匹配了你的 Go Pod - 重点看
spec.ingress:如果没定义from,就是拒绝所有入站;如果定义了from.namespaceSelector却忘了加matchLabels,也可能导致同 namespace 的调用被拦 - 临时验证:删掉策略再试
curl;别用kubectl delete networkpolicy --all -n <ns>,而是精准删某一条,避免误伤
抓包定位 TCP 层卡点(Go 应用超时但无错误日志时必做)
Go 的 http.Client 默认超时是 30 秒,且不打印底层连接细节。如果 curl 也卡住,就得看真实数据包是否发出去、对方是否回 SYN-ACK。
推荐组合操作:
- 在 Go Pod 所在节点上运行:
kubectl debug node/<node-name> -it --image=nicolaka/netshoot -- tcpdump -i any host <go-pod-ip> and port 8080 -w /tmp/go.pcap - 同时在另一终端触发请求:
kubectl exec <client-pod> -- curl -v http://<go-service-name>:8080/healthz - 抓完后
kubectl cp下来用 Wireshark 看:有没有 SYN 发出?有没有收到 SYN-ACK?如果只有 SYN 没回包,问题在目标 Pod 的 iptables INPUT 链、kube-proxy 规则缺失、或目标 Pod 根本没监听该端口(netstat -tuln | grep 8080)
真正难缠的问题往往藏在 iptables 规则顺序、CNI 插件版本兼容性、或内核参数(比如 net.ipv4.tcp_tw_recycle 在跨 VPC 场景下会丢 ACK)里,这些没法靠改 Go 代码解决——得从 Node 层开始盯日志和配置。


















