Für ein gutes Dutzend Domains, die einfach nur auf eine andere Zieldomain umleiten sollen (sampledomain.co, sampledomain.eu, sampledomain.info, example-tools.nrw, example-server.de, example.eu und einige mehr), lief bei mir bisher ein eigener kleiner Redirect-Service im Cluster, ein schlanker Container, der nichts weiter tat, als eingehende Requests per HTTP-Redirect auf die richtige Zieldomain umzubiegen.
Das hat funktioniert, aber es kostete CPU und RAM für etwas, das mein Ingress-Controller eigentlich schon von Haus aus kann. Ich habe die komplette Redirect-Logik daher aus den eigenen Services herausgezogen und stattdessen vollständig mit Traefik-Boardmitteln abgebildet: IngressRoute + Middleware, kein eigener Container mehr nötig. Das Ergebnis: Die CPU-Auslastung im Cluster ist dadurch von ~60 % auf ~15 % gesunken, für Funktionalität, die vorher extra deployed und gepflegt werden musste.
Der alte Ansatz: eigener Redirect-Service pro Domain
Vorher lief für jede Domain-Gruppe ein eigener kleiner Webserver-Container (z. B. nginx oder eine selbstgeschriebene Redirect-App), der auf einen Service gemappt und über eine IngressRoute erreichbar war. Jeder dieser Container brauchte eigene Ressourcen-Requests/Limits, ein eigenes Image, eigene Rollouts, für eine Aufgabe, die sich in einer Zeile Middleware-Konfiguration erledigen lässt.
Der neue Ansatz: noop@internal + RedirectRegex
Der Kern des neuen Setups sind zwei Traefik-Bausteine:
noop@internal, ein interner No-Op-Service, den Traefik seit Version 3 mitbringt. Er wird referenziert, ohne dass irgendein echter Kubernetes-Serviceoder Backend-Pod dahinterstehen muss.RedirectRegex-Middleware, wandelt eingehende Requests per Regex-Replacement auf eine Zieldomain um, bevor überhaupt ein Backend involviert wäre.
Für jede Domain-Gruppe sieht das dann so aus:
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: redirect-to-example
namespace: redirect-tools
spec:
redirectRegex:
regex: "^https?://(www\\.)?(example-server\\.de|example\\.eu|s\\.example\\.de)/(.*)"
replacement: "https://example.de/${3}"
permanent: true
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: redirects-example
namespace: redirect-tools
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: >
Host(`www.example.de`) ||
Host(`example-server.de`) || Host(`www.example-server.de`) ||
Host(`example.eu`) || Host(`www.example.eu`) ||
Host(`s.example.de`)
middlewares:
- name: add-header
- name: redirect-to-example
services:
- name: noop@internal
kind: TraefikService
tls:
secretName: redirects-tls
Kein Deployment, kein Service, kein Image zum Pflegen, die IngressRoute referenziert direkt noop@internal als TraefikService, die eigentliche Arbeit macht die Middleware. Für jede weitere Domain-Gruppe kommt einfach ein weiteres Middleware/IngressRoute-Paar dazu, nach demselben Schema.
Ein Punkt, der beim Debuggen wichtig war: Traefiks RedirectRegex kann nur 301 (permanent) oder 302 (temporär) ausliefern, kein 308. Das ist eine bewusste Einschränkung von Traefik (siehe traefik/traefik#7829); wer strikt 308 braucht, muss das an anderer Stelle lösen.
HTTP → HTTPS: aus jeder Ingress-Middleware raus, rein in die Traefik-Static-Config
Vorher hatte praktisch jede Ingress-Definition eine eigene Middleware, um HTTP-Requests auf HTTPS umzuleiten, bevor der eigentliche Redirect greifen konnte, doppelte Arbeit, doppelte Config, die an mehreren Stellen synchron gehalten werden musste.
Auch das lässt sich global in Traefik selbst lösen, statt es pro Ingress zu wiederholen. In der Traefik-Static-Config (bei mir als Deployment-Args):
- --entryPoints.web.address=:8000/tcp
- --entryPoints.web.http.redirections.entryPoint.to=:443
- --entryPoints.web.http.redirections.entryPoint.scheme=https
- --entryPoints.web.http.redirections.entryPoint.permanent=true
- --entryPoints.websecure.address=:8443/tcp
Wichtig dabei: redirections.entryPoint.to sollte auf den öffentlich sichtbaren Port zeigen (hier :443), nicht auf den internen Container-Port des websecure-Entrypoints (:8443). Sonst landet der interne Port im generierten Location-Header und der Redirect zeigt am Ende auf https://domain.tld:8443/ statt sauber auf https://domain.tld/.
Mit dieser globalen Konfiguration entfällt die HTTP→HTTPS-Middleware in jeder einzelnen Ingress-Definition im Cluster, nicht nur bei den Redirect-Domains, sondern überall. Jeder eingehende Request auf Port 80 wird zentral an einer Stelle behandelt.
Ergebnis
- Kein eigener Redirect-Container mehr pro Domain-Gruppe, nur noch deklarative
Middleware/IngressRoute-Ressourcen. - Keine verstreute HTTP→HTTPS-Middleware mehr in jedem einzelnen Ingress, sondern eine zentrale Regel in der Traefik-Static-Config.
- CPU-Auslastung im Cluster von ~60 % auf ~15 % gesunken.
- Weniger Images, weniger Rollouts, weniger Angriffsfläche, für eine Aufgabe, die der Ingress-Controller ohnehin schon mitbringt.
Die Erkenntnis dahinter ist eigentlich simpel, aber leicht zu übersehen: Bevor man für eine Aufgabe einen eigenen Service baut oder deployed, lohnt sich der Blick in die Doku des eigenen Ingress-Controllers, oft steckt die Lösung schon in Boardmitteln, die man ohnehin laufen hat.