从 入口控制器 NGINX到Envoy 网关的零停机迁移

来源: Cloud Native Computing Foundation
作者: Andrew Katsikas, Pelotech
发布时间: 2026/5/25 19:00:00
原文链接: https://www.cncf.io/blog/2026/5/25/zero-downtime-migration-from-ingress-nginx-to-envoy-gateway/


发布于2026年5月25日,作者:Andrew Katsikas,Pelotech

本文重点介绍的 CNCF 项目

](https://www.cncf.io/projects/kubernetes “Go to Kubernetes”)

在生产环境中运行 Ingress NGINX 的团队,随着 Kubernetes 网络向 Gateway API 演进,正在越来越多地评估迁移路径。

对许多组织而言,挑战不仅在于选择 Gateway API 实现方案,更在于设计一种能在切换期间将运营风险降至最低的迁移策略。

大多数工程团队知道自己需要迁移,但缺乏足够带宽进行妥善评估,不确定哪个 Gateway API 控制器才是长期正确的选择,并且意识到一旦 DNS TTL 与现实不符,仓促的切换就会导致生产流量丢失。

本文是我们最近为一家 AWS 客户完成的 Ingress NGINX 迁移案例研究。文中详细介绍了我们如何选择 Envoy Gateway,如何先在自有基础设施上测试迁移,为什么首次成功的切换还不够好,以及最终实现干净零停机结果的加权 DNS 方法。文末还附有简短 FAQ,涵盖了我们在这次迁移中经常被问到的问题。

如果你正在自行完成这一迁移,本文的目标是为你省去我们已经完成的前期调研工作。

为什么从 Ingress NGINX 迁移到 Gateway API

Ingress NGINX 控制器是 Kubernetes 生态系统中部署最广泛的控制器之一,目前大量生产集群都在运行它。

随着无安全补丁、无新增功能,且 Ingress API 已停滞不动,Gateway API 成为了合理的下一步。它是一个更具表现力的规范,用专用资源替代了注解,以处理相同的问题。

在近期为 AWS 上的客户提供的服务中,我们在确定了 Envoy Gateway 之前,评估了多个 Gateway API 实现方案和迁移方法。

由于我们在 Foundation(我们成熟的 GitOps Kubernetes 平台)中使用了 Ingress NGINX,这次迁移对客户和对我们自身同样重要。

在我们研究这项工作期间阅读的几乎所有迁移指南,都在“流量已迁移”处戛然而止。如果你是在做演示,这倒是一个不错的结果。但在生产环境中,在不丢弃正在处理的请求的情况下完成流量迁移,则完全是另一个问题,而这也是本文余下部分要讨论的内容。

将客户从 Ingress NGINX 迁移到 Envoy Gateway

选择合适的 Gateway API 控制器

第一步是在低风险环境中亲自动手实践。我们使用了 Kind(Kubernetes IN Docker),它可以在 Docker 容器内部启动一个本地 Kubernetes 集群。这是在不涉及真实基础设施的情况下进行原型设计和实验的好方法,我们在整个评估过程中都使用了它。

我们开始通过一个名为 ing-switch 的项目来评估选项。它是一个迁移工具,能扫描集群中所有主流控制器的 Ingress 资源,映射带有影响评级的注解,并通过 CLI 或可视化 UI 生成迁移清单。它为我们提供了一个有用的起点,帮助我们了解现有环境以及迁移实际涉及的内容。

我们想探索的一件事是,单个控制器能否同时满足 Ingress 和 Gateway API 的需求。其思路是,双模式控制器可以充当桥梁,在过渡期间让两者并行运行,而不是进行硬切换。

我们最初广泛撒网,包括了 CNCF 生态系统之外的项目。随着评估的推进,CNCF 一致性成为了一项有意义的筛选条件。云原生计算基金会(CNCF)托管着 Kubernetes 生态系统中最重要的项目,包括 ArgoCD、cert-manager、ExternalDNS 以及许多构成 Foundation 核心的其他项目。

在为客户做出长期基础设施决策时,我们关注那些已获得社区共识并满足 CNCF 生产就绪标准的项目。

除了 CNCF 状态,我们还关注一些具体事项:

  • 与我们当前使用的注解保持一致性
  • 支持生产环境中的实际需求,如 mTLS 和请求缓冲
  • 一个遵循 Gateway API 专用资源模型,而不是注解泛滥的控制器

以下是我们根据这些标准考虑的不同 Gateway API 控制器之间的比较

控制器

CNCF 状态

我们的评估说明

Envoy Gateway

CNCF 项目

由 CNCF 在其自有基础设施上运行。满足我们对 mTLS 和请求缓冲的需求。已选定。

Traefik

非 CNCF

与我们长期方向的一致性较弱。

NGINX Gateway Fabric

非 CNCF

不属于我们确定的 CNCF 筛选范围。

Istio

CNCF 项目

功能集全面。

Higress

CNCF 项目

未出现在官方 Kubernetes Gateway API 一致性测试结果中。

关于 Envoy Gateway 贡献者数据的说明:更大的 Envoy 项目有广泛贡献;Envoy Gateway 本身目前有 4 位贡献者,其中一家组织贡献占比达 51% 或以上。

Envoy Gateway 脱颖而出。它是一个 CNCF 项目,规范完善,CNCF 在其自有基础设施上运行。达到 CNCF 毕业标准让我们对工具选择充满信心,而了解这些标准背后的人在内部分做出相同选择,则是一个更强烈的信号。

首先在自有基础设施上测试 Envoy Gateway

选定 Envoy Gateway 后,下一个问题是测试地点。

在将其交付客户之前,我们希望先在自有基础设施上进行验证。我们构建了一个连接到 AWS Network Load Balancer 的 Envoy Gateway 组件,并依赖另外两个我们已经信任的 Foundation 组件:用于自动 DNS 记录管理的 ExternalDNS 和用于 TLS 的 cert-manager。这些集成点我们很熟悉,因此可以专注于迁移本身。

作为试验场,我们选择了内部的 Goldilocks 实例。Goldilocks 是一个为 Kubernetes 工作负载生成资源请求和限制建议的工具。它的 Helm chart 同时支持 Ingress 和 Gateway API,这意味着我们可以在不进行任何应用级更改的情况下同时运行两者。它也是一个部署相当简单的应用程序,因此非常适合在不引入多余变量的情况下演练迁移机制。

为了监控切换过程,我们编写了一个简单的 shell 脚本,轮询我们的端点,并通过 tee 将输出同时发送到终端和日志文件。这为我们提供了整个过程中 HTTP 状态码的清晰、可回顾的记录。

一次成功的 Gateway API 迁移,但还不够好

第一次切换进行得相当顺利。我们启动了 Envoy Gateway HTTPRoute,与现有的 Ingress 并存,监视着轮询脚本,然后执行了切换。有一个手动步骤值得一提:由于我们使用 ArgoCD 管理集群,并且没有使用 prune 选项,旧的 Ingress 资源没有自动清理。我们不得不通过 Argo 手动删除它。这不是大问题,只是在真实迁移计划中需要考虑。

迁移成功了。然而,在查看日志文件时,我们发现切换期间存在一段停机时间。罪魁祸首是 DNS。当你交换一条 A 记录时,你受制于旧记录上设置的 TTL(生存时间)。在该 TTL 过期之前,客户端仍然解析到旧地址。如果旧的 Ingress 已被删除,这些请求将无处可去。我们完成了迁移,但并不干净。

这对我们来说还不够好。大多数迁移指南到这里就结束了。但我们的没有,因为让流量迁移是一回事,而让流量迁移过程中不丢弃任何请求则是另一回事。我们回到了绘图板。

通过加权 DNS 实现零停机

第一次尝试的问题是顺序。我们在 DNS 来得及更新之前就删除了旧的 Ingress。在过渡期间,流量需要一个稳定的目的地。

我们最终采用了通过 ExternalDNS 和 AWS Route 53 实现的 加权 DNS 记录。不是硬切换,而是让 Ingress 和 HTTPRoute 同时运行,各自注册相同的主机名,但设置不同的权重。通过将 Ingress 权重设置高、HTTPRoute 权重设置为零,HTTPRoute 将处于活动状态但不接收流量,实际上处于闲置状态。一旦我们确认一切都正确启动,就可以交换权重,将流量迁移过去,而无需创建或删除任何 DNS 记录。

ExternalDNS 会监视 Ingress 和 HTTPRoute 资源上的注释,并自动管理加权的 Route 53 记录。Ingress 的注释如下所示:

`
external-dns.alpha.kubernetes.io/aws-weight: “100”
`

并且HTTPRoute起始于:

`
external-dns.alpha.kubernetes.io/aws-weight: “0”
`

这两个资源都指向同一个主机名,两者均在 Route 53(AWS 域名注册与解析服务)中注册,所有流量都通过 Ingress(入口控制器)流动。当准备进行切换时,我们交换了权重:

`

Ingress

external-dns.alpha.kubernetes.io/aws-weight: “0”
#HTTPRoute
external-dns.alpha.kubernetes.io/aws-weight: “100”
`

轮询脚本在切换期间持续运行,并确认了结果:没有出现任何失败请求。我们还验证了请求现已通过新的 AWS 负载均衡器,并按预期通过 HTTPRoute 进行路由。

值得注意: 这种方法还使得回滚变得非常简单。如果切换后出现任何问题,只需将权重交换回去即可。无需重建 DNS 记录,无需重新部署资源,回滚的传播方式与切换完全相同。加权 DNS 模式也与控制器无关。我们将其用于 Envoy Gateway,但同样的方法适用于 ExternalDNS 能够管理的任何 Gateway API 实现。

实际生产环境下暴露的问题

Goldilocks 测试让我们对机制有了信心。随后,生产环境带来了我们内部测试中未暴露的需求。

其中一些需求我们已经以类似的方式解决。客户需要带有证书转发的 mTLS,以及请求缓冲区限制。我们在评估阶段就干净利落地解决了这两个问题,这让我们在进入客户合作时真正充满信心。由于我们已经以类似方式处理过这些问题,因此在迁移过程中并未发现它们。

我们完全没有预料到的是多命名空间(multi-namespace)模型。客户在每个集群中运行多个命名空间以代表不同的环境,这是一种常见且合理的模式。挑战在于,在 Gateway API 1.5 之前,主机名必须在 Gateway 层和 HTTPRoute 层都进行定义。

Gateway 是集群级资源,通常由平台或基础设施团队拥有。HTTPRoute 是应用级资源,由开发人员拥有。

来源: Gateway API

当主机名配置位于 Gateway 级别时,你实际上是在将应用层关注点向上提升到基础设施层。这恰恰打破了 Gateway API 本应实现的责任分离。

在单命名空间规模下,这种做法尚可忍受。但在跨多个代表不同环境的命名空间时,这就变成了一个真正的问题。Gateway API 1.5 是一个稳定版本,并直接解决了这个问题。问题在于控制器还没有跟上该规范的更新。

Gateway API 的下一步

Gateway API 1.5 引入了 ListenerSet,这是一种新的资源类型,旨在实现这种责任分离。ListenerSet 允许应用团队定义自己的监听器,而无需触碰 Gateway 资源本身。基础设施关注点保留在基础设施层,应用关注点保留在应用层。

Envoy Gateway 已实现了 ListenerSet,目前处于候选发布版(Release Candidate)阶段,稳定版本预计几天内发布。我们已经在特性标志(feature flag)后测试了该候选版,并准备好在稳定版本发布后迅速行动。我们对 Envoy Gateway 团队充满信心,期待在稳定版本发布后实施这一功能,因为它将显著改善我们在跨命名空间时分离基础设施与应用关注点的方式。

回顾:正确完成 Ingress NGINX 迁移

从 Ingress NGINX 迁移的压力是真实存在的,团队每多使用一个月基于功能冻结 API(feature-frozen API)构建的 EOL(End-of-Life,生命周期终止)控制器,就离 Kubernetes 的发展方向更远一步。这种紧迫性是合理的,但不能成为偷工减料或实施次优方案的借口。

我们最初的目标是帮助一个客户实现零停机迁移,建立一个稳固的长期基础,不采取任何捷径。加权 DNS 方法提供了我们想要的干净切换。Envoy Gateway 给了我们一个值得信赖的控制器。更深刻的教训是,一次能够迁移流量与一次零请求丢失的迁移之间的区别,在于大多数指南跳过的那几个步骤。

如果 Ingress NGINX 在你的技术栈中,现在正是开始规划的好时机。你今天做出的基础设施决策将决定你未来能多顺畅地采用后续技术。

如果你的团队正在进行这次迁移,或者在犹豫现在是否是开始的好时机,我们已经完成了评估、测试和验证这些艰苦工作,并且很乐意与你讨论具体细节。立即联系我们