三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

从Ingress Nginx迁移到Kubernetes Gateway API:下一代云原生网关实战指南

从Ingress Nginx迁移到Kubernetes Gateway API:下一代云原生网关实战指南

1. 项目概述:从 Ingress Nginx 到 Gateway API 的必然演进

最近在云原生社区里,一个消息引发了不小的讨论:Ingress Nginx 项目即将进入维护模式,不再增加新功能。这对于大量依赖它作为 Kubernetes 集群入口网关的团队来说,无疑是一个需要认真对待的信号。我自己的生产环境里也跑着不少 Ingress Nginx 的实例,听到这个消息后,第一反应不是焦虑,而是觉得这是一个契机,一个推动技术栈向更标准、更强大方向演进的契机。这个契机,就是 Kubernetes Gateway API。

简单来说,这个项目就是教你如何从熟悉的 Ingress Nginx 平稳过渡到代表未来的 Gateway API,并利用其构建下一代云原生路由体系。它解决了什么问题?最直接的,是解决了 Ingress 资源模型表达能力不足、厂商实现碎片化以及多租户支持薄弱的核心痛点。举个例子,在 Ingress 时代,如果你想做一个基于请求头X-User-Type: vip的灰度发布,或者实现精细化的流量切分和镜像,原生的 Ingress 规范要么不支持,要么需要借助各种 Annotation(注解)来实现,而这些注解在不同 Ingress Controller(如 Nginx, Contour, Traefik)之间完全不通用,换一个就得重写配置,维护成本极高。

Gateway API 就是为了终结这种混乱而生的。它是一套由 Kubernetes SIG-Network 社区主导设计的、表达力更强的官方标准 API。它不再是一个“万能”的 Ingress 资源,而是拆解成了GatewayClass,Gateway,HTTPRoute等一组资源,各司其职,清晰定义了基础设施提供商、集群管理员、应用开发者的职责边界。这不仅仅是 API 的升级,更是运维模型和权限模型的升级。

那么,这个项目适合谁?如果你是正在使用 Ingress Nginx 的运维工程师或平台开发者,担心未来的技术债务,那么你需要了解如何迁移。如果你是刚开始设计 Kubernetes 入口方案的新团队,那么直接拥抱 Gateway API 无疑是更前瞻的选择。即便你只是对云原生网络感兴趣,理解 Gateway API 的设计哲学,也能让你对 Kubernetes 的服务网络有更深刻的认识。接下来,我将手把手带你从概念到实操,完成这次关键的架构升级。

2. 核心架构解析:为什么 Gateway API 是“下一代”

要理解为什么迁移是值得的,我们必须先抛开具体的配置语法,深入看看 Gateway API 在架构设计上到底做了哪些革新。这不仅仅是换了个 YAML 文件格式那么简单,而是一次对 Kubernetes 入口流量管理范式的重新定义。

2.1 角色分离与多租户支持

这是 Gateway API 最核心的进步。在传统的 Ingress 模型里,通常只有一个Ingress资源。开发者在里面定义主机名、路径规则和后端服务。但问题来了:谁来决定监听哪些端口和协议?谁来配置负载均衡器?SSL 证书由谁管理?这些职责往往模糊地混杂在一起,要么需要集群管理员介入,要么开发者通过注解拥有过大的权限,安全边界不清。

Gateway API 通过引入明确的角色,优雅地解决了这个问题:

  1. 基础设施提供商:他们定义GatewayClass。这相当于一个“网关类型”的模板,声明了底层实现的种类,比如“使用 Contour 实现的网关”、“使用 Istio 实现的网关”。他们负责让这个GatewayClass在集群中可用。
  2. 集群管理员:他们创建Gateway资源。这个资源代表一个具体的、部署好的网关实例。管理员在这里配置网络层的关键属性:监听哪些端口(如 80, 443)、使用什么协议(HTTP, HTTPS, TLS)、为哪些主机名提供服务(*.example.com),以及绑定 TLS 证书。Gateway引用一个GatewayClass,从而确定了具体的实现技术。通过 Kubernetes 的 RBAC,可以严格限制只有管理员能操作Gateway资源。
  3. 应用开发者:他们创建HTTPRoute(或TCPRoute,GRPCRoute等)资源。这个资源才是真正定义路由规则的地方:将特定主机名下的特定路径(如/api/v1/*),转发到自己的后端 Service。开发者完全不需要关心网关监听什么端口、证书从哪里来,他们只需要将自己的HTTPRoute通过parentRefs字段关联到管理员创建好的Gateway上即可。

这种分离带来了巨大的好处:平台团队可以集中管理网络入口和安全策略(TLS),应用团队可以自助式地发布和配置自己的路由规则,互不干扰,完美契合了云原生环境下的多租户和自助服务需求。

2.2 跨实现的可移植性

Ingress 的一个主要痛点是“注解地狱”。为了实现高级功能(如超时、重试、认证),你必须使用特定 Ingress Controller 的注解,例如nginx.ingress.kubernetes.io/proxy-connect-timeout: "30s"。一旦你想从 Nginx Ingress Controller 切换到 Traefik,所有这些配置都需要重写,迁移成本巨大。

Gateway API 将许多常见的高级功能直接设计成了 API 字段,成为了标准的一部分。例如,在HTTPRoute的规则中,你可以直接配置:

rules: - matches: - path: value: "/api" filters: - type: RequestHeaderModifier requestHeaderModifier: add: - name: "X-Env" value: "canary" backendRefs: - name: my-canary-service port: 80

上面的配置表示:匹配路径/api,在转发前添加一个请求头X-Env: canary,然后转发到my-canary-service。这个RequestHeaderModifier过滤器是 Gateway API 的标准字段,任何兼容的实现(如 Envoy Gateway, Contour, Istio)都必须以相同的方式支持它。这意味着你的路由配置在不同网关实现间有了可移植性。

当然,Gateway API 也通过ExtensionRef机制允许厂商提供自定义功能,但它鼓励并将通用功能标准化,这极大地减少了供应商锁定的风险。

2.3 更丰富的路由匹配与流量管理能力

原生的 Ingress 只支持基于主机(host)和路径(path)的匹配,功能非常基础。Gateway API 的HTTPRoute则强大得多:

  • 多维匹配:可以同时基于路径、请求头(Header)、查询参数(Query Params)甚至 HTTP 方法(GET, POST)进行组合匹配。这使得实现基于用户身份、设备类型或 API 版本的精细化路由成为可能。
  • 流量切分:原生支持将流量按百分比分配给不同的后端服务。这是实现金丝雀发布、蓝绿部署的核心功能,无需再依赖服务网格或复杂的注解。
    rules: - matches: - path: value: "/" backendRefs: - name: production-service port: 80 weight: 90 - name: canary-service port: 80 weight: 10
  • 过滤器链:除了前面提到的修改头部的过滤器,还支持重定向、URL 重写、请求镜像等。特别是请求镜像,可以将一部分生产流量复制到测试环境,用于监控或压测,而对原请求不产生影响。

这些能力原本需要借助服务网格(Service Mesh)或高级的 Ingress Controller 扩展才能实现,现在在入口网关层通过标准 API 即可完成,技术栈得以简化。

注意:Gateway API 目前仍处于发展阶段,其 API 分为Experimental(实验)、Standard(标准)和Extended(扩展)三个通道。生产环境采用时,建议重点关注已进入Standard通道的资源,如GatewayClass,Gateway,HTTPRoute。对于TCPRoute或更高级的GRPCRoute,需评估其成熟度及所用网关实现的兼容情况。

3. 实战迁移:从 Ingress Nginx 配置到 Gateway API 资源

理论讲得再多,不如动手实践。我们假设一个非常典型的 Ingress Nginx 配置场景,然后一步步将其转换为 Gateway API 的配置。这个例子涵盖了 HTTPS、多路径路由和简单的重写规则。

3.1 原始 Ingress Nginx 配置示例

假设我们有一个名为my-app的应用,它有两个服务:前端web-ui和后端api-service。我们希望通过app.example.com域名访问,其中/路径走前端,/api/路径走后端,并且需要自动将/api/前缀重写掉(即后端服务接收到的请求路径不包含/api)。同时,我们已有一个 TLS 证书。

对应的 Ingress Nginx 的 YAML 可能如下所示:

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-app-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: tls: - hosts: - app.example.com secretName: my-app-tls rules: - host: app.example.com http: paths: - path: / pathType: Prefix backend: service: name: web-ui port: number: 80 - path: /api(/|$)(.*) pathType: Prefix backend: service: name: api-service port: number: 8080

这个配置做了几件事:

  1. 通过注解cert-manager.io/cluster-issuer自动管理 TLS 证书(假设已安装 cert-manager)。
  2. 定义 TLS 部分,指定域名和存储证书的 Secret。
  3. 定义两条路由规则:
    • 路径/转发到web-ui服务的 80 端口。
    • 路径/api(/|$)(.*)使用正则表达式匹配,并通过rewrite-target注解将捕获组$2(即/api之后的部分)重写为新的路径,然后转发到api-service的 8080 端口。

3.2 Gateway API 资源配置详解

现在,我们将上述功能用 Gateway API 的资源来实现。我们需要创建三个资源:Gateway,HTTPRoute,并且证书管理方式也可能发生变化。

第一步:创建 Gateway 资源(由集群管理员操作)

Gateway资源定义了网关实例的“监听器”。它不关心具体的路由规则,只关心网络层面的配置。

apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: prod-gateway namespace: infra-team # 通常由平台团队管理,放在独立命名空间 spec: gatewayClassName: contour # 指定使用的 GatewayClass,这里以 Contour 为例 listeners: - name: https-app protocol: HTTPS port: 443 hostname: "app.example.com" tls: mode: Terminate certificateRefs: - kind: Secret name: my-app-tls namespace: default # 证书所在的命名空间 allowedRoutes: namespaces: from: Same

关键点解析

  • gatewayClassName: contour:这指向一个已由基础设施团队定义好的GatewayClass,它代表了底层使用 Contour 作为数据平面。
  • listeners:定义了一个监听器,在 443 端口上监听 HTTPS 协议,且只针对主机名app.example.com
  • tls.mode: Terminate:表示在此网关上终止 TLS 连接。
  • certificateRefs:引用了一个名为my-app-tls的 Kubernetes Secret,该 Secret 应包含有效的 TLS 证书和私钥。注意:Gateway API 本身不管理证书生命周期,你仍需使用 cert-manager 等工具生成证书并创建此 Secret。cert-manager 也已支持为 Gateway API 签发证书。
  • allowedRoutes:这是一个重要的安全边界。namespaces.from: Same表示只允许与当前Gateway资源在同一命名空间(infra-team)中的HTTPRoute绑定到此监听器。你也可以设置为All或通过selector选择特定命名空间,以实现灵活的跨命名空间路由绑定。

第二步:创建 HTTPRoute 资源(由应用开发者操作)

HTTPRoute资源定义了具体的路由规则,并绑定到上一步创建的Gateway

apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: my-app-route namespace: default # 应用所在的命名空间 spec: parentRefs: - name: prod-gateway namespace: infra-team # 指定 Gateway 所在的命名空间 sectionName: https-app # 指定绑定到 Gateway 的哪个监听器 hostnames: - "app.example.com" rules: # 规则1:匹配根路径,转发到前端服务 - matches: - path: type: PathPrefix value: / backendRefs: - name: web-ui port: 80 # 规则2:匹配 /api 路径,重写后转发到后端服务 - matches: - path: type: PathPrefix value: /api filters: - type: URLRewrite urlRewrite: path: type: ReplacePrefix replacePrefixMatch: /api replacement: / backendRefs: - name: api-service port: 8080

关键点解析

  • parentRefs:这是将本路由规则“挂载”到网关的关键。它指明了使用哪个Gatewayprod-gateway,位于infra-team命名空间)的哪个监听器(https-app)。
  • hostnames:进一步限定此路由规则仅对app.example.com生效。虽然Gateway监听器已经限定了主机名,但在HTTPRoute中再次声明是一个好习惯,也便于管理。
  • rules:包含两个规则。
    • 第一个规则匹配路径前缀/,直接转发到web-ui服务。
    • 第二个规则匹配路径前缀/api。这里使用了 Gateway API 标准过滤器URLRewrite。其配置是:当匹配到前缀/api时,将其替换为/。这样,到达api-service的请求路径就不再包含/api前缀了。这比 Ingress Nginx 的正则表达式重写更直观、更声明式。

3.3 迁移过程中的核心差异与注意事项

通过上面的对比,我们可以清晰地看到迁移带来的变化和需要注意的细节:

  1. 配置拆分与职责分离:一个Ingress变成了一个Gateway+ 一个或多个HTTPRoute。网络配置(端口、证书)和路由配置(路径、后端)被物理分离,分别由不同角色管理。
  2. 注解的消亡与标准字段的崛起nginx.ingress.kubernetes.io/rewrite-target这种厂商特定的注解,被替换成了标准的filters字段下的URLRewrite过滤器。这大大提升了配置的可移植性。
  3. 命名空间隔离与安全:Gateway API 显式地支持跨命名空间的路由绑定,并通过allowedRoutes进行控制。这为大型集群的多团队协作提供了安全的模型。在 Ingress 中,虽然也可以通过 RBAC 控制,但模型上不如 Gateway API 清晰。
  4. 证书管理:两者都需要 Secret 存储证书。区别在于,Gateway API 的Gateway资源显式地引用这个 Secret。cert-manager 等工具对两者的支持都在不断成熟中。
  5. 路径匹配语法:Gateway API 的路径匹配类型(Exact,PathPrefix,RegularExpression)更规范。它不再直接使用 Nginx 风格的正则,而是通过type: RegularExpression来声明,语义更清晰。

实操心得:在迁移初期,建议在测试环境并行运行 Ingress Nginx 和新的 Gateway API 网关(如 Envoy Gateway)。可以先将一部分非核心域名的流量切换到新网关,通过对比访问日志和监控指标,验证路由规则和流量行为是否完全一致。特别注意重写(Rewrite)、重定向(Redirect)和超时(Timeout)等行为的差异,这些往往是配置不一致导致问题的高发区。

4. 环境搭建与网关实现选型

了解了如何编写配置后,我们需要一个实际的 Kubernetes 环境和一个实现了 Gateway API 的网关控制器来运行它。目前社区有多种实现,我们需要根据自身情况做出选择。

4.1 主流 Gateway API 实现对比

选择哪个实现,取决于你现有的技术栈、对功能的需求以及对复杂度的容忍度。

实现方案核心数据平面特点与优势适用场景
Envoy GatewayEnvoyKubernetes SIG-Network 官方孵化项目,旨在提供最符合 Gateway API 标准的、开箱即用的参考实现。设计简洁,专注于 Gateway API 功能。希望紧跟标准、寻求轻量级和官方参考实现的新项目或团队。
ContourEnvoy由 VMware 开源,是 Gateway API 的早期和积极推动者。功能成熟,社区活跃,除了 Gateway API 也支持其自身的HTTPProxyCRD(功能更丰富)。已经使用或考虑使用 Contour 的团队,或者需要更平滑地从其自定义 CRD 过渡。
IstioEnvoy作为全功能服务网格,其入口网关 Istio Ingress Gateway 已全面支持 Gateway API。提供了最强大的流量管理、安全性和可观测性能力。已经部署或计划部署 Istio 服务网格的团队,希望统一入口网关和网格内部流量的管理平面。
Apache APISIX Ingress ControllerApache APISIX基于高性能 API 网关 APISIX,对 Gateway API 支持良好。提供了强大的插件生态和动态配置能力。看重高性能、丰富插件生态(如认证、限流、日志)的团队。
Kong Ingress ControllerKong基于 Kong 网关,同样提供了对 Gateway API 的支持以及强大的插件平台。已经使用 Kong 生态系统,或需要其特定商业插件和支持的团队。

对于从 Ingress Nginx 迁移且希望尽可能简单直接的团队,Envoy Gateway是一个极佳的起点。它没有历史包袱,完全围绕 Gateway API 构建,让我们能更纯粹地体验新标准。下面我们就以 Envoy Gateway 为例进行部署。

4.2 使用 Envoy Gateway 快速搭建环境

Envoy Gateway 的安装非常简单,它本身也是一个 Pod 运行在你的集群中。

  1. 安装 Gateway API CRDs: Gateway API 的资源类型(如Gateway,HTTPRoute)需要通过 Custom Resource Definitions (CRDs) 来定义。首先安装它们。

    kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml

    执行后,使用kubectl get crd | grep gateway.networking.k8s.io检查是否成功创建了gateways,httproutes等 CRD。

  2. 安装 Envoy Gateway: 同样通过一句命令部署 Envoy Gateway 及其所需的 RBAC 等资源。

    kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/v1.0.0/install.yaml

    这会在envoy-gateway-system命名空间下部署一个Deployment。使用kubectl get pod -n envoy-gateway-system确认 Pod 状态为Running

  3. 验证安装与创建 GatewayClass: 安装完成后,Envoy Gateway 会自动创建一个名为envoyGatewayClass。这是基础设施提供商提供的“网关类型”。

    kubectl get gatewayclass

    你应该能看到一个名为envoyGatewayClass,其CONTROLLER字段为gateway.envoyproxy.io/gatewayclass-controller

至此,一个支持 Gateway API 的网关环境就准备就绪了。接下来,你就可以应用我们在第 3 节中编写的GatewayHTTPRoute配置了。不过请注意,在之前的Gateway示例中,我们使用了gatewayClassName: contour,如果你用的是 Envoy Gateway,需要将其改为gatewayClassName: envoy

4.3 部署示例应用并测试路由

让我们完成一个端到端的测试,部署一个简单的 Echo 应用。

  1. 部署后端服务

    apiVersion: v1 kind: Service metadata: name: echo-service spec: ports: - port: 80 targetPort: 8080 selector: app: echo --- apiVersion: apps/v1 kind: Deployment metadata: name: echo-deployment spec: replicas: 2 selector: matchLabels: app: echo template: metadata: labels: app: echo spec: containers: - name: echo image: hashicorp/http-echo args: - "-text=Hello from Echo Pod!" ports: - containerPort: 8080

    应用这个 YAML 文件,它会创建一个返回固定文本的 Echo 服务。

  2. 创建 Gateway 资源(使用 Envoy Gateway):

    apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: demo-gateway spec: gatewayClassName: envoy # 关键:使用 envoy 这个 GatewayClass listeners: - name: http protocol: HTTP port: 80 allowedRoutes: namespaces: from: All # 允许所有命名空间的 HTTPRoute 绑定

    这个Gateway定义了一个监听 80 端口的 HTTP 监听器。由于是测试,我们暂不配置 TLS。

  3. 创建 HTTPRoute 资源

    apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: echo-route spec: parentRefs: - name: demo-gateway rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: echo-service port: 80

    这个路由规则将所有流量转发到echo-service

  4. 获取访问地址并测试: 应用上述所有配置后,Envoy Gateway 会创建对应的 Envoy Proxy Pod 和 Service。查看这个 Service:

    kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=demo-gateway

    你会看到一个类型为LoadBalancerNodePort的 Service。获取其外部 IP(EXTERNAL-IP)或使用节点 IP+端口。 使用curl访问该地址,你应该能看到Hello from Echo Pod!的响应。

注意事项:在生产环境中,Gateway监听器通常会配置为 HTTPS,并关联 TLS 证书。你需要提前准备好证书 Secret,并在Gatewaytls字段中正确引用。对于自动证书管理,可以集成 cert-manager,它已经提供了CertificateCRD 来自动为 Gateway API 资源签发和续期证书,其配置逻辑与为 Ingress 签发证书类似,但引用的资源类型变成了Gateway

5. 高级特性实践与迁移策略

掌握了基础迁移后,我们可以探索一些 Gateway API 的高级特性,并制定一个稳妥的生产环境迁移策略。

5.1 实现高级流量管理:金丝雀发布

Gateway API 原生支持流量权重分配,这使得实现金丝雀发布变得非常简单。假设我们有一个v1版本的服务,现在要上线v2版本,希望先导流 10% 的流量进行验证。

对应的HTTPRoute配置如下:

apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: canary-release-route spec: parentRefs: - name: prod-gateway hostnames: - "app.example.com" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: app-service-v1 port: 80 weight: 90 - name: app-service-v2 port: 80 weight: 10

关键点:在backendRefs中,可以为一个规则指定多个后端服务,并通过weight字段(权重值,总和通常为 100)来分配流量比例。网关会根据这个比例将请求分发到不同的服务。你可以通过逐步调整weight值(例如 90/10 -> 50/50 -> 0/100)来完成平滑的版本升级或回滚。这完全通过声明式 API 完成,无需修改网关的部署或复杂的注解。

5.2 基于请求头的动态路由

除了路径和权重,基于请求头的路由是灰度发布、A/B 测试的常用手段。例如,只有包含特定 HTTP 头X-Canary: true的请求才被路由到新版本。

apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: header-based-route spec: parentRefs: - name: prod-gateway hostnames: - "app.example.com" rules: # 规则1:匹配特定请求头的流量去 v2 - matches: - headers: - name: X-Canary value: "true" backendRefs: - name: app-service-v2 port: 80 # 规则2:其他所有流量去 v1(兜底规则) - matches: - path: type: PathPrefix value: / backendRefs: - name: app-service-v1 port: 80

匹配顺序HTTPRoute中的规则是按顺序评估的。第一个匹配的规则会被执行。因此,我们将检查X-Canary头的规则放在前面,兜底的通用路径规则放在后面。

5.3 生产环境渐进式迁移策略

对于已存在大量 Ingress Nginx 配置的生产系统,一刀切切换是危险的。建议采用渐进式迁移策略:

  1. 并行运行,双网关共存:在集群中同时部署 Ingress Nginx Controller 和新的 Gateway API 控制器(如 Envoy Gateway)。它们可以监听不同的 Service(NodePort/LoadBalancer),或者通过不同的 IngressClass/GatewayClass 区分。这是风险最低的阶段。
  2. 逐业务迁移,小范围验证
    • 选择试点:挑选一个非核心、流量较小的服务作为第一个迁移对象。
    • 配置转换:将该服务的 Ingress 配置手动转换为Gateway+HTTPRoute配置。
    • DNS 测试:在测试环境中,将试点服务的测试域名(如test-app.example.com)解析到新网关的地址。进行全面测试,包括功能、性能、监控和日志。
  3. 流量切换与监控
    • 蓝绿 DNS 切换:在确认试点服务稳定后,可以在 DNS 层面将少量生产流量(通过权重或分地区解析)指向新网关。例如,先切 1% 的流量。
    • 严密监控:观察新网关的延迟、错误率、资源消耗等关键指标,并与旧网关进行对比。同时确保日志格式和字段符合现有日志分析系统的要求。
    • 逐步放大:如果一切正常,逐步增加切流比例,如 5% -> 20% -> 50% -> 100%。
  4. 批量迁移与自动化
    • 在积累一定经验后,可以编写脚本或使用工具(如ingress2gateway这类转换工具,但需仔细核对)来辅助批量转换配置。
    • 建立标准的迁移流程和检查清单。
  5. 最终切换与清理
    • 当所有流量都成功迁移至新网关,且稳定运行足够长时间(如一个业务周期)后,可以下线旧的 Ingress Nginx Controller。
    • 清理旧的Ingress资源。

实操心得:在整个迁移过程中,监控和可观测性是生命线。确保新网关的 metrics(如请求数、延迟、4xx/5xx 错误)能够无缝集成到现有的 Prometheus + Grafana 监控体系中。同时,访问日志的格式和输出位置也需要调整适配,以确保业务排查和审计不受影响。Envoy 等网关通常有丰富的指标和灵活的日志配置,需要提前做好对接工作。

6. 常见问题与深度排查指南

在实际迁移和运维 Gateway API 的过程中,你肯定会遇到各种问题。下面我整理了一些典型问题的排查思路和解决方法,这些很多都是我在实践中踩过的坑。

6.1 路由不生效:HTTPRoute 状态排查

创建了GatewayHTTPRoute后,访问网关地址却得到404503,这是最常见的问题。首先,要学会查看资源的状态字段。

  1. 检查Gateway状态

    kubectl describe gateway <gateway-name>

    关注Status部分。Listeners列表下每个监听器应有Accepted: TrueReady: True。如果AcceptedFalse,查看Conditions信息,常见原因有:

    • GatewayClass不存在或控制器不支持。
    • 端口冲突(如该端口已被其他Gateway或 Pod 占用)。
    • TLS 证书引用的Secret不存在或格式错误。
  2. 检查HTTPRoute状态

    kubectl describe httproute <httproute-name>

    同样查看StatusParents列表应显示它已成功绑定到预期的Gateway监听器,状态为Accepted: True。如果未绑定成功,检查:

    • parentRefs字段中的namenamespace是否正确。
    • Gateway监听器的allowedRoutes配置是否允许当前HTTPRoute所在的命名空间进行绑定。
    • hostnames是否与Gateway监听器允许的主机名匹配。

6.2 后端服务无法连接:深入 Pod 与 Endpoint

如果路由状态正常,但返回502 Bad Gateway503 Service Unavailable,问题可能出在网关到后端服务的连接上。

  1. 检查 Service 与 Endpoint

    kubectl get svc <service-name> -o wide kubectl get endpoints <service-name>

    确认Service存在,且Endpoints列表不为空。空的Endpoints意味着没有 Pod 匹配Serviceselector,可能是 Deployment 未成功创建或标签不匹配。

  2. 检查网关数据平面日志: 直接查看 Envoy Proxy 容器的日志,这能提供最直接的错误信息。首先找到由你的Gateway资源创建的 Envoy Proxy Pod(通常在envoy-gateway-system或其他指定命名空间)。

    kubectl logs -f <envoy-proxy-pod-name> -c envoy -n <gateway-namespace>

    在日志中搜索你的后端服务域名或集群名,常见的错误有:

    • no healthy upstream:后端 Pod 不健康或就绪探针失败。
    • upstream connect error or disconnect/reset before headers:网络策略(NetworkPolicy)阻止了网关 Pod 访问应用 Pod,或者应用端口未正确监听。

6.3 TLS/HTTPS 相关问题

配置 HTTPS 时问题频发,需要层层排查。

  1. 证书 Secret 格式:Gateway API 要求 TLS 证书 Secret 必须是kubernetes.io/tls类型,且包含tls.crttls.key两个键名。
    kubectl get secret <tls-secret-name> -o jsonpath='{.type}' # 应返回 `kubernetes.io/tls` kubectl get secret <tls-secret-name> -o jsonpath='{.data}' | jq keys # 应包含 `tls.crt` 和 `tls.key`
  2. SNI 匹配:如果Gateway的监听器配置了多个主机名,或者HTTPRoutehostnamesGateway监听器的hostname不匹配,可能会导致 SSL 握手失败。确保它们之间的一致性。
  3. 证书链完整性:确保tls.crt中包含了完整的证书链(服务器证书 + 中间 CA 证书),而不仅仅是叶子证书。不完整的链可能导致某些客户端无法验证。

6.4 从 Ingress 注解到 Gateway API 过滤器的映射

迁移时,最大的工作量之一就是翻译那些五花八门的 Nginx 注解。下面是一个常见注解的映射参考:

Ingress Nginx 注解Gateway API 等效实现说明与注意事项
nginx.ingress.kubernetes.io/rewrite-targetHTTPRoute中的URLRewrite过滤器Gateway API 的替换逻辑更清晰,需指定type: ReplacePrefixReplaceFullPath
nginx.ingress.kubernetes.io/configuration-snippet可能对应EnvoyPatchPolicy(扩展) 或自定义过滤器这是 Nginx 特有的配置片段,迁移最复杂。Gateway API 标准方式是用其内置过滤器(如头修改、重定向)。对于必须的 Envoy 特定配置,可查阅所用实现的扩展机制(如 Envoy Gateway 的EnvoyProxyCRD)。建议优先重构业务逻辑,避免使用配置片段。
nginx.ingress.kubernetes.io/proxy-buffering网关实现特定的配置或策略这类性能调优参数通常在 Gateway 或 GatewayClass 级别通过实现相关的自定义资源进行配置,而非在路由规则中。
nginx.ingress.kubernetes.io/ssl-redirectGateway中配置 HTTP 80 -> HTTPS 443 的重定向监听器,或使用HTTPRouteRequestRedirect过滤器。最佳实践是在Gateway中设置一个 HTTP 监听器,其唯一作用就是返回 301/302 重定向到 HTTPS。

一个重要的心态调整:迁移不仅是语法的转换,更是架构思维的升级。与其追求 100% 原样的功能映射,不如借此机会审视那些复杂的 Nginx 注解是否真的必要。很多时候,那些注解是为了弥补 Ingress 标准能力的不足。利用 Gateway API 更强大的标准功能(如流量切分、多维度匹配),或许能以更简洁、标准的方式实现业务需求,从而降低长期的维护成本。

← 返回列表