Kubernetes Gateway API生产迁移与流量治理

Kubernetes Ingress 解决了“把 HTTP 服务暴露出去”的基础问题,但复杂路由、跨团队权限、流量切分和实现差异往往依赖控制器私有注解。Gateway API 将基础设施、监听器和应用路由拆成不同资源,目标不是简单替换 YAML,而是让平台团队与应用团队之间的职责边界更清楚。

本文面向已经运行 Ingress、准备建设统一入口或需要灰度流量治理的团队。示例使用稳定 API 字段;控制器支持范围、扩展字段和安装版本应以所选实现的兼容矩阵为准。迁移必须先在测试集群验证,不应直接删除现有 Ingress。

一、先理解资源模型

资源 常见负责人 主要职责
GatewayClass 平台团队 选择控制器和入口实现
Gateway 集群或网络团队 地址、端口、协议、TLS和可接入范围
HTTPRoute 应用团队 域名、路径、请求匹配、后端和流量权重
GRPCRoute 应用团队 gRPC方法匹配和后端路由
ReferenceGrant 资源拥有者 明确允许跨命名空间引用

一个 Gateway 只能引用一个 GatewayClass,但可连接多个 Route。监听器通过 allowedRoutes 控制哪些命名空间能够挂载路由;Route 再通过 parentRefs 选择具体 Gateway 或监听器。这种双向约束比“所有人都改同一份入口配置”更适合多团队环境。

Gateway API 是规范,不是数据平面。只有安装了支持它的控制器,资源状态才会真正转化为负载均衡器、代理或云网络配置。

二、迁移前建立清单

先导出现有 Ingress,不要凭印象迁移:

kubectl get ingress -A -o yaml > ingress-backup.yaml
kubectl get ingressclass
kubectl get secret -A --field-selector type=kubernetes.io/tls
kubectl get svc,endpointslice -A

逐项记录:

  • 域名、路径、后端 Service 和端口;
  • TLS Secret 所在命名空间、证书续期方式;
  • 重写、跳转、限流、认证、白名单和会话保持注解;
  • WebSocket、gRPC、长连接和大文件上传;
  • 默认后端、错误页和健康检查;
  • 真实客户端 IP、代理头和访问日志;
  • 公网、内网、独享和共享入口;
  • DNS TTL、负载均衡地址及回滚入口。

最容易遗漏的是控制器私有注解。应建立“原功能—Gateway API标准字段—实现扩展—暂不支持”的映射表。没有等价能力的功能不能假装已经迁移,必须保留旧入口、调整架构或等待实现支持。

三、先验证控制器与一致性

选择实现时至少比较:

  1. 支持的 Gateway API 版本和 Standard/Experimental 通道;
  2. HTTPRoute、GRPCRoute、ReferenceGrant 等资源的一致性等级;
  3. 是否支持云负载均衡、裸机地址池或现有数据平面;
  4. TLS终止、流量权重、重写、镜像、超时和重试能力;
  5. 指标、日志、Trace、配置下发状态和数据平面健康;
  6. 升级策略、回滚方式和多副本高可用;
  7. 与现有 Ingress 控制器能否并行运行。

不要只看 CRD 能否创建。资源被 API Server 接收,不代表控制器已经接受配置。生产验收必须检查 status.conditions 中的 Accepted、Programmed、ResolvedRefs 等条件。

四、建立一个最小入口

下面示例将基础设施和业务路由分离到两个命名空间。类名应替换为实际控制器提供的 GatewayClass。

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: public-gateway
  namespace: gateway-infra
spec:
  gatewayClassName: production
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      hostname: "*.example.com"
      allowedRoutes:
        namespaces:
          from: Selector
          selector:
            matchLabels:
              gateway-access: public

为允许接入的业务命名空间增加标签,再创建 Route:

kubectl label namespace app-prod gateway-access=public
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: orders
  namespace: app-prod
spec:
  parentRefs:
    - name: public-gateway
      namespace: gateway-infra
      sectionName: http
  hostnames:
    - orders.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: orders-service
          port: 8080

验证时不要只访问首页:

kubectl get gateway -n gateway-infra public-gateway -o yaml
kubectl get httproute -n app-prod orders -o yaml
kubectl describe gateway -n gateway-infra public-gateway
kubectl describe httproute -n app-prod orders

再使用指定 Host 的请求验证 DNS 切换前的入口:

curl -v --resolve orders.example.com:80:<GATEWAY_IP> \
  http://orders.example.com/api/health

五、TLS与HTTP跳转

TLS终止通常属于 Gateway 监听器,由平台团队管理证书引用:

listeners:
  - name: https
    protocol: HTTPS
    port: 443
    hostname: "*.example.com"
    tls:
      mode: Terminate
      certificateRefs:
        - kind: Secret
          name: wildcard-example-com

HTTP跳转应显式定义 Route,而不是假设存在默认行为:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: redirect-to-https
  namespace: app-prod
spec:
  parentRefs:
    - name: public-gateway
      namespace: gateway-infra
      sectionName: http
  hostnames: ["orders.example.com"]
  rules:
    - filters:
        - type: RequestRedirect
          requestRedirect:
            scheme: https
            port: 443
            statusCode: 301

如果证书 Secret 与 Gateway 不在同一命名空间,应使用实现支持的跨命名空间方式并配置 ReferenceGrant。不要为了省事给控制器开放读取所有 Secret 的权限。

六、流量切分与灰度发布

backendRefs.weight 可表达权重路由:

rules:
  - backendRefs:
      - name: orders-v1
        port: 8080
        weight: 90
      - name: orders-v2
        port: 8080
        weight: 10

权重不是精确的逐请求计数,短时间、小样本或长连接下比例可能明显偏离。灰度验收应按足够长时间窗口观察请求量、错误率、延迟和业务指标,并确认控制器对会话保持、HTTP/2连接和重试的处理方式。

生产灰度建议按以下顺序:

  1. 新版本保持零生产流量,先做就绪探测和内部验证;
  2. 切入 1%~5% 流量,观察技术和业务指标;
  3. 逐步提升到 10%、25%、50%和100%;
  4. 每一级设置最短观察时间与停止条件;
  5. 回滚只调整权重,不在事故期间同时修改镜像、路由和证书。

七、跨命名空间引用

跨命名空间是权限边界,不应默认放开。若 app-prod 的 HTTPRoute 需要引用 shared-services 中的 Service,应由目标命名空间创建授权:

apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-orders-route
  namespace: shared-services
spec:
  from:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      namespace: app-prod
  to:
    - group: ""
      kind: Service
      name: shared-api

授权应尽量限定来源命名空间、资源类型和目标名称。定期清理已经不存在的 Route 对应授权,避免长期积累隐形访问路径。

八、从Ingress分阶段迁移

阶段1:并行准备

  • 安装 Gateway API CRD 和目标控制器;
  • 保留原 Ingress 控制器与现有 DNS;
  • 用测试域名验证入口、证书和日志;
  • 对照注解映射表补齐能力差异。

阶段2:影子验证

  • 使用临时域名或 curl --resolve 访问新入口;
  • 对相同接口执行功能、性能和安全验证;
  • 对比响应头、客户端IP、超时、上传大小和错误页;
  • 检查 Route 状态与控制器日志。

阶段3:小流量切换

  • 降低 DNS TTL,但不要在切换瞬间才修改;
  • 先迁移低风险域名或少量流量;
  • 保留旧入口地址和完整回滚步骤;
  • 观察 DNS缓存、连接排空和证书握手。

阶段4:完成与清理

  • 生产验证通过后再移除旧 Ingress;
  • 清理无用注解、负载均衡器和安全组;
  • 更新架构图、值班手册和故障演练;
  • 保留迁移记录和关键指标对比。

九、观测与故障定位

建议为入口建立四层证据:

层级 关键证据
API对象 Accepted、Programmed、ResolvedRefs、事件
控制器 配置解析、下发失败、证书与权限错误
数据平面 请求量、状态码、连接、TLS、上游延迟
业务服务 EndpointSlice、健康检查、应用错误和依赖

常用检查:

kubectl get gateway,httproute -A
kubectl get gateway -A -o wide
kubectl describe httproute -n app-prod orders
kubectl get endpointslice -n app-prod -l kubernetes.io/service-name=orders-service
kubectl get events -A --sort-by=.lastTimestamp

典型问题包括:

  • Accepted=False:监听器不允许该命名空间或主机名不匹配;
  • ResolvedRefs=False:Service、端口、Secret或跨命名空间授权错误;
  • Gateway有地址但无法访问:安全组、防火墙、负载均衡健康检查或数据平面异常;
  • 返回404:Host、路径、监听器和Route附着关系不一致;
  • 返回503:后端无可用Endpoint、端口错误或就绪探测失败;
  • TLS失败:证书链、SAN、Secret格式或引用权限错误。

十、回滚设计

迁移前必须写明回滚触发器:错误率、P99、TLS失败率、关键业务成功率或入口可用性达到什么阈值时回滚。回滚动作应单一且可预测:

  1. 停止继续扩大流量;
  2. 将 DNS 或上游负载均衡指回旧入口;
  3. 保留新资源,不在事故期间立即删除;
  4. 等待连接和 DNS缓存收敛;
  5. 比较两条入口的日志和指标,确认根因后再重试。

如果迁移期间同时改变证书、域名、应用版本和网络策略,回滚将很难定位问题。一次迁移尽量只改变入口控制面。

十一、上线检查清单

  • [ ] 已完成所有 Ingress 注解和特殊行为清单;
  • [ ] 目标控制器支持所需资源和功能等级;
  • [ ] Gateway与Route状态条件全部符合预期;
  • [ ] HTTP、HTTPS、重定向、上传、WebSocket和gRPC均已验证;
  • [ ] TLS证书续期、私钥权限和到期告警已验证;
  • [ ] 跨命名空间引用使用最小范围ReferenceGrant;
  • [ ] 灰度权重、观察窗口、停止条件和回滚均已演练;
  • [ ] 入口指标、访问日志、控制器日志和业务监控能够关联;
  • [ ] DNS TTL、旧入口保留时间和连接排空策略明确;
  • [ ] 值班手册记录常见状态条件与排障命令。

十二、参考资料

Copyright © yan-jian.com 2023 - 2026 · Powered by GitBook更新时间: 2026-10-20 17:11:32

results matching ""

    No results matching ""