记一次 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 found、falling back、error syncing。 rewrite-targetannotation 只负责路径重写,和端口问题无关。端口写错时 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 的那条,会明确写出找不到指定端口、回退到第一个可用端口的行为。