Aller au contenu principal

Traefik

· 4 minutes de lecture

La configuration d'un reverse proxy traditionnel exige une intervention manuelle à chaque ajout ou modification d'un service : éditer un fichier de configuration, tester la syntaxe, recharger le process. Dans un environnement conteneurisé où les services démarrent et s'arrêtent fréquemment, cette approche ne tient pas. Traefik résout ce problème en découvrant automatiquement les services depuis Docker ou Kubernetes et en générant sa configuration à la volée, sans interruption de service.

Modèle mental

Traefik sépare clairement la configuration statique (démarrée une fois au lancement) de la configuration dynamique (mise à jour en temps réel depuis les providers).

Configuration statique : entrypoints (ports d'écoute), providers (sources de config), certificate resolvers (ACME). Ne peut pas être rechargée à chaud.

Configuration dynamique : routers, services, middlewares. Rechargée à chaud depuis les labels Docker, les annotations Kubernetes, ou des fichiers de config.

Configuration statique (flags CLI / traefik.yml)
└── Entrypoints (ports 80, 443)
└── Providers (Docker, Kubernetes, File)
└── Certificate resolvers (Let's Encrypt)

Configuration dynamique (labels, annotations, fichiers)
└── Routers (règles de matching)
└── Middlewares (transformations)
└── Services (backends)

Un router fait le matching entre une requête entrante et un service. Une règle de router combine des prédicats : Host(\api.example.com`), PathPrefix(`/api`), Method(`GET`), Headers(`X-Api-Key`, `.*`)`.

Déploiement avec Docker

Traefik lit les labels Docker en montant le socket Docker en lecture seule.

services:
traefik:
image: traefik:v3.0
command:
- --api.dashboard=true
- --api.insecure=false
- --providers.docker=true
- --providers.docker.exposedByDefault=false # sécurité : opt-in par service
- --providers.docker.network=proxy # réseau Docker par défaut pour les backends
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.websecure.address=:443
- --certificatesresolvers.letsencrypt.acme.email=admin@example.com
- --certificatesresolvers.letsencrypt.acme.storage=/acme.json
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./acme.json:/acme.json
networks:
- proxy

networks:
proxy:
external: true
touch acme.json && chmod 600 acme.json
docker network create proxy
docker compose up -d

Un service s'expose avec quelques labels :

services:
api:
image: myapp:latest
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`api.example.com`)"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
- "traefik.http.services.api.loadbalancer.server.port=8000"

Traefik détecte le conteneur au démarrage et configure immédiatement le router — sans redémarrer Traefik.

Middlewares

Les middlewares transforment les requêtes entre le router et le backend. Ils se définissent séparément et s'attachent à un ou plusieurs routers.

Redirection HTTPS (déjà faite au niveau de l'entrypoint ci-dessus, mais faisable par middleware aussi) :

labels:
- "traefik.http.middlewares.redirect-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.redirect-https.redirectscheme.permanent=true"
- "traefik.http.routers.api-http.middlewares=redirect-https"

BasicAuth :

# Générer le hash du mot de passe
htpasswd -nb admin secretpassword
# Résultat : admin:$apr1$...
labels:
- "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$..." # doubler les $
- "traefik.http.routers.dashboard.middlewares=auth"

Rate limiting :

labels:
- "traefik.http.middlewares.ratelimit.ratelimit.average=100" # requêtes/s moyennes
- "traefik.http.middlewares.ratelimit.ratelimit.burst=50" # pic autorisé
- "traefik.http.routers.api.middlewares=ratelimit"

Modification de headers :

labels:
- "traefik.http.middlewares.secheaders.headers.forceSTSHeader=true"
- "traefik.http.middlewares.secheaders.headers.stsSeconds=63072000"
- "traefik.http.middlewares.secheaders.headers.contentTypeNosniff=true"
- "traefik.http.middlewares.secheaders.headers.frameDeny=true"
- "traefik.http.routers.api.middlewares=secheaders"

Chaîner plusieurs middlewares :

labels:
- "traefik.http.routers.api.middlewares=auth,ratelimit,secheaders"

L'ordre des middlewares dans la chaîne est alphabétique par défaut — pour contrôler l'ordre, utiliser des fichiers de configuration dynamique.

Routing TCP

Traefik peut aussi proxifier du trafic TCP (base de données, MQTT, etc.) via le provider Docker.

services:
postgres:
image: postgres:16
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.tcp.routers.postgres.rule=HostSNI(`*`)" # sans TLS : accepter tout
- "traefik.tcp.routers.postgres.entrypoints=postgres"
- "traefik.tcp.services.postgres.loadbalancer.server.port=5432"
# Dans la configuration statique Traefik
command:
- --entrypoints.postgres.address=:5432

Pour le routing TCP avec TLS, HostSNI peut filtrer sur le nom du serveur (SNI) — permet de router plusieurs services TLS sur le même port.

Déploiement Kubernetes (IngressRoute)

En Kubernetes, Traefik expose une CRD IngressRoute plus expressive que l'API Ingress standard :

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: api-route
namespace: default
spec:
entryPoints:
- websecure
routes:
- match: Host(`api.example.com`) && PathPrefix(`/v2`)
kind: Rule
middlewares:
- name: ratelimit
services:
- name: api-service
port: 8000
tls:
certResolver: letsencrypt
# Installation via Helm
helm repo add traefik https://traefik.github.io/charts
helm install traefik traefik/traefik \
--set ingressRoute.dashboard.enabled=false \
--set ports.web.redirectTo.port=websecure

Certificate Resolvers

Traefik supporte deux challenges ACME pour Let's Encrypt :

HTTP-01 : Let's Encrypt contacte le serveur sur le port 80 pour vérifier la possession du domaine. Le domaine doit résoudre vers l'IP publique de la machine. Ne supporte pas les wildcards.

DNS-01 : Traefik crée un enregistrement TXT dans la zone DNS du domaine pour prouver la possession. Fonctionne derrière un NAT, pour des machines non exposées publiquement, et supporte les wildcard (*.example.com). Nécessite une intégration avec le provider DNS (Route53, Cloudflare, OVH, etc.).

command:
- --certificatesresolvers.cloudflare.acme.dnschallenge=true
- --certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare
- --certificatesresolvers.cloudflare.acme.email=admin@example.com
- --certificatesresolvers.cloudflare.acme.storage=/acme.json
environment:
CF_API_EMAIL: admin@example.com
CF_API_KEY: your_cloudflare_api_key

Dashboard et observabilité

Le dashboard Traefik (port 8080 par défaut) liste les routers, middlewares, services et l'état des certificats TLS. En production, le protéger impérativement :

labels:
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$..."

Traefik expose des métriques Prometheus sur /metrics — compatibles avec Grafana pour visualiser le trafic, la latence et les erreurs par router.

command:
- --metrics.prometheus=true
- --metrics.prometheus.buckets=0.1,0.3,1.0,2.5
- --accesslog=true
- --accesslog.format=json

Les logs d'accès en JSON simplifient l'ingestion dans des stacks de centralisation (Loki, Elasticsearch).