引言
在 Kubernetes 集群中,如何将内部服务安全、高效地暴露给外部用户,是每个平台工程师必须面对的核心问题。自 K8s 诞生以来,Ingress 长期扮演着"官方网关"的角色;然而随着微服务架构的复杂化,Ingress 的诸多限制逐渐暴露。2023 年 GA 的 Gateway API,正是 Kubernetes 社区给出的下一代标准答案。本文将系统梳理从 Ingress 到 Gateway API 的演进脉络,并给出可落地的迁移实践。
一、Ingress:单层入口与注解地狱
Ingress 的核心设计非常简洁:它定义了一组规则,将集群外部的 HTTP/HTTPS 流量路由到集群内的 Service。所有流量先经过云厂商或自建的一层负载均衡(LoadBalancer),再由 Ingress Controller 根据域名和路径分发到后端 Pod。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: frontend-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rate-limit: "100"
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-svc
port:
number: 80
tls:
- hosts:
- app.example.com
secretName: app-tls
上述 YAML 展示了一个典型的 Ingress 资源。它依赖 nginx.ingress.kubernetes.io/* 这类 annotations 来实现重写、SSL 重定向和速率限制——这正是社区戏称的 “annotations hell”(注解地狱)。不同 Controller(Nginx、Traefik、HAProxy)的注解互不兼容,导致配置锁定严重。
Ingress 的工作流程可概括为:
- 用户创建 Ingress 资源;
- Ingress Controller(如 NGINX Ingress Controller)监听资源变更;
- Controller 生成底层代理配置(如 nginx.conf)并重载;
- 外部流量经 LoadBalancer 到达 Controller,再按规则转发。
二、Ingress 的三大瓶颈
随着集群规模和多租户需求的增加,Ingress 的设计短板日益明显。
2.1 无法跨命名空间路由
Ingress 只能引用同命名空间的 Service。若平台团队希望在 infra 命名空间部署统一网关,而将业务服务分散在 team-a、team-b 等命名空间,Ingress 无法直接支持,只能借助繁琐的外部 Service 拼接。
2.2 协议支持受限
Ingress 仅原生支持 HTTP/HTTPS。对于 TCP、UDP、gRPC(TLS 模式)、数据库等四层流量,必须绕过 Ingress,使用 LoadBalancer 类型的 Service,导致网络入口分散、策略难以统一。
2.3 缺乏高级流量能力
Ingress 标准未定义流量分割(traffic splitting)、镜像(mirroring)、超时重试、蓝绿发布等高级能力。这些功能全部由各 Controller 通过私有注解实现,既不可移植,也难以维护。
三、Service Mesh 的补位:Istio Gateway
在 Gateway API 出现之前,许多团队选择用 Istio 的 Gateway 资源来弥补 Ingress 的不足。
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: public-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: app-tls
hosts:
- "app.example.com"
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: frontend-vs
spec:
hosts:
- app.example.com
gateways:
- public-gateway
http:
- route:
- destination:
host: frontend-svc
port:
number: 80
Istio Gateway 解耦了"监听器配置"与"路由规则",且支持丰富的流量策略。但它本质上是 Service Mesh 的附属品,引入了 Sidecar 的复杂度和资源开销,对于不需要服务间 mTLS 或精细可观测性的场景显得过重。
四、Gateway API:面向角色的下一代标准
Gateway API 由 SIG-Network 主导设计,核心目标有三:
- 角色分离:基础设施管理员、集群操作员、应用开发者各司其职;
- 可扩展性:原生支持 HTTP、TCP、TLS、gRPC 等多协议;
- 跨命名空间:允许 Gateway 引用其他命名空间的 Service。
4.1 核心资源模型
| 资源 | 对应角色 | 职责 |
|---|---|---|
GatewayClass | 基础设施管理员 | 定义一类网关的模板(如 nginx、istio、traefik) |
Gateway | 集群操作员 | 配置监听器、TLS、地址等网络端点 |
HTTPRoute / TCPRoute / TLSRoute / GRPCRoute | 应用开发者 | 定义具体的路由规则和后端服务 |
这种分层模型让不同团队可以独立操作各自资源,避免权限混乱。
4.2 Gateway + HTTPRoute 示例
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: nginx
spec:
controllerName: gateway.nginx.org/nginx-gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: production-gateway
namespace: infra
spec:
gatewayClassName: nginx
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: app-tls
allowedRoutes:
namespaces:
from: All
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: frontend-route
namespace: team-a
spec:
parentRefs:
- name: production-gateway
namespace: infra
hostnames:
- "app.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: frontend-svc
port: 80
注意:这里的 HTTPRoute 位于 team-a 命名空间,却能挂载到 infra 命名空间的 Gateway 上。allowedRoutes.namespaces.from: All 显式授权了这种跨命名空间引用。
五、Ingress 到 Gateway API 的迁移实践
迁移不是一次性替换,而是渐进式推进。推荐按以下步骤实施:
5.1 前置条件:部署 Gateway API CRDs
多数集群默认未安装 Gateway API 的自定义资源。需要先部署 CRDs:
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/standard-install.yaml
5.2 选择并部署 Gateway Controller
根据团队现有技术栈,选择对应的 Gateway 实现:
| 方案 | 特点 | 适用场景 |
|---|---|---|
| NGINX Gateway Fabric | 官方实现,轻量,与 NGINX Ingress 配置语法接近 | 已有 Nginx 生态,追求标准合规 |
| Traefik | 原生支持 Gateway API,Dashboard 直观 | 云原生友好的中小集群 |
| Istio | 功能最全,与 Mesh 无缝集成 | 已部署 Service Mesh 的环境 |
| Envoy Gateway | 基于 Envoy,扩展性强 | 需要高级流量治理的大型平台 |
5.3 并行部署与灰度切换
- 在新命名空间(如
gateway-api)部署 Gateway 和 Gateway Controller; - 将部分域名的 DNS 指向新 Gateway 的 LoadBalancer IP;
- 逐步将 Ingress 规则翻译为 HTTPRoute,验证功能一致性;
- 全域切换后,保留旧 Ingress Controller 一段时间作为回滚预案。
六、NGINX Ingress Controller vs NGINX Gateway Fabric
拥有 Nginx 技术栈的团队常纠结这两个项目。二者定位截然不同:
| 维度 | NGINX Ingress Controller | NGINX Gateway Fabric |
|---|---|---|
| 标准遵循 | 私有 annotations 为主 | 原生 Gateway API |
| 配置来源 | Ingress 资源 | Gateway + HTTPRoute |
| 跨命名空间 | 不支持 | 原生支持 |
| 商业特性 | Plus 版本提供 WAF、JWT | 同样支持 Plus 扩展 |
| 社区归属 | Kubernetes Ingress-Nginx(社区) | NGINX 官方 + SIG-Network |
简言之,新项目首选 Gateway Fabric;存量 Ingress 可渐进迁移。二者甚至可以共存于同一集群,通过不同 LoadBalancer 入口分担流量。
七、Traefik 作为 Gateway Controller
Traefik 从 v3 起对 Gateway API 提供了开箱即用的支持。启用方式极其简单:
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: traefik
spec:
controllerName: traefik.io/gateway-controller
Traefik 的优势在于其自动服务发现和简洁的 Dashboard。对于不想深度定制 Envoy 配置的团队,Traefik 是平衡易用性与功能性的优选。
八、实战:金丝雀发布与流量镜像
以下示例展示 Gateway API 在实际场景中的威力。
8.1 金丝雀发布(Canary)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: frontend-canary
spec:
parentRefs:
- name: production-gateway
namespace: infra
hostnames:
- app.example.com
rules:
- matches:
- headers:
- name: canary
value: "true"
backendRefs:
- name: frontend-v2
port: 80
- backendRefs:
- name: frontend-v1
port: 80
weight: 90
- name: frontend-v2
port: 80
weight: 10
上述规则实现了双重策略:
- 带
canary: trueHeader 的请求 100% 进入 v2; - 普通请求按 90:10 比例分流到 v1 与 v2。
8.2 流量镜像(Traffic Mirroring)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: frontend-mirror
spec:
parentRefs:
- name: production-gateway
namespace: infra
hostnames:
- app.example.com
rules:
- backendRefs:
- name: frontend-v1
port: 80
filters:
- type: RequestMirror
requestMirror:
backendRef:
name: frontend-v2
port: 80
流量镜像将请求的副本发送给 v2,同时不影响主请求的响应。这对上线前的影子验证极为有用。
九、Ingress 与 Gateway API 综合对比
| 特性 | Ingress | Gateway API |
|---|---|---|
| 协议支持 | HTTP/HTTPS | HTTP/HTTPS/TCP/TLS/gRPC |
| 跨命名空间 | 不支持 | 原生支持 |
| 角色分离 | 无 | Gateway / Route 分层 |
| 流量分割 | 依赖注解 | 内置 weight |
| 流量镜像 | 不支持 | RequestMirror filter |
| 可移植性 | 注解锁定厂商 | 标准资源,厂商无关 |
| 成熟度 | 极高,生态丰富 | GA,逐渐主流 |
结语
Gateway API 不是对 Ingress 的简单修补,而是一次面向未来云原生网络的架构升级。它通过角色分离降低协作成本,通过标准资源打破厂商锁定,通过丰富的路由能力支撑现代化的发布策略。对于正在建设 Kubernetes 平台的团队,建议在新集群直接采用 Gateway API;存量集群则可按业务域逐步迁移。服务暴露的演进之路,从 Ingress 到 Gateway API,正是 Kubernetes 网络从"能用"走向"好用"的缩影。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。