Traefik
Modern HTTP reverse proxy and load balancer. Automatic service discovery, Docker/Kubernetes integration, Let's Encrypt automatic certificate acquisition.
Server
Traefik Proxy
Overview
Traefik Proxy is a modern HTTP reverse proxy and load balancer designed for microservice architectures. It integrates with existing infrastructure components (Docker, Kubernetes, etc.) to automatically and dynamically configure itself. By listening to service registry/orchestrator APIs and generating routes in real-time, it significantly simplifies microservice deployment. With automatic Let's Encrypt integration, comprehensive observability features, and a chainable middleware system, it is widely adopted in modern cloud-native environments.
Details
Traefik Proxy features a sophisticated architecture composed of EntryPoints (network listeners), Routers (routing logic), Middlewares (request/response processing), and Services (backend servers). A dual configuration system of static configuration (loaded at startup) and dynamic configuration (updated at runtime) enables configuration changes without restarts. It integrates with diverse providers like Docker, Kubernetes, Consul, and Etcd to provide service discovery capabilities. Advanced load balancing features include Weighted Round Robin, health checks, failover, and mirroring.
Key Features
- Dynamic Configuration Management: Zero-downtime configuration changes through orchestrator integration
- Automatic Service Discovery: Automatic route generation from Docker/Kubernetes and other providers
- Automatic HTTPS: Let's Encrypt integration with wildcard certificate support
- Comprehensive Observability: Metrics, logging, and distributed tracing capabilities
- Middleware System: Flexible processing for authentication, header manipulation, redirects, etc.
- Single Binary: Simple deployment with a single executable file
Pros and Cons
Pros
- Automatic configuration optimized for microservices and container environments
- Dynamic configuration system enabling configuration changes without restarts
- Significant simplification of certificate management through automatic Let's Encrypt integration
- Rich observability integration with Prometheus, OpenTelemetry, and more
- Flexible request processing through chainable middleware
- Easy deployment with official Docker images and single binary
Cons
- High learning curve due to the combination of static and dynamic configurations
- Configuration complexity risks due to provider dependencies
- Configuration complexity with advanced routing rules
- Overhead compared to traditional static proxies
- Difficult debugging and troubleshooting in large-scale environments
- Risk of configuration update stoppage during provider failures
Reference Pages
- Traefik Proxy Official Website
- Traefik Proxy Documentation
- Traefik GitHub Repository
- Traefik Community
Code Examples
Basic Configuration and HTTP Routing
# traefik.yml (static configuration)
api:
dashboard: true
insecure: true
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
providers:
file:
directory: "/etc/traefik/dynamic"
watch: true
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
certificatesResolvers:
letsencrypt:
acme:
email: [email protected]
storage: acme.json
httpChallenge:
entryPoint: web
log:
level: INFO
accessLog: {}
metrics:
prometheus:
addEntryPointsLabels: true
addServicesLabels: true
# dynamic.yml (dynamic configuration)
http:
routers:
api-router:
rule: "Host(`api.example.com`)"
service: api-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt
middlewares:
- auth-middleware
- rate-limit
frontend-router:
rule: "Host(`www.example.com`)"
service: frontend-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt
middlewares:
auth-middleware:
basicAuth:
users:
- "admin:$2y$10$..."
rate-limit:
rateLimit:
burst: 100
average: 50
services:
api-service:
loadBalancer:
servers:
- url: "http://api-server1:8080"
- url: "http://api-server2:8080"
healthCheck:
path: "/health"
interval: "30s"
timeout: "5s"
frontend-service:
loadBalancer:
servers:
- url: "http://frontend-server:3000"
Docker Compose Integration and Service Discovery
# docker-compose.yml
version: '3.8'
services:
traefik:
image: traefik:v3.0
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "8080:8080"
command:
- --api.dashboard=true
- --api.insecure=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --certificatesresolvers.letsencrypt.acme.httpchallenge=true
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
- --certificatesresolvers.letsencrypt.acme.email=your-email@example.com
- --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
- --log.level=INFO
- --accesslog=true
- --metrics.prometheus=true
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- letsencrypt:/letsencrypt
networks:
- traefik-network
web-app:
image: nginx:alpine
container_name: web-app
labels:
- "traefik.enable=true"
- "traefik.http.routers.webapp.rule=Host(`app.example.com`)"
- "traefik.http.routers.webapp.entrypoints=websecure"
- "traefik.http.routers.webapp.tls.certresolver=letsencrypt"
- "traefik.http.services.webapp.loadbalancer.server.port=80"
- "traefik.http.middlewares.webapp-auth.basicauth.users=admin:$$2y$$10$$..."
- "traefik.http.routers.webapp.middlewares=webapp-auth"
networks:
- traefik-network
api-app:
image: node:alpine
container_name: api-app
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`api.example.com`) && PathPrefix(`/api`)"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
- "traefik.http.services.api.loadbalancer.server.port=3000"
- "traefik.http.middlewares.api-ratelimit.ratelimit.average=100"
- "traefik.http.middlewares.api-ratelimit.ratelimit.burst=200"
- "traefik.http.routers.api.middlewares=api-ratelimit"
networks:
- traefik-network
volumes:
letsencrypt:
networks:
traefik-network:
external: true
Kubernetes Integration (IngressRoute CRD)
# traefik-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik
namespace: traefik-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: traefik
rules:
- apiGroups: [""]
resources: ["services", "endpoints", "secrets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["extensions", "networking.k8s.io"]
resources: ["ingresses", "ingressclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: ["traefik.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: traefik
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik
subjects:
- kind: ServiceAccount
name: traefik
namespace: traefik-system
---
# traefik-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: traefik
namespace: traefik-system
labels:
app: traefik
spec:
replicas: 2
selector:
matchLabels:
app: traefik
template:
metadata:
labels:
app: traefik
spec:
serviceAccountName: traefik
containers:
- name: traefik
image: traefik:v3.0
args:
- --api.dashboard=true
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --providers.kubernetescrd
- --certificatesresolvers.letsencrypt.acme.httpchallenge=true
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
- [email protected]
- --certificatesresolvers.letsencrypt.acme.storage=/data/acme.json
- --log.level=INFO
- --accesslog=true
- --metrics.prometheus=true
ports:
- name: web
containerPort: 80
- name: websecure
containerPort: 443
- name: admin
containerPort: 8080
volumeMounts:
- name: data
mountPath: /data
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
volumes:
- name: data
persistentVolumeClaim:
claimName: traefik-data
---
# traefik-ingressroute.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: api-ingressroute
namespace: default
spec:
entryPoints:
- websecure
routes:
- match: Host(`api.example.com`)
kind: Rule
services:
- name: api-service
port: 80
middlewares:
- name: api-auth
- name: api-ratelimit
tls:
certResolver: letsencrypt
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: api-auth
namespace: default
spec:
basicAuth:
secret: api-auth-secret
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: api-ratelimit
namespace: default
spec:
rateLimit:
average: 100
burst: 200
---
apiVersion: v1
kind: Secret
metadata:
name: api-auth-secret
namespace: default
data:
users: YWRtaW46JGFwcjEkSDZKeFhXb3lQYVhuE... # htpasswd format
Load Balancing and Health Check Configuration
# Weighted round-robin configuration
http:
services:
weighted-service:
weighted:
services:
- name: service-v1
weight: 70
- name: service-v2
weight: 30
service-v1:
loadBalancer:
servers:
- url: "http://app-v1-1:8080"
- url: "http://app-v1-2:8080"
healthCheck:
path: "/health"
interval: "10s"
timeout: "3s"
scheme: "http"
service-v2:
loadBalancer:
servers:
- url: "http://app-v2-1:8080"
- url: "http://app-v2-2:8080"
healthCheck:
path: "/health"
interval: "10s"
timeout: "3s"
# Sticky session configuration
sticky-service:
loadBalancer:
servers:
- url: "http://backend1:8080"
- url: "http://backend2:8080"
sticky:
cookie:
name: "server-session"
secure: true
httpOnly: true
# Failover configuration
failover-service:
failover:
service: primary-service
fallback: backup-service
primary-service:
loadBalancer:
servers:
- url: "http://primary-server:8080"
healthCheck:
path: "/health"
interval: "5s"
backup-service:
loadBalancer:
servers:
- url: "http://backup-server:8080"
Advanced Middleware Configuration
# Authentication and authorization middleware
http:
middlewares:
# OAuth2 authentication
oauth-auth:
forwardAuth:
address: "http://oauth-provider:4181"
authResponseHeaders:
- "X-Forwarded-User"
- "X-Auth-User"
- "X-Secret"
# JWT authentication
jwt-auth:
plugin:
jwt:
secret: "your-jwt-secret"
alg: "HS256"
# Rate limiting
rate-limit-strict:
rateLimit:
extractorFunc: "request.host"
rateLimitKey: "client.ip"
average: 6
period: "1m"
burst: 12
# CORS configuration
cors-middleware:
headers:
accessControlAllowMethods:
- GET
- OPTIONS
- PUT
- POST
- DELETE
accessControlAllowOriginList:
- "https://example.com"
- "https://api.example.com"
accessControlMaxAge: 100
addVaryHeader: true
# Security headers
security-headers:
headers:
contentTypeNosniff: true
browserXssFilter: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 31536000
# Request transformation
transform-request:
addPrefix:
prefix: "/api/v1"
# Response transformation
transform-response:
headers:
customRequestHeaders:
X-Custom-Request-Header: "request-value"
customResponseHeaders:
X-Custom-Response-Header: "response-value"
routers:
protected-api:
rule: "Host(`secure.example.com`)"
service: api-service
middlewares:
- oauth-auth
- rate-limit-strict
- cors-middleware
- security-headers
- transform-request
tls:
certResolver: letsencrypt
TCP Routing and SSL Termination
# TCP configuration
tcp:
routers:
mysql-router:
rule: "HostSNI(`mysql.example.com`)"
service: mysql-service
tls:
passthrough: false
certResolver: letsencrypt
postgres-router:
rule: "HostSNI(`postgres.example.com`)"
service: postgres-service
tls:
passthrough: true
redis-router:
rule: "HostSNI(`*`)"
service: redis-service
entryPoints:
- redis
services:
mysql-service:
loadBalancer:
servers:
- address: "mysql-master:3306"
- address: "mysql-slave:3306"
proxyProtocol:
version: 1
postgres-service:
loadBalancer:
servers:
- address: "postgres-primary:5432"
- address: "postgres-secondary:5432"
redis-service:
loadBalancer:
servers:
- address: "redis-node1:6379"
- address: "redis-node2:6379"
- address: "redis-node3:6379"
entryPoints:
redis:
address: ":6379"
mysql:
address: ":3306"
postgres:
address: ":5432"
Monitoring and Logging Configuration
# traefik.yml
log:
level: INFO
format: json
accessLog:
filePath: "/var/log/traefik/access.log"
format: json
fields:
defaultMode: keep
headers:
defaultMode: drop
names:
User-Agent: keep
Authorization: drop
Content-Type: keep
metrics:
prometheus:
addEntryPointsLabels: true
addServicesLabels: true
buckets:
- 0.1
- 0.3
- 1.2
- 5.0
tracing:
jaeger:
samplingServerURL: "http://jaeger:14268/api/sampling"
localAgentHostPort: "jaeger:6831"
ping:
entryPoint: "ping"
entryPoints:
ping:
address: ":8082"
api:
dashboard: true
debug: true
Troubleshooting
# Check Traefik status
docker logs traefik
# Check configuration
curl http://localhost:8080/api/rawdata
# Check router status
curl http://localhost:8080/api/http/routers
# Check service status
curl http://localhost:8080/api/http/services
# Check middleware status
curl http://localhost:8080/api/http/middlewares
# Check health
curl http://localhost:8082/ping
# Check metrics
curl http://localhost:8080/metrics
# Reload configuration (file provider)
docker exec traefik kill -SIGUSR1 1
# Change log level
docker exec traefik traefik --log.level=DEBUG
# Check SSL certificates
openssl s_client -connect your-domain.com:443 -servername your-domain.com
# Validate Docker Compose configuration
docker-compose config