Skip to main content

Traefik

Traefik is a cloud-native reverse proxy and ingress controller. It watches Kubernetes Ingress resources (and its own IngressRoute CRDs) and routes external traffic to Services.

Why it's in KubeAid​

Traefik is the default ingress controller on KubeAid clusters: kubeaid-cli renders a traefik Argo CD Application (plus an optional traefik-internal instance) for every cluster it provisions. ingress-nginx is available as an alternative if you prefer NGINX. TLS certificates come from the sibling cert-manager chart.

Upstream chart: traefik (v41.2.0 pinned here).

Key values / KubeAid-specific configuration​

Upstream values live under the traefik: key. KubeAid defaults (values.yaml):

  • ports.web permanently redirects HTTP to HTTPS; ports.websecure has TLS enabled.
  • PROXY protocol is enabled on both entrypoints (additionalArguments), so Traefik sees real client IPs behind a load balancer. The LB must actually send PROXY protocol — e.g. on Hetzner Cloud the Service needs load-balancer.hetzner.cloud/uses-proxyprotocol: "true", otherwise every connection is rejected.
  • providers.kubernetesIngress.publishedService.enabled: true — populates Ingress status.loadBalancer, without which Argo CD apps behind Traefik stay stuck in Progressing.
  • 2 replicas, PodDisruptionBudget (maxUnavailable: 1), Prometheus ServiceMonitor enabled, instanceLabelOverride: traefik.

KubeAid-specific keys rendered from this wrapper's templates/:

  • wildcardCertificates — cert-manager Certificates for wildcard domains (each must start with *.), issued by the ClusterIssuer named in wildcardCertificates.issuer.
  • ipwhitelists — a map of name → CIDR list, rendered as Traefik ipWhiteList Middlewares.
  • middleware.jwt — an opt-in JWT-validation Middleware (requires middleware.jwt.public_key).

Per-cluster override via kubeaid-config, e.g. an internal-only load balancer:

traefik:
service:
annotations:
service.beta.kubernetes.io/aws-load-balancer-scheme: "internal"

The equivalent annotations on AKS/Azure:

service:
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true" # internal LB
# or, for an internet-facing LB:
# service.beta.kubernetes.io/azure-load-balancer-internal: "false"
# service.beta.kubernetes.io/azure-load-balancer-resource-group: <your-resource-group-name>

and on AWS for an internet-facing (rather than internal) load balancer:

service:
annotations:
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"

Operational notes​

  • Several Traefik resources drift from the rendered state at runtime (Service clusterIP, Deployment checksum annotations, ClusterRole rules, dashboard IngressRoute, PDB). Add ignoreDifferences to the Argo CD Application — see examples/argocd-application-ignore-drift.yaml.
  • Running multiple Traefik instances requires binding each to its own ingress class with --providers.kubernetesingress.ingressclass=<class>, or they fight over Ingress status updates.
  • The dashboard is not exposed by default; reach it with kubectl -n traefik port-forward <pod> 9000:9000 → http://localhost:9000/dashboard/.
  • Traefik has a default limit on request body size that can affect file uploads; reconfigure it with a middleware — see examples/request-body-middleware.yaml.

Client certificate (mTLS) auth​

Docs: https://doc.traefik.io/traefik/https/tls/#client-authentication-mtls. The CA cert Secret's key must be named ca.crt or tls.ca:

kubectl create secret generic internalca-cert --namespace traefik --dry-run=client --from-file=/path/to/ca.crt -o yaml | kubeseal --controller-namespace system --controller-name sealed-secrets -o yaml

Then reference it from tlsOptions in values:

tlsOptions:
tls-client-auth:
clientAuth:
clientAuthType: VerifyClientCertIfGiven
secretNames:
- internalca-cert