Skip to content

Traefik

Important

Deploy as a DaemonSet to show the real public IP in applications.

Install

Add the Traefik Helm repository:

helm repo add traefik https://traefik.github.io/charts

Install with custom configuration from values.yaml:

helm install traefik traefik/traefik \
  --namespace=traefik \
  --create-namespace \
  --values values.yaml \
  --set deployment.kind=DaemonSet

Verify:

kubectl get services -n traefik

Values Summary

Key settings from setup/traefik/values.yaml:

HTTP → HTTPS redirect

k3s schema incompatibility

The k3s-bundled Traefik chart does not allow ports.web.redirections in its schema. Use a Middleware + additionalArguments instead (see below).

Create the middleware in kube-system:

apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: redirect-https
  namespace: kube-system
spec:
  redirectScheme:
    scheme: https
    permanent: true

Then wire it into the web entrypoint via additionalArguments in the Helm values:

additionalArguments:
- --entryPoints.web.http.middlewares=kube-system-redirect-https@kubernetescrd

This applies the redirect globally to all HTTP traffic. Since cert-manager uses DNS-01 challenges (not HTTP-01), there is no /.well-known/acme-challenge/ path conflict.

Prometheus metrics on port 9100 (metrics entrypoint):

metrics:
  prometheus:
    entryPoint: metrics
ports:
  metrics:
    port: 9100
    expose:
      default: true
    exposedPort: 9100

Forwarded headers — trusted from all IPs (cluster is behind GRE + MikroTik):

ports:
  web:
    forwardedHeaders:
      trustedIPs:
        - 0.0.0.0/0
    proxyProtocol:
      trustedIPs:
        - 0.0.0.0/0

LoadBalancer service — static internal IP assigned via MetalLB:

service:
  type: LoadBalancer
  spec:
    loadBalancerIP: <internal-traefik-ip>
    externalTrafficPolicy: Local

ServiceMonitor — picked up by kube-prometheus-stack:

serviceMonitor:
  enabled: true
  additionalLabels:
    release: monitoring

Exposing Apps

Two options for exposing applications:

  • Standard Kubernetes Ingress — works with any ingress provider (see example.ingress.yaml)
  • Traefik IngressRoute CRD — more configuration options, less boilerplate (preferred, see example.ingress-route.yaml)

Documentation: - Traefik Kubernetes CRD provider - Traefik Kubernetes Ingress provider

DaemonSet Mode

Run one Traefik pod per node with --set deployment.kind=DaemonSet. This is required to expose the real public IP in applications (instead of a shared cluster IP).