我不会起名字322· 后端 / 算法 / 数据库
📘 技术栈 | 🧩 力扣 Hot100 | 🐹 Go 项目 | 🟥 Redis | 🐬 MySQL
文章目录
- Ingress 404 与 503 分别意味着什么:3 层转发里的失败点
- 一、先把转发链路画出来
- 二、404:规则没匹配上
- 原因 1:host 不匹配
- 原因 2:path 匹配规则和你想的不一样
- 原因 3:IngressClass 不匹配
- 原因 4:多个 Ingress 冲突 / 规则没被加载
- 三、503:没有可用的后端
- 第一步永远是看 Endpoint
- 原因 1:selector 和 Pod 标签对不上
- 原因 2:Pod 没有 Ready
- 原因 3:端口对不上
- 原因 4:全部后端被摘除(滚动发布期间)
- 四、502:连上了但连接失败
- 五、一个完整的排查流程
- 六、带走物
Ingress 404 与 503 分别意味着什么:3 层转发里的失败点
一、先把转发链路画出来
Ingress 不是"一个组件",它至少跨三层:
外部流量 ↓ ① Ingress Controller(Nginx / Traefik / ALB) ↓ 按 host + path 匹配 Ingress 规则 ② Service(ClusterIP) ↓ 按 selector 找 Endpoint ③ Pod404 和 503 分别对应这条链路上不同的失败位置,这是排查的第一分水岭。
| 状态码 | 失败位置 | 含义 |
|---|---|---|
| 404 | ① Ingress 层 | 规则根本没匹配上,流量没离开 Controller |
| 503 | ② Service 层 | 规则匹配上了,但后端没有可用 Endpoint |
| 502 | ③ Pod 层 | 连上了 Pod 但连接失败/被提前关闭 |
记住这个映射,排查时能省一半时间。
二、404:规则没匹配上
404 说明 Ingress Controller收到了请求,但找不到要转发给谁。它压根没往后走。
原因 1:host 不匹配
spec:rules:-host:api.example.com# 只认这个 hosthttp:paths:-path:/pathType:Prefixbackend:service:name:api-svcport:{number:8080}如果你用curl http://<IP>/直接打 IP(不带 Host 头),host 是空的,不匹配任何规则 →404。
验证:
# 不带 Host → 404curl-ihttp://<ingress-ip>/# 带 Host → 正常curl-i-H"Host: api.example.com"http://<ingress-ip>/原因 2:path 匹配规则和你想的不一样
pathType有三个取值,行为差别很大:
| pathType | 行为 |
|---|---|
Exact | 完全相等才匹配 |
Prefix | 按路径前缀匹配(逐段,不是字符串前缀) |
ImplementationSpecific | 取决于 Controller 实现(Nginx 下是正则) |
Prefix是按/分段匹配的,不是字符串前缀:
path: /api Prefix ✅ /api 匹配 ✅ /api/v1 匹配 ❌ /apiary 不匹配(不是完整的一段)这一点经常导致"路径看着像前缀但就是 404"。
原因 3:IngressClass 不匹配
集群里有多个 Ingress Controller 时,必须指定 class:
metadata:annotations:kubernetes.io/ingress.class:nginx# 旧写法spec:ingressClassName:nginx# 新写法(推荐)没写或者写错了,这个 Ingress 会被 Controller 忽略,表现就是 404。
kubectl get ingressclass kubectl get ingress<name>-oyaml|grep-iclass原因 4:多个 Ingress 冲突 / 规则没被加载
# 看 Ingress 有没有被 Controller 认领(看 ADDRESS 字段有没有值)kubectl get ingress-A# 看 Controller 日志里的 reloadkubectl logs-ningress-nginx deploy/ingress-nginx-controller|grep-i"reload\|error"三、503:没有可用的后端
503 说明规则匹配上了,但Controller 找不到可用的 Pod 来转发。
第一步永远是看 Endpoint
kubectl get endpoints<service-name>-n<ns># 或者kubectl get endpointslices-n<ns>NAME ENDPOINTS api-svc <none> ← 空的就是问题所在ENDPOINTS为空 = Service 没有选中任何健康 Pod = 503。
原因 1:selector 和 Pod 标签对不上
# Service 选什么kubectl get svc api-svc-ojsonpath='{.spec.selector}'# Pod 实际有什么标签kubectl get pod-lapp=api --show-labels最常见的就是app: api和app: api-server这种一字之差。
原因 2:Pod 没有 Ready
Endpoint 只收Ready的 Pod。Pod Running 但 NotReady 不会被加入。
kubectl get pod-lapp=api# NAME READY STATUS RESTARTS# api-0 0/1 Running 0 ← Running 但 0/1,NotReady原因通常是readinessProbe 失败:
kubectl describe pod api-0|grep-A5Readiness# Readiness probe failed: HTTP probe failed with statuscode: 500注意:readiness 失败不会重启 Pod,只会把它从 Service 摘掉。所以现象是"Pod 看着在跑,但访问 503"。
原因 3:端口对不上
# Servicespec:ports:-port:80targetPort:8080# 要和应用实际监听的端口一致targetPort写错时,Endpoint 会有 IP 但端口不通。这种情况通常表现为 502 或连接超时,但部分 Controller 也会报 503。
# 确认 Pod 实际监听的端口kubectlexec<pod>-- ss-lntp原因 4:全部后端被摘除(滚动发布期间)
滚动更新时旧 Pod 被终止、新 Pod 还没 Ready,会出现短暂的 503。
解法是配置优雅停机 + preStop,让旧 Pod 在退出前先等一会儿,等 endpoint 同步完成:
lifecycle:preStop:exec:command:["sh","-c","sleep 10"]# 给 endpoint 摘除留出时间terminationGracePeriodSeconds:40关于这个时间差的完整机制在滚动更新那篇里详细讲过。
四、502:连上了但连接失败
502 说明 Controller 找到了 Pod 并尝试连接,但连接层面失败:
- Pod 内的进程没监听那个端口;
- 应用启动时就把连接关了;
- keepalive 连接被复用但已被关闭。
排查重点是从 Controller 到 Pod 这一段:
# 直接打 Pod IP(绕过 Service,确认应用本身是否正常)kubectl get pod-owide# 拿到 Pod IPkubectl run-it--rmcurl--image=curlimages/curl--restart=Never --\curl-ihttp://<pod-ip>:8080/healthz- Pod IP 直接访问正常 → 问题在 Service/Endpoint 层;
- Pod IP 也不通 → 问题在应用本身(端口、启动、崩溃)。
五、一个完整的排查流程
# 1. 看状态码,判断失败位置# 404 → Controller 层;503 → Service/Endpoint 层;502 → Pod 连接层# 2. 404:查规则kubectl get ingress<name>-oyaml# host / path / pathType / ingressClassNamecurl-i-H"Host: <host>"http://<ip>/# 带 Host 再试一次kubectl logs-ningress-nginx deploy/ingress-nginx-controller--tail=50# 3. 503:查 Endpointkubectl get endpoints<svc>kubectl get svc<svc>-ojsonpath='{.spec.selector}'kubectl get pod-l<selector>--show-labels kubectl describe pod<pod>|grep-A5Readiness# 4. 502:绕过 Service 直连 Podcurlhttp://<pod-ip>:<port>/healthz kubectlexec<pod>-- ss-lntp六、带走物
| 状态码 | 一句话定位 | 第一个要看的命令 |
|---|---|---|
| 404 | Ingress 规则没匹配上(host / path / class) | kubectl get ingress -o yaml |
| 503 | 规则匹配了但 Service 没有可用 Endpoint | kubectl get endpoints |
| 502 | 找到 Pod 但连接失败 | 直连 Pod IP 验证 |
| 504 | Pod 连上了但响应超时 | 查应用耗时 |
一句话结论:404 是"不知道往哪转",503 是"知道往哪转但没人接",502 是"有人但连不上"——状态码已经告诉你失败在第几层了,顺着那一层查就行。