Traefik Mesh Traffic Splitting: Canary Deployments with the TraefikService CRD
Traefik Mesh uses the TraefikService CRD for weight-based HTTP traffic splitting, enabling canary rollouts without sidecars or a separate control plane.
29 Mar 2026, 15:34 UTC

The Problem: Lightweight Canary Rollouts Without Sidecars
You want to shift a small percentage of traffic to a new service version, but you don’t want the operational overhead of a full-blown service mesh with sidecar injection, a separate control plane, or mTLS certificate rotation. Traefik Mesh (formerly Maesh) was built for exactly this scenario: a mesh that runs as a set of Traefik Proxy pods, no sidecars, no etcd, and configuration driven entirely by Kubernetes CRDs. The feature that makes canary deployments practical is the TraefikService custom resource, which lets you define weight-based routing between two or more Kubernetes Services.
How TraefikService Implements Weight-Based Splitting
The TraefikService CRD references existing Kubernetes Service objects and assigns each a weight. The mesh controller (embedded in every Traefik proxy pod) programs the proxy layer to distribute incoming HTTP/HTTP2 requests proportionally. Because the control plane lives in the data plane, weight changes propagate in sub-second latency—no gRPC round-trip to a central controller.
Key characteristics:
- Native Service references—no new abstraction for subsets.
- Layer-7 (HTTP/HTTP2) only; TCP/UDP splitting requires different tooling.
- Inherits Traefik’s built-in retries, timeouts, and sticky sessions per backend.
- Optional mTLS via SPIFFE certificates; splitting occurs inside the encrypted mesh.
Worked Example: 90/10 Canary Rollout
Assume you have two Deployments, myapp-stable and myapp-canary, each exposed via a ClusterIP Service (myapp-stable-svc, myapp-canary-svc). You want 10% of mesh traffic to hit the canary.
1. Create the TraefikService
apiVersion: maesh.containo.us/v1alpha1
kind: TraefikService
metadata:
name: myapp-split
namespace: default
spec:
services:
- name: myapp-stable-svc
weight: 90
- name: myapp-canary-svc
weight: 10
Apply it from a workstation with kubectl access to the cluster (cluster-admin or a role that can create TraefikService resources in the target namespace):
kubectl apply -f myapp-split.yaml
2. Verify the Split
Traefik Mesh exposes a mesh-wide DNS name of the form <traefikservice-name>.<namespace>.maesh. From any pod in the mesh (or a temporary debug pod), run:
for i in {1..100}; do curl -s http://myapp-split.default.maesh/version; done | sort | uniq -c
You should see roughly a 90/10 distribution between the stable and canary version strings. Because weight updates are eventually consistent across proxies, a brief imbalance (a few seconds) is normal after each change.
3. Progress the Rollout
Adjust the weights by editing the resource (or via GitOps):
kubectl patch traefikservice myapp-split -n default --type=merge -p '{"spec":{"services":[{"name":"myapp-stable-svc","weight":50},{"name":"myapp-canary-svc","weight":50}]}}'
Repeat the curl test to confirm the new ratio. When you’re satisfied, set the canary weight to 100 and decommission the stable Deployment.
Trade-offs and Limitations
| Area | Implication |
|---|---|
| Project status | Deprecated and archived since 2023. No security patches for CVEs after the v1.4.0 release. |
| Protocol support | HTTP/HTTP2 only. TCP/UDP services need a different solution (e.g., Traefik Enterprise TCP routers or a sidecar mesh). |
| Observability | No built-in metrics for split ratios. You must correlate access logs or use the deprecated Traefik Pilot. |
| Migration path | TraefikService schema differs from Gateway API HTTPRoute weight fields. Migration requires rewriting traffic policies. |
| Consistency | Weight changes are eventually consistent; brief imbalance may occur during rollout. |
Actionable Closing
If you’re running Traefik Mesh today, treat it as a maintenance-only component. Plan migration to Gateway API with Traefik Proxy’s native HTTPRoute weight support, or evaluate Traefik Enterprise for a supported control plane. For new clusters, start with Gateway API and a supported ingress controller (Traefik, NGINX, Envoy) to avoid technical debt. The TraefikService pattern—native Service references, weight-based splitting, sub-second propagation—remains a clean mental model; just map it to the standard HTTPRoute backendRefs with weight fields when you move forward.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.