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.webpermanently redirects HTTP to HTTPS;ports.websecurehas 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 needsload-balancer.hetzner.cloud/uses-proxyprotocol: "true", otherwise every connection is rejected. providers.kubernetesIngress.publishedService.enabled: true— populates Ingressstatus.loadBalancer, without which Argo CD apps behind Traefik stay stuck inProgressing.- 2 replicas, PodDisruptionBudget (
maxUnavailable: 1), PrometheusServiceMonitorenabled,instanceLabelOverride: traefik.
KubeAid-specific keys rendered from this wrapper's templates/:
wildcardCertificates— cert-managerCertificates for wildcard domains (each must start with*.), issued by the ClusterIssuer named inwildcardCertificates.issuer.ipwhitelists— a map of name → CIDR list, rendered as TraefikipWhiteListMiddlewares.middleware.jwt— an opt-in JWT-validation Middleware (requiresmiddleware.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). AddignoreDifferencesto 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