Skip to content

Kubernetes IngressRoute

IngressRoute 是 Traefik HTTP 路由器的 CRD 实现

在创建 IngressRoute 对象之前,你需要将 Traefik Kubernetes CRD(如 定义文件RBAC)应用到你的 Kubernetes 集群。

这会注册 IngressRoute 类型以及其它 Traefik 专属资源。

配置示例

你可以按如下方式声明一个 IngressRoute

yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: test-name
  namespace: apps

spec:
  ingressClassName: traefik-lb
  entryPoints:
    - web
  parentRefs:
    - name: parent-gateway
      namespace: default  # 可选 - 默认为同一命名空间
  routes:
  - kind: Rule
    # 基于 Host 的规则
    match: Host(`test.example.com`)
    # 挂载中间件
    middlewares:
    - name: middleware1
      namespace: apps
    # 启用路由可观测性
    observability:
      accessLogs: true
      metrics: true
      tracing: true
    # 设置优先级
    priority: 10
    services:
    # 目标 Kubernetes Service
    - kind: Service
      name: foo
      namespace: apps
      # 自定义 Traefik 与后端之间的连接
      passHostHeader: true
      port: 80
      responseForwarding:
        flushInterval: 1ms
      scheme: https
      sticky:
        cookie:
          httpOnly: true
          name: cookie
          secure: true
      strategy: wrr
      weight: 10
  tls:
    # 使用证书解析器生成 TLS 证书
    certResolver: foo
    domains:
    - main: example.net
      sans:
      - a.example.net
      - b.example.net
    # 自定义 TLS 选项
    options:
      name: opt
      namespace: apps
    # 从 Kubernetes Secret 添加 TLS 证书
    secretName: supersecret

配置选项

字段描述默认值必填
ingressClassName定义要使用的 IngressClass 集群资源。它取代了已弃用的 kubernetes.io/ingress.class 注解。spec 字段优先于该注解。
entryPointsEntryPoint 名称列表。如果未指定,HTTP 路由器将接受默认 EntryPoint 列表中所有 EntryPoint 的请求。
parentRefs父级 IngressRoute 资源的引用列表,用于多层路由。指定后,此 IngressRoute 的路由器将成为所引用的父 IngressRoute 路由器的子项。详见"多层路由"一节。
parentRefs[n].name引用的父级 IngressRoute 资源名称。
parentRefs[n].namespace引用的父级 IngressRoute 资源命名空间。如果未指定,默认为子 IngressRoute 所在的同一命名空间。跨命名空间引用需要启用 allowCrossNamespace provider 选项。
routes路由列表。
routes[n].kind路由匹配类型,目前只允许 Rule。"Rule"
routes[n].match定义与底层路由器对应的规则。
routes[n].priority定义用于区分相同长度规则的优先级。如果未设置,优先级直接等于规则的长度,最长的具有最高优先级。优先级为 0 会被忽略,使用默认规则长度排序。支持负值。0
routes[n].middlewares要附加到 IngressRoute 的中间件列表。更多信息见下文。""
routes[n].middlewares[m].name中间件名称。字符 @ 不允许。
routes[n].middlewares[m].namespace中间件命名空间。如果中间件与 IngressRoute 位于同一命名空间,可留空。
routes[n].observability.accessLogs定义路由是否产生访问日志。false
routes[n].observability.metrics定义路由是否产生指标。false
routes[n].observability.tracing定义路由是否产生链路追踪数据。false
routes[n].services任何 TraefikService 和 Kubernetes Service 的组合。
tlsTLS 配置。可以是空值({}):此时会生成自签名证书(如果定义了 tlsStore,则使用其默认证书)。
tls.secretName用于存储证书的 Secret 名称(与 IngressRoute 同一命名空间)。""
tls.options要使用的 TLSOption 引用。
tls.options.nameTLSOption 名称。""
tls.options.namespaceTLSOption 命名空间。""
tls.certResolver用于生成自动 TLS 证书的证书解析器名称。""
tls.domains使用生成的证书提供服务的域名列表(一个 tls.domain 对应一个证书)。
tls.domains[n].main主域名。""
tls.domains[n].sans备用域名(SANs)列表。

Middleware

  • 你可以将 中间件 列表附加到每个 HTTP 路由器。
  • 中间件仅在规则匹配时生效,并在请求被转发到 service 之前应用。
  • 中间件按它们在 router 中声明的顺序应用。
  • 在 Kubernetes 中,middlewares 选项允许你通过名称和命名空间附加中间件(当 Middleware 与 IngressRoute 在同一命名空间时,命名空间可省略)。

IngressRoute 附加多个中间件

yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: my-app
  namespace: apps

spec:
  entryPoints:
    - websecure
  routes:
  - match: Host(`example.com`)
    kind: Rule
    middlewares:
    # 与 IngressRoute 同一命名空间
    - name: middleware01
    # 默认命名空间
    - name: middleware02
      namespace: apps
    # 其它命名空间
    - name: middleware03
      namespace: other-ns
    services:
    - name: whoami
      port: 80

routes.services.kind

由于 name 字段可以引用不同类型的对象,使用 kind 字段来避免歧义。kind 允许以下值:

TLS Options

options 字段允许精细控制 TLS 参数。它引用 TLSOption,仅在定义了 Host 规则时应用。

服务器名称关联

TLS 选项引用始终映射到规则的 Host 部分中找到的主机名,而非路由器或路由器规则。一个规则中也可能有多个 Host 部分。在这种情况下,TLS 选项引用将映射到同样数量的主机名。

TLS 选项是从上述映射中挑选出来的,基于 TLS 握手期间提供的服务器名称,这一切都在实际路由发生之前完成。

在域名劫持(domain fronting)的情况下,如果与 Host Header 和 SNI 关联的 TLS 选项不同,Traefik 将以状态码 421 响应。

冲突的 TLS Options

由于 TLS 选项引用映射到主机名,如果某个配置引入了相同主机名(来自 Host 规则)被两个 TLS 选项引用匹配的情况,就会发生冲突,如下例所示。

示例

IngressRoute01

yaml
  apiVersion: traefik.io/v1alpha1
  kind: IngressRoute
  metadata:
    name: IngressRoute01
    namespace: apps

  spec:
    entryPoints:
      - foo
    routes:
    - match: Host(`example.net`)
      kind: Rule
    tls:
      options: foo
      ...

IngressRoute02

yaml
  apiVersion: traefik.io/v1alpha1
  kind: IngressRoute
  metadata:
    name: IngressRoute02
    namespace: apps

  spec:
    entryPoints:
      - foo
    routes:
    - match: Host(`example.net`)
      kind: Rule
    tls:
      options: bar
    ...

如果发生这种情况,两个映射都会被丢弃,这些路由器的主机名(示例中的 example.net)会改用默认 TLS 选项。

使用 IngressRoute 进行多层路由

多层路由允许在 IngressRoute 之间创建层次关系,父级 IngressRoute 可以在子 IngressRoute 做出路由决策之前应用中间件。

这对于基于身份验证的路由特别有用:父 IngressRoute 对请求进行身份验证并添加上下文(例如,将用户角色作为 Header),子 IngressRoute 基于该上下文进行路由。

当子 IngressRoute 引用具有多个路由的父 IngressRoute 时,所有父路由器都将成为所有子路由器的父级。

有关多层路由概念、验证规则和使用场景的详细信息,请参阅专用的 多层路由 页面。

配置要求

根 IngressRoute

  • 没有 parentRefs(层次结构顶部)
  • 可以entryPointstlsobservability 配置
  • 可以是父 IngressRoute(有子项)或独立 IngressRoute(有 service)

中间层 IngressRoute

  • 通过 parentRefs 引用其父 IngressRoute
  • 有一个或多个子 IngressRoute
  • 不得定义 service
  • 不得entryPointstlsobservability 配置

叶子 IngressRoute

  • 通过 parentRefs 引用其父 IngressRoute
  • 必须定义 service
  • 不得entryPointstlsobservability 配置

跨命名空间引用

跨命名空间父引用需要启用 allowCrossNamespace provider 选项。如果禁用,子 IngressRoute 创建将被跳过并记录错误。

示例:基于身份验证的路由

父 IngressRoute 配合 ForwardAuth 及子 IngressRoute

Parent IngressRoute

yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: api-parent
  namespace: default
spec:
  entryPoints:
    - websecure
  tls:
    certResolver: letsencrypt
  routes:
    # 带身份验证的父路由 - 没有 services
    - match: Host(`api.example.com`) && PathPrefix(`/api`)
      kind: Rule
      middlewares:
        - name: auth-middleware
          namespace: default
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: auth-middleware
  namespace: default
spec:
  forwardAuth:
    address: "http://auth-service.default.svc.cluster.local:8080/auth"
    authResponseHeaders:
      - X-User-Role
      - X-User-Name

Child IngressRoutes

yaml
# 管理员用户的子 IngressRoute
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: api-admin
  namespace: default
spec:
  parentRefs:
    - name: api-parent
      namespace: default  # 可选 - 默认为同一命名空间
  routes:
    - match: HeadersRegexp(`X-User-Role`, `admin`)
      kind: Rule
      services:
        - name: admin-service
          port: 80
---
# 普通用户的子 IngressRoute
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: api-user
  namespace: default
spec:
  parentRefs:
    - name: api-parent
  routes:
    - match: HeadersRegexp(`X-User-Role`, `user`)
      kind: Rule
      services:
        - name: user-service
          port: 80

Services

yaml
apiVersion: v1
kind: Service
metadata:
  name: auth-service
  namespace: default
spec:
  ports:
    - port: 8080
  selector:
    app: auth-service
---
apiVersion: v1
kind: Service
metadata:
  name: admin-service
  namespace: default
spec:
  ports:
    - port: 80
  selector:
    app: admin-backend
---
apiVersion: v1
kind: Service
metadata:
  name: user-service
  namespace: default
spec:
  ports:
    - port: 80
  selector:
    app: user-backend

工作原理:

  1. https://api.example.com/api/endpoint 的请求匹配父路由器
  2. auth-middleware(ForwardAuth)使用 auth-service 验证请求
  3. auth-service 返回 200 OK 并携带 X-User-Role 头(例如 adminuser
  4. 子路由器根据修改后的请求(带 X-User-Role 头)评估规则
  5. 根据角色将请求路由到 admin-serviceuser-service

在生产环境使用 Traefik OSS?

如果你在工作中使用 Traefik,可以考虑为其添加企业级 API 网关能力或获取 Traefik OSS 的商业支持。

基于 MIT 协议发布