Mastering Traefik Mesh: A Lightweight, Non‑Intrusive Service Mesh for Kubernetes
This guide introduces Traefik Mesh, a lightweight, non‑intrusive service mesh built on Traefik and SMI‑compatible Kubernetes, explains its sidecar‑free architecture, details installation via Helm, outlines static and dynamic configuration options, and provides step‑by‑step examples for deploying and testing services with traffic routing, retries, ACLs, and traffic splitting.
Non‑intrusive Service Mesh
Traefik meshis a lightweight service mesh that is simple to install and use. It is built on Traefik and conforms to the latest SMI (Service Mesh Interface) specifications for Kubernetes clusters.
The main feature of Traefik mesh is its non‑intrusive nature: deploying it does not modify existing Kubernetes objects. Traefik mesh operates without sidecars; routing is handled by a proxy running on each node, and the mesh controller runs in a separate Pod that processes configuration and deployment for the proxy nodes.
Its logic relies on CoreDNS, which is lightly reconfigured to allow Mesh endpoints alongside standard Kubernetes endpoints.
Installation
Prerequisites: Kubernetes 1.11+ CoreDNS 1.3+ Helm v3
Installation is straightforward with Helm:
helm repo add traefik-mesh https://helm.traefik.io/mesh
helm repo updateDownload the chart: helm pull traefik-mesh/traefik-mesh Extract the chart: tar xf traefik-mesh-3.0.6.tgz Traefik mesh deploys four services:
controller – the mesh controller that analyses and applies configuration.
proxy – the data‑plane proxy handling traffic on each node.
tracing – tracing configuration.
metrics – monitoring configuration.
Install the mesh: helm install traefik-mesh . The mesh requires a compatible CoreDNS ConfigMap. Example modifications:
#### Begin Maesh Block
maesh:53 {
errors
rewrite continue {
name regex ([a-zA-Z0-9-_]*)\.([a-zv0-9-_]*)\.maesh default-{1}-6d61657368-{2}.default.svc.cluster.local
answer name default-([a-zA-Z0-9-_]*)-6d61657368-([a-zA-Z0-9-_]*)\.default\.svc\.cluster\.local {1}.{2}.maesh
}
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
#### End Maesh Block
#### Begin Traefik Mesh Block
traefik.mesh:53 {
errors
rewrite continue {
name regex ([a-zA-Z0-9-_]*)\.([a-zv0-9-_]*)\.traefik.mesh default-{1}-6d61657368-{2}.default.svc.cluster.local
answer name default-([a-zA-Z0-9-_]*)-6d61657368-([a-zA-Z0-9-_]*)\.default\.svc\.cluster\.local {1}.{2}.traefik.mesh
}
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
#### End Traefik Mesh BlockIf CoreDNS reports the error "plugin/forward: this plugin can only be used once per Server Block", check that the ConfigMap does not contain duplicate forward sections.
Configuration
Traefik mesh configuration is split into static and dynamic parts.
Static Configuration
Specify image versions for the controller and Traefik components.
Set log level and format for controller and proxies.
Choose the mesh mode (default HTTP).
Enable tracing support.
Activate ACL mode to block all traffic unless explicitly allowed via SMI traffic targets.
Dynamic Configuration
Dynamic settings are applied through Kubernetes annotations and SMI objects. Supported parameters include:
Traffic‑Type (http, tcp, udp)
Scheme (http, https, h2c)
Retry attempts
Circuit‑Breaker expression
Rate‑Limit (average and burst)
Traffic‑Split
Traffic‑Target
Example annotation for a service:
mesh.traefik.io/traffic-type: "http"
mesh.traefik.io/retry-attempts: "2"Access control is defined with an HTTPRouteGroup and a corresponding TrafficTarget that grants a client ServiceAccount permission to access specific routes.
Example Deployment
The following manifests deploy a namespace whoami with two applications (HTTP and TCP) and the necessary ServiceAccounts, Deployments, Services, and a client pod.
apiVersion: v1
kind: Namespace
metadata:
name: whoami
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: whoami-server
namespace: whoami
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: whoami-client
namespace: whoami
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: whoami
namespace: whoami
spec:
replicas: 2
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
serviceAccount: whoami-server
containers:
- name: whoami
image: traefik/whoami:v1.6.0
imagePullPolicy: IfNotPresent
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: whoami-tcp
namespace: whoami
spec:
replicas: 2
selector:
matchLabels:
app: whoami-tcp
template:
metadata:
labels:
app: whoami-tcp
spec:
serviceAccount: whoami-server
containers:
- name: whoami-tcp
image: traefik/whoamitcp:v0.1.0
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
name: whoami
namespace: whoami
labels:
app: whoami
spec:
type: ClusterIP
ports:
- port: 80
name: whoami
selector:
app: whoami
---
apiVersion: v1
kind: Service
metadata:
name: whoami-tcp
namespace: whoami
labels:
app: whoami-tcp
spec:
type: ClusterIP
ports:
- port: 8080
name: whoami-tcp
selector:
app: whoami-tcp
---
apiVersion: v1
kind: Pod
metadata:
name: whoami-client
namespace: whoami
spec:
serviceAccountName: whoami-client
containers:
- name: whoami-client
image: giantswarm/tiny-tools:3.9
command:
- "sleep"
- "3600"Check deployment status: kubectl get all -n whoami Test connectivity:
# kubectl -n whoami exec whoami-client -- curl -s whoami.whoami.svc.cluster.local
Hostname: whoami-576cb59fd-qvnl7
IP: 127.0.0.1
IP: 172.16.235.193
RemoteAddr: 172.16.7.181:33150
GET / HTTP/1.1
Host: whoami.whoami.svc.cluster.local
User-Agent: curl/7.64.0
Accept: */*
# kubectl -n whoami exec -ti whoami-client -- nc whoami-tcp.whoami.svc.cluster.local 8080
my data
Received: my dataTo enable Traefik mesh for the services, add the appropriate annotations:
apiVersion: v1
kind: Service
metadata:
name: whoami
namespace: whoami
labels:
app: whoami
annotations:
mesh.traefik.io/traffic-type: "http"
mesh.traefik.io/retry-attempts: "2"
spec:
type: ClusterIP
ports:
- port: 80
name: whoami
selector:
app: whoami
---
apiVersion: v1
kind: Service
metadata:
name: whoami-tcp
namespace: whoami
labels:
app: whoami-tcp
annotations:
mesh.traefik.io/traffic-type: "tcp"
spec:
type: ClusterIP
ports:
- port: 8080
name: whoami-tcp
selector:
app: whoami-tcpAfter adding the annotations, the service DNS can be accessed via the traefik.mesh domain instead of svc.cluster.local:
# Before: curl whoami.whoami.svc.cluster.local
# After: curl whoami.whoami.traefik.meshBoth the original and mesh‑enabled addresses remain functional, allowing users to choose their preferred method.
References: https://traefik.io/traefik/ https://smi-spec.io/ https://coredns.io/
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Ops Development Stories
Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
