2. Ingress 资源对象精讲
Ingress 是 Kubernetes 中用于暴露 HTTP/HTTPS 服务的原生 API 对象。它本身并不具备流量转发能力,真正干活的是 Ingress Controller(如 ingress-nginx、Traefik、HAProxy Ingress 等)。理解 Ingress,关键要抓住三件事:规则如何描述、请求如何被匹配、控制器如何把规则翻译成实际的代理配置。本节围绕 Ingress 的规则结构、host/path 匹配语义、TLS 配置、注解机制、默认后端以及常见陷阱展开。
一、Ingress 的规则结构
一个 Ingress 对象的核心是 spec.rules,每条规则由 host 和 http.paths 组成。每个 path 又包含 path、pathType 和 backend。backend 指向一个 Service 及其端口,由控制器据此生成 upstream。下面是一个典型示例:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
tls:
- hosts: ["www.example.com"]
secretName: example-tls
rules:
- host: www.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-svc
port:
number: 8080
- path: /static
pathType: Prefix
backend:
service:
name: static-svc
port:
number: 80
defaultBackend:
service:
name: fallback-svc
port:
number: 80
注意 ingressClassName 字段:它决定这条 Ingress 由哪个控制器接管。若集群中存在多个控制器而 Ingress 未指定 class,可能出现“规则写了但没人处理”的情况,这是新手最常见的困惑之一。
二、host 与 path 的匹配语义
host 匹配:Ingress 的 host 是精确匹配(不区分大小写),不支持通配符前缀,但支持形如 *.example.com 的单层通配。若请求的 Host 头与任何规则都不匹配,则交给 defaultBackend 处理。
path 匹配:pathType 有三种取值,语义差异很大:
Exact:路径必须完全相等,/api只匹配/api,不匹配/api/或/api/v1。Prefix:按路径段前缀匹配。/api可匹配/api、/api/、/api/v1,但不会匹配/apix。ImplementationSpecific:由控制器自行决定,ingress-nginx 默认按前缀处理,但行为可能随版本变化,生产环境应显式指定。
当多条 path 同时匹配时,采用最长前缀优先原则。例如同时存在 /api 和 /api/v2,请求 /api/v2/users 会命中后者。这一点与 Nginx 的 location 匹配逻辑一致,但 Ingress 层面只保证语义,具体实现仍由控制器负责。
三、TLS 配置
Ingress 的 TLS 通过 spec.tls 声明,每个条目包含 hosts 和 secretName。secretName 指向一个类型为 kubernetes.io/tls 的 Secret,其中必须包含 tls.crt 和 tls.key 两个键。控制器读取该 Secret 后,在入口处完成 TLS 终止,后端 Service 通常仍以 HTTP 明文通信。
常见做法是用 cert-manager 自动签发和续期证书,它会根据 Ingress 上的注解自动创建对应的 Secret。若手动创建,可用如下命令:
kubectl create secret tls example-tls \
--cert=fullchain.pem \
--key=privkey.pem
需要特别注意:tls.hosts 必须与 rules[].host 一致,否则控制器可能不会为该 host 加载证书,导致浏览器收到默认自签证书或握手失败。此外,Secret 必须与 Ingress 处于同一命名空间。
四、注解机制
Ingress 的通用字段只覆盖了最基本的 HTTP 路由,大量高级能力(重写、限流、超时、灰度、会话保持等)都通过 annotations 暴露。注解是控制器私有的,不同控制器支持的注解完全不同。以 ingress-nginx 为例:
nginx.ingress.kubernetes.io/rewrite-target:重写请求路径,常与正则捕获组配合。nginx.ingress.kubernetes.io/proxy-body-size:限制上传体积,默认 1m,上传大文件时必须调整。nginx.ingress.kubernetes.io/ssl-redirect:是否强制 HTTP 跳转 HTTPS。nginx.ingress.kubernetes.io/canary与canary-weight:实现按权重灰度发布。
注解写错不会导致 Ingress 创建失败,只会被控制器忽略,因此排查时要用 kubectl describe ingress 查看控制器事件,并核对控制器文档中的注解名称与版本。
五、默认后端与常见陷阱
defaultBackend 用于兜底:当请求的 host 或 path 没有任何规则匹配时,转发到该后端。若不设置,ingress-nginx 会返回 404。它适合放置一个统一的错误页或降级服务。
实践中容易踩的坑包括:
- pathType 未指定:v1 中该字段必填,缺失会被 API Server 拒绝。
- Prefix 与 Exact 混用导致意外命中:例如
/用 Prefix 会吞掉所有未匹配路径,需谨慎。 - rewrite-target 与 path 不匹配:重写规则写错会把请求打到后端不存在的路径,表现为 404。
- 多个 Ingress 争抢同一 host:不同 Ingress 定义相同 host/path 时,行为取决于控制器,可能互相覆盖。
- 忽略 ingressClassName:规则存在但无控制器接管,请求直接失败。
ingressClassName 与控制器匹配,再用 kubectl describe ingress 查看事件与后端解析结果,最后检查控制器 Pod 日志中的 upstream 与 404/502 记录。