Kubernetes Gateway API HTTP 路由实践指南

🎉 欢迎关注我的公众号「键盘下的小宇宙」 🎉

您的每一次关注、点赞和分享,都是我坚持创作的最大动力

🔍 微信搜索「键盘下的小宇宙」,让我们一起探索技术的无限可能~

1. 概述

在 Kubernetes 集群中,流量管理是一个核心挑战,特别是随着微服务架构的广泛采用。Gateway API 作为 Kubernetes 官方推荐的下一代服务网格解决方案,提供了更灵活、更强大的流量管理能力。其中,HTTPRoute 资源是 Gateway API 中处理 HTTP 流量的核心组件,它允许我们基于主机名、路径、请求头和查询参数等多种条件来精确匹配和路由 HTTP 请求。

通过合理配置 HTTPRoute,我们可以实现从简单的单服务路由到复杂的微服务流量管理,包括金丝雀发布、蓝绿部署等高级场景。本文将结合实际使用经验,详细介绍 HTTPRoute 的配置和最佳实践。

2. HTTP 路由基础

2.1 基本概念

在开始配置 HTTPRoute 之前,我们需要了解几个核心概念:

  • HTTPRoute:这是我们配置路由规则的主要资源,它定义了如何匹配 HTTP 流量以及将匹配的流量发送到哪里。
  • Gateway:相当于集群的流量入口,所有 HTTPRoute 都需要通过 parentRefs 字段关联到一个或多个 Gateway 才能生效。
  • 后端服务:指的是最终处理请求的 Kubernetes Service,HTTPRoute 会将匹配的流量转发到这些服务。

2.2 基本配置示例

# Gateway 资源配置
apiVersion: gateway.networking.k8s.io/v1  # API 版本
kind: Gateway                             # 资源类型
metadata:
  name: example-gateway                   # Gateway 名称
spec:
  gatewayClassName: example-gateway-class  # Gateway 类名,由具体的实现提供
  listeners:
  - name: http                            # 监听器名称
    protocol: HTTP                        # 协议类型
    port: 80                              # 监听端口
---
# HTTPRoute 资源配置
apiVersion: gateway.networking.k8s.io/v1  # API 版本
kind: HTTPRoute                           # 资源类型
metadata:
  name: example-route                     # HTTPRoute 名称
spec:
  parentRefs:
  - name: example-gateway                 # 引用的 Gateway 名称
  hostnames:
  - "example.com"                         # 匹配的主机名
  rules:
  - backendRefs:
    - name: example-svc                   # 后端服务名称
      port: 80                            # 后端服务端口

3. 匹配规则

3.1 路径匹配

路径匹配是 HTTP 路由中最常用的匹配方式之一,Gateway API 提供了三种路径匹配类型,每种都有其特定的使用场景:

3.1.1 精确匹配
apiVersion: gateway.networking.k8s.io/v1  # API 版本
kind: HTTPRoute                           # 资源类型
metadata:
  name: exact-path-route                  # HTTPRoute 名称
  namespace: default                      # 命名空间
spec:
  parentRefs:
  - name: example-gateway                 # 引用的 Gateway 名称
  rules:
  - matches:
    - path:
          type: Exact                     # 路径匹配类型:精确匹配
          value: /exact                   # 匹配的路径值
    backendRefs:
    - name: exact-service                 # 后端服务名称
      port: 80                            # 后端服务端口
3.1.2 前缀匹配
apiVersion: gateway.networking.k8s.io/v1  # API 版本
kind: HTTPRoute                           # 资源类型
metadata:
  name: prefix-path-route                 # HTTPRoute 名称
  namespace: default                      # 命名空间
spec:
  parentRefs:
  - name: example-gateway                 # 引用的 Gateway 名称
  rules:
  - matches:
    - path:
          type: PathPrefix                # 路径匹配类型:前缀匹配
          value: /api                     # 匹配的路径前缀
    backendRefs:
    - name: api-service                   # 后端服务名称
      port: 80                            # 后端服务端口
3.1.3 正则表达式匹配
apiVersion: gateway.networking.k8s.io/v1  # API 版本
kind: HTTPRoute                           # 资源类型
metadata:
  name: regex-path-route                  # HTTPRoute 名称
  namespace: default                      # 命名空间
spec:
  parentRefs:
  - name: example-gateway                 # 引用的 Gateway 名称
  rules:
  - matches:
    - path:
          type: RegularExpression         # 路径匹配类型:正则表达式匹配
          value: ^/user/[0-9]+$           # 匹配的正则表达式
    backendRefs:
    - name: user-service                  # 后端服务名称
      port: 80                            # 后端服务端口

3.2 主机匹配

apiVersion: gateway.networking.k8s.io/v1  # API 版本
kind: HTTPRoute                           # 资源类型
metadata:
  name: host-route                        # HTTPRoute 名称
  namespace: default                      # 命名空间
spec:
  parentRefs:
  - name: example-gateway                 # 引用的 Gateway 名称
  hostnames:
  - example.com                           # 匹配的主机名
  - www.example.com                       # 匹配的主机名
  rules:
  - matches:
    - path:
          type: PathPrefix                # 路径匹配类型:前缀匹配
          value: /                        # 匹配所有路径
    backendRefs:
    - name: example-service               # 后端服务名称
      port: 80                            # 后端服务端口

3.3 头部匹配

apiVersion: gateway.networking.k8s.io/v1  # API 版本
kind: HTTPRoute                           # 资源类型
metadata:
  name: bar-route                         # HTTPRoute 名称
spec:
  parentRefs:
  - name: example-gateway                 # 引用的 Gateway 名称
  hostnames:
  - "bar.example.com"                     # 匹配的主机名
  rules:
  - matches:
    - headers:
      - type: Exact                       # 头部匹配类型:精确匹配
        name: env                         # 头部名称
        value: canary                     # 头部值
    backendRefs:
    - name: bar-svc-canary                # 后端服务名称(金丝雀版本)
      port: 8080                          # 后端服务端口
  - backendRefs:                          # 默认规则,当没有匹配到头部时使用
    - name: bar-svc                       # 后端服务名称(稳定版本)
      port: 8080                          # 后端服务端口

4. 路由规则优先级

在配置 HTTPRoute 时,规则的优先级是一个非常重要的概念,直接影响流量的路由结果:

  • 规则顺序决定匹配顺序:Gateway API 会严格按照规则在 YAML 文件中定义的顺序进行匹配,所以一定要注意规则的排列顺序。
  • 具体规则优先:在配置时,应该将更具体的匹配规则放在前面,比如精确路径匹配应该放在路径前缀匹配之前,否则可能会导致更具体的规则永远不会被匹配到。
  • 匹配即停止:一旦请求匹配到某条规则,Gateway API 就会停止后续规则的匹配,直接使用该规则进行路由。
  • 复合匹配优先级:当同时使用多种匹配条件时,包含更多匹配条件的规则会被认为更具体,优先级更高。例如,同时匹配路径和头部的规则会优先于只匹配路径的规则。

在实际使用中,我建议先配置最具体的规则,然后逐步添加更通用的规则,最后以一个默认规则作为兜底,这样可以确保流量被正确路由。

5. 多规则路由

apiVersion: gateway.networking.k8s.io/v1  # API 版本
kind: HTTPRoute                           # 资源类型
metadata:
  name: multi-rule-route                  # HTTPRoute 名称
  namespace: default                      # 命名空间
spec:
  parentRefs:
  - name: example-gateway                 # 引用的 Gateway 名称
  rules:
  - matches:
    - path:
          type: PathPrefix                # 路径匹配类型:前缀匹配
          value: /api                     # 匹配以 /api 开头的路径
    backendRefs:
    - name: api-service                   # 后端服务名称(API 服务)
      port: 80                            # 后端服务端口
  - matches:
    - path:
          type: PathPrefix                # 路径匹配类型:前缀匹配
          value: /web                     # 匹配以 /web 开头的路径
    backendRefs:
    - name: web-service                   # 后端服务名称(Web 服务)
      port: 80                            # 后端服务端口
  - matches:
    - path:
          type: PathPrefix                # 路径匹配类型:前缀匹配
          value: /                        # 匹配所有路径(默认规则)
    backendRefs:
    - name: default-service               # 后端服务名称(默认服务)
      port: 80                            # 后端服务端口

6. 高级路由场景

6.1 基于主机和路径的组合路由

apiVersion: gateway.networking.k8s.io/v1  # API 版本
kind: HTTPRoute                           # 资源类型
metadata:
  name: foo-route                         # HTTPRoute 名称
spec:
  parentRefs:
  - name: example-gateway                 # 引用的 Gateway 名称
  hostnames:
  - "foo.example.com"                     # 匹配的主机名
  rules:
  - matches:
    - path:
        type: PathPrefix                  # 路径匹配类型:前缀匹配
        value: /login                     # 匹配以 /login 开头的路径
    backendRefs:
    - name: foo-svc                       # 后端服务名称
      port: 8080                          # 后端服务端口

6.2 基于头部的金丝雀发布

apiVersion: gateway.networking.k8s.io/v1  # API 版本
kind: HTTPRoute                           # 资源类型
metadata:
  name: bar-route                         # HTTPRoute 名称
spec:
  parentRefs:
  - name: example-gateway                 # 引用的 Gateway 名称
  hostnames:
  - "bar.example.com"                     # 匹配的主机名
  rules:
  - matches:
    - headers:
      - type: Exact                       # 头部匹配类型:精确匹配
        name: env                         # 头部名称
        value: canary                     # 头部值
    backendRefs:
    - name: bar-svc-canary                # 后端服务名称(金丝雀版本)
      port: 8080                          # 后端服务端口
  - backendRefs:                          # 默认规则,当没有匹配到头部时使用
    - name: bar-svc                       # 后端服务名称(稳定版本)
      port: 8080                          # 后端服务端口

7. 路由合并

路由合并是 Gateway API 的一个强大特性,它允许多个 HTTPRoute 资源绑定到同一个 Gateway 上,只要它们的规则不冲突,就会被自动合并成一个统一的路由表。

  • 团队隔离:每个团队可以在自己的命名空间中管理自己的 HTTPRoute,不需要关心其他团队的配置。
  • 共享入口:所有团队可以共享同一个 Gateway 作为流量入口,避免了为每个团队创建单独入口的复杂性。
  • 冲突检测:如果两个 HTTPRoute 配置了冲突的规则(比如相同的主机名和路径但不同的后端服务),Gateway API 会在创建或更新资源时检测到并拒绝这些冲突的配置,确保路由规则的一致性。

需要注意的是,为了安全起见,Gateway 资源可以通过 allowedRoutes 字段限制哪些命名空间中的 HTTPRoute 可以绑定到它,这在多租户环境中尤为重要。

8. 典型应用场景

在实际生产环境中,HTTPRoute 可以应用于多种场景:

  • 单服务部署:对于简单的应用,我们可以创建一个基本的 HTTPRoute,将所有流量直接路由到后端服务,这是最常见的使用场景。

  • 静态网站托管:通过配置路径前缀匹配,将所有请求转发到静态文件服务,实现静态网站的托管。

  • API 网关:在微服务架构中,HTTPRoute 可以作为 API 网关使用,为不同的微服务提供统一的入口,并根据路径将请求路由到对应的服务。例如,将 /api/users 路由到用户服务,将 /api/orders 路由到订单服务。

  • 多版本 API 管理:通过路径前缀匹配,我们可以在同一个域名下管理多个版本的 API,例如将 /v1 路由到旧版本 API,将 /v2 路由到新版本 API。

  • 金丝雀发布:利用头部匹配或查询参数匹配,我们可以实现金丝雀发布,例如将带有 X-Canary: true 头部的请求路由到新版本服务,其他请求继续路由到旧版本服务。

  • 蓝绿部署:通过修改 HTTPRoute 的后端服务引用,我们可以实现零 downtime 的蓝绿部署,在测试确认新版本正常后,将所有流量切换到新版本。

9. 生产环境配置建议

在生产环境中,HTTPRoute 和 Gateway 的配置需要更加谨慎,以下是一些基于实际经验的配置建议:

9.1 Gateway 配置

在生产环境中,我们通常会创建一个专门的命名空间来管理 Gateway 资源,并为其配置 HTTPS 支持:

# 生产环境 Gateway 配置示例
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: production-gateway
  namespace: gateway-system  # 使用专门的命名空间管理 Gateway 资源
spec:
  gatewayClassName: nginx  # 根据实际使用的实现选择,如 nginx、istio、contour 等
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:  # 限制可以绑定到该 Gateway 的路由
      namespaces:
        from: Same  # 只允许同一命名空间的 HTTPRoute 绑定
  - name: https
    protocol: HTTPS
    port: 443
    tls:
      mode: Terminate  # 在 Gateway 层面终止 TLS
      certificateRefs:
      - kind: Secret
        name: production-tls  # 引用 TLS 证书 Secret,需要提前创建
    allowedRoutes:
      namespaces:
        from: Same

配置说明

  • 命名空间隔离:使用专门的 gateway-system 命名空间管理 Gateway 资源,与业务服务分离。
  • HTTPS 配置:配置 HTTPS 监听器,并引用提前创建好的 TLS 证书 Secret。
  • 安全限制:通过 allowedRoutes 限制只有同一命名空间的 HTTPRoute 可以绑定,提高安全性。

在实际部署中,我建议为不同环境(如开发、测试、生产)创建不同的 Gateway 资源,避免环境间的干扰。

9.2 HTTPRoute 配置

对于 HTTPRoute,我们通常会在各个业务服务的命名空间中创建,并引用 gateway-system 命名空间中的 Gateway:

# 生产环境 HTTPRoute 配置示例
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: production-api-route
  namespace: api-services  # 在业务服务的命名空间中创建
spec:
  parentRefs:
  - name: production-gateway
    namespace: gateway-system  # 引用不同命名空间的 Gateway
  hostnames:
  - "api.example.com"  # 配置实际的域名
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /v1
    backendRefs:
    - name: api-v1-service
      port: 8080
      weight: 100  # 流量权重,用于流量分割
  - matches:
    - path:
        type: PathPrefix
        value: /v2
    backendRefs:
    - name: api-v2-service
      port: 8080
      weight: 100

配置说明

  • 跨命名空间引用:通过在 parentRefs 中指定 namespace 字段,可以引用不同命名空间中的 Gateway。
  • 流量权重:通过 weight 字段可以实现流量分割,这在蓝绿部署和金丝雀发布中非常有用。
  • 域名配置:在 hostnames 字段中配置实际使用的域名,确保流量能够正确路由。

9.3 生产环境最佳实践

基于实际生产环境的经验,以下是一些 HTTPRoute 和 Gateway 配置的最佳实践:

  1. 启用 HTTPS:在生产环境中,务必为所有服务配置 HTTPS,保护数据传输安全。可以在 Gateway 层面统一配置 TLS 终止,简化后端服务的配置。

  2. 配置健康检查:为后端服务配置健康检查,确保 Gateway 只将流量转发到健康的实例。不同的 Gateway 实现可能有不同的健康检查配置方式,需要根据实际使用的实现进行配置。

  3. 设置合理的超时和重试策略:根据服务的特性和响应时间,配置适当的超时和重试机制。对于 API 服务,通常建议设置较短的超时时间,避免请求长时间阻塞。

  4. 利用流量分割:通过 weight 参数可以实现流量的精细控制,这在蓝绿部署和金丝雀发布中非常有用。例如,我们可以先将 10% 的流量路由到新版本服务,观察一段时间后再逐步增加流量比例。

  5. 配置资源限制:为 Gateway 相关的 Pod 设置合理的 CPU 和内存限制,避免资源耗尽影响整个集群的稳定性。

  6. 实现完善的监控和日志:配置详细的监控和日志,包括请求量、响应时间、错误率等指标,以便及时发现和解决问题。可以使用 Prometheus 和 Grafana 进行监控,使用 ELK 或 Loki 进行日志管理。

  7. 使用命名空间隔离:将 Gateway 资源部署在专门的命名空间(如 gateway-system)中,并通过 allowedRoutes 字段限制可以绑定的 HTTPRoute,实现权限隔离和安全控制。

  8. 版本控制配置:将 Gateway 和 HTTPRoute 的配置纳入版本控制系统(如 Git),并使用 CI/CD 流程进行部署,确保配置的可追溯性和一致性。

  9. 定期审查路由规则:定期审查和清理不再使用的路由规则,避免规则冲突和配置冗余,保持路由表的简洁性。

  10. 测试变更:在生产环境中修改路由规则之前,务必在测试环境中进行充分的测试,确保变更不会影响现有的流量路由。

10. 实用配置技巧

除了上述生产环境最佳实践外,以下是一些在日常使用中积累的实用配置技巧:

  1. 命名规范:为 HTTPRoute 和 Gateway 使用清晰、描述性的名称,建议使用 <service>-<environment>-route 这样的命名格式,例如 api-production-route

  2. 规则组织:在配置 HTTPRoute 时,将相关的路由规则组织在一起,并按照从具体到通用的顺序排列,确保更具体的规则能够被优先匹配。

  3. 使用注释:在 YAML 配置中添加详细的注释,解释每个字段的作用和配置原因,方便后续的维护和理解。

  4. 模块化配置:对于复杂的应用,可以将不同功能模块的路由规则分离到不同的 HTTPRoute 资源中,提高配置的可维护性。

  5. 版本管理:使用 Git 等版本控制系统管理路由配置,记录配置的变更历史,便于回滚和审计。

  6. 渐进式部署:在发布新功能或新版本时,使用流量分割功能进行渐进式部署,降低风险。

  7. 文档化:为每个 HTTPRoute 配置编写简要的文档,说明其用途、匹配规则和后端服务,方便团队成员理解和使用。

11. 总结

  • 丰富的匹配规则:支持路径、主机名、头部等多种匹配条件,可以满足各种复杂场景的需求。
  • 清晰的优先级机制:通过规则的顺序和具体性来确定优先级,使路由行为更加可预测。
  • 强大的路由合并能力:允许多个团队在不同的命名空间中独立管理路由规则,同时共享同一个 Gateway 入口。
  • 高级流量管理特性:支持流量分割、金丝雀发布等高级场景,为应用的部署和升级提供了更多可能性。

要充分发挥 HTTPRoute 的优势,还需要我们在配置时遵循最佳实践,注意规则的优先级和安全性,同时结合实际的业务需求进行合理的配置。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐