Traefik
a modern proxy for Microservices
#breakfast-club
by Ole Rößner
$ whoami
- Ole Rößner
- married, father
- neusta GmbH (Bremen)
- Coding, Coaching and Consulting
- Symfony Enthusiast
- Clean Code Evangelist
- Former DJ
Edge Router?
Auto Service Discovery?
Simple Example with
Docker-Compose
# docker-compose.yaml
version: '3'
services:
traefik:
# The official Traefik docker image
image: traefik:2.2
# Enables the web UI and tells Traefik to listen to docker
command: --api.insecure=true --providers.docker
ports:
# The HTTP port
- "80:80"
# The Web UI (enabled by --api.insecure=true)
- "8080:8080"
volumes:
# So that Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock:ro
# docker-compose.yaml
# [...]
whoami:
# A container that exposes an API to show its IP address
image: containous/whoami
labels:
# /etc/hosts -> 127.0.0.1 app.test
- "traefik.http.routers.whoami.rule=Host(`app.test`)"
# docker-compose.yaml
# [...]
hello:
# A container that always answers "Hello World!" on port 8000
image: djbasster/hello-react-php
labels:
- "traefik.http.routers.hello.rule=Path(`/hello`)"
Routing Rules
- Headers(`key`, `value`)
- HeadersRegexp(`key`, `regexp`)
- Host(`example.com`, ...)
- HostRegexp(`example.com`, `{subdomain:[a-z]+}.example.com`, ...)
- Method(`GET`, ...)
- Path(`/path`, `/articles/{cat:[a-z]+}/{id:[0-9]+}`, ...)
- PathPrefix(`/products/`, `/articles/{cat:[a-z]+}/{id:[0-9]+}`)
- Query(`foo=bar`, `bar=baz`)
&&
,
||
and
()
possible!
Image Source: Dribbble
Quiz Time
Priority & Service Injection
## Dynamic configuration
http:
routers:
Router-1:
rule: "HostRegexp(`.*\.traefik\.com`)"
# ...
Router-2:
rule: "Host(`foobar.traefik.com`)"
# ...
Name | Rule | Priority |
---|---|---|
Router-1 |
HostRegexp(`.*\.traefik\.com`) |
30 |
Router-2 | Host(`foobar.traefik.com`) |
26 |
What's wrong here?
Priority & Service Injection
## Dynamic configuration
http:
routers:
Router-1:
rule: "HostRegexp(`.*\.traefik\.com`)"
priority: 1
# ...
Router-2:
rule: "Host(`foobar.traefik.com`)"
priority: 2
# ...
priority = 0
Use the default rules length sorting!
⚠️
Service Injection?
Service Injection?
http:
routers:
monolyth:
rule: "Host(`www.my-old-fat-website.com`)"
service: website
# priority: 35 (implicit)
# ...
microservice:
rule: "Host(`www.my-old-fat-website.com`) && Path(`/votes`)"
service: voting-service
# priority: 53 (implicit)
# ...
Maintenance Injection
version: '3'
services:
website:
image: my-website
labels:
- traefik.http.routers.website.rule=Host(`example.com`)
foo-service:
image: foo-service
labels:
- traefik.http.routers.foo.rule=Host(`example.com`) && Path(`/foo`)
maintenance:
image: my-static-maintenance-site
labels:
- traefik.http.routers.maintenance.rule=Host(`example.com`)
- traefik.http.routers.maintenance.priority=1
- traefik.http.middlewares.maintenance-stripper.stripprefixregex.regex=/.*
- traefik.http.routers.maintenance.middlewares=maintenance-stripper@docker
version: '3'
services:
website:
image: my-website
labels:
- traefik.http.routers.website.rule=Host(`example.com`)
foo-service:
image: foo-service
labels:
- traefik.http.routers.foo.rule=Host(`example.com`) && Path(`/foo`)
maintenance:
image: my-static-maintenance-site
labels:
- traefik.http.routers.maintenance.rule=Host(`example.com`)
- traefik.http.routers.maintenance.priority=9999
- traefik.http.middlewares.maintenance-stripper.stripprefixregex.regex=/.*
- traefik.http.routers.maintenance.middlewares=maintenance-stripper@docker
docker-compose up -d maintenance
Services
File Provider VS Docker-Compose
## Dynamic configuration: File Provider
http:
services:
my-service:
loadBalancer:
servers:
- url: "http://<private-ip-server-1>:<private-port-server-1>/"
- url: "http://<private-ip-server-2>:<private-port-server-2>/"
## docker-compose.yaml
version: "3"
services:
my-service:
image: my-service-image
deploy:
replicas: 6
labels:
- "traefik.http.routers.my-service.rule=Host(`example.com`)"
Example: Sticky Sessions
## docker-compose.yaml
version: "3"
services:
my-service:
image: my-service-image
deploy:
replicas: 6
labels:
- "traefik.http.routers.my-service.rule=Host(`example.com`)"
- "traefik.http.routers.my-service.service=my-service-svc"
- "traefik.http.services.my-service-svc.loadbalancer.sticky.cookie=true"
Traefik Docs: Sticky Sessions
Example: Explicit Port
## docker-compose.yaml
version: "3"
services:
my-service:
image: my-service-image # exposes 8080 and 9000
labels:
- "traefik.http.routers.my-service.rule=Host(`example.com`)"
- "traefik.http.routers.my-service.service=my-service-svc"
- "traefik.http.services.my-service-svc.loadbalancer.server.port=8080"
What else is a Service for?
Middlewares
Middleware | Purpose | Area |
---|---|---|
AddPrefix | Add a Path Prefix | Path Modifier |
BasicAuth | Basic auth mechanism | Security, Authentication |
Buffering | Buffers the request/response | Request Lifecycle |
Chain | Combine multiple pieces of middleware | Middleware tool |
CircuitBreaker | Stop calling unhealthy services | Request Lifecycle |
Compress | Compress the response | Content Modifier |
DigestAuth | Adds Digest Authentication | Security, Authentication |
Errors | Define custom error pages | Request Lifecycle |
ForwardAuth | Authentication delegation | Security, Authentication |
Headers | Add / Update headers | Security |
IPWhiteList | Limit the allowed client IPs | Security, Request lifecycle |
InFlightReq | Limit the number of simultaneous connections | Security, Request lifecycle |
PassTLSClientCert | Adding Client Certificates in a Header | Security |
RateLimit | Limit the call frequency | Security, Request lifecycle |
RedirectScheme | Redirect easily the client elsewhere | Request lifecycle |
RedirectRegex | Redirect the client elsewhere | Request lifecycle |
ReplacePath | Change the path of the request | Path Modifier |
ReplacePathRegex | Change the path of the request | Path Modifier |
Retry | Automatically retry the request in case of errors | Request lifecycle |
StripPrefix | Change the path of the request | Path Modifier |
StripPrefixRegex | Change the path of the request | Path Modifier |
HTTP -> HTTPS Redirect
version: '3'
services:
traefik:
image: traefik:2.0
# ...
labels:
- traefik.http.middlewares.http-to-https.redirectscheme.permanent=true
- traefik.http.middlewares.http-to-https.redirectscheme.port=443
- traefik.http.middlewares.http-to-https.redirectscheme.scheme=https
website:
# ...
labels:
- traefik.http.routers.website.entrypoints=web
- traefik.http.routers.website.middlewares=http-to-https@docker
- traefik.http.routers.website.rule=Host(`example.com`)
- traefik.http.routers.website-secured.entrypoints=web-secure
- traefik.http.routers.website-secured.rule=Host(`example.com`)
version: '3'
services:
traefik:
image: traefik:2.1
command:
# ...
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entryPoint.to=websecure
- --entrypoints.web.http.redirections.entryPoint.scheme=https
- --entrypoints.web.http.redirections.entrypoint.permanent=true
- --entrypoints.websecure.address=:443
website:
# ...
labels:
- traefik.http.routers.website.entrypoints=websecure # optional!
- traefik.http.routers.website.rule=Host(`example.com`)
OLD!
NEW!
Example: GZIP Compression
version: '3'
services:
traefik:
image: traefik:2.2
# ...
labels:
- traefik.http.middlewares.gzip.compress=true
whoami:
image: containous/whoami
labels:
- traefik.http.routers.whoami.rule=Host(`app.test`)
- traefik.http.routers.whoami.middlewares=gzip@docker
Example: Headers
version: '3'
services:
traefik:
image: traefik:2.2
# ...
labels:
- traefik.http.middlewares.testHeader.headers.customrequestheaders.X-Script-Name=test
- traefik.http.middlewares.testHeader.headers.customresponseheaders.X-Custom-Response-Header=value
- traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist=https://example.org
whoami:
image: containous/whoami
labels:
- traefik.http.routers.whoami.rule=Host(`app.test`)
- traefik.http.routers.whoami.middlewares=testHeader
Example: Rate Limit
version: '3'
services:
traefik:
image: traefik:2.2
# ...
labels:
# Here, an average of 100 requests per second is allowed.
# In addition, a burst of 50 requests is allowed.
- traefik.http.middlewares.test-ratelimit.ratelimit.average=100
- traefik.http.middlewares.test-ratelimit.ratelimit.burst=50
whoami:
image: containous/whoami
labels:
- traefik.http.routers.whoami.rule=Host(`app.test`)
- traefik.http.routers.whoami.middlewares=test-ratelimit@docker
Let's Encrypt
version: '3'
services:
traefik:
image: traefik:2.2
command:
- # ...
- --certificatesresolvers.myresolver.acme.email=your-email@example.com
- --certificatesresolvers.myresolver.acme.storage=acme.json
# used during the challenge
- --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web
# during development
- --certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
blog:
image: my-blog
# ...
labels:
- traefik.http.routers.blog.rule=Host(`example.com`) && Path(`/blog`)
- traefik.http.routers.blog.tls=true
- traefik.http.routers.blog.tls.certresolver=myresolver
Provider: Traefik Docs
Metrics
Metrics Support
Traefik supports 4 metrics backends:
- Datadog
- InfluxDB
- Prometheus
- StatsD
version: '3'
services:
traefik:
image: traefik:2.2
command:
- --api.insecure=true
- --providers.docker
- --metrics.prometheus=true
- --entryPoints.metrics.address=:8082
- --metrics.prometheus.entryPoint=metrics
Example: Prometheus
Tracing
Tracing Support
Traefik supports six tracing backends:
- Jaeger
- Zipkin
- Datadog
- Instana
- Haystack
- Elastic
B3-Propagation & OpenCensus compatible!
version: '3'
services:
traefik:
image: traefik:2.2
command:
- --api.insecure=true
- --providers.docker
- --tracing.zipkin=true
- --tracing.zipkin.httpEndpoint=http://localhost:9411/api/v2/spans
- --tracing.zipkin.sampleRate=0.2
Example: Zipkin
<label class="sr-only">Traefik loves Kubernetes</label>
Ingress Controller
# deployment.yaml
containers:
- name: traefik
image: traefik:v2.2
args:
- --log.level=DEBUG
- --api
- --api.insecure
- --entrypoints.web.address=:80
- --providers.kubernetesingress
ports:
- name: web
containerPort: 80
- name: admin
containerPort: 8080
Custom Resource Definition (CRD)
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: my-route
spec:
entryPoints:
- foo
routes:
- kind: Rule
match: Host(`test.example.com`)
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: gzip
spec:
compress: {}
Questions?
Questions!
Image Source: Dribbble
Traefik
By neusta Coaching-Team
Traefik
The Cloud Native Edge Router
- 2,535