8.1. Ingress 之后:Gateway API
Ingress 解决了「域名和路径转发到哪个 Service」,但把 TLS、流量分割、头路由、跨命名空间授权都塞进注解,导致不同控制器的行为互不兼容。Gateway API 用类型化资源把「谁管入口、谁管路由、谁管后端」拆开,是 Ingress 的下一代标准。
- 层级:
L3 · 平台
- 难度:
进阶
- 预计:
50 分钟
- 前置:
Service、Ingress、TLS 基础
8.1.1. Ingress 的边界
Ingress 的核心字段只有 rules、tls 和 backend。灰度权重、重写、超时、重试、mTLS 等能力通常靠控制器注解实现,例如 ingress-nginx 的 nginx.ingress.kubernetes.io/*。这带来三个问题:
注解不是标准,换控制器就要重写。
权限边界模糊:应用团队改一个 Ingress,可能顺带改掉入口的安全策略。
多团队共享入口时,难以表达「网关管理员」与「路由所有者」的分工。
Gateway API 把这些问题拆成 GatewayClass → Gateway → HTTPRoute 三层。
8.1.2. 资源模型
资源 |
谁负责 |
作用 |
|---|---|---|
|
平台/基础设施团队 |
声明使用哪个网关实现,如 Envoy Gateway、Traefik |
|
平台/网关管理员 |
定义监听端口、TLS、允许挂载的命名空间 |
|
应用团队 |
定义域名、路径、头匹配、后端与权重 |
图:GatewayClass 选择实现,Gateway 管监听与 TLS,HTTPRoute 管应用路由。
8.1.3. 安装 Envoy Gateway
helm install eg oci://docker.io/envoyproxy/gateway-helm \
--version v1.2.0 \
-n envoy-gateway-system --create-namespace
kubectl get gatewayclass
如果使用 Traefik、Kong 或 HAProxy,安装对应的 Gateway API 实现即可;HTTPRoute 的写法基本一致,差异在 GatewayClass 与部分扩展字段。
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: prod-gw
namespace: default
spec:
gatewayClassName: eg
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: Same
kubectl apply -f gateway.yaml
kubectl get gateway prod-gw
8.1.4. HTTPRoute:路径、头与权重
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: demoapp
namespace: default
spec:
parentRefs:
- name: prod-gw
hostnames:
- demo.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: demoapp-v1
port: 80
weight: 90
- name: demoapp-v2
port: 80
weight: 10
权重是 Gateway API 的原生字段,不需要控制器注解。把 90/10 改成 50/50 再观察错误率,就是最小可用的金丝雀发布。
8.1.4.1. 头匹配与重定向
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: demoapp-canary
namespace: default
spec:
parentRefs:
- name: prod-gw
hostnames:
- demo.example.com
rules:
- matches:
- headers:
- name: x-canary
value: "true"
backendRefs:
- name: demoapp-v2
port: 80
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: demoapp-v1
port: 80
带 x-canary: true 的请求进入 v2,其余进入 v1。与 Ingress 注解相比,这种规则是类型化、可校验、可移植的。
8.1.5. 实验:从 Gateway 到两个版本
kubectl create deployment demoapp-v1 --image=ikubernetes/demoapp:v1.0
kubectl create deployment demoapp-v2 --image=ikubernetes/demoapp:v2.0
kubectl expose deployment demoapp-v1 --name=demoapp-v1 --port=80
kubectl expose deployment demoapp-v2 --name=demoapp-v2 --port=80
kubectl apply -f gateway.yaml
kubectl apply -f httproute-demoapp.yaml
kubectl get httproute demoapp -o yaml
用 curl -H 'Host: demo.example.com' http://<gateway-ip>/ 连续请求,观察 v1/v2 比例。Envoy Gateway 的 Gateway 地址可用 kubectl get gateway prod-gw -o jsonpath='{.status.addresses[0].value}' 获取。
8.1.6. 与 Ingress 的迁移策略
先让新旧入口并行,DNS 或负载均衡按比例切流。
把 Ingress 注解翻译成 HTTPRoute 的 matches/filters/backendRefs。
验证 TLS、重写、超时、重试、灰度、访问日志。
确认回滚路径后,再删除旧 Ingress。
不要一次性重写所有入口;先挑一个无状态、低风险的域名试点。
8.1.7. 验证清单
GatewayClass处于Accepted,Gateway有地址且Programmed。HTTPRoute的parentRefs指向正确的 Gateway。权重、头匹配、路径匹配都按预期生效。
TLS 证书与监听器配置正确,HTTP 能按需重定向到 HTTPS。
跨命名空间路由已通过
allowedRoutes显式授权。
8.1.8. 排错表
现象 |
原因 |
处理 |
|---|---|---|
Gateway 一直 |
没有可用的 GatewayClass/控制器 |
|
HTTPRoute |
parentRefs 名字/命名空间错误 |
|
404 |
hostname/path 不匹配 |
检查 Host 头与 |
权重不生效 |
后端 Service 没有 Endpoints |
|
TLS 握手失败 |
Secret 不在 Gateway 命名空间/格式错 |
检查 |
8.1.9. 进阶挑战
用 HTTPRoute 实现
/api与/web两个后端的路由。配置 HTTP → HTTPS 重定向,并验证 HSTS 头。
用两个 Gateway 实现内外网隔离,
allowedRoutes只允许指定命名空间。把现有 ingress-nginx 的一个域名迁移到 Gateway API,写一份回滚步骤。
8.1.10. 小结
Gateway API 用 GatewayClass/Gateway/HTTPRoute 拆分角色与职责。
权重、头匹配、重定向是原生字段,不再依赖控制器注解。
迁移要并行运行、逐域名切换,不要一次性替换所有入口。
新项目优先 Gateway API;存量 ingress-nginx 可以按域名逐步迁移。