Kubernetes Ingress und Gateway mit Traefik

Installieren

Erstellen Sie eine leere Helm‑values.yaml‑Datei. Traefik funktioniert „Out‑of‑the‑Box“, sodass die Datei vorerst nicht nötig ist. In den folgenden Schritten fügen wir ihr aber benutzerdefinierte Konfigurationen hinzu.

touch values.yaml

Wählen Sie das Ziel‑Kubernetes‑Cluster aus, zum Beispiel indem Sie die Umgebungsvariable KUBECONFIG setzen:

export KUBECONFIG=/pfad/zur/kubeconfig/datei

Installieren Sie Traefik im traefik‑Namespace des Clusters:

helm install traefik oci://ghcr.io/traefik/helm/traefik \
    --create-namespace \
    --namespace=traefik \
    --values=values.yaml \
    --version=38.0.2 \
    --wait
Weiterführende Links …

Aktualisieren

Verwenden Sie den folgenden Befehl, um das Release zu aktualisieren – zum Beispiel nachdem Sie Änderungen an der values.yaml vorgenommen haben:

helm upgrade traefik oci://ghcr.io/traefik/helm/traefik \
    --namespace=traefik \
    --values=values.yaml \
    --version=38.0.2 \
    --wait

Konfigurieren

Floating‑IP reservieren

Fügen Sie die Annotation loadbalancer.openstack.org/keep-floatingip hinzu, wenn Sie die IP-Adresse des Load Balancers reservieren möchten:

# values.yaml
service:
  annotations:
    loadbalancer.openstack.org/keep-floatingip: "true"

Wenn Sie eine bereits reservierte IP mit Traefik nutzen wollen, fügen Sie die folgende Konfiguration hinzu:

# values.yaml
service:
  annotations:
    loadbalancer.openstack.org/keep-floatingip: "true"
    loadbalancer.openstack.org/load-balancer-address: "192.0.2.255" # Beispiel‑IP
  spec:
    loadBalancerIP: "192.0.2.255" # Beispiel‑IP
Weiterführende Links …

Proxy‑Protocol nutzen

Aktivieren Sie das Proxy‑Protocol im Load Balancer (über die Annotation) und in Traefik, falls Ihre Anwendung die IP-Adressen der Clients kennen muss. Andernfalls sieht die Anwendung nur die internen IP-Adressen der Load‑Balancer.

# values.yaml
ports:
  web:
    proxyProtocol:
      trustedIPs:
        - "10.250.0.0/16"
  websecure:
    proxyProtocol:
      trustedIPs:
        - "10.250.0.0/16"
service:
  annotations:
    loadbalancer.openstack.org/proxy-protocol: v2

Als trustedIPs tragen Sie bitte die interne IP-Adresse Ihres Load Balancers ein bzw. den möglichen IP-Adressraum. Zur Zeit ist dies der oben gezeigte Bereich, welcher auch mit dem „Nodes CIDR“ übereinstimmt, der Ihnen im PSKE Dashboard angezeigt wird.

Weiterführende Links …

Übermittlung von Nutzungsstatistiken deaktivieren

Die Erfassung von Nutzungsstatistiken ist standardmäßig deaktiviert, Traefik prüft jedoch regelmäßig, ob eine neue Version verfügbar ist und gibt dabei Informationen preis. Fügen Sie die folgende Einstellungen hinzu, um beides zu deaktivieren:

# values.yaml
global:
  checkNewVersion: false # Standard: true
  sendAnonymousUsage: false # Standard: false
Weiterführende Links …

Logging konfigurieren

Stellen Sie das Log-Format auf JSON ein, um die Log-Daten maschinell leichter verarbeiten und analysieren zu können. Durch das Anpassen des Log‑Levels entstehen weniger unnötige Ausgaben:

# values.yaml
logs:
  general:
    format: json # Standard: common
    level: ERROR # Standard: INFO
Weiterführende Links …

Access‑Logs aktivieren

Traefik Access-Logs werden normalerweise nicht gebraucht, aber wenn Fehler auftreten können sie hilfreich sein. Falls aktiviert, kann die Ausgabe des Access-Logs gefiltert werden, zum Beispiel nach Dauer der Requests (in Sekunden) oder nach HTTP‑Statuscodes:

# values.yaml
logs:
  access:
    enabled: true # Standard: false
    format: json # Standard: common
    filters:
      minduration: "5" # Standard: ""
      statuscodes: "400" # Standard: ""
Weiterführende Links …

Pfad-Filterung und -Bereinigung deaktivieren

Traefik blockiert standardmäßig manche URL‑encoded Zeichen in der URL und führt Pfad-Bereinigung durch. Falls nötig, können Sie dieses Verhalten mit den folgenden Einstellungen deaktivieren:

# values.yaml
ports:
  web:
    http:
      encodedCharacters:
        allowEncodedSlash: true   # Standard: false
        allowEncodedBackSlash: true # Standard: false
        allowEncodedNullCharacter: true  # Standard: false
        allowEncodedSemicolon: true # Standard: false
        allowEncodedPercent: true  # Standard: false
        allowEncodedQuestionMark: true # Standard: false
        allowEncodedHash: true # Standard: false
      sanitizePath: false # Standard: true
  websecure:
    http:
      encodedCharacters:
        allowEncodedSlash: true   # Standard: false
        allowEncodedBackSlash: true # Standard: false
        allowEncodedNullCharacter: true  # Standard: false
        allowEncodedSemicolon: true # Standard: false
        allowEncodedPercent: true  # Standard: false
        allowEncodedQuestionMark: true # Standard: false
        allowEncodedHash: true # Standard: false
      sanitizePath: false # Standard: true
Weiterführende Links …

Verwenden

Test‑Deployment vorbereiten

Erstellen Sie eine Datei httpbin.yaml mit folgendem Inhalt:

# httpbin.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
  namespace: httpbin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
  template:
    metadata:
      labels:
        app: httpbin
    spec:
      containers:
        # Bitte eine aktuelle Version des Containers verwenden.
        - image: ghcr.io/mccutchen/go-httpbin:2.20
          imagePullPolicy: IfNotPresent
          name: httpbin
          ports:
            - containerPort: 8080
          securityContext:
            allowPrivilegeEscalation: false
            capabilities:
              drop:
                - ALL
            readOnlyRootFilesystem: true
            runAsNonRoot: true
          resources:
            limits:
              memory: 50Mi
            requests:
              cpu: 50m
          livenessProbe:
            tcpSocket:
              port: 8080
          readinessProbe:
            httpGet:
              path: /status/200
              port: 8080
              scheme: HTTP
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  namespace: httpbin
  labels:
    app: httpbin
    service: httpbin
spec:
  ports:
    - name: http
      port: 8080
      targetPort: 8080
  selector:
    app: httpbin

Erstellen Sie die Deployment- und Service‑Ressourcen im Namespace httpbin:

kubectl apply --filename=httpbin.yaml

Kubernetes Ingress erstellen

Fügen Sie die folgende Ergänzung ans Ende der Datei httpbin.yaml ein:

# httpbin.yaml
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: httpbin
  namespace: httpbin
spec:
  ingressClassName: traefik
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: httpbin
                port:
                  number: 8080
  # tls:
  #   - hosts:
  #       - example.com
  #     secretName: httpbin-tls

Erstellen Sie die Ingress‑Ressource:

kubectl apply --filename=httpbin.yaml

Testen Sie den Ingress mit curl:

EXTERNAL_IP=$(kubectl --namespace=traefik get svc/traefik \
	--output=jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl --header Host:example.com --verbose "http://${EXTERNAL_IP:?}/status/200"
Weiterführende Links …

Basic‑Auth zum Ingress hinzufügen

Erstellen Sie in httpbin.yaml ein Secret und einen Basic‑Auth‑Middleware:

# httpbin.yaml
---
kind: Secret
apiVersion: v1
metadata:
  name: basic-auth
  namespace: httpbin
type: Opaque
data:
  # Username: admin
  # Password: insecure
  # Bitte ein sicheres Passwort benutzen!
  auth: YWRtaW46JGFwcjEkWU5iT0trNVkkNlVaa2pKN1dneUpVYWcvYXlqdzE3Lgo=
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: basic-auth
  namespace: httpbin
spec:
  basicAuth:
    secret: basic-auth

Fügen Sie die folgende Annotation zur Ingress‑Ressource hinzu. Der Annotationswert hat das Format <namespace>-<middleware>@kubernetescrd:

# httpbin.yaml
metadata:
  annotations:
    traefik.ingress.kubernetes.io/router.middlewares: httpbin-basic-auth@kubernetescrd
Weiterführende Links …

IP‑Allow‑List zum Ingress hinzufügen

Erstellen Sie einen IP‑Allow‑List‑Middleware:

# httpbin.yaml
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: ip-allow-list
  namespace: httpbin
spec:
  ipAllowList:
    sourceRange:
      - 192.0.2.255 # Beispiel
      - 198.51.100.0/24 # Beispiel

Fügen Sie dann die Annotation zur Ingress‑Ressource hinzu:

# httpbin.yaml
metadata:
  annotations:
    traefik.ingress.kubernetes.io/router.middlewares: httpbin-ip-allow-list@kubernetescrd

Oder beide Middlewares gleichzeitig:

# httpbin.yaml
metadata:
  annotations:
    traefik.ingress.kubernetes.io/router.middlewares: |-
        httpbin-basic-auth@kubernetescrd,httpbin-ip-allow-list@kubernetescrd
Weiterführende Links …

Kubernetes Gateway erstellen

Aktivieren Sie den Kubernetes‑Gateway‑Provider von Traefik in der Datei values.yaml und aktualisieren Sie Ihr Release:

# values.yaml
providers:
  kubernetesGateway:
    enabled: true # Standard: false
gateway:
  enabled: false # Wird in dieser Anleitung nicht gebraucht. Standard: true

Fügen Sie einen Gateway‑ und einen HTTPRoute‑Eintrag in die Datei httpbin.yaml ein:

# httpbin.yaml
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: httpbin
  namespace: httpbin
spec:
  gatewayClassName: traefik
  listeners:
    - allowedRoutes:
        namespaces:
          from: Same
      name: web # Der Name des HTTP‑Endpoints von Traefik
      port: 8000 # Der Standard‑Port des HTTP‑Endpoints von Traefik
      protocol: HTTP
  # - allowedRoutes:
  #     namespaces:
  #       from: Same
  #   name: websecure # Der Name des HTTPS‑Endpoints von Traefik
  #   port: 8443 # Der Standard‑Port des HTTPS‑Endpoints von Traefik
  #   protocol: HTTPS
  #   tls:
  #     certificateRefs:
  #       - kind: Secret
  #         name: httpbin-tls
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: httpbin
  namespace: httpbin
spec:
  parentRefs:
    - name: httpbin
      namespace: httpbin
  hostnames:
    - example.com
  rules:
    - backendRefs:
        - name: httpbin # Der Name Ihres Kubernetes‑Services
          namespace: httpbin
          port: 8080 # Der Port Ihres Kubernetes‑Services
      matches:
        - path:
            type: PathPrefix
            value: /

Erstellen Sie die Ressourcen:

kubectl apply --filename=httpbin.yaml

Falls bereits ein Ingress vorhanden ist, löschen Sie ihn, um Verwirrung zu vermeiden:

kubectl --namespace=httpbin delete --ignore-not-found ingress/httpbin

Jetzt können Sie prüfen, ob Gateway und HTTPRoute wie erwartet funktionieren:

EXTERNAL_IP=$(kubectl --namespace=traefik get svc/traefik \
	--output=jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl --header Host:example.com --verbose "http://${EXTERNAL_IP:?}/status/200"

Fügen Sie die Middlewares (siehe oben, im Abschnitt Kubernetes Ingress erstellen) als Filter zur HTTPRoute hinzu:

# httpbin.yaml
      filters:
        - type: ExtensionRef
          extensionRef:
            group: traefik.io
            kind: Middleware
            name: ip-allow-list
        - type: ExtensionRef
          extensionRef:
            group: traefik.io
            kind: Middleware
            name: basic-auth
Weiterführende Links …

Deinstallieren

Bevor Sie Traefik deinstallieren, müssen Sie entscheiden, ob Sie die Floating‑IP-Adresse reservieren möchten.

Floating‑IP-Adresse reservieren …
helm upgrade traefik oci://ghcr.io/traefik/helm/traefik \
    --namespace=traefik \
    --reuse-values \
    --set-string=service.annotations.loadbalancer\\.openstack\\.org/keep-floatingip=true

Notieren Sie sich die IP-Adresse, damit Sie sie später wiederverwenden können:

kubectl --namespace=traefik get svc/traefik \
    --output=jsonpath='{.status.loadBalancer.ingress[0].ip}'
Oder Floating‑IP-Adresse freigeben …
helm upgrade traefik oci://ghcr.io/traefik/helm/traefik \
    --namespace=traefik \
    --reuse-values \
    --set-string=service.annotations.loadbalancer\\.openstack\\.org/keep-floatingip=false

Dann können Sie Traefik deinstallieren:

helm uninstall traefik --namespace=traefik

Prüfen Sie, ob noch irgendwo Traefik‑CustomResourceDefinitions (CRDs) verwendet werden:

kubectl api-resources --api-group=traefik.io --output=name |
    tr '\n' ',' | sed -E 's/,$//' |
    xargs --no-run-if-empty kubectl get --all-namespaces
kubectl api-resources --api-group=hub.traefik.io --output=name |
    tr '\n' ',' | sed -E 's/,$//' |
    xargs --no-run-if-empty kubectl get --all-namespaces

Dies könnten zum Beispiel die Middlewares sein, die im Abschnitt Kubernetes Ingress erstellen erstellt wurden. Falls nichts gefunden wird (zweimal „No resources found“) – oder wenn Sie sich sicher sind, dass Sie die gefundenen Ressourcen nicht mehr benötigen – können Sie die CRDs löschen:

kubectl api-resources --api-group=traefik.io --output=name |
    xargs --no-run-if-empty kubectl delete crds
kubectl api-resources --api-group=hub.traefik.io --output=name |
    xargs --no-run-if-empty kubectl delete crds

Anschließend löschen Sie den Namespace:

kubectl delete namespace traefik