Traefik 的 Kubernetes IngressRoute CRD 完全指南:从 HTTP 路由声明、TLS 配置到 Multi-Layer Routing
【免费下载链接】traefikThe Cloud Native Application Proxy项目地址: https://gitcode.com/GitHub_Trending/tr/traefik
IngressRoute是 Traefik 官方 CRD 体系中针对 HTTP 七层路由的声明式资源,它把 Traefik HTTP Router 的路由、中间件、服务、TLS 等概念以traefik.io/v1alpha1的 Kubernetes 原生对象方式落地到集群中。本文以 docs/content/reference/routing-configuration/kubernetes/crd/http/ingressroute.md 为主线,结合 ingressroute.go 的类型定义、CRD 清单与源码实现,系统讲解 IngressRoute 的字段语义、middleware 绑定、TLS Option 的 Server Name 关联与冲突处理,以及基于parentRefs的多层级路由。读完你将能够直接编写可上生产环境的 IngressRoute 清单,并理解其背后与 Traefik HTTP Router 的映射原理。
IngressRoute 是什么:HTTP Router 的 CRD 实现
IngressRoute是 Traefik 核心路由模型中 HTTP Router 的 CRD 化实现。在源码层面,这一点被明确写在类型注释中:
IngressRoute is the CRD implementation of a Traefik HTTP Router.(见 ingressroute.go)
它的职责是把"入口请求"与"能够处理这些请求的 Service"连接起来——由match规则决定哪些请求进入该路由,由services决定请求最终被转发给谁,这与 File Provider 中http.routers的结构一一对应。每创建一个 IngressRoute,Traefik 的 kubernetes CRD provider 就会在集群里监听这些对象,并将其翻译为动态配置中的 HTTP Router。
Traefik 的 CRD 体系还包含面向其他协议/用途的同族资源:
- TCP 的 IngressRouteTCP(四层/SNI 路由)
- UDP 的 IngressRouteUDP(UDP 负载均衡)
- Middleware、TraefikService、ServersTransport、TLSOption、TLSStore 等配套资源
本文聚焦于 HTTP 场景下的IngressRoute。
前置条件:先安装 CRD Definitions 与 RBAC
在创建任何IngressRoute对象之前,需要先把 Traefik 提供的 Kubernetes CRD 定义与 RBAC 应用到集群:
- CRD 定义文件 kubernetes-crd-definition-v1.yml:注册
IngressRoute及其他 Traefik 专属资源。从该清单(kubernetes-crd-definition-v1.yml)可以看到关键元信息:CRD 名称ingressroutes.traefik.io,group 为traefik.io,kind 为IngressRoute,作用域scope: Namespaced(即 IngressRoute 是命名空间级资源)。 - RBAC 文件 kubernetes-crd-rbac.yml:授予 Traefik Pod 对上述 CRD 资源的 list/watch/get 权限。
应用方式(常规做法,按仓库实际文件路径执行):
kubectl apply -f docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml kubectl apply -f docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml说明:这两个 yml 是随仓库分发的完整清单。你也可以从 Helm Chart 或官方安装入口获取等效内容,本文以仓库内路径为准。
完成上述安装后,traefik.io/v1alpha1API 组下的资源即可在集群中被创建。
完整配置示例
一个声明完整的IngressRoute如下(摘自关联文档并附逐段注解):
apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test-name namespace: apps spec: ingressClassName: traefik-lb entryPoints: - web parentRefs: - name: parent-gateway namespace: default # 可选,缺省为与当前 IngressRoute 同一 namespace routes: - kind: Rule # 基于 Host 的路由规则 match: Host(`test.example.com`) # 挂载中间件 middlewares: - name: middleware1 namespace: apps # 打开该 Router 的观测能力 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: # 使用某个证书解析器自动签发证书 certResolver: foo domains: - main: example.net sans: - a.example.net - b.example.net # 自定义 TLS 参数选项 options: name: opt namespace: apps # 从 Kubernetes Secret 中加载 TLS 证书 secretName: supersecret在这个示例里可以看到 IngressRoute 的全部能力面:通过match做七层规则匹配、通过middlewares注入中间件、通过observability打开该路由维度的访问日志/指标/链路追踪、通过services引用后端、通过tls完成证书与 TLS 参数管理,并通过parentRefs参与到多层级路由中。
配置字段详解
spec 顶层字段
| 字段 | 说明 | 默认 | 必填 |
|---|---|---|---|
ingressClassName | 指定要使用的 IngressClass 集群资源,替代已废弃的kubernetes.io/ingress.class注解。当二者同时存在时,spec 字段优先级更高 | — | 否 |
entryPoints | EntryPoints 名称列表。若未指定,HTTP 路由器将接受来自默认 EntryPoints 列表中所有入口的请求。EntryPoint 需在 Traefik 静态配置中定义(源码注释:Entry points have to be configured in the static configuration. Default: all.,见 ingressroute.go) | — | 否 |
parentRefs | 父 IngressRoute 引用列表,用于多层级路由。一旦指定,该 IngressRoute 的路由将成为被引用父 IngressRoute 路由的子路由,详见下文 多层级路由 | — | 否 |
parentRefs[n].name | 被引用的父 IngressRoute 资源名称 | — | 是 |
parentRefs[n].namespace | 被引用的父 IngressRoute 所在 namespace。缺省时与该子 IngressRoute 同 namespace。跨 namespace 引用需要启用 provider 的allowCrossNamespace选项 | — | 否 |
routes | 路由列表 | — | 是 |
tls | TLS 配置。可以为空值{}:此时会生成自签名证书(若定义了 默认证书 则使用默认证书) | — | 否 |
routes[n] 路由级字段
| 字段 | 说明 | 默认 | 必填 |
|---|---|---|---|
routes[n].kind | 路由匹配类型,目前只允许Rule(类型上有+kubebuilder:validation:Enum=Rule约束,见 ingressroute.go) | "Rule" | 否 |
routes[n].match | 对应底层 路由规则,例如Host(\example.com`)、PathPrefix(`/api`)` 及其组合 | — | 是 |
routes[n].priority | 用于消解"同长度规则"的路由 优先级。若未设置,优先级直接等于规则字符串长度——越长优先级越高;显式设置为0会被忽略(回退到默认的长度排序);支持负值。类型约束上限为9223372036854774807(见 ingressroute.go) | 0 | 否 |
routes[n].middlewares | 要挂载到该 IngressRoute 的中间件引用列表,详见下文 Middleware 挂载 | "" | 否 |
routes[n].middlewares[m].name | 中间件名称。@字符不允许出现在名称中 | — | 是 |
routes[n].middlewares[m].namespace | 中间件所在 namespace。若中间件与 IngressRoute 同 namespace 可留空 | — | 否 |
routes[n].observability.accessLogs | 是否让该路由产生 访问日志,详见 Router 观测性 | false | 否 |
routes[n].observability.metrics | 是否让该路由产生 指标 | false | 否 |
routes[n].observability.tracing | 是否让该路由产生 链路追踪 | false | 否 |
routes[n].observability.traceVerbosity | 该路由追踪的详细级别,合法值为minimal与detailed(类型约束见 ingressroute.go) | minimal | 否 |
routes[n].services | 后端服务列表,可以是 TraefikService 与 Kubernetes Service 的任意组合,完整选项见 service.md 的 Configuration Options | — | 否 |
tls 字段
| 字段 | 说明 | 默认 | 必填 |
|---|---|---|---|
tls.secretName | 存放证书的 Kubernetes Secret 名称(与 IngressRoute 同 namespace) | "" | 否 |
tls.options.name | 要使用的 TLSOption 名称,详见下文 TLS Options | "" | 否 |
tls.options.namespace | TLSOption 所在 namespace | "" | 否 |
tls.certResolver | 用于自动签发证书的 证书解析器 名称(需在静态配置中定义) | "" | 否 |
tls.domains | 使用证书解析器签发的域名列表(一个tls.domain对应一张证书),更多细节见 ACME 的 Domain Definition | — | 否 |
tls.domains[n].main | 主域名 | "" | 是 |
tls.domains[n].sans | 备用域名(SANs)列表 | — | 否 |
从类型定义看(ingressroute.go 的 TLS struct),tls还隐含支持store(TLSStore 引用,且只能指向defaultTLSStore)以及默认行为:不指定options时使用defaultTLSOption;secretName为空且不配置 certResolver 时,tls: {}会启用自签名证书或 fallback 到默认证书。
routes[n].services:引用 Kubernetes Service 还是 TraefikService
由于routes[n].services[m].name可能指向不同类型对象,需要借助kind字段消歧,合法取值有:
Service(默认值):引用一个 Kubernetes Service,此时 Traefik 会直接对 Service 对应的 Endpoints 做负载均衡;TraefikService:引用一个 TraefikService 对象,用于声明 WRRS(加权轮询)、Mirroring(流量镜像)、Failover 等高级拓扑。
类型定义中的 kubebuilder 约束给出了支持范围:+kubebuilder:validation:Enum=Service;TraefikService(见 ingressroute.go)。
LoadBalancerSpec(见 ingressroute.go)里的常用子字段还有若干值得注意的默认与约束:
port:Kubernetes Service 的端口,类型为intstr.IntOrString,因此既可以写数字端口也可以引用 Service 的命名端口;scheme:默认按端口推断——Kubernetes Service 端口为 443 时默认https,否则默认http(源码注释:It defaults to https when Kubernetes Service port is 443, http otherwise);passHostHeader:是否把客户端 Host 头转发给上游,默认true;strategy:负载均衡策略,合法值wrr(加权轮询)、p2c(随机两选一)、hrw(一致性最高随机权重)、leasttime(最小响应时间);RoundRobin已废弃但出于向后兼容仍可解析;responseForwarding.flushInterval:将响应体拷贝给客户端时每次刷新的间隔,负值表示每次写入立即刷新;当反代识别出流式响应时该配置会被忽略(直接即时刷新),默认100ms(见 ingressroute.go);weight:权重,仅当 name 指向一个嵌入了加权轮询(WRR)的 TraefikService 时才应填写;sticky.cookie:会话保持,可配置 cookie 的name、httpOnly、secure、sameSite等属性;- 更完整的
nativeLB、nodePortLB、healthCheck、passiveHealthCheck、serversTransport等字段,可查阅 service.md。
Middleware 挂载
IngressRoute 支持在每个 HTTP 路由上挂载一个中间件引用列表(中间件总览),要点如下:
- 中间件仅在规则匹配成功之后、请求转发给 Service 之前生效;
- 中间件按其在路由中声明的顺序依次执行;
- 在 Kubernetes 中,通过
name+namespace定位中间件;当中间件与 IngressRoute 同 namespace 时可省略 namespace; - 中间件名称中不允许出现
@字符(该字符在动态配置中用于分隔"provider 限定名",在 CRD 场景下无意义)。
挂载多个中间件、且中间件分属不同 namespace 的完整示例:
apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: my-app namespace: apps spec: entryPoints: - websecure routes: - match: Host(`example.com`) kind: Rule middlewares: # 与 IngressRoute 同 namespace,可省略 namespace - name: middleware01 # 明确写出与 IngressRoute 同 namespace 的中间件 - name: middleware02 namespace: apps # 引用其他 namespace 的中间件 - name: middleware03 namespace: other-ns services: - name: whoami port: 80与路由级的middlewares相区分,service 级同样存在middlewares字段(见 ingressroute.go 的 LoadBalancerSpec),它用于在路由把请求交给具体 Service 之前、于服务这一层再叠加中间件——这与动态配置中 "service 内部 middleware" 的语义保持一致。
TLS Options 的 Server Name Association 与冲突处理
TLS 配置的生效条件与 Server Name 映射
s级tls.options引用一个 TLSOption,用于对 TLS 参数做细粒度控制,但只有该路由规则中包含Host(...)匹配时才生效。
映射机制非常关键:
- 一个 TLS options 引用总是被映射到规则
Host部分里的主机名上——不是映射到某个 router,也不是映射到某条 router rule; - 一条规则中可能含有多个
Host部分,此时这个 TLS options 引用会被映射到同样多的主机名; - 在实际路由发生之前,Traefik 会基于 TLS 握手阶段提供的 SNI(Server Name Indication)从上述映射中挑选对应主机名的 TLS Option;
- 在 domain fronting(域名前置)场景下,如果 Host 头关联的 TLS options 与 SNI 关联的 TLS options 不一致,Traefik 会返回状态码
421(Misdirected Request)。
冲突的 TLS Options
由于 TLS options 引用是按主机名映射的,一旦某条配置让同一个主机名(来自Host规则)同时命中两个不同的 TLS options 引用,就会产生冲突。例如:
# IngressRoute01 —— 绑定 foo 选项 apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: IngressRoute01 namespace: apps spec: entryPoints: - foo routes: - match: Host(`example.net`) kind: Rule tls: options: name: foo# IngressRoute02 —— 绑定 bar 选项 apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: IngressRoute02 namespace: apps spec: entryPoints: - foo routes: - match: Host(`example.net`) kind: Rule tls: options: name: bar上面的example.net同时被 IngressRoute01(期望foo)与 IngressRoute02(期望bar)映射。冲突发生时,两份映射都会被丢弃,这些 router 对应的主机名(即示例中的example.net)会转而关联默认 TLS Options。这保证了行为可预期:与其在多个选项间不确定地挑选,不如全部回退到默认值并避免 TLS 配置的二义性。
parentRefs 多层级路由(Multi-Layer Routing)
多层级路由允许在 IngressRoute 之间建立层级关系:父 IngressRoute 可以先执行中间件,再让子 IngressRoute 做最终的路由决策。这在"基于认证的路由"场景中尤其有用——父 IngressRoute 先完成认证并把上下文(例如用户角色作为响应头)注入请求,子 IngressRoute 再基于该上下文做出分流。
当子 IngressRoute 引用了一个含多条路由的父 IngressRoute 时,父方的全部路由器都会成为子方全部路由器的父路由器(全连接语义)。
关于多层级路由的完整概念、校验规则与更多用例,可参阅专门的 Multi-Layer Routing 文档。作为补充,该特性的 Provider 支持范围(File、KV、Kubernetes CRD)与流程图(Request → EntryPoint → Parent Router → Middleware → Child Router → Service)均在该文档中有更详尽的展开。
三类节点的配置约束
Root IngressRoutes(根节点)
- 不包含
parentRefs(位于层级顶端); - 可以配置
entryPoints、tls、observability; - 既可以是带子节点的父 IngressRoute,也可以是带 Service 的独立 IngressRoute。
Intermediate IngressRoutes(中间节点)
- 通过
parentRefs引用其父 IngressRoute; - 拥有一个或多个子 IngressRoute;
- 不得定义
service; - 不得配置
entryPoints、tls、observability。
Leaf IngressRoutes(叶子节点)
- 通过
parentRefs引用其父 IngressRoute; - 必须定义
service; - 不得配置
entryPoints、tls、observability。
中间与叶子节点"不得配置 entryPoints/tls/observability"意味着真正的流量入口(EntryPoint、TLS 终止、观测开关)只允许出现在根节点上——流量从父到子逐层"降级"为纯路由决策,这是该模型的可校验性所在。
跨 Namespace 引用
跨 namespace 的父引用要求启用 provider 的allowCrossNamespace选项(见 kubernetes.go)。若该选项被禁用,跨 namespace 的子 IngressRoute 创建会被跳过,并记录一条错误日志。
仓库源码与测试对此有完整覆盖:pkg/provider/kubernetes/crd/kubernetes.go中的isNamespaceAllowed/resolveReference(约 kubernetes.go)实现了"同 namespace 放行、跨 namespace 需 allowCrossNamespace"的判定;crd provider fixtures 中即有parent_refs_cross_namespace_allowed.yml、parent_refs_cross_namespace_denied.yml、parent_refs_default_namespace.yml、parent_refs_missing_parent.yml、parent_refs_single_parent_multiple_routes.yml、parent_refs_multiple_parents.yml等用例。集成测试侧也有可运行的样例,例如 integration/fixtures/k8s/07-ingressroute-cross-namespace.yml(构造other-ns并演示跨 namespace 引用)。
实战:基于认证的多层级路由
下面用完整的 ForwardAuth 场景演示"父层认证 + 子层按角色分流"。
父 IngressRoute + 认证 Middleware:
# Parent IngressRoute 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子 IngressRoutes(按角色分流):
# Child IngressRoute for admin users apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: api-admin namespace: default spec: parentRefs: - name: api-parent namespace: default # 可选,缺省为与父对象同 namespace routes: - match: HeadersRegexp(`X-User-Role`, `admin`) kind: Rule services: - name: admin-service port: 80 --- # Child IngressRoute for regular users 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配套 Service:
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请求流转过程:
- 请求
https://api.example.com/api/endpoint命中父路由api-parent; auth-middleware(ForwardAuth)将该请求交给auth-service校验;auth-service返回200 OK并在响应中携带X-User-Role头(例如admin或user);- 携带了新请求头的请求进入子路由匹配阶段,子路由基于修改后的请求(含
X-User-Role)评估规则; - 依据角色,请求被转发到
admin-service或user-service。
这一模式还可推广到"分层中间件应用":把通用中间件(限流、CORS 等)收敛在父层(针对某个域名/路径),把业务特定的中间件留在子层,从而避免在每个路由上重复声明。
排查与验证提示
- 规则语法:
match字段使用与动态配置完全一致的 Traefik 路由规则语法(Host、PathPrefix、HeadersRegexp等),可在文档中按需查用组合运算符与优先级计算逻辑。 - 优先级冲突:当多条路由命中同一请求时,先按
priority(若有)再按规则长度排序;0值会被忽略。 - TLS 排障:若出现 421 或 TLS options 未按预期生效,优先检查是否触发了上文"同一主机名多 TLS options"的冲突回退,或是否在无
Host规则的场景下配置了options。 - 层级校验错误:中间/叶子节点若误配了
entryPoints/tls/observability/service(中间节点不应有 service、叶子节点必须有 service),Traefik 会按 Multi-Layer Routing 校验规则 拒绝或跳过相应对象并记录错误,注意观察 Traefik 日志。 - 可复用样例:仓库中 crd fixtures 与 integration/fixtures/k8s 提供了大量可直接参考的 IngressRoute 与配套 Service/Middleware 清单。
小结
IngressRoute把 Traefik HTTP Router 的完整能力——规则匹配、中间件链、服务负载均衡、TLS 终止/签发、每路由观测开关——以声明式 CRD 的形式带进 Kubernetes 生态。理解它的关键,在于把握三层映射:routes[n].match对应 Router 规则、routes[n].services对应上游 Service、tls对应 TLS 配置并按Host/SNI 关联到主机名;而parentRefs引入的层级模型又让"认证 / 上下文注入在父层、分流决策在子层"的复杂编排成为可能。结合 字段定义源码、CRD 清单 与 provider 实现 阅读本指南,即可在集群中稳定地声明、演进与排障这类核心路由资源。
【免费下载链接】traefikThe Cloud Native Application Proxy项目地址: https://gitcode.com/GitHub_Trending/tr/traefik
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考