TraefikService
TraefikService 是建立在 Kubernetes Service 之上的自定义资源,提供在 Kubernetes Service 之间进行加权轮询、最高随机权重负载均衡、流量镜像和故障转移等高级能力。
服务定义如何访问最终处理传入请求的实际端点。在 Traefik 中,目标可以是暴露 Pod 的标准 Kubernetes 服务,也可以是 TraefikService。后者允许组合以下高级负载均衡选项:
- 加权轮询负载均衡。
- 最高随机权重负载均衡。
- 流量镜像。
- 故障转移。
加权轮询¶
WRR 根据权重在多个服务之间分配请求。WRR TraefikService 可以在 Kubernetes Service 和其他 TraefikService 实例(另一个 WRR 服务或镜像服务)之间进行流量负载均衡。
配置示例¶
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: test-name
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Host(`example.com`) && PathPrefix(`/foo`)
kind: Rule
services:
# Set a WRR TraefikService
- name: wrr1
namespace: apps
kind: TraefikService
tls:
# Add a TLS certificate from a Kubernetes Secret
secretName: supersecretapiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: wrr1
namespace: apps
spec:
weighted:
services:
# Kubernetes Service
- name: svc1
namespace: apps
port: 80
weight: 1
# Second level WRR service
- name: wrr2
namespace: apps
kind: TraefikService
weight: 1
# Mirroring service
# The service is described in the Mirroring example
- name: mirror1
namespace: apps
kind: TraefikService
weight: 1apiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: wrr2
namespace: apps
spec:
weighted:
services:
# Kubernetes Service
- name: svc2
namespace: apps
port: 80
weight: 1
# Kubernetes Service
- name: svc3
namespace: apps
port: 80
weight: 1
apiVersion: v1
kind: Service
metadata:
name: svc1
namespace: apps
spec:
ports:
- name: http
port: 80
selector:
app: traefiklabs
task: app1
---
apiVersion: v1
kind: Service
metadata:
name: svc2
namespace: apps
spec:
ports:
- name: http
port: 80
selector:
app: traefiklabs
task: app2
---
apiVersion: v1
kind: Service
metadata:
name: svc3
namespace: apps
spec:
ports:
- name: http
port: 80
selector:
app: traefiklabs
task: app3apiVersion: v1
kind: Secret
metadata:
name: supersecret
namespace: apps
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=配置选项¶
| 字段 | 说明 | 默认值 | 必填 |
|---|---|---|---|
services |
由 TraefikService 和 Kubernetes 服务任意组合构成的列表。 完整选项见 Service 文档。 |
否 | |
services[m].weight |
服务权重。 | "" | 否 |
sticky.cookie.name |
WRR 服务级别用于会话粘性的 Cookie 名称。 启用粘性会话后,初始响应会设置 Set-Cookie 响应头,让客户端知道由哪台服务器处理第一次响应。后续请求中,客户端应发送带有该值的 Cookie,以保持与同一服务器的会话。 如果 Cookie 指定的服务器不再健康,请求将转发给新服务器,并通过 Cookie 记录新服务器。 更多信息请参阅多层粘性。 |
sha1 的缩写 (例如 _1d52e)。 |
否 |
sticky.cookie.httpOnly |
启用后,阻止 JavaScript 等客户端 API 访问 WRR 服务级别用于会话粘性的 Cookie。 译注:上游此处将 HttpOnly 的作用误写为允许脚本访问;此处依据 RFC 6265 第 4.1.2.6 节修正。 更多信息请参阅多层粘性。 |
false | 否 |
sticky.cookie.secure |
仅允许通过加密连接(即 HTTPS)传输 WRR 服务级别用于会话粘性的 Cookie。 更多信息请参阅多层粘性。 |
false | 否 |
sticky.cookie.sameSite |
WRR 服务级别用于会话粘性的 Cookie 的 SameSite 策略。 允许值: - none- lax- strict- None- Lax- Strict更多信息请参阅多层粘性。 |
"" | 否 |
sticky.cookie.maxAge |
WRR 服务级别用于会话粘性的 Cookie 过期前的秒数。 负数表示立即过期。 0 表示永不过期。 |
0 | 否 |
多层粘性¶
链式组合或混合使用负载均衡器时,例如服务器负载均衡器是服务负载均衡器的一个“子级”, 若希望粘性贯穿整个请求路径,就必须在所有需要的层级配置该选项。 这意味着客户端需要在 Cookie 中发送与粘性层级数量相同的键值对。
要让粘性会话在整个路径上生效,必须在每个负载均衡层级指定粘性会话。
例如,下例中两个 whoami 服务之间存在一次加权轮询负载均衡,因此构成第一级;
每个 whoami 服务又是一个 replicaset,会作为服务器负载均衡器处理,因此构成第二级。
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: ingressroutebar
namespace: apps
spec:
entryPoints:
- web
routes:
- match: Host(`example.com`) && PathPrefix(`/foo`)
kind: Rule
services:
- name: wrr1
namespace: apps
kind: TraefikServiceapiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: wrr1
namespace: apps
spec:
weighted:
services:
- name: whoami1
kind: Service
port: 80
weight: 1
# Stickiness level2 (on the Kubernetes service)
sticky:
cookie:
name: lvl2
- name: whoami2
kind: Service
weight: 1
port: 80
# Stickiness level2 (on the Kubernetes service)
sticky:
cookie:
name: lvl2
# Stickiness level2 (on the WRR service)
sticky:
cookie:
name: lvl1上例中,客户端为了始终与同一服务器保持会话,需要在每次请求的 Cookie 中指定两个层级,例如使用 curl:
# Assuming `10.42.0.6` is the IP address of one of the replicas (a pod then) of the `whoami1` service.
curl -H Host:example.com -b "lvl1=default-whoami1-80; lvl2=http://10.42.0.6:80" http://localhost:8000/foo
最高随机权重¶
HRW(最高随机权重)负载均衡器通过一致性哈希,确保来自同一客户端 IP 的请求始终路由到同一服务。与按权重分配请求的加权轮询不同,HRW 根据客户端的远端地址提供一致的路由结果。
这特别适合不依赖粘性 Cookie 的会话亲和性,因为同一客户端会根据其 IP 地址持续访问同一个后端服务。
配置示例¶
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: test-hrw
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Host(`example.com`) && PathPrefix(`/app`)
kind: Rule
services:
# Set an HRW TraefikService
- name: hrw1
namespace: apps
kind: TraefikService
tls:
secretName: supersecretapiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: hrw1
namespace: apps
spec:
highestRandomWeight:
services:
# Kubernetes Service with weight 10
- name: svc1
namespace: apps
port: 80
weight: 10
# Kubernetes Service with weight 20
- name: svc2
namespace: apps
port: 80
weight: 20
# Another TraefikService
- name: wrr1
namespace: apps
kind: TraefikService
weight: 15apiVersion: v1
kind: Service
metadata:
name: svc1
namespace: apps
spec:
ports:
- name: http
port: 80
selector:
app: traefiklabs
task: app1
---
apiVersion: v1
kind: Service
metadata:
name: svc2
namespace: apps
spec:
ports:
- name: http
port: 80
selector:
app: traefiklabs
task: app2配置选项¶
| 字段 | 说明 | 默认值 | 必填 |
|---|---|---|---|
services |
由 TraefikService 和 Kubernetes 服务任意组合构成的列表。每个服务必须分配权重。 | 是 | |
services[m].kind |
目标服务类型。 允许两个值: - Service:Kubernetes Service - TraefikService:Traefik 服务。 |
"" | 否 |
services[m].name |
服务名称。 不允许使用字符 @。 |
"" | 是 |
services[m].namespace |
服务命名空间。 | "" | 否 |
services[m].port |
服务端口,可以是端口号或端口名称。 仅当类型为 Service 时生效。 |
"" | 否 |
services[m].weight |
HRW 算法使用的服务权重。对同一个客户端 IP,权重越高的服务被选中的概率越大。 | 1 | 否 |
services[m].responseForwarding.flushInterval |
复制响应体时,向客户端刷新数据的间隔,单位为毫秒。 负值表示每次写入客户端后立即刷新。 流式响应会忽略此配置,所有写入都会立即刷新到客户端。 仅当类型为 Service 时生效。 |
100ms | 否 |
services[m].scheme |
向上游 Kubernetes Service 发起请求时使用的协议。 仅当类型为 Service 时生效。 |
"http" 如果 port 为 443 或包含字符串 https,则为 "https"。 |
否 |
services[m].serversTransport |
用于配置 Traefik 与服务器之间传输行为的 ServersTransport 资源名称。 仅当类型为 Service 时生效。 |
"" | 否 |
services[m].passHostHeader |
将客户端 Host 请求头转发给服务器。 仅当类型为 Service 时生效。 |
true | 否 |
services[m].healthCheck.scheme |
健康检查端点的服务器 URL 协议。 仅当类型为 Service 时生效。 仅适用于 ExternalName 类型的 Kubernetes 服务。 |
"" | 否 |
services[m].healthCheck.mode |
健康检查模式。 设置为 grpc 时,使用 gRPC 健康检查协议探测服务器。 仅当类型为 Service 时生效。 仅适用于 ExternalName 类型的 Kubernetes 服务。 |
"http" | 否 |
services[m].healthCheck.path |
健康检查端点的服务器 URL 路径。 仅当类型为 Service 时生效。 仅适用于 ExternalName 类型的 Kubernetes 服务。 |
"" | 否 |
services[m].healthCheck.interval |
对健康目标执行健康检查的频率。 仅当类型为 Service 时生效。 仅适用于 ExternalName 类型的 Kubernetes 服务。 |
"30s" | 否 |
services[m].healthCheck.unhealthyInterval |
对不健康目标执行健康检查的频率。 未定义时,使用 interval 的值。仅当类型为 Service 时生效。 仅适用于 ExternalName 类型的 Kubernetes 服务。 |
"30s" | 否 |
services[m].healthCheck.method |
健康检查端点使用的 HTTP 方法。 仅当类型为 Service 时生效。 仅适用于 ExternalName 类型的 Kubernetes 服务。 |
"GET" | 否 |
services[m].healthCheck.status |
健康检查响应的预期 HTTP 状态码。 仅适用于 ExternalName 类型的 Kubernetes 服务。 未设置时,预期状态码为 200 到 399。 仅当类型为 Service 时生效。 |
否 | |
services[m].healthCheck.port |
健康检查端点的 URL 端口。 仅当类型为 Service 时生效。 仅适用于 ExternalName 类型的 Kubernetes 服务。 |
否 | |
services[m].healthCheck.timeout |
判定服务器不健康之前允许等待的最长时间。 仅当类型为 Service 时生效。 仅适用于 ExternalName 类型的 Kubernetes 服务。 |
"5s" | 否 |
services[m].healthCheck.hostname |
健康检查请求的 Host 请求头值。 仅当类型为 Service 时生效。 仅适用于 ExternalName 类型的 Kubernetes 服务。 |
"" | 否 |
services[m].healthCheck.followRedirect |
健康检查是否跟随重定向。 仅当类型为 Service 时生效。 仅适用于 ExternalName 类型的 Kubernetes 服务。 |
true | 否 |
services[m].healthCheck.headers |
发送到健康检查端点的请求头映射。 仅当类型为 Service 时生效。 仅适用于 ExternalName 类型的 Kubernetes 服务。 |
否 | |
services[m].sticky.cookie.name |
用于会话粘性的 Cookie 名称。 仅当类型为 Service 时生效。 |
sha1 的缩写 (例如 _1d52e)。 |
否 |
services[m].sticky.cookie.httpOnly |
启用后,阻止 JavaScript 等客户端 API 访问该 Cookie。 译注:上游此处将 HttpOnly 的作用误写为允许脚本访问;此处依据 RFC 6265 第 4.1.2.6 节修正。 仅当类型为 Service 时生效。 |
false | 否 |
services[m].sticky.cookie.secure |
仅允许通过加密连接(即 HTTPS)传输该 Cookie。 仅当类型为 Service 时生效。 |
false | 否 |
services[m].sticky.cookie.sameSite |
SameSite 策略。 允许值不区分大小写: - none- lax- strict- None- Lax- Strict仅当类型为 Service 时生效。 |
"" | 否 |
services[m].sticky.cookie.maxAge |
Cookie 过期前的秒数。 负数表示立即过期。 0 表示永不过期。 仅当类型为 Service 时生效。 |
0 | 否 |
services[m].strategy |
服务器之间的负载均衡策略。 支持值: wrr、p2c、hrw、leasttime。仅当类型为 Service 时生效。 |
"wrr" | 否 |
services[m].nativeLB |
允许使用 Kubernetes Service 提供的 Pod 间负载均衡,而不是 Traefik 自身的负载均衡。 具体而言,将 nativeLB 设为 true 会让 Traefik 将流量路由到 Kubernetes Service,使用 kube-proxy、Cilium、Calico 等集群网络机制,并由 Kubernetes 自身执行负载均衡。设为 false 时,Traefik 直接将流量路由到 Pod,并在内部作出负载均衡决策。无论 nativeLB 如何配置,Traefik 默认都会为了性能复用已建立的后端连接。但连接复用与 nativeLB: true 结合时可能造成负载不均;如果无法接受,可以将 maxIdleConnsPerHost 设为 -1 以禁用连接复用。仅当类型为 Service 时生效。 |
false | 否 |
services[m].nodePortLB |
服务类型为 NodePort 时使用 nodePort IP 地址。 这样,当 Traefik 运行在 Kubernetes 集群外部、但与节点位于同一网络时,仍能访问服务。 仅当类型为 Service 时生效。 |
false | 否 |
HRW 的工作原理¶
最高随机权重算法将一致性哈希与加权负载均衡结合:
- 一致性哈希:对每个传入请求的客户端远端地址进行哈希,确保路由一致性。
- 加权选择:根据客户端 IP 的哈希值与服务权重,为每个服务计算一个随机值。
- 选择最大值:将请求发送给计算结果最大的服务。
这种方式具有以下优点:
- 会话亲和性:客户端持续访问同一个后端服务
- 加权分配:权重更高的服务更容易被选中
- 无需状态:与粘性 Cookie 不同,无需客户端或服务端维护状态
- 容错:某个服务不可用时,请求会以一致的方式重新分配给其余服务
流量镜像¶
流量镜像可以将发往某个服务的请求复制到其他服务。
镜像服务允许同时将流量发送给多个服务:
- 主服务接收 100% 的流量,
- 镜像服务接收指定百分比的流量。
例如升级应用版本时,可以将当前版本对应的服务设为主服务,将新版本对应的服务设为镜像服务。 这样就能在保持当前版本可访问的同时,开始测试新版本的行为。
镜像 TraefikService 可以引用 Kubernetes Service 和其他 TraefikService 实例,例如另一个 WRR 服务或镜像服务。
请注意,默认情况下,镜像操作会将整个请求缓存在内存中。
如何修改此行为,请参阅下例中的 maxBodySize 选项。
配置示例¶
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: ingressroutebar
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`example.com`) && PathPrefix(`/foo`)
kind: Rule
services:
- name: mirror1
namespace: default
kind: TraefikService# Mirroring from a k8s Service
apiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: mirror1
namespace: default
spec:
mirroring:
name: svc1 # svc1 receives 100% of the traffic
port: 80
mirrorBody: true # Default: true
maxBodySize: 1048576
mirrors:
- name: svc2 # svc2 receives a copy of 20% of this traffic
port: 80
percent: 20
- name: svc3 # svc3 receives a copy of 15% of this traffic
kind: TraefikService
percent: 15# Mirroring from a Traefik Service
apiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: mirror1
namespace: default
spec:
mirroring:
name: wrr1 # wrr1 receives 100% of the traffic
kind: TraefikService
mirrors:
- name: svc2 # svc2 receives a copy of 20% of this traffic
port: 80
percent: 20
- name: svc3 # svc3 receives a copy of 10% of this traffic
kind: TraefikService
percent: 10apiVersion: v1
kind: Service
metadata:
name: svc1
namespace: default
spec:
ports:
- name: http
port: 80
selector:
app: traefiklabs
task: app1
---
apiVersion: v1
kind: Service
metadata:
name: svc2
namespace: default
spec:
ports:
- name: http
port: 80
selector:
app: traefiklabs
task: app2配置选项¶
主服务选项¶
主服务属性直接设置在选项的根层级。
主服务提供与 Service 相同的选项。
完整的服务选项见 Service 文档。
镜像主服务的专用选项如下。
| 字段 | 说明 | 默认值 | 必填 |
|---|---|---|---|
mirrorBody |
定义是否镜像请求体。 | true | 否 |
maxBodySize |
请求体允许的最大大小。 超过此大小时,不会镜像该请求。 -1 表示大小不受限制。 |
-1 | 否 |
mirrors |
目标镜像服务列表。 可以由 TraefikService 和 Kubernetes 服务任意组合构成。 完整选项见 Service 文档。 |
是 |
镜像服务选项¶
镜像服务属性设置在 mirrors 列表中。
镜像服务提供与 Service 相同的选项。
完整的服务选项见 Service 文档。
镜像服务的专用选项如下。
| 字段 | 说明 | 默认值 | 必填 |
|---|---|---|---|
mirrors[m].percent |
路由到该服务的流量百分比。 | 0 | 否 |
故障转移¶
主服务返回 errors 配置中指定的 HTTP 状态码时,故障转移服务会将所有请求转发到备用服务。
基于健康检查状态的故障转移
目前只能通过 File 提供者为故障转移服务定义 HealthCheck。
配置示例¶
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: test-name
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Host(`example.com`) && PathPrefix(`/foo`)
kind: Rule
services:
# Set a Failover TraefikService
- name: failover1
namespace: apps
kind: TraefikServiceapiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: failover1
namespace: apps
spec:
failover:
service:
name: svc1
port: 80
fallback:
name: svc2
port: 80
errors:
status:
- "500-503"
- "429"apiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: failover1
namespace: apps
spec:
failover:
service:
name: wrr1
kind: TraefikService
fallback:
name: wrr2
kind: TraefikService
errors:
status:
- "500-503"apiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: failover1
namespace: apps
spec:
failover:
service:
name: svc1
port: 80
fallback:
name: svc2
port: 80
errors:
status:
- "500-503"
- "429"
maxRequestBodyBytes: 1048576apiVersion: v1
kind: Service
metadata:
name: svc1
namespace: apps
spec:
ports:
- name: http
port: 80
selector:
app: traefiklabs
task: app1
---
apiVersion: v1
kind: Service
metadata:
name: svc2
namespace: apps
spec:
ports:
- name: http
port: 80
selector:
app: traefiklabs
task: app2配置选项¶
主服务与备用服务选项¶
service 和 fallback 字段分别使用与 Service 相同的选项定义目标服务。
完整的服务选项见 Service 文档。
故障转移专用选项¶
| 字段 | 说明 | 默认值 | 必填 |
|---|---|---|---|
service |
接收转发请求的主服务,提供与 Service 相同的选项。 |
是 | |
fallback |
主服务返回匹配的错误状态码时使用的备用服务,提供与 Service 相同的选项。 |
是 | |
errors.status |
应当切换到备用服务的 HTTP 状态码范围列表。 每项可以是单个状态码,例如 "429",也可以是一个范围,例如 "500-503"。 |
否 | |
errors.maxRequestBodyBytes |
请求体允许的最大大小。 超过此大小时,不会向备用服务重放请求。 -1 表示大小不受限制。 |
-1 | 否 |