4. 基于路径的路由:配置不同路径转发到不同后端 Service

基于路径的路由是 Ingress 最核心的流量分发策略之一。它允许你根据 HTTP 请求的 URL 路径(如 /api、/web、/static),将流量精确地转发到不同的后端 Service。这种模式在微服务架构中极为常见,例如将前端页面、后端 API 和静态资源分别部署为独立的 Service,并通过同一个域名对外暴露。

4.1 路径路由的核心原理

Ingress Controller 在接收到客户端请求后,会执行以下匹配逻辑:

  1. 域名匹配:首先检查请求的 Host 头是否匹配 Ingress 规则中定义的域名。
  2. 路径匹配:在匹配的域名下,按照 Ingress 规则中定义的路径列表进行匹配。匹配规则分为两种:前缀匹配(Prefix) 和 精确匹配(Exact)。
  3. 流量转发:将匹配成功的请求转发到对应的后端 Service 的端口上。
路径匹配优先级:当多个路径规则可能同时匹配时,精确匹配(Exact) 的优先级高于 前缀匹配(Prefix)。如果多个前缀规则都能匹配,则选择 最长匹配 的路径。

4.2 路径匹配类型对比

匹配类型 Ingress 路径值 请求路径示例 是否匹配 说明
Prefix /api /api ✅ 是 前缀匹配,默认行为
Prefix /api /api/v1/users ✅ 是 以 /api 开头即匹配
Prefix /api /api2 ❌ 否 路径段不匹配,/api2 不是 /api 的子路径
Exact /login /login ✅ 是 必须完全一致
Exact /login /login/ ❌ 否 尾部斜杠导致不匹配

4.3 典型部署案例:多服务路径分发

假设我们有一个电商应用,由三个独立的微服务组成:

  • 前端服务(frontend-svc):提供用户界面,监听 80 端口。
  • API 服务(api-svc):提供 RESTful API,监听 8080 端口。
  • 静态资源服务(static-svc):提供图片、CSS、JS 等静态文件,监听 80 端口。

我们希望所有请求都通过同一个域名 shop.example.com 访问,并根据路径进行分发:

  • / → 转发到 frontend-svc
  • /api/* → 转发到 api-svc
  • /static/* → 转发到 static-svc

4.3.1 Ingress YAML 配置示例

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: shop-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
  - host: shop.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend-svc
            port:
              number: 80
      - path: /api(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: api-svc
            port:
              number: 8080
      - path: /static(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: static-svc
            port:
              number: 80
关键注解说明:nginx.ingress.kubernetes.io/rewrite-target: /$2 用于路径重写。当请求 /api/v1/products 到达 Ingress 时,匹配到 /api(/|$)(.*) 规则,$2 捕获了 v1/products,然后 Ingress 会将请求路径重写为 /v1/products 再转发给后端 api-svc。这样后端服务无需感知 Ingress 层的前缀。

4.4 基于路径的路由流量图

下图展示了客户端请求 shop.example.com 时,Ingress Controller 如何根据路径将流量分发到不同的后端 Service:

基于路径的路由流量分发架构 客户端 shop.example.com Ingress Controller 路径匹配规则 / → frontend-svc /api/* → api-svc /static/* → static-svc frontend-svc:80 api-svc:8080 static-svc:80 路径 / 路径 /api/* 路径 /static/*

4.5 路径重写与流量转发细节

在实际生产环境中,路径重写(Rewrite)是一个非常重要的功能。上面的 YAML 示例中使用了 rewrite-target 注解,其工作原理如下:

原始请求路径 匹配规则 捕获组 重写后路径 目标 Service
/api/v1/products /api(/|$)(.*) $2 = v1/products /v1/products api-svc:8080
/static/images/logo.png /static(/|$)(.*) $2 = images/logo.png /images/logo.png static-svc:80
/ / 无 / frontend-svc:80
路径重写注意事项:如果后端 Service 已经包含了路径前缀逻辑(例如 API 服务期望接收 /api/v1/products 而不是 /v1/products),则不应使用 rewrite-target 注解,或者调整正则表达式以保留前缀。错误的路径重写会导致后端服务返回 404 错误。

4.6 多路径路由的最佳实践

  • 路径规划:在设计路径时,应避免路径冲突。例如,不要同时定义 /api 和 /api/v1 两个前缀规则,除非你明确需要不同的后端处理。
  • 使用正则表达式:Nginx Ingress Controller 支持正则表达式路径匹配,可以实现更灵活的路径分发,但要注意正则表达式的性能开销。
  • 默认后端:建议为 Ingress 配置一个默认后端(default backend),用于处理所有未匹配的路径请求,避免返回 404 或 502 错误。
  • 测试验证:在应用 Ingress 规则后,使用 curl 或浏览器开发者工具验证不同路径的请求是否被正确路由到预期的后端 Service。