2026年K8s Gateway API迁移完全指南:从Ingress到Gateway API
2026年K8s Gateway API迁移完全指南:从Ingress到Gateway API
如果你在2026年还在用Kubernetes Ingress管理集群流量,你正在错过云原生流量管理的未来。Gateway API在2025年底正式成为Kubernetes GA API,各大厂商(Istio、Contour、Traefik、Kong)已全面支持。Ingress的设计缺陷——单角色、扩展性差、无法表达复杂路由——在微服务规模爆炸的今天已经不可接受了。
Gateway API引入了Gateway、GatewayClass、HTTPRoute等角色分离的API,支持多团队协作、多集群部署、流量拆分和镜像。本文将从架构对比开始,给出完整的迁移步骤,覆盖流量管理、多租户和多集群场景。
为什么Gateway API取代Ingress?
| 对比维度 | Ingress | Gateway API |
|---|---|---|
| API成熟度 | GA(但已停止演进) | GA(2025.11) |
| 角色分离 | 无(全由集群管理员管理) | 三角色(基础设施/集群/应用) |
| 路由表达能力 | 有限(path+host) | 强大(header/query/weight/mirror) |
| 多协议支持 | 仅HTTP/HTTPS | HTTP/TLS/TCP/UDP/gRPC |
| 流量拆分 | 需要annotation hack | 原生支持(weight字段) |
| 多租户 | 不支持 | 原生支持(Namespace隔离) |
| 扩展性 | 依赖annotation | 原生扩展(PolicyAttachment) |
| 跨集群 | 不支持 | 支持Multi-cluster Gateway |
核心差异:Ingress把所有配置混在一起,而Gateway API实现了角色分离——基础设施团队管GatewayClass,运维团队管Gateway,开发团队管Route。
一、架构对比
1.1 Ingress架构
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
rules:
- host: api.example.com
http:
paths:
- path: /v1/users(/|$)(.*)
pathType: Prefix
backend:
service:
name: user-service
port:
number: 8080
问题:所有配置挤在一个Ingress对象里,annotation满天飞,不同厂商的annotation互不兼容。
1.2 Gateway API架构
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: istio
spec:
controllerName: istio.io/gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: api-gateway
namespace: infra
spec:
gatewayClassName: istio
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
shared-gateway-access: "true"
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: user-route
namespace: app-team
spec:
parentRefs:
- name: api-gateway
namespace: infra
rules:
- matches:
- path:
type: PathPrefix
value: /v1/users
backendRefs:
- name: user-service
port: 8080
weight: 90
- name: user-service-canary
port: 8080
weight: 10
优势:角色清晰——GatewayClass由平台团队定义,Gateway由运维团队配置,HTTPRoute由开发团队管理。
二、逐步迁移指南
2.1 安装Gateway API CRD
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml
2.2 安装控制器(以Istio为例)
istioctl install --set profile=minimal
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: istio
spec:
controllerName: istio.io/gateway-controller
EOF
2.3 迁移Ingress到Gateway+HTTPRoute
迁移脚本思路:
for ingress in $(kubectl get ingress -A -o name); do
namespace=$(echo $ingress | cut -d'/' -f1 | cut -d'.' -f1)
name=$(echo $ingress | cut -d'/' -f2)
kubectl get $ingress -o yaml | python3 ingress2gateway.py > gateway-route.yaml
kubectl apply -f gateway-route.yaml
echo "Migrated $ingress, verify before deleting"
done
2.4 自动化迁移工具
import yaml
import sys
def ingress_to_gateway_route(ingress_data):
metadata = ingress_data['metadata']
spec = ingress_data['spec']
gateway = {
'apiVersion': 'gateway.networking.k8s.io/v1',
'kind': 'Gateway',
'metadata': {
'name': f"{metadata['name']}-gateway",
'namespace': metadata.get('namespace', 'default'),
},
'spec': {
'gatewayClassName': 'istio',
'listeners': [],
},
}
routes = []
for rule in spec.get('rules', []):
host = rule.get('host', '*')
listener_name = f"http-{host.replace('.', '-')}" if host != '*' else 'http'
gateway['spec']['listeners'].append({
'name': listener_name,
'port': 80,
'protocol': 'HTTP',
'hostname': host if host != '*' else None,
})
for path in rule.get('http', {}).get('paths', []):
route = {
'apiVersion': 'gateway.networking.k8s.io/v1',
'kind': 'HTTPRoute',
'metadata': {
'name': f"{metadata['name']}-route",
'namespace': metadata.get('namespace', 'default'),
},
'spec': {
'parentRefs': [{'name': f"{metadata['name']}-gateway"}],
'rules': [{
'matches': [{
'path': {
'type': 'PathPrefix',
'value': path.get('path', '/'),
}
}],
'backendRefs': [{
'name': path['backend']['service']['name'],
'port': path['backend']['service']['port']['number'],
}],
}],
},
}
routes.append(route)
return gateway, routes
if __name__ == '__main__':
ingress = yaml.safe_load(sys.stdin)
gw, routes = ingress_to_gateway_route(ingress)
for doc in [gw] + routes:
print('---')
print(yaml.dump(doc, default_flow_style=False))
三、流量管理
3.1 流量拆分(金丝雀发布)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: canary-route
spec:
parentRefs:
- name: api-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /api/v2
backendRefs:
- name: api-v2-stable
port: 8080
weight: 95
- name: api-v2-canary
port: 8080
weight: 5
3.2 流量镜像
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: HTTPRouteFilter
metadata:
name: mirror-filter
spec:
type: RequestMirror
requestMirror:
backendRef:
name: api-mirror
port: 8080
3.3 基于Header的路由
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: header-route
spec:
parentRefs:
- name: api-gateway
rules:
- matches:
- headers:
- type: Exact
name: X-Feature-Flag
value: new-ui
backendRefs:
- name: frontend-v2
port: 80
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: frontend-v1
port: 80
3.4 gRPC路由
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: grpc-route
spec:
parentRefs:
- name: api-gateway
rules:
- matches:
- method:
service: "com.example.UserService"
method: "GetUser"
backendRefs:
- name: user-grpc-service
port: 50051
四、多集群与多租户
4.1 多集群Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-cross-namespace
namespace: app-team
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: infra
to:
- group: ""
kind: Service
4.2 多租户隔离
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: tenant-a-gateway
namespace: tenant-a
spec:
gatewayClassName: istio
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Same
租户隔离策略对比:
| 策略 | 隔离级别 | 资源开销 | 管理复杂度 | 适用场景 |
|---|---|---|---|---|
| 共享Gateway | Route级 | 低 | 低 | 小规模、信任租户 |
| Namespace隔离 | Namespace级 | 中 | 中 | 中规模、一般隔离 |
| 独立Gateway | Gateway级 | 高 | 高 | 大规模、强隔离需求 |
5个常见陷阱
| # | 陷阱 | 后果 | 解决方案 |
|---|---|---|---|
| 1 | 直接删除Ingress再创建Gateway | 流量中断 | 先并行运行,验证后再删除 |
| 2 | HTTPRoute引用其他Namespace的Gateway | 权限被拒 | 创建ReferenceGrant |
| 3 | Gateway的allowedRoutes配置过严 | Route无法绑定 | 检查namespace selector |
| 4 | 忽略GatewayClass的参数 | 控制器行为不符预期 | 仔细阅读GatewayClassSpec.parametersRef |
| 5 | 流量拆分weight总和不为100 | 行为未定义(实现相关) | 确保weight总和为100 |
10个常见错误排查
| # | 错误现象 | 可能原因 | 排查方法 |
|---|---|---|---|
| 1 | HTTPRoute的Parents条件为Accepted: False |
Gateway不允许该Namespace | 检查Gateway的allowedRoutes |
| 2 | 流量未到达后端 | Route匹配规则错误 | 用kubectl describe httproute检查ResolvedRefs |
| 3 | GatewayNotReady |
控制器未安装或未运行 | 检查GatewayClass和控制器Pod |
| 4 | TLS证书未生效 | 证书Secret不存在或格式错误 | 检查Secret类型为kubernetes.io/tls |
| 5 | 金丝雀流量比例不对 | weight计算错误 | 确认weight总和为100且比例正确 |
| 6 | 跨Namespace引用被拒 | 缺少ReferenceGrant | 创建ReferenceGrant允许跨Namespace引用 |
| 7 | GRPCRoute不生效 | Gateway listener未配置H2C | 添加protocol: HTTP的listener并启用H2C |
| 8 | 流量镜像不工作 | 控制器不支持RequestMirror | 确认控制器实现支持该扩展 |
| 9 | Gateway IP未分配 | 控制器未配置LB | 检查控制器的Service和LoadBalancer |
| 10 | 迁移后性能下降 | 控制器配置未优化 | 对比Ingress和Gateway的代理配置 |
工具推荐
在Gateway API迁移过程中,以下工具可以帮助你处理配置和编码问题:
- JSON格式化工具 — 格式化Gateway API的Status和条件信息,方便调试路由状态
- Base64编码工具 — 对TLS证书和密钥进行Base64编码,用于Kubernetes Secret
- 哈希计算工具 — 为Gateway配置生成版本指纹,用于配置变更检测和回滚判断
总结:Gateway API不是Ingress的"升级版",而是流量管理的"重新设计"。三角色分离让平台、运维、开发各司其职;原生流量拆分让金丝雀发布不再依赖annotation hack;多协议支持让gRPC和TCP服务也能享受统一的流量管理。2026年,Ingress已经进入维护模式,Gateway API是唯一的方向。迁移的核心原则:先并行、再验证、最后切换——不要一步到位,让Ingress和Gateway API共存一段时间,确认流量正常后再移除Ingress。
本站提供浏览器本地工具,免注册即可试用 →