Choosing TrafficSplit for Canary Deployments in Traefik Mesh
A decision guide that compares TrafficSplit with Istio‑based alternatives, explains trade‑offs, and shows how to implement and validate a weight‑based canary rollout.
30 Sept 2026, 12:58 UTC

Decision and Constraints
When you need to shift a percentage of live traffic from one version of a service to another without editing the service manifests, Traefik Mesh offers the TrafficSplit Custom Resource Definition (CRD). This approach works only if the following constraints are satisfied:
- Traefik Mesh version 2.2 or later is installed in the cluster.
- The target pods have an Istio‑compatible sidecar (Envoy) injected; without the proxy the TrafficSplit rules are ignored.
- Both service variants reside in the same mesh namespace; cross‑namespace splits require additional gateway or ServiceMeshPolicy configuration.
If these conditions are met, you can proceed to evaluate the available options for implementing weight‑based routing.
Option Comparison
| Option | Weight Control | Protocol Support | Relative Complexity |
|---|---|---|---|
| TrafficSplit (native CRD) | Yes (0‑100) | HTTP/HTTPS, gRPC, TCP | Low |
| DestinationRule + VirtualService (Istio) | Yes | HTTP/HTTPS, gRPC, TCP | Medium |
| Manual service annotation (e.g., version label) | No | N/A | High |
Trade‑offs
Using TrafficSplit gives you a concise YAML definition that is automatically propagated to the Envoy sidecars. The downside is that you lose access to some advanced Istio traffic‑management features such as fault injection, request timeouts, and TCP retry policies that are available in a full VirtualService. If your canary scenario only needs weight‑based splitting, the native CRD is usually the simplest choice.
Implementation Example
Create a file named frontend-split.yaml with the following contents. Replace the placeholders with your actual service names and namespace.
apiVersion: split.traefik.io/v1alpha1
kind: TrafficSplit
metadata:
name: frontend-split
namespace: prod
spec:
service: frontend
backends:
- serviceName: frontend:v1
weight: 80
- serviceName: frontend:v2
weight: 20
Apply the manifest with a user that has edit permissions in the prod namespace:
kubectl apply -f frontend-split.yaml
After applying, the controller will rewrite the Envoy configuration of the sidecars attached to frontend:v1 and frontend:v2 pods.
Verification and Validation
- Check the status of the TrafficSplit resource:
kubectl get traefiksplit frontend-split -n prod -o yaml
Look for status.currentStatus: Synced and confirm that the weight values under status.backends match the spec (80 and 20).
- Send test requests to the service endpoint (e.g., via
curlor a test pod) and observe the distribution of responses. A rough 80/20 split should appear over a sufficient number of calls. - If Prometheus scraping is enabled, query the metric:
traefikmesh_requests_total{route=\"frontend-split\"}
The two time series corresponding to backend=frontend:v1 and backend=frontend:v2 should reflect approximately an 80%/20% ratio.
Limitations
- TrafficSplit does not support advanced policies such as request‑level retries, timeouts, or fault injection. For those needs you must fall back to a full Istio
VirtualService. - The resource only works for services inside the same mesh namespace. To split traffic across namespaces you must configure a gateway or a
ServiceMeshPolicythat allows cross‑namespace sidecar communication. - If the Envoy sidecar is missing from any of the target pods, the split is ignored and all traffic goes to the default weight (usually 100% to the first backend). Verify sidecar injection with
kubectl describe pod <pod-name> -n prodand look for the Envoy container.
By following the steps above you can decide whether TrafficSplit meets your canary‑deployment requirements, apply the configuration, and validate that the weight‑based routing is active.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.