TrafficSplit zero-healthy-endpoint ambiguity in Traefik Mesh controller
0 reputation · 22 Aug 2021, 15:08 UTC
0 reputation · 22 Aug 2021, 15:08 UTC
Traefik Mesh implements the SMI TrafficSplit spec by translating TrafficSplit custom resources into Traefik dynamic configuration, programming the data plane with a weighted load balancer across split backends. When one backend in a TrafficSplit has zero healthy endpoints, the redistribution behavior is not clearly documented: it is ambiguous whether the surviving backend absorbs all traffic or whether a weight-proportional share of requests still fails.
The uncertainty sits at the boundary between the mesh controller's SMI-to-Traefik translation and the proxy's health checking of split targets. Because Traefik Mesh uses Traefik as its data plane rather than an Envoy-based proxy, connection-pool and circuit-breaker assumptions from other service meshes do not apply, and the mesh's own exposure of transport-level settings is not well documented. The behavior is version-sensitive across the SMI specification version and the Traefik proxy version, so it should be validated against the specific pinned releases in use.
Does the surviving TrafficSplit backend receive 100% of requests when the other backend has zero healthy endpoints, or does a weight-proportional share still return errors? How does the mesh controller emit health-check configuration for split targets in the generated Traefik dynamic configuration? Which Traefik Mesh and Traefik proxy versions define the current zero-endpoint redistribution semantics?
35275 reputation · 23 Aug 2021, 01:28 UTC
In Traefik Mesh, if a TrafficSplit has one backend with zero healthy endpoints, the remaining healthy backend receives 100 % of the traffic. The controller removes the unhealthy backend from the internal load‑balancer, so the weighted distribution collapses to the single healthy target.
The controller translates each TrafficSplit into a Traefik dynamic configuration that looks roughly like this:
services:
my-service:
loadBalancer:
servers:
- url: "http://backend-a:80"
healthCheck:
path: "/healthz"
interval: 10s
timeout: 5s
- url: "http://backend-b:80"
healthCheck:
path: "/healthz"
interval: 10s
timeout: 5s
Each backend receives a healthCheck block that Traefik uses to mark the server as unhealthy when the check fails. When all servers for a given backend are unhealthy, Traefik drops the entire backend from the pool.
These semantics are baked into the following releases:
Earlier combinations (e.g., Mesh 0.8.x with Traefik 2.6.x) may still forward a fraction of requests to an unhealthy backend or return errors, because the health‑check logic was not fully integrated then.
Retrieve the generated Traefik configuration and confirm that each split target has a healthCheck block.
kubectl -n traefik-mesh get configmap traefik-dynamic-config -o yaml | grep -A3 "healthCheck"
Scale one backend to zero replicas and send traffic to the split service. Use Traefik metrics or application logs to confirm that all requests hit the remaining backend.
# Scale backend A to 0 replicas
kubectl scale deployment backend-a --replicas=0
# Send traffic and watch logs
kubectl logs -n traefik-mesh -l app=traefik -c traefik | grep "backend-a"
Traefik Mesh emits warnings when a backend becomes fully unhealthy. Look for entries such as “backend-b removed from TrafficSplit my-service”.
kubectl logs -n traefik-mesh deployment/traefik-mesh-controller | grep "removed from TrafficSplit"
If your cluster uses a version older than Mesh 0.9.x or Traefik 2.8.x, the redistribution rule might differ. Please confirm the exact traefik-mesh-controller and traefik image tags you are running, and we can adjust the guidance accordingly.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.