Implement weight‑based traffic splitting in Traefik Mesh with TrafficSplit
Guide to route a percentage of requests to different service versions using a TrafficSplit custom resource in Traefik Mesh.
27 Jul 2025, 00:25 UTC

Overview
This guide shows how to configure weight‑based traffic splitting in Traefik Mesh so that a portion of incoming requests goes to one version of a service and the remainder to another version, without modifying the application.
Desired outcome
Route, for example, 70 % of traffic to version v1 and 30 % to version v2 of a service named myservice.
Prerequisites
- A Kubernetes cluster (v1.21 or newer) with Traefik Mesh installed and mTLS enabled.
kubectlconfigured with cluster‑admin or mesh‑admin permissions.- Two Deployments that represent the service versions, each labelled with
app=myserviceand a version label, e.g.version=v1orversion=v2. - A headless Service that selects both Deployments via the
app=myservicelabel (no version label).
Procedure
- Save the following TrafficSplit manifest to a file, e.g.
trafficsplit-myservice.yaml. Adjust the namespace, service name, and weight values as needed.
apiVersion: split.traefik.io/v1alpha1
kind: TrafficSplit
metadata:
name: myservice-split
namespace: default # replace with your namespace
spec:
service: myservice # must match the Service that selects both Deployments
backends:
- service: myservice-v1 # optional: you can reference the same Service and use selectors
weight: 70
tags:
version: v1
- service: myservice-v2
weight: 30
tags:
version: v2
- Apply the manifest:
kubectl apply -f trafficsplit-myservice.yaml
Traefik Mesh controller will reconcile the TrafficSplit and update the Envoy sidecar configuration for the matching pods.
Expected checks
- Verify the Mesh controller is ready:
kubectl get meshcontroller -n traefik-mesh -o wide
Look for READY: True.
- Confirm the TrafficSplit was accepted:
kubectl get trafficsplits -n default -o yaml
The observedGeneration should match the metadata.generation of the object.
- Inspect the generated proxy configuration (optional):
kubectl get proxies -n default -l app=myservice -o yaml
Each proxy’s spec.config should contain a weighted cluster referencing the two backends.
- Validate request distribution:
# Assuming an ingress exposes the service at http://myservice.example.com
for i in {1..100}; do
curl -s -H "Host: myservice.example.com" http:/// | grep -o "X-Version: [^"]*";
done | sort | uniq -c
Each version should return a distinct header (e.g., X-Version: v1 or X-Version: v2) applied by the Deployments. The counts should approximate the 70/30 split.
Recovery options
- If the split does not behave as expected, delete the TrafficSplit to revert to default routing:
kubectl delete trafficsplit myservice-split -n default
- Check the Mesh controller logs for errors:
kubectl logs -n traefik-mesh deploy/traefik-mesh-controller
- Correct any issues (e.g., mismatched labels, weight sum not equal to 100) and re‑apply the manifest.
Limitations
- Traefik Mesh traffic splitting requires mTLS to be enabled; disabling mTLS prevents the controller from applying the TrafficSplit resource.
- The Service referenced in the TrafficSplit must select all pod versions intended for the split. If a version’s pods lack the Service’s selector, they will be excluded from the weighted routing.
- Weight values must be integers that sum to 100; otherwise the controller will reject the resource.
Practical verification tip
To avoid reliance on external tools, have each version emit a unique response header (e.g., X-Version: v1) in its container. Then a simple curl loop as shown above provides an immediate, observable check of the distribution.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.