Go应用需确保Pod标签、Service的targetPort与Ingress中service.name及pathType三者严格匹配:Go监听端口须与targetPort一致(如8080),Service selector须精确匹配Pod标签,Ingress需正确配置service.name、pathType和ingressClassName,并提供健康检查接口。

Go 应用本身不“部署 Ingress”,Ingress 是 Kubernetes 集群级资源,和你的 main.go 无关;真正要做的,是让 Go 服务能被 Ingress Controller(比如 ingress-nginx)正确发现、健康探测、并转发流量——这取决于三处配置是否严丝合缝:Pod 标签、Service 的 targetPort、Ingress 中的 service.name 和 pathType。
Go 服务监听端口必须和 Service 的 targetPort 完全一致
这是 404 或连接拒绝最常发生的根源。Ingress Controller 不会修改请求目标端口,它只把流量打到 Service 的 port,再由 kube-proxy 转发到 Pod 的 targetPort,最终抵达 Go 进程监听地址。
- Go 代码里写的是
http.ListenAndServe(":8080", handler)→ Service 的targetPort必须是8080(数字或字符串均可),不能是80或留空 - 若用
ListenAndServeTLS(":443", ...),Service 必须显式暴露targetPort: 443,且 Ingress YAML 中需包含tls字段并绑定有效证书 - 避免监听
127.0.0.1:8080—— 这会导致 Service 无法从集群内访问 Pod,必须用:8080或0.0.0.0:8080 - 建议在 Go 启动时打印监听地址:
log.Printf("listening on %s", os.Getenv("PORT")),并在 Deployment 中统一通过env: [{name: PORT, value: "8080"}]注入
Service 必须是 ClusterIP 类型且 selector 精确匹配 Pod 标签
Ingress 只能路由到 Service,不能直连 Pod。而 Service 要能选中你的 Go Pod,标签必须完全对齐。
- Deployment 中 Pod template 的
metadata.labels必须包含稳定键值,如app: my-go-api - Service 的
spec.selector必须一字不差地复现该键值:app: my-go-api;拼错、大小写不一致、多空格都会导致Endpoints为空 - Service 类型严禁设为
NodePort或LoadBalancer—— Ingress 不关心这些端口,它们反而可能干扰调试 - 验证方式:
kubectl get endpoints my-go-service,输出中应有 IP:PORT 列表;若为空,说明 selector 没匹配上
Ingress YAML 中 service.name 和 pathType 容易写错
即使前两步都对了,Ingress 资源本身写错字段也会导致 404。Kubernetes v1.19+ 默认使用 networking.k8s.io/v1,字段名和语义已变更。
-
spec.rules.http.paths.backend.service.name必须等于 Service 的metadata.name(不是 Deployment 名,也不是容器名),大小写敏感 -
pathType必须显式声明:Prefix(前缀匹配)、Exact(精确匹配)或ImplementationSpecific;默认不填在某些版本下行为未定义 - 若用
path: "/api"+pathType: Prefix,它会匹配/api、/api/、/api/users,但不会匹配/apis - 必须指定
ingressClassName: nginx(或你实际安装的控制器名),尤其当集群存在多个 Ingress Controller 时,缺省值不再自动 fallback
健康检查失败会导致流量被静默剔除
Ingress Controller(如 ingress-nginx)会主动向 Service 的 targetPort 发起 GET 请求探测健康状态,默认路径是 /healthz 或 /。返回非 2xx 就会把后端 Pod 从 upstream 摘掉。
- 不要依赖
livenessProbe替代它——后者探测的是 Pod IP + containerPort,前者走的是 Service ClusterIP + targetPort - 最简实现:
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) }) - 如果 Ingress 配了
path: /api且启用了rewrite-target,健康检查仍走根路径,不受重写影响,所以/healthz必须在 Go 服务中直接响应 - 可通过
kubectl logs -n ingress-nginx deploy/ingress-nginx-controller | grep healthz查看探测日志和返回码
最常被忽略的一点:Ingress Controller 本身必须已就绪且对外暴露了 IP。用 kubectl get svc -n ingress-nginx 确认 ingress-nginx-controller Service 有 EXTERNAL-IP(云环境)或至少分配了 CLUSTER-IP(裸机环境需配合 hostNetwork 或 NodePort)。没有这个前提,Ingress 规则再正确也收不到任何流量。

















