Kubernetes Ingress 实战:域名路由、TLS 证书与 502/404 排查

Kubernetes Ingress 实战:域名路由、TLS 证书与 502/404 排查

服务部署进 K8s 后,第一个绕不开的问题是:外面怎么访问?给每个 Service 开一个 type: LoadBalancer 太贵,NodePort 端口又丑又难记。Ingress 就是标准答案------一个入口,按域名和路径把流量分发到不同 Service,顺带把 TLS 证书也统一收口。

但 Ingress 也是新手翻车重灾区:配好了访问却 404,或者一直 502。这篇从最小可用配置讲起,把域名路由、TLS、以及最常见的两类报错排查讲清楚。

前置:Ingress 资源 ≠ Ingress Controller

这是第一个概念坑。你写的 Ingress YAML 只是一份「路由规则声明」,它本身不干活。真正接收流量、执行规则的是 Ingress Controller(一个跑在集群里的 Pod,通常是 Nginx、Traefik 或云厂商的实现)。没装 Controller,你的 Ingress 资源就是一张贴在墙上没人看的通知。

装最常用的 ingress-nginx:

bash 复制代码
# 用官方清单一键装,会创建 ingress-nginx 命名空间和 controller
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.2/deploy/static/provider/cloud/deploy.yaml

# 确认 controller Pod 起来了,并拿到对外 IP
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx ingress-nginx-controller

最后那个 svc 的 EXTERNAL-IP 就是集群入口 IP,把你的域名 A 记录解析到它。

最小可用:按域名路由到 Service

假设有两个服务 web-svc(80) 和 api-svc(8080),想让 example.com 走前端、api.example.com 走后端:

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: main-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx        # 指定用哪个 controller,别漏
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-svc
            port:
              number: 80
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-svc
            port:
              number: 8080

几个必须注意的点:

  • ingressClassName: nginx 不能漏。多个 controller 共存时,漏了会导致没有 controller 认领这条规则,访问直接 404。
  • pathTypePrefix(前缀匹配)和 Exact(精确匹配)。大多数场景用 Prefix
  • service.port.numberService 的端口,不是 Pod 容器端口。这俩经常配错。

应用后验证:

bash 复制代码
kubectl get ingress main-ingress
# 直接指定 Host 头测试,绕过 DNS
curl -H "Host: api.example.com" http://<EXTERNAL-IP>/health

加上 HTTPS:TLS 证书收口

Ingress 的一大价值是统一终结 TLS,后端 Service 只跑明文 HTTP。先把证书和私钥存成 Secret:

bash 复制代码
kubectl create secret tls example-tls \
  --cert=fullchain.pem --key=privkey.pem

然后在 Ingress 里引用它:

yaml 复制代码
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - example.com
    - api.example.com
    secretName: example-tls    # 引用上面创建的 Secret
  rules:
  # ... rules 同上

tls.hosts 里的域名必须和证书里的 CN/SAN 匹配,也要和 rules.host 对上。配好后 ingress-nginx 默认会把 HTTP 301 跳转到 HTTPS。

生产环境别手动管证书,用 cert-manager 自动签发和续期 Let's Encrypt 证书,加个 annotation 就行:

yaml 复制代码
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod

排查一:访问 404 Not Found

nginx 返回 404(注意看响应头 Server: nginx,确认是 controller 返回的而非后端),常见原因按概率排:

  1. ingressClassName 漏了或写错 ------没 controller 认领。kubectl describe ingress 看有没有 Successfully synced 事件。
  2. Host 不匹配 ------请求的域名和 rules.host 对不上。用 curl -H "Host: ..." 显式指定测试。
  3. path/pathType 不匹配 ------比如 pathType: Exact 配了 / 但你访问 /foo
bash 复制代码
# 直接看 controller 日志,404 会打出它匹配到哪条规则(或没匹配到)
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=50

排查二:一直 502 Bad Gateway

502 意味着 controller 找到了规则、但连不上后端。这几乎总是 Service 到 Pod 这一段的问题,而不是 Ingress 本身:

bash 复制代码
# 1. Service 有没有选中 Pod?ENDPOINTS 为空就是标签选错了
kubectl get endpoints api-svc
# 若 ENDPOINTS 是 <none>,说明 Service 的 selector 没匹配到任何 Pod

# 2. Service 端口和容器端口对得上吗?
kubectl describe svc api-svc

# 3. Pod 本身健康吗?
kubectl get pods -l app=api

最高频的 502 根因就一个:Service 的 selector 和 Pod 的 labels 不一致 ,导致 ENDPOINTS 为空,Ingress 转发到一个没有后端的 Service。改对标签,endpoints 立刻就有值了。

另一个常见 502:后端是 HTTPS 但没告诉 nginx。若 Service 后面是 HTTPS,要加 annotation:

yaml 复制代码
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"

小结

  • Ingress 资源只是路由声明,必须先装 Ingress Controller 才生效。
  • 写 Ingress 三件套别漏:ingressClassName、正确的 host、指向 Service 端口的 backend。
  • TLS 用 kubectl create secret tls 存证书再在 spec.tls 引用;生产用 cert-manager 自动续期。
  • 404 看 Ingress 层 (class/host/path 匹配),502 看后端 (先查 kubectl get endpoints 是不是空的)。
  • 一句话记忆点:404 是「规则没匹配上」,502 是「匹配上了但后端连不通」,先分清是哪一层,排查方向立刻收敛。
相关推荐
敖行客 Allthinker6 小时前
Parallels Ubuntu虚拟机项目如何让手机访问?完整解决方案
linux·运维·ubuntu
BullSmall7 小时前
Anolis OS 8.10 完整安装 Docker CE(生产可用,解决 podman 冲突)
docker·容器·podman
元Y亨H8 小时前
生产环境监控与故障应急处理(5-5-5 标准)指南
运维
heimeiyingwang9 小时前
【架构实战】可观测性三支柱:日志、指标、链路的融合
elasticsearch·架构·kubernetes
观山岳五楼9 小时前
Ubuntu 24 怎么使用Ubuntu 20 的镜像源
linux·运维·ubuntu
寒晓星9 小时前
[linux]线程及多线程
linux·运维
慧一居士10 小时前
Linux如何设置固定的静态ip
运维
阿里云云原生11 小时前
阿里云 AgentTeams 7月第二周产品动态
云原生
国服第二切图仔11 小时前
13其他工具 - Skill/LSP/Sleep等
linux·运维·里氏替换原则
暴力求解12 小时前
Linux ---线程控制(二)
linux·运维·服务器·操作系统