技术博客

Ingress NGINX 正式退役:迁移到 Gateway API 完整操作指南

2026 年 3 月 24 日,Kubernetes 社区宣布 ingress-nginx 停止维护,不再有新版本、Bug 修复和安全补丁。本文从实际操作角度讲解迁移路径:为什么退役、迁移到什么(Gateway API + Envoy Gateway/Nginx Gateway Fabric/Cilium Gateway)、现有 Ingress 资源如何转换为 HTTPRoute、迁移过程如何做到零停机,以及迁移后的验证方法。

KubernetesGateway APIIngressHTTPRouteEnvoyCilium云原生迁移

2026 年 3 月 24 日,Kubernetes SIG Network 正式宣布:ingress-nginx 停止维护

从那天起,kubernetes/ingress-nginx 仓库不再发布新版本,不再修复 Bug,也不再处理任何安全漏洞。如果你的集群还在运行 ingress-nginx,继续使用意味着承担越来越大的安全风险。

本文讲清楚:迁到哪里,怎么迁,迁的过程中怎么不中断服务。


为什么退役

ingress-nginx 退役的核心原因:

1. Ingress API 本身的局限性
   Kubernetes Ingress API 设计于 2015 年,功能有限
   高级功能(流量权重/Header 路由/gRPC)只能靠 Annotation 实现
   Annotation 不是标准 API,不同实现互不兼容,难以迁移

2. Gateway API 已经成熟
   Gateway API 从 2023 年开始 v1 GA,功能远比 Ingress 强
   设计更清晰(Gateway / HTTPRoute / GRPCRoute 分层)
   社区已经将精力转向 Gateway API

3. ingress-nginx 积累了太多历史债务
   代码库复杂度高,维护成本大
   在新版本 Kubernetes 上持续出现兼容性问题

结果:社区决定不再投入,直接退役

Gateway API 基础概念

迁移之前,先理解 Gateway API 的三层结构:

传统 Ingress(单层):
  Ingress → 规则配置 + 实现 混在一起

Gateway API(三层分离):

  GatewayClass        (由集群管理员管理)
  └── 定义使用哪种实现(Envoy/Nginx/Cilium)

  Gateway             (由平台团队管理)
  └── 定义监听端口和协议(80/443)
  └── 关联到具体的 GatewayClass

  HTTPRoute/GRPCRoute  (由应用团队管理)
  └── 定义路由规则(域名/路径/Header/权重)
  └── 关联到 Gateway,指向后端 Service

优势:
  不同团队各自管理各自的层级(多租户友好)
  路由规则是标准 API,不是 Annotation
  换实现(Envoy→Cilium)只需改 GatewayClass,HTTPRoute 不用动

选择替代实现

目前 Gateway API 的主要实现:

实现方案对比(2026):

Envoy Gateway(推荐,最通用)
  ├── 厂商:CNCF 孵化项目
  ├── 底层:Envoy Proxy
  ├── 特点:功能最全,社区最活跃
  ├── 适用:通用场景,从 ingress-nginx 迁移首选
  └── 官网:gateway.envoyproxy.io

Nginx Gateway Fabric(官方 NGINX 支持)
  ├── 厂商:F5/NGINX
  ├── 底层:NGINX OSS
  ├── 特点:原 ingress-nginx 用户迁移成本最低
  ├── 适用:习惯 NGINX 的团队
  └── 官网:docs.nginx.com/nginx-gateway-fabric

Cilium Gateway(如果已用 Cilium CNI)
  ├── 厂商:Isovalent(Cisco)
  ├── 底层:eBPF + Envoy
  ├── 特点:CNI + Gateway 一体,性能最好
  ├── 适用:已经使用 Cilium CNI 的集群
  └── 官网:docs.cilium.io/en/stable/network/servicemesh/gateway-api

选型建议:
  全新集群 → Envoy Gateway 或 Cilium Gateway
  已用 NGINX,想平滑迁移 → Nginx Gateway Fabric
  已用 Cilium CNI → 直接启用 Cilium Gateway

迁移操作:以 Envoy Gateway 为例

第一步:安装 Gateway API CRD 和 Envoy Gateway

# 安装 Gateway API CRD(v1.2 或更高)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml

# 安装 Envoy Gateway
helm install eg oci://docker.io/envoyproxy/gateway-helm \
  --version v1.3.0 \
  --namespace envoy-gateway-system \
  --create-namespace

# 等待 Envoy Gateway 就绪
kubectl wait --timeout=5m \
  -n envoy-gateway-system \
  deployment/envoy-gateway \
  --for=condition=Available

第二步:创建 GatewayClass 和 Gateway

# GatewayClass:告诉集群使用 Envoy Gateway 实现
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: envoy
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller

---
# Gateway:定义监听端口
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: prod-gateway
  namespace: envoy-gateway-system
spec:
  gatewayClassName: envoy
  listeners:
  - name: http
    port: 80
    protocol: HTTP
  - name: https
    port: 443
    protocol: HTTPS
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        name: prod-tls-cert
        namespace: envoy-gateway-system
# 确认 Gateway 获取到外部 IP
kubectl get gateway -n envoy-gateway-system
# NAME           CLASS   ADDRESS          PROGRAMMED   AGE
# prod-gateway   envoy   203.0.113.100    True         2m

第三步:将 Ingress 转换为 HTTPRoute

# 迁移前(旧的 Ingress):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend-service
            port:
              number: 80
# 迁移后(新的 HTTPRoute):
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: myapp-route
  namespace: default
spec:
  parentRefs:
  - name: prod-gateway
    namespace: envoy-gateway-system
  hostnames:
  - "myapp.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /api
    backendRefs:
    - name: api-service
      port: 8080
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: frontend-service
      port: 80

常见 Annotation 的迁移对照

原 ingress-nginx Annotation → Gateway API 等效实现

nginx.ingress.kubernetes.io/ssl-redirect: "true"
→ HTTPRoute 添加 filters: [{type: RequestRedirect, requestRedirect: {scheme: https}}]

nginx.ingress.kubernetes.io/rewrite-target: /
→ HTTPRoute filters: [{type: URLRewrite, urlRewrite: {path: {type: ReplaceFullPath}}}]

nginx.ingress.kubernetes.io/proxy-body-size: "50m"
→ EnvoyProxy 配置(BackendTrafficPolicy)

nginx.ingress.kubernetes.io/rate-limit
→ BackendTrafficPolicy rateLimit 字段

nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20"
→ HTTPRoute 多个 backendRefs 设置 weight 字段

示例(流量权重):
# Canary 发布:90% 流量走 stable,10% 走 canary
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: canary-route
spec:
  parentRefs:
  - name: prod-gateway
    namespace: envoy-gateway-system
  hostnames:
  - "myapp.example.com"
  rules:
  - backendRefs:
    - name: myapp-stable
      port: 80
      weight: 90
    - name: myapp-canary
      port: 80
      weight: 10

零停机迁移策略

推荐的迁移顺序(不影响生产流量):

阶段 1:并行运行(1-2 周)
  ├── 保留 ingress-nginx 继续处理流量
  ├── 安装 Gateway API + Envoy Gateway
  ├── 创建 HTTPRoute,但使用不同域名测试
  └── 验证功能一致性

阶段 2:DNS 切量(按服务逐一迁移)
  ├── 低重要性服务先迁(内部工具/测试环境)
  ├── 改 DNS:将域名指向新的 Gateway 地址
  ├── 观察 1-2 天,确认无异常
  └── 继续迁移下一批服务

阶段 3:完成迁移
  ├── 所有服务切换完毕
  ├── 删除旧的 Ingress 资源
  └── 卸载 ingress-nginx

验证命令:
# 测试新的 HTTPRoute 是否正常响应
curl -H "Host: myapp.example.com" \
  http://<gateway-external-ip>/api/health

# 检查 HTTPRoute 状态
kubectl get httproute -A
# 确认 Accepted 和 ResolvedRefs 都为 True

# 对比新旧响应头(确认行为一致)
curl -v -H "Host: myapp.example.com" http://<old-nginx-ip>/api/health
curl -v -H "Host: myapp.example.com" http://<new-gateway-ip>/api/health

小结

Ingress NGINX 退役是 Kubernetes 生态演进的必然结果——Gateway API 在设计上更合理、功能更强、扩展性更好。

迁移有一定工作量,但不需要着急地“一次全迁”。合理的策略是:先并行部署新实现,按服务逐一切流量,验证稳定后再删除旧资源。整个过程可以做到对线上业务零影响。

如果你的集群已经在用 Cilium CNI,Gateway API 的启用只需要改一个 Helm 参数,是成本最低的迁移路线。