K8S nginx 运行正常但 curl 访问 Connection refused 如何解决?

文章导读
这种情况通常是 Service 的 targetPort 与容器实际监听端口不一致,或者 Nginx 只监听了容器内的 127.0.0.1 导致外部无法访问。
📋 目录
  1. A 命令速用版
  2. B 为什么会这样
  3. C 分步处理
  4. D 怎么验证是否生效
  5. E 常见坑
  6. F 参考来源
A A

这种情况通常是 Service 的 targetPort 与容器实际监听端口不一致,或者 Nginx 只监听了容器内的 127.0.0.1 导致外部无法访问。

先说结论:优先检查 Service 定义中的 targetPort 是否与容器内 Nginx 监听端口一致,并确认 Nginx 配置未绑定 localhost。

  • 先确认:Pod 状态为 Running 不代表网络可达,需检查端口监听情况
  • 先处理:修正 Service 端口映射或 Nginx listen 配置
  • 再验证:从集群内部和外部分别测试连通性

命令速用版

# 查看 Pod 所在节点和 IP
kubectl get pod <pod-name> -o wide

# 进入容器内部检查监听端口
kubectl exec -it <pod-name> -- netstat -tunlp

# 查看 Service 端口映射
kubectl get svc <svc-name> -o yaml

为什么会这样

Kubernetes 中 Pod 就绪(Ready)仅表示存活探针通过,不保证网络端口正确开放。Connection refused 通常意味着请求到达了目标 IP,但目标进程没有在该端口监听。常见原因包括 Service 的 targetPort 写错了,或者 Nginx 配置文件里写死了 listen 127.0.0.1:80,导致只接受容器内部请求,拒绝来自 Service 网桥的流量。

分步处理

1. 检查容器内实际监听端口

使用 exec 进入容器,确认 Nginx 到底监听的是哪个端口和地址。

kubectl exec <pod-name> -- cat /etc/nginx/nginx.conf | grep listen

如果看到 listen 127.0.0.1:80;,需要改为 listen 80;listen 0.0.0.0:80;

2. 核对 Service 端口配置

查看 Service 的 targetPort 是否匹配容器端口。

K8S nginx 运行正常但 curl 访问 Connection refused 如何解决?
kubectl describe svc <svc-name>

关注 Port 和 TargetPort 字段。TargetPort 必须等于容器内 Nginx 监听端口。

3. 检查 Endpoint 是否关联

如果 Service 没有关联到 Pod,流量无法转发。

kubectl get endpoints <svc-name>

如果 ENDPOINTS 为空,检查 Pod 的 label 是否与 Service 的 selector 匹配。

怎么验证是否生效

集群内验证:创建一个临时 busybox Pod,尝试 curl Service 名称。

kubectl run -it `--rm` debug `--image`=busybox `--restart`=Never -- curl http://<svc-name>

集群外验证:如果是 NodePort 或 LoadBalancer,使用节点 IP 或外部 IP 测试。

curl -v http://<node-ip>:<node-port>

如果返回 HTTP 200 或 301/302 且无 Connection refused,则修复成功。

常见坑

  • 容器端口定义缺失:Deployment yaml 中 containers.ports 未定义,虽不影响运行,但会影响部分网络策略工具识别。
  • readinessProbe 误判:探针配置了错误的端口或路径,导致 Pod 状态 Ready 但实际服务未启动。
  • NetworkPolicy 限制:集群启用了网络策略,默认拒绝所有入站流量,需显式允许。

参考来源