Skip to content

路由

Ingress 提供灵活的路由功能来匹配请求并将它们路由到相应的后端服务。您可以按主机名和路径匹配请求,支持精确、正则表达式和通配符匹配。

主机匹配

主机匹配是路由请求的主要方式。Ingress 支持三种主机匹配方式:精确(exact)正则(regex)通配符(wildcard)

自动 host_type(默认)

省略 host_type 或设为 host_type: auto,Ingress 会在编译路由索引时(进程启动或配置 Reload)根据 host 字符串自动选择匹配类型:

  1. host 中含正则元字符 ( ) [ ] ^ $ | + ? \ → 按 regex 处理
  2. 否则若含 * → 按 wildcard 处理
  3. 否则 → exact

会先判断正则再判断 *,因此像 ^.*\.example\.com$ 这类完整正则不会被误判为通配符。

解析后的类型会写回规则上的 host_type,供后续逻辑使用(如 service.name 捕获、错误页分支等)。若必须按字面量匹配 host(即使看起来像模式),请显式写 host_type: exact

省略 host_type 的示例:

yaml
rules:
  # 编译为 regex(括号、\w 等)
  - host: ^([a-z0-9-]+)\.inlets\.example\.com$
    backend:
      service:
        name: inlets
        port: 8080
  # 编译为 wildcard
  - host: '*.api.example.com'
    backend:
      service:
        name: api-gateway
        port: 8080
  # 编译为 exact
  - host: idp.example.com
    backend:
      service:
        name: idp
        port: 443

精确匹配

精确匹配按字面量完全匹配主机名。在自动 host_type 下,普通主机名(无正则元字符且无 *)会解析为 exact

yaml
rules:
  - host: example.com
    backend:
      service:
        name: backend-service
        port: 8080

这将精确匹配 Host: example.com 的请求。

正则表达式匹配

正则表达式匹配允许您使用正则表达式来匹配主机名。可显式写 host_type: regex,也可在模式中含正则元字符时省略 host_type,由编译阶段自动推断为 regex。

yaml
rules:
  - host: ^t-(\w+).example.work
    host_type: regex
    backend:
      service:
        name: task.$1.svc
        port: 8080

在此示例中,$1 引用 host 正则中的第一个捕获组。对 t-myapp.example.work 的请求将被路由到 task.myapp.svc

说明: 在 Go 的 regexp 中,\w 等价于 [0-9A-Za-z_]不包含连字符 -。若子域带横线(如 my-app.example.work),需使用允许 - 的写法,例如 ^t-([a-zA-Z0-9-]+).example.work,不能仅依赖 (\w+)

Service 名称捕获模板

当使用 host_type: regex 时,也可以在 service.name 中使用带作用域的捕获模板(高级用法):

  • ${host.<索引>}:来自 host 正则的捕获组
  • ${path.<索引>}:来自命中 path 正则的捕获组
yaml
rules:
  - host: ^t-(\w+)-(dev|prod).example.work$
    host_type: regex
    backend:
      service:
        name: task.${host.1}.${host.2}.svc
        port: 8080
    paths:
      - path: ^/api/v1/([^/]+)/([^/]+)$
        backend:
          service:
            name: ${path.2}.${path.1}.${host.2}.${host.1}.svc
            port: 8080

兼容性说明:

  • service.name 中旧写法 $1$2...(基于 host 正则)是默认优先/基础用法,并持续完全兼容。
  • request.path.rewrites 仍使用重写语法里的 $1$2...(例如 ^/api/(.*):/v2/$1)。

通配符匹配

通配符匹配使用 * 作为通配符。可显式写 host_type: wildcard,也可在 host* 且无正则元字符时省略 host_type(见上文「自动 host_type」一节)。

yaml
rules:
  - host: '*.example.work'
    host_type: wildcard
    backend:
      service:
        name: wildcard-service
        port: 8080

这将匹配 example.work 的任何子域,例如 app.example.workapi.example.work 等。

基于路径的路由

您可以在主机规则内定义基于路径的路由规则。路径使用正则表达式模式匹配:

yaml
rules:
  - host: example.com
    backend:
      service:
        name: default-service
        port: 8080
    paths:
      - path: /api
        backend:
          service:
            name: api-service
            port: 8080
      - path: /admin
        backend:
          service:
            name: admin-service
            port: 8080

路径匹配使用正则表达式模式。路径 /api 将匹配 /api/api//api/users 等。

路径匹配优先级

路径按定义的顺序匹配。将使用第一个匹配的路径。如果没有路径匹配,将使用主机级后端。

请求重写

在路由到后端服务时,您可以重写请求路径、头和查询参数。

路径重写

使用正则表达式模式重写请求路径:

yaml
rules:
  - host: example.com
    backend:
      service:
        name: backend-service
        port: 8080
        request:
          path:
            rewrites:
              - ^/api/v1/(.*):/api/v2/$1
              - ^/old:/new

重写格式为 pattern:replacement,其中 pattern 是正则表达式,replacement 是新路径。可以使用 $1$2 等引用捕获组。

Host 头重写

重写发送到后端的 Host 头:

yaml
rules:
  - host: example.com
    backend:
      service:
        name: backend-service
        port: 8080
        request:
          host:
            rewrite: true

rewrite: true 时,Host 头将设置为后端服务名称和端口。

头修改

添加或修改请求头:

yaml
rules:
  - host: example.com
    backend:
      service:
        name: backend-service
        port: 8080
        request:
          headers:
            X-Forwarded-Proto: https
            X-Custom-Header: value

查询参数修改

添加或修改查询参数:

yaml
rules:
  - host: example.com
    backend:
      service:
        name: backend-service
        port: 8080
        request:
          query:
            api_key: secret-key
            version: v2

重定向

除了代理到后端服务,您还可以重定向请求:

yaml
rules:
  - host: old.example.com
    backend:
      redirect:
        url: https://new.example.com
        permanent: true
  • url: 重定向目标 URL
  • permanent: 如果为 true,返回 301 重定向;如果为 false,返回 302 重定向

Handler 后端

除了转发到 service,您还可以设置 backend.type: handler,并通过 handler.type 选择:

  • static_response(默认)
  • file_server
  • templates
  • script
yaml
rules:
  - host: handler.example.com
    backend:
      service:
        name: api-service
        port: 8080
    paths:
      - path: /custom/handler/json
        backend:
          type: handler
          handler:
            type: static_response
            status_code: 200
            headers:
              Content-Type: application/json
            body: |
              {"message":"Hello, World!"}
      - path: /custom/handler/files
        backend:
          type: handler
          handler:
            type: file_server
            root_dir: /app/public
            index_file: index.html
      - path: /custom/handler/templates
        backend:
          type: handler
          handler:
            type: templates
            root_dir: /app/templates
      - path: /custom/handler/script/js
        backend:
          type: handler
          handler:
            type: script
            engine: javascript
            script: |
              ctx.response.status_code = 200
              ctx.type = "application/json"
              ctx.body = JSON.stringify({ method: ctx.method, path: ctx.path })
              ctx.setHeader("X-Handler-Engine", "javascript")
      - path: /custom/handler/script/go
        backend:
          type: handler
          handler:
            type: script
            engine: go
            script: |
              ctx.SetHeader("X-Handler-Engine", "go")
              ctx.String(200, "%s %s", ctx.Method, ctx.Path)
  • backend.type: service(默认)或 handler
  • handler.type: static_response(默认)、file_servertemplatesscript
  • handler.type=static_response:支持 status_codeheadersbody
  • handler.type=file_server:支持 root_dirindex_file
  • handler.type=templates:支持 root_dir
  • handler.type=script:支持 enginescript
    • engine=javascript:使用 goja;提供 ctx
      • ctx.request / ctx.response
      • 别名:ctx.methodctx.pathctx.headers
      • 响应别名:ctx.statusctx.response.status_code)、ctx.typectx.response.content_type)、ctx.bodyctx.response.body
      • 方法:ctx.setHeader(key, value)ctx.response.setHeader(key, value)
    • engine=go:使用 yaegi 执行脚本,ctx 为原生 *zoox.Context(例如:ctx.SetHeader(...)ctx.String(...)ctx.Fetch()

回退服务

如果没有规则匹配请求,则使用回退服务:

yaml
fallback:
  service:
    name: fallback-service
    port: 8080

回退服务对于处理未匹配的请求或提供默认后端很有用。

路由示例

同一主机上的多个服务

yaml
rules:
  - host: example.com
    backend:
      service:
        name: web-service
        port: 8080
    paths:
      - path: /api
        backend:
          service:
            name: api-service
            port: 8081
      - path: /admin
        backend:
          service:
            name: admin-service
            port: 8082

带路径重写的正则主机

yaml
rules:
  - host: ^t-(\w+).example.work
    host_type: regex
    backend:
      service:
        name: task.$1.svc
        port: 8080
    paths:
      - path: /api/v1/([^/]+)
        backend:
          service:
            name: $1.example.work
            port: 8080
            request:
              path:
                rewrites:
                  - ^/api/v1/([^/]+):/api/v1/task/$1

通配符主机匹配

yaml
rules:
  - host: '*.example.work'
    host_type: wildcard
    backend:
      service:
        name: wildcard-service
        port: 8080

这匹配 example.work 的任何子域并路由到同一个后端服务。

匹配如何构建(预编译)

Ingress 不会在每次请求时再为 host、path 解析正则。

  • 进程启动或配置 Reload 时,prepare() 会构建内部路由索引core/compile.go):对每条规则先解析最终 host_type(含省略或 auto 时的自动推断),再对作为 regex / wildcardhost 以及每条 paths[].path,使用 Go regexp 只编译一次
  • 配置里规则的顺序会保留。 匹配按规则顺序遍历;命中的 host 规则生效;在同一 host 下 命中的 path 生效(与优化前语义一致)。
  • 若存在非法模式(例如 hostpath 的正则无法编译),启动或 Reload 会直接报错失败,需先修正配置。这与早期「可能直到第一次匹配请求才暴露错误」的行为不同。

请求路径上实际仍使用预编译索引。若启用缓存,按主机缓存的路由结果可能以 match.host:v2:<hostname> 形式的键保存(见 缓存),直至 cache.ttl 过期。

最佳实践

  1. 顺序很重要:将更具体的规则放在通用规则之前
  2. 尽可能使用精确匹配:普通主机名会推断为 exact,通常比正则或通配符更快
  3. 需要时可省略 host_type 或写 auto:看起来像正则或通配符的 host 会在编译阶段自动识别;若需覆盖(例如含 * 或括号但必须按字面量匹配),请显式写 host_type
  4. 测试正则表达式模式:确保模式符合预期;非法模式会在启动或重载阶段失败
  5. 使用路径路由:按路径组织路由以提高可维护性
  6. 设置回退:始终为未匹配的请求配置回退服务

Released under the MIT License.