Kubernetes Gateway API 实战:用 HTTPRoute 治理流量

Kubernetes Gateway API 是社区力推的新一代流量治理标准,用来取代已经显出疲态的 Ingress。它通过 Gateway、GatewayClass、HTTPRoute 等一组角色化资源,把“谁能建网关、怎么路由流量”拆得清清楚楚,原生支持流量分割、基于请求头的路由、跨命名空间引用等 Ingress 难以实现的能力。如果你正在被 Ingress 的 annotations 满天飞、功能受限所困扰,Gateway API 值得立刻评估。

一、为什么需要 Gateway API:Ingress 的三大痛点

经典 Ingress 只有一条规则模型:一个 Ingress 资源描述“域名 + 路径 → 后端 Service”。这带来三个绕不开的问题。

  • 表达能力弱:加权负载均衡、基于请求头的路由、请求/响应改写,几乎都要靠各厂商私有的 annotation(如 nginx.ingress.kubernetes.io/ 前缀),可移植性极差。
  • 权限不分租户:任何能创建 Ingress 的人都能指向任意 Service,基础设施团队无法把“建网关”和“配路由”两个权限分离开。
  • 扩展靠碎片:想加新功能就得等控制器厂商实现新 annotation,社区无法用一套标准覆盖所有实现。

Gateway API 的核心思路是面向角色(role-oriented):把“基础设施提供方”“网关运维方”“应用开发者”三种角色用不同的 CRD 分开,谁该管什么一目了然。它与我们之前讲过的 Nginx 反向代理 思想一脉相承,只是把配置搬到了声明式 API 上。

二、Gateway API 的核心资源模型

落地前先厘清四个关键资源:

资源角色负责方作用
GatewayClass集群级模板基础设施团队定义“网关由哪种控制器实现”(类似 StorageClass)
Gateway网关实例平台/运维团队声明监听端口、域名与可被谁引用
HTTPRoute路由规则应用开发者把请求按路径/头/方法转发到具体 Service
ReferenceGrant跨命名空间授权运维团队允许某命名空间的 HTTPRoute 引用另一个命名空间的 Service

这种拆分让“建网关”和“配路由”彻底解耦:平台团队把 Gateway 建好交给开发者,开发者只需关心自己的 HTTPRoute,互不踩脚。

三、环境准备:安装 CRD 与控制器

Gateway API 本身是 CRD,需要先在集群里安装标准资源定义,再选一个支持它的控制器(主流有 Istio、Envoy Gateway、NGINX Gateway Fabric)。下面以 Envoy Gateway 为例。

# 安装 Gateway API 标准 CRD(与具体控制器解耦)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml

# 用 Helm 安装 Envoy Gateway 控制器
helm repo add envoy-gateway https://helm.envoy.io
helm install eg oci://docker.io/envoyproxy/gateway-helm --version v1.2.0 -n envoy-gateway --create-namespace

# 等待控制器就绪
kubectl rollout status deployment -n envoy-gateway envoy-gateway

由于控制器本身以容器方式运行,建议把它和业务的 Docker 镜像统一纳入镜像仓库与版本管理,避免环境漂移。

四、定义 Gateway:把“门”立起来

Gateway 资源声明“监听什么端口、允许哪些命名空间把路由挂上来”。下面这段由平台团队维护:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: public-gateway
  namespace: gateway-system
spec:
  gatewayClassName: eg          # 对应 Envoy Gateway 提供的 GatewayClass
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: All               # 允许所有命名空间的 HTTPRoute 挂到这个网关

创建后,Envoy Gateway 会自动生成一个 LoadBalancer 类型的 Service,把外部流量接进来。

五、用 HTTPRoute 做路由与流量分割

开发者现在只需写 HTTPRoute,把它 parentRef 指向上面的 Gateway 即可。最基础的“路径路由”:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: store-route
  namespace: store
spec:
  parentRefs:
  - name: public-gateway
    namespace: gateway-system
  hostnames: ["store.example.com"]
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /api
    backendRefs:
    - name: store-api
      port: 8080

更香的是原生流量分割——再也不用靠 annotation 凑权重。下面把 /api 按 80/20 切到新旧两个版本,做灰度发布:

rules:
- matches:
  - path:
      type: PathPrefix
      value: /api
  backendRefs:
  - name: store-api-v1
    port: 8080
    weight: 80
  - name: store-api-v2
    port: 8080
    weight: 20

六、进阶:基于头的路由、重定向与重写

Gateway API 把很多 Ingress 需要 annotation 才能实现的能力变成了一等公民。例如“带 x-canary: true 头的请求全打到 v2”:

rules:
- matches:
  - headers:
    - type: Exact
      name: x-canary
      value: "true"
    path:
      type: PathPrefix
      value: /api
  backendRefs:
  - name: store-api-v2
    port: 8080
- matches:
  - path:
      type: PathPrefix
      value: /api
  backendRefs:
  - name: store-api-v1
    port: 8080

请求路径重写也只需在 rule 里加 filters,例如把 /api 转发到后端时剥掉前缀:

rules:
- matches:
  - path:
      type: PathPrefix
      value: /api
  filters:
  - type: URLRewrite
    urlRewrite:
      path:
        type: ReplacePrefixMatch
        replacePrefixMatch: /
  backendRefs:
  - name: store-api
    port: 8080

七、与 Ingress-NGINX 的差异与迁移建议

如果你已经在用经典 Ingress,可以参考下面这张对照表决定迁移节奏:

能力Ingress (Ingress-NGINX)Gateway API
加权负载均衡靠 annotation,厂商私有HTTPRoute backendRefs.weight 原生
基于头的路由有限、需 annotationmatches.headers 原生
跨命名空间引用不支持ReferenceGrant 原生
角色/权限分离无GatewayClass/Gateway/HTTPRoute 分角色
可移植性实现相关标准 CRD,多控制器通用

迁移不必一步到位:很多控制器(如 NGINX Gateway Fabric、Istio)可同时支持 Ingress 与 Gateway API,建议先在新业务上试点 HTTPRoute,跑稳后再逐步把老 Ingress 搬迁过来。

八、生产排障 Checklist

现象优先排查项
HTTPRoute 不生效parentRefs 的 name/namespace 是否写对;Gateway 的 allowedRoutes 是否放行该命名空间
跨命名空间 503是否缺少 ReferenceGrant 授权 Service 所在命名空间
权重不生效确认控制器版本支持流量分割,且后端 Service 就绪
外部访问不通检查 Gateway 对应 LoadBalancer Service 是否拿到外部 IP、安全组是否放通

排障时可以 kubectl describe gateway/public-gateway 与 kubectl get httproute -A 看控制器写入的状态与条件,比翻 Ingress 日志直观得多。

九、用 GitHub Actions 把网关配置纳入 CI/CD

Gateway/HTTPRoute 都是声明式 YAML,天然适合放进 Git 做版本化与自动化发布。在 GitHub Actions 里加一步即可:

# .github/workflows/deploy-gateway.yml
name: deploy-gateway
on:
  push:
    paths: ["gateway/**"]
jobs:
  apply:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: azure/setup-kubectl@v4
    - run: kubectl apply -f gateway/gateway.yaml
    - run: kubectl apply -f gateway/store-route.yaml

把网关配置和代码一起走 PR 审核,既能审计变更,也能在回滚时一键 kubectl apply 旧版本,运维体验比手动改 Ingress 清爽太多。

十、超时、重试与熔断:把韧性写进路由

入口网关是整条链路的咽喉,网络抖动和后端偶发慢响应都会在这里被成倍放大。Gateway API 通过 HTTPRoute 的 timeouts 与 retry 字段把韧性策略声明化,不再依赖控制器私有配置,也不需要去改 Ingress 那一长串难以维护的 annotation。

rules:
- matches:
  - path:
      type: PathPrefix
      value: /api
  timeouts:
    request: "10s"          # 单次请求最长 10 秒
    backendRequest: "8s"
  retry:
    attempts: 3
    perTryTimeout: "2s"
    retryOn: "5xx,reset,connect-failure"
  backendRefs:
  - name: store-api
    port: 8080

这样配置后,即使后端短暂抖动,网关也会在每次尝试 2 秒超时的前提下最多重试 3 次,既保护了用户体验,又避免把瞬时压力无脑转嫁给上游。再配合上游服务自身的熔断(例如 Resilience4j),就能挡住绝大部分级联故障,而这整套配置如今都是可读、可审计的 YAML。

十一、TLS 终止与证书管理

生产环境的入口必须走 HTTPS,否则不仅有安全风险,还会被现代浏览器标记为“不安全”。Gateway 的 listener 可以直接声明 TLS 终止,并引用集群里的 Secret 作为证书;再配合 cert-manager 自动签发与续期,运维心智负担会大幅降低,不必再为证书过期半夜爬起来手动轮换。

listeners:
- name: https
  protocol: HTTPS
  port: 443
  tls:
    mode: Terminate
    certificateRefs:
    - name: example-com-tls      # 由 cert-manager 维护的 Secret
      group: ""
      kind: Secret

把证书生命周期整体交给 cert-manager 之后,你只需要在 HTTPRoute 上配好域名,剩下的签发、续期、轮换都由控制器自动完成,再也不用盯着证书过期邮件提心吊胆。这也是 Gateway API 相比传统 Ingress 在“生产就绪”维度上更省心的一点。

十二、小结

Gateway API 不是 Ingress 的修补,而是重新设计:用角色化资源和原生流量治理能力,解决了 Ingress 表达弱、权限混、难扩展的顽疾。它已经是 Kubernetes 流量治理的事实下一代标准,新项目建议直接上手 HTTPRoute,老项目可平滑迁移。把它和 GitOps/CI 结合起来,你的入口网络会更清晰、更可控。

上一篇 Docker Agent 实战:用 YAML 编排 AI 代理
下一篇 Java SPI 实战:用 ServiceLoader 构建可插拔架构
最新评论
Docker 网络模式详解:bridge/host 生产选型 - FSData
Docker 网络模式详解:bridge/host 生产选型 - FSData
8月20日
[…] 注意最后那条:把端口绑定到 127.0.0.1,再由宿主机上的 Nginx 反代进来,比直接 -p 80:80 暴露安全得多,也方便统一做
Vue3 + TypeScript 工程化:类型安全的前端架构 - FSData
Vue3 + TypeScript 工程化:类型安全的前端架构 - FSData
8月20日
[…] Pinia 的工程化用法,可以参考我们之前的实战文章 《Vue3 组合式 API + Pinia:状态管理从入门到实战》,那里覆盖了 Sto
2026 年最值得装的 10 个 VS Code 插件(AI/前端/后端/效率全覆盖) - FSData
2026 年最值得装的 10 个 VS Code 插件(AI/前端/后端/效率全覆盖) - FSData
8月19日
[…] 状态,点一下就能起停容器,配合我们讲过的 Docker Compose 编排 […]
Redis 缓存设计:穿透、击穿、雪崩与最佳实践 - FSData
Redis 缓存设计:穿透、击穿、雪崩与最佳实践 - FSData
8月19日
[…] 缓存三大坑的本质都是”缓存失效导致请求穿透到数据库”。记住口诀:穿透用布隆、击穿用锁、雪崩用错峰。配合合理的过期策略
GitHub Actions 实战:从零搭建 CI/CD 流水线 - FSData
GitHub Actions 实战:从零搭建 CI/CD 流水线 - FSData
8月19日
[…] Docker 镜像部署。结合我们之前写的 Docker Compose 一键编排实战,可以在 CI […]