Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
本文介绍如何使用 ingress-nginx 将工作负载从应用程序路由加载项 迁移到 应用程序路由网关 API 实现,该实现通过 Kubernetes 网关 API 为流量提供服务。 这两个数据平面可以在同一 AKS 群集上并行运行,从而可以通过使用 DNS 切换客户端流量来执行零停机切换,而不是进行原地替换。
迁移原因
Caution
Kubernetes SIG 网络和安全响应委员会宣布停用Ingress NGINX 项目,维护已于 2026 年 3 月结束。 Microsoft将在 2026 年 11 月前为应用程序路由加载项 NGINX 入口资源提供关键安全修补程序的官方支持。
AKS 与上游 Kubernetes 保持一致,并使用 网关 API 作为入口和 L7 流量管理的长期标准。 根据要求,在 2026 年 11 月终止支持之前迁移:
- 应用程序路由加载项用户 和 OSS NGINX 用户:迁移到 应用程序路由 Gateway API 实现,以获得基于 Gateway API 的入口流量管理体验,或迁移到 Application Gateway for Containers,它同时支持 Ingress API 和 Gateway API。
- 服务网格或高级入口要求:考虑 使用 Istio 服务网格加载项的网关 API 入口。 无需向工作负载中注入边车,即可将它用于处理入口流量。 如果需要请求标头和正文大小限制、Lua 脚本或速率限制,请查看 网关 API 限制和替代方法。
对于基于 ingress-nginx 的应用程序路由外接程序,由 Microsoft 提供支持的安全补丁将于 2026 年 11 月终止。 AKS 上受支持的后继方案是应用程序路由 Gateway API 实现,它会部署一个轻量级的 Istio 控制平面,该控制平面仅协调属于 approuting-istioGatewayClass 的 Gateway API 资源,不支持 Istio CRD 或数据平面边车注入。
迁移的工作原理
ingress-nginx 加载项以及 Gateway API 实现的部署和服务各自都会获得自己的 Azure 负载均衡器 前端 IP。 在其解析得到的主机名指向 Gateway API 代理之前,客户端会一直访问 ingress-nginx 的 IP。
没有可原地将 ingress-nginx 负载均衡器 IP 替换为 Gateway API 负载均衡器 IP 的标志。 策略是并行运行这两个数据平面,验证新路径,然后将客户端移动到新的 IP。 如果上游系统(Azure Front Door 源站、Traffic Manager 终结点、防火墙允许列表)绑定了现有的 ingress-nginx IP,请将该上游配置更新为新的 Gateway IP,而不要尝试重新分配现有 IP——当拥有这些 IP 的 Service 被删除时,AKS 会删除其托管的公共 IP,即使将其标记为 Static 也是如此,因此你无法安全地执行原地 IP 替换。
主要差异
| 方面 | ingress-nginx 插件 | Gateway API(Istio)实现 |
|---|---|---|
| API |
networking.k8s.io/v1
Ingress
|
gateway.networking.k8s.io/v1
Gateway 和 HTTPRoute |
| Az CLI Enable 标志 | --enable-app-routing |
--enable-app-routing-istio(与 --enable-gateway-api 一起使用;需要 Managed Gateway API 加载项支持) |
| 类名 | webapprouting.kubernetes.azure.com |
approuting-istio |
| 数据平面服务 |
nginx 在 app-routing-system 中 |
<gateway-name>-approuting-istio 在 Gateway 的命名空间中 |
| Azure DNS/密钥保管库 TLS 连接 | 内置 | 使用应用程序路由网关 API 实现配置 Azure DNS 和 TLS |
先决条件
Azure CLI 2.86.0 或更高版本。
如果群集已启用 Istio 服务网格加载项,请先禁用它,并删除遗留的
networking.istio.ioCRD 和istioGatewayClass,然后再开始。 应用程序路由网关 API 控制平面在存在这些 CRD 时无法启动。 请参阅清理命令 的限制 。
设置本文其余部分使用的环境变量:
export RG=<resource-group>
export CLUSTER=<cluster-name>
步骤 1:清点当前入口
应用程序路由加载项可以运行多个 ingress-nginx 控制器。 每个 NginxIngressController 都有自己的入口类和自己的负载均衡器 IP。 清点所有这些,而不仅仅是默认控制器。 包括任何上游引用项,例如 Azure Front Door 源站、流量管理器终结点和防火墙允许列表。
列出加载项控制器及其 Ingress 类。 默认控制器使用类 webapprouting.kubernetes.azure.com。
kubectl get nginxingresscontrollers -o custom-columns=NAME:.metadata.name,CLASS:.spec.ingressClassName
列出所有 Ingress。 迁移其 CLASS 与上一个输出中的某个类匹配的项。
HOSTS 显示 DNS 中要更新的主机名,并 ADDRESS 显示控制器的负载均衡器 IP。
kubectl get ingress -A
后续步骤中,将把你要迁移的控制器 IP 记作 INGRESS_NGINX_IP。 从 ADDRESS 列中设置它:
INGRESS_NGINX_IP=<address-from-the-previous-output>
如果有多个控制器,请为每个控制器的 IP 和主机名重复步骤 3 到 7。
步骤 2:启用网关 API 实现
启用托管网关 API CRD 和应用程序路由网关 API 实现。 Ingress-nginx 继续处理流量。
az aks update --resource-group $RG --name $CLUSTER --enable-gateway-api
az aks update --resource-group $RG --name $CLUSTER --enable-app-routing-istio
验证控制平面和 GatewayClass 是否已就绪:
kubectl -n aks-istio-system rollout status deploy/istiod --timeout=5m
kubectl get gatewayclass approuting-istio
步骤 3:降低 DNS TTL
注释
如果客户端通过 IP 而不是 DNS 访问群集,请跳过此步骤。 步骤 7 中的切换是 DNS 更改,因此低 TTL 仅在 DNS 位于路径中时才相关。
对于解析为 INGRESS_NGINX_IP的每个主机名,将记录 TTL 降低到 60 秒(或提供程序允许的最小值)。 等待上一个 TTL 窗口完全过期,然后再继续。 如果上一个 TTL 为 1 小时,请等待至少一小时。 如果跳过此步骤,缓存解析程序在删除 Ingress后继续将客户端发送到 ingress-nginx。
步骤 4:将每个 Ingress 转换为 Gateway 和 HTTPRoute
为每个 Ingress 创建与之匹配的 Gateway 和 HTTPRoute。 有关各字段的转换说明(包括如何转换路径匹配规则、重定向、重写和标头处理),请参照 Kubernetes Gateway API 迁移指南。 若要批量转换现有清单,而不是手动编写,可以考虑使用 ingress2gateway;这是一个 Kubernetes SIG Network 工具,可读取 Ingress 资源(包括 ingress-nginx 注解)并生成等效的 Gateway API 资源——请将其输出视为起点,并在应用前进行审核。
默认情况下,ingress2gateway 只读取带有 nginx 类的 Ingress 资源,因此它会跳过应用程序路由类上的 Ingress 资源,除非你传入该类。 传入步骤 1 中的类和 --providers=ingress-nginx --ingress-nginx-ingress-class=<class>,并为每个类运行一次工具。
以下示例将一个用于主机Ingress、路径前缀为httpbin.contoso.com、后端为/get的 ingress-nginx httpbin:8000 进行转换。 作为参考,源内容 Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: httpbin
namespace: demo
spec:
ingressClassName: webapprouting.kubernetes.azure.com
rules:
- host: httpbin.contoso.com
http:
paths:
- path: /get
pathType: Prefix
backend:
service:
name: httpbin
port:
number: 8000
等效的 Gateway 和 HTTPRoute:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: httpbin-gateway
namespace: demo
spec:
gatewayClassName: approuting-istio
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin
namespace: demo
spec:
parentRefs:
- name: httpbin-gateway
hostnames: ["httpbin.contoso.com"]
rules:
- matches:
- path:
type: PathPrefix
value: /get
backendRefs:
- name: httpbin
port: 8000
等待 Gateway 完成配置并获取其公网 IP:
kubectl wait --for=condition=Programmed -n demo \
gateways.gateway.networking.k8s.io/httpbin-gateway --timeout=5m
GW_IP=$(kubectl get gateway -n demo httpbin-gateway -o jsonpath='{.status.addresses[0].value}')
步骤 5:在网关上预配 TLS
如果原始 Ingress 终止了 HTTPS 连接,请在更改 DNS 之前在新的 Gateway 服务器上配置 TLS。 按照配置 Azure DNS 和 TLS 以及 Application Routing 的 Gateway API 实现,让 Application Routing 操作器从 Azure 密钥保管库 同步证书,并为你设置侦听器certificateRefs。 如果需要完全控制证书同步,请按照 保护应用程序路由 Gateway API Ingress 流量 手动配置机密存储 CSI 驱动程序。
步骤 6:在切换客户端流量之前验证网关
使用 curl --resolve 固定 DNS 解析来探测这两个数据平面。 当你将探测程序置于循环中连续运行几分钟时,两者都应持续返回 200。
Important
在对网关 IP 进行充分验证之前,请勿切换。 步骤 7 中的 DNS 切换是真实客户端流量切入新数据平面的时刻;在这一刻,网关侧的任何故障都会变成客户可感知的服务中断。 那些通过直接访问 GW_IP 很容易发现的缺陷,在混入生产流量后就更难分类排查了。
# New Gateway path
curl -sS -o /dev/null -w '%{http_code}\n' \
--resolve "httpbin.contoso.com:80:${GW_IP}" \
http://httpbin.contoso.com/get
# Old ingress-nginx path (should still work)
curl -sS -o /dev/null -w '%{http_code}\n' \
--resolve "httpbin.contoso.com:80:${INGRESS_NGINX_IP}" \
http://httpbin.contoso.com/get
如果在步骤 5 中添加了 TLS 侦听器,还要通过将端口切换为 443 并将方案切换为 https:// 来探测 HTTPS。
在翻转 DNS 之前,请至少针对 GW_IP 以下项(使用 --resolve 或 Host 标头)进行验证:
-
每个主机名和路由,即原始
Ingress提供服务的所有主机名和路由,而不只是某个理想情况下的 URL。 对于共享同一主机但路径前缀、请求头匹配条件或方法不同的路由,必须分别访问到每一个路由。 - 由 提供生产证书的
Gateway。 验证证书链和 SAN 列表是否与客户端预期匹配;不依赖--insecure。 - 应用程序行为,而不仅仅是 HTTP 状态代码。 提交 POST 请求正文,测试身份验证,并在你的工作负载使用长时间运行的响应(流式处理、WebSocket、gRPC)时,确认它们能够端到端正常工作。
-
持续负载至少数分钟,来自探测循环,并观察是否出现间歇性的 5xx 响应、延迟回退,或
Gateway/HTTPRoute状态条件的频繁波动。 - 尽可能在非生产配置中进行上游集成——例如,将暂存 Front Door 源站或 Traffic Manager 终结点指向
GW_IP,并验证健康探测通过。
每次前面的检查都一致通过后,才继续执行步骤 7。 如果出现任何问题,请在 Gateway 侧进行修复,此时 ingress-nginx 仍在为实际客户端提供服务——在 DNS 变更之前,你始终有无限的回滚余地。
步骤 7:剪切
- 将该主机名的 DNS A 记录更新为指向
GW_IP。 由于已在步骤 3 中降低 TTL,因此排空将在几分钟内发生。 - 如果任何上游系统固定了 ingress-nginx IP(例如 Azure Front Door 源站、Traffic Manager 终结点或客户防火墙允许列表),请同时将其更新为
GW_IP。 请勿尝试将现有 IP 重新指派给网关:集群的云提供商会创建并管理 ingress-nginx Service 的公网 IP,并且当该 Service 被删除时,即使您将其设置为Static,这个公网 IP 也会被删除。 - 观察 ingress-nginx 上的流量下降情况。 抓取
ingress-nginx请求速率指标,直到请求数降至零。 - 将 DNS TTL 保持低等待数小时观察,然后将其提升回正常值。
步骤 8:清理
在 Gateway API 路径上的流量稳定后,停止加载项在集群上协调默认的 NginxIngressController,然后删除所有现有的 NginxIngressController 自定义资源。 此步骤中的 az aks approuting update --nginx None 命令会使控制器停止协调新资源,但它先前创建的 nginx Deployment 和 Service 仍会保留在集群中,直到您删除其所属的 NginxIngressController。
更新集群,使应用程序路由加载项不再管理默认的 ingress-nginx 控制器:
az aks approuting update --resource-group $RG --name $CLUSTER --nginx None
然后删除剩余 NginxIngressController 的资源:
kubectl delete nginxingresscontrollers.approuting.kubernetes.azure.com --all
验证稳定状态后,将 DNS TTL 提升回其正常值。
回滚
这两个数据平面可以共存,因此在禁用 ingress-nginx 插件之前的任何时刻,都可以进行对称回滚。 此过程会在整个切换过程中始终保留原始 Ingress 资源,因此回滚时只需还原 DNS:
如果在切换后删除了
Ingress资源,请重新创建它们。将 DNS 翻回到
INGRESS_NGINX_IP并等待 TTL 窗口清空。(可选)禁用网关 API 实现:
az aks update --resource-group $RG --name $CLUSTER --disable-app-routing-istio
运行 kubectl delete nginxingresscontrollers.approuting.kubernetes.azure.com 后,ingress-nginx 控制器就不存在了。 回退到该状态后,需要重新启用 Default NginxIngressController 加载项,并重新创建您删除的所有 Ingress 资源。 在禁用 ingress-nginx 之前验证所选路径。