将 Ingress NGINX 迁移到 Azure Kubernetes Service 上的 Gateway API
很遗憾 Ingress NGINX 项目已经走到了生命的尽头……自 2026年3月起,官方已经不再维护它了。Azure Kubernetes Service (AKS) 官方给出了若干迁移方案,其中包括使用使用 Gateway API 替代它。Gateway API 与 Ingress NGINX 的功能类似,但某些行为有所不同。但对 Ingress NGINX 的非常规使用,可能导致在迁移到 Gateway API 时出现一些挑战。
SNI 与 Host 🔗
在 Ingress Nginx 中,可使用 A 域名用于 TLS Termination,然后用 B 域名进行路由匹配。在企业应用中,这可能是一种常见模式。比如,应用的域名为 B,指向 CDN (比如 Front Door),利用 CDN 的 TLS 证书续期,可大大减少维护性工作。在 CDN 中使用 A 域名配置后端的源。这样发给 Nginx Ingress 的请求会使用 A 域名建立 TLS 连接,但 HTTP 请求的 Host 是 B 域名,用于内部的路由匹配。当 B 域名是第三方域名并且不拥有该域名证书时,这种模式是非常有用的。
但是,在 Gateway API 中,TLS Termination 的 SNI 与 HTTP 请求的 Host 必须一致,或者至少有交集(见文档《Hostname Intersection》),否则会出现路由匹配失败,返回 404 Not Found的问题。也就是说,Gateway API 不支持使用 A 域名进行 TLS Termination,然后使用 B 域名进行路由匹配的模式。
这该怎么解决?
URL 规范化 🔗
Ingress NGINX 默认会对请求的 URL 进行规范化处理。比如将请求地址里的两个斜杠 // 规范化为一个斜杠 /,将请求地址里的 .. 规范化为上级目录 ../。但是 Gateway API 不会对请求的 URL 进行规范化处理。也就是说,如果请求地址里有两个斜杠 //,那么 Gateway API 会将其作为两个斜杠处理,而不会将其规范化为一个斜杠 /。这可能会导致路由匹配失败,返回 404 Not Found 的问题。
比如,Ingress NGINX 会将请求地址 domain.com//health 规范化为 domain.com/health,然后进行路由匹配。而 Gateway API 会直接将请求地址 domain.com//health 原样进行路由匹配,结果会失败,返回 404 Not Found 的问题。