编程 记一次 K8s 503 排障:Ingress backend 端口写成 targetPort,Ingress-NGINX 只给 Warning 不给 Error

2026-09-03 00:04:09

记一次 K8s 503 排障:Ingress backend 端口写成 targetPort,Ingress-NGINX 只给 Warning 不给 Error

现象

Pod 健康、Service 端口看着也正常,但客户端经 Ingress 访问持续 503。按常规思路查了 3 小时,没头绪。

根因

Ingress backend.service.port.number 引用的必须是 Service 的 port(对外暴露端口),不是 targetPort(Pod 容器端口)。常见写法是 port: 80, targetPort: 8080,若 Ingress 里把后端端口误写成 8080,Ingress Controller 在 Service 里找不到对应端口时不会报 Error,只在日志里写一条 Warning,然后默默 fallback——选第一个可用端口来转发。

小流量或内网探测可能"碰巧通了",一旦请求量上来就持续 503。Service 端口的匹配失败被 fallback 掩盖,是这次排障耗时的主要原因。

关键认知

  • Ingress Controller 很少报 Error,大量异常以 Warning 形式出现。排查时要主动搜日志里的 W 开头行,重点抓 not foundfalling backerror syncing
  • rewrite-target annotation 只负责路径重写,和端口问题无关。端口写错时 Controller 连 Service 端口都找不到,而路径重写发生在路由匹配之后,根本执行不到。
  • 不要把 Service 改成 LoadBalancer 试——浪费 LB 费用,问题不在 Service 类型。
  • 也别怀疑 DNS 去改 /etc/hosts——Ingress 对外访问链路不依赖 Pod 所在节点的 hosts 解析。

排障 checklist

# 1. 确认 Service 的 port 与 targetPort 实际取值
kubectl get svc  -o yaml

# 2. 对比 Ingress 里 backend.service.port.number
kubectl get ingress  -o yaml
# 该值必须等于 Service 的 port,不是 targetPort

# 3. 核对 Service 名字拼写是否与 Ingress 引用一致
kubectl get svc

# 4. 确认 IngressClass 与 Controller 匹配
kubectl get ingressclass
# 检查 Ingress 的 ingressClassName 字段是否指向实际部署的 Controller

# 5. 看 Controller Pod 本身是否健康
kubectl get pods -n ingress-nginx

# 6. 重点搜日志关键词
kubectl logs -n ingress-nginx deploy/ingress-nginx-controller --tail=500 | grep -iE "falling back|error syncing|not found"

修复

把 Ingress 中 backend.service.port.number 从 8080 改为 80——即 Service 的 port

spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name:
port:
number: 80   # Service port,不是 targetPort

改完等待 Controller 重新同步,503 即恢复。

弯路记录

这次排障多花的时间主要在两步:一是盯着 Ingress 日志里的 E 开头的 Error 行看,什么都没抓到;二是把 Service 的 targetPort 当成"正确端口"反复核对 Ingress 配置,方向反了。最终是随手 grep "Warning" 看到 falling back 才定位到问题——注意日志中 W 开头行里带 falling back 的那条,会明确写出找不到指定端口、回退到第一个可用端口的行为。

推荐文章

程序员茄子在线接单