Traefik & Kubernetes

The Kubernetes Ingress Controller.

Routing Configuration

The provider then watches for incoming ingresses events, such as the example below, and derives the corresponding dynamic configuration from it, which in turn will create the resulting routers, services, handlers, etc.

Configuration Example

Configuring Kubernetes Ingress Controller

RBAC

  1. ---
  2. apiVersion: rbac.authorization.k8s.io/v1
  3. kind: ClusterRole
  4. metadata:
  5. name: traefik-ingress-controller
  6. rules:
  7. - apiGroups:
  8. - ""
  9. resources:
  10. - services
  11. - secrets
  12. verbs:
  13. - get
  14. - list
  15. - watch
  16. - apiGroups:
  17. - discovery.k8s.io
  18. resources:
  19. - endpointslices
  20. verbs:
  21. - list
  22. - watch
  23. - apiGroups:
  24. - extensions
  25. - networking.k8s.io
  26. resources:
  27. - ingresses
  28. - ingressclasses
  29. verbs:
  30. - get
  31. - list
  32. - watch
  33. - apiGroups:
  34. - extensions
  35. - networking.k8s.io
  36. resources:
  37. - ingresses/status
  38. verbs:
  39. - update
  40. ---
  41. apiVersion: rbac.authorization.k8s.io/v1
  42. kind: ClusterRoleBinding
  43. metadata:
  44. name: traefik-ingress-controller
  45. roleRef:
  46. apiGroup: rbac.authorization.k8s.io
  47. kind: ClusterRole
  48. name: traefik-ingress-controller
  49. subjects:
  50. - kind: ServiceAccount
  51. name: traefik-ingress-controller
  52. namespace: default

Ingress

  1. apiVersion: networking.k8s.io/v1
  2. kind: Ingress
  3. metadata:
  4. name: myingress
  5. annotations:
  6. traefik.ingress.kubernetes.io/router.entrypoints: web
  7. spec:
  8. rules:
  9. - host: example.com
  10. http:
  11. paths:
  12. - path: /bar
  13. pathType: Exact
  14. backend:
  15. service:
  16. name: whoami
  17. port:
  18. number: 80
  19. - path: /foo
  20. pathType: Exact
  21. backend:
  22. service:
  23. name: whoami
  24. port:
  25. number: 80

Traefik

  1. apiVersion: v1
  2. kind: ServiceAccount
  3. metadata:
  4. name: traefik-ingress-controller
  5. ---
  6. apiVersion: apps/v1
  7. kind: Deployment
  8. metadata:
  9. name: traefik
  10. labels:
  11. app: traefik
  12. spec:
  13. replicas: 1
  14. selector:
  15. matchLabels:
  16. app: traefik
  17. template:
  18. metadata:
  19. labels:
  20. app: traefik
  21. spec:
  22. serviceAccountName: traefik-ingress-controller
  23. containers:
  24. - name: traefik
  25. image: traefik:v3.2
  26. args:
  27. - --entryPoints.web.address=:80
  28. - --providers.kubernetesingress
  29. ports:
  30. - name: web
  31. containerPort: 80
  32. ---
  33. apiVersion: v1
  34. kind: Service
  35. metadata:
  36. name: traefik
  37. spec:
  38. type: LoadBalancer
  39. selector:
  40. app: traefik
  41. ports:
  42. - protocol: TCP
  43. port: 80
  44. name: web
  45. targetPort: 80

Whoami

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: whoami
  5. labels:
  6. app: traefiklabs
  7. name: whoami
  8. spec:
  9. replicas: 2
  10. selector:
  11. matchLabels:
  12. app: traefiklabs
  13. task: whoami
  14. template:
  15. metadata:
  16. labels:
  17. app: traefiklabs
  18. task: whoami
  19. spec:
  20. containers:
  21. - name: whoami
  22. image: traefik/whoami
  23. ports:
  24. - containerPort: 80
  25. ---
  26. apiVersion: v1
  27. kind: Service
  28. metadata:
  29. name: whoami
  30. spec:
  31. ports:
  32. - name: http
  33. port: 80
  34. selector:
  35. app: traefiklabs
  36. task: whoami

Annotations

Referencing resources in annotations

In an annotation, when referencing a resource defined by another provider, the provider namespace syntax must be used.

On Ingress

traefik.ingress.kubernetes.io/router.entrypoints

See entry points for more information.

  1. traefik.ingress.kubernetes.io/router.entrypoints: ep1,ep2

traefik.ingress.kubernetes.io/router.middlewares

See middlewares and middlewares overview for more information.

  1. traefik.ingress.kubernetes.io/router.middlewares: auth@file,default-prefix@kubernetescrd

traefik.ingress.kubernetes.io/router.priority

See priority for more information.

  1. traefik.ingress.kubernetes.io/router.priority: "42"

traefik.ingress.kubernetes.io/router.rulesyntax

See rule syntax for more information.

  1. traefik.ingress.kubernetes.io/router.rulesyntax: "v2"

traefik.ingress.kubernetes.io/router.pathmatcher

Overrides the default router rule type used for a path. Only path-related matcher name should be specified: Path, PathPrefix or PathRegexp.

Default PathPrefix

  1. traefik.ingress.kubernetes.io/router.pathmatcher: Path

traefik.ingress.kubernetes.io/router.tls

See tls for more information.

  1. traefik.ingress.kubernetes.io/router.tls: "true"

traefik.ingress.kubernetes.io/router.tls.certresolver

See certResolver for more information.

  1. traefik.ingress.kubernetes.io/router.tls.certresolver: myresolver

traefik.ingress.kubernetes.io/router.tls.domains.n.main

See domains for more information.

  1. traefik.ingress.kubernetes.io/router.tls.domains.0.main: example.org

traefik.ingress.kubernetes.io/router.tls.domains.n.sans

See domains for more information.

  1. traefik.ingress.kubernetes.io/router.tls.domains.0.sans: test.example.org,dev.example.org

traefik.ingress.kubernetes.io/router.tls.options

See options for more information.

  1. traefik.ingress.kubernetes.io/router.tls.options: foobar@file

On Service

traefik.ingress.kubernetes.io/service.nativelb

Controls, when creating the load-balancer, whether the LB’s children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. The Kubernetes Service itself does load-balance to the pods. Please note that, by default, Traefik reuses the established connections to the backends for performance purposes. This can prevent the requests load balancing between the replicas from behaving as one would expect when the option is set. By default, NativeLB is false.

  1. traefik.ingress.kubernetes.io/service.nativelb: "true"

traefik.ingress.kubernetes.io/service.nodeportlb

Controls, when creating the load-balancer, whether the LB’s children are directly the nodes internal IPs using the nodePort when the service type is NodePort. It allows services to be reachable when Traefik runs externally from the Kubernetes cluster but within the same network of the nodes. By default, NodePortLB is false.

  1. traefik.ingress.kubernetes.io/service.nodeportlb: "true"

traefik.ingress.kubernetes.io/service.serversscheme

Overrides the default scheme.

  1. traefik.ingress.kubernetes.io/service.serversscheme: h2c

traefik.ingress.kubernetes.io/service.serverstransport

See ServersTransport for more information.

  1. traefik.ingress.kubernetes.io/service.serverstransport: foobar@file

traefik.ingress.kubernetes.io/service.passhostheader

See pass Host header for more information.

  1. traefik.ingress.kubernetes.io/service.passhostheader: "true"

traefik.ingress.kubernetes.io/service.sticky.cookie

See sticky sessions for more information.

  1. traefik.ingress.kubernetes.io/service.sticky.cookie: "true"

traefik.ingress.kubernetes.io/service.sticky.cookie.name

See sticky sessions for more information.

  1. traefik.ingress.kubernetes.io/service.sticky.cookie.name: foobar

traefik.ingress.kubernetes.io/service.sticky.cookie.secure

See sticky sessions for more information.

  1. traefik.ingress.kubernetes.io/service.sticky.cookie.secure: "true"

traefik.ingress.kubernetes.io/service.sticky.cookie.samesite

See sticky sessions for more information.

  1. traefik.ingress.kubernetes.io/service.sticky.cookie.samesite: "none"

traefik.ingress.kubernetes.io/service.sticky.cookie.httponly

See sticky sessions for more information.

  1. traefik.ingress.kubernetes.io/service.sticky.cookie.httponly: "true"

traefik.ingress.kubernetes.io/service.sticky.cookie.maxage

See sticky sessions for more information.

  1. traefik.ingress.kubernetes.io/service.sticky.cookie.maxage: 42

Path Types on Kubernetes 1.18+

If the Kubernetes cluster version is 1.18+, the new pathType property can be leveraged to define the rules matchers:

  • Exact: This path type forces the rule matcher to Path
  • Prefix: This path type forces the rule matcher to PathPrefix

Please see this documentation for more information.

Multiple Matches

In the case of multiple matches, Traefik will not ensure the priority of a Path matcher over a PathPrefix matcher, as stated in this documentation.

TLS

Enabling TLS via HTTP Options on Entrypoint

TLS can be enabled through the HTTP options of an Entrypoint:

CLI

  1. # Static configuration
  2. --entryPoints.websecure.address=:443
  3. --entryPoints.websecure.http.tls

File (YAML)

  1. # Static configuration
  2. entryPoints:
  3. websecure:
  4. address: ':443'
  5. http:
  6. tls: {}

File (TOML)

  1. # Static configuration
  2. [entryPoints.websecure]
  3. address = ":443"
  4. [entryPoints.websecure.http.tls]

This way, any Ingress attached to this Entrypoint will have TLS termination by default.

Configuring Kubernetes Ingress Controller with TLS on Entrypoint

RBAC

  1. ---
  2. apiVersion: rbac.authorization.k8s.io/v1
  3. kind: ClusterRole
  4. metadata:
  5. name: traefik-ingress-controller
  6. rules:
  7. - apiGroups:
  8. - ""
  9. resources:
  10. - services
  11. - secrets
  12. verbs:
  13. - get
  14. - list
  15. - watch
  16. - apiGroups:
  17. - discovery.k8s.io
  18. resources:
  19. - endpointslices
  20. verbs:
  21. - get
  22. - list
  23. - watch
  24. - apiGroups:
  25. - extensions
  26. - networking.k8s.io
  27. resources:
  28. - ingresses
  29. - ingressclasses
  30. verbs:
  31. - get
  32. - list
  33. - watch
  34. - apiGroups:
  35. - extensions
  36. - networking.k8s.io
  37. resources:
  38. - ingresses/status
  39. verbs:
  40. - update
  41. ---
  42. apiVersion: rbac.authorization.k8s.io/v1
  43. kind: ClusterRoleBinding
  44. metadata:
  45. name: traefik-ingress-controller
  46. roleRef:
  47. apiGroup: rbac.authorization.k8s.io
  48. kind: ClusterRole
  49. name: traefik-ingress-controller
  50. subjects:
  51. - kind: ServiceAccount
  52. name: traefik-ingress-controller
  53. namespace: default

Ingress

  1. apiVersion: networking.k8s.io/v1
  2. kind: Ingress
  3. metadata:
  4. name: myingress
  5. annotations:
  6. traefik.ingress.kubernetes.io/router.entrypoints: websecure
  7. spec:
  8. rules:
  9. - host: example.com
  10. http:
  11. paths:
  12. - path: /bar
  13. pathType: Exact
  14. backend:
  15. service:
  16. name: whoami
  17. port:
  18. number: 80
  19. - path: /foo
  20. pathType: Exact
  21. backend:
  22. service:
  23. name: whoami
  24. port:
  25. number: 80

Traefik

  1. apiVersion: v1
  2. kind: ServiceAccount
  3. metadata:
  4. name: traefik-ingress-controller
  5. ---
  6. apiVersion: apps/v1
  7. kind: Deployment
  8. metadata:
  9. name: traefik
  10. labels:
  11. app: traefik
  12. spec:
  13. replicas: 1
  14. selector:
  15. matchLabels:
  16. app: traefik
  17. template:
  18. metadata:
  19. labels:
  20. app: traefik
  21. spec:
  22. serviceAccountName: traefik-ingress-controller
  23. containers:
  24. - name: traefik
  25. image: traefik:v3.2
  26. args:
  27. - --entryPoints.websecure.address=:443
  28. - --entryPoints.websecure.http.tls
  29. - --providers.kubernetesingress
  30. ports:
  31. - name: websecure
  32. containerPort: 443
  33. ---
  34. apiVersion: v1
  35. kind: Service
  36. metadata:
  37. name: traefik
  38. spec:
  39. type: LoadBalancer
  40. selector:
  41. app: traefik
  42. ports:
  43. - protocol: TCP
  44. port: 443
  45. name: websecure
  46. targetPort: 443

Whoami

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: whoami
  5. labels:
  6. app: traefiklabs
  7. name: whoami
  8. spec:
  9. replicas: 2
  10. selector:
  11. matchLabels:
  12. app: traefiklabs
  13. task: whoami
  14. template:
  15. metadata:
  16. labels:
  17. app: traefiklabs
  18. task: whoami
  19. spec:
  20. containers:
  21. - name: whoami
  22. image: traefik/whoami
  23. ports:
  24. - containerPort: 80
  25. ---
  26. apiVersion: v1
  27. kind: Service
  28. metadata:
  29. name: whoami
  30. spec:
  31. ports:
  32. - name: http
  33. port: 80
  34. selector:
  35. app: traefiklabs
  36. task: whoami

Enabling TLS via Annotations

To enable TLS on the underlying router created from an Ingress, one should configure it through annotations:

  1. traefik.ingress.kubernetes.io/router.tls: "true"

For more options, please refer to the available annotations.

Configuring Kubernetes Ingress Controller with TLS

RBAC

  1. ---
  2. apiVersion: rbac.authorization.k8s.io/v1
  3. kind: ClusterRole
  4. metadata:
  5. name: traefik-ingress-controller
  6. rules:
  7. - apiGroups:
  8. - ""
  9. resources:
  10. - services
  11. - secrets
  12. verbs:
  13. - get
  14. - list
  15. - watch
  16. - apiGroups:
  17. - discovery.k8s.io
  18. resources:
  19. - endpointslices
  20. verbs:
  21. - get
  22. - list
  23. - watch
  24. - apiGroups:
  25. - extensions
  26. - networking.k8s.io
  27. resources:
  28. - ingresses
  29. - ingressclasses
  30. verbs:
  31. - get
  32. - list
  33. - watch
  34. - apiGroups:
  35. - extensions
  36. - networking.k8s.io
  37. resources:
  38. - ingresses/status
  39. verbs:
  40. - update
  41. ---
  42. apiVersion: rbac.authorization.k8s.io/v1
  43. kind: ClusterRoleBinding
  44. metadata:
  45. name: traefik-ingress-controller
  46. roleRef:
  47. apiGroup: rbac.authorization.k8s.io
  48. kind: ClusterRole
  49. name: traefik-ingress-controller
  50. subjects:
  51. - kind: ServiceAccount
  52. name: traefik-ingress-controller
  53. namespace: default

Ingress

  1. apiVersion: networking.k8s.io/v1
  2. kind: Ingress
  3. metadata:
  4. name: myingress
  5. annotations:
  6. traefik.ingress.kubernetes.io/router.entrypoints: websecure
  7. traefik.ingress.kubernetes.io/router.tls: true
  8. spec:
  9. rules:
  10. - host: example.com
  11. http:
  12. paths:
  13. - path: /bar
  14. pathType: Exact
  15. backend:
  16. service:
  17. name: whoami
  18. port:
  19. number: 80
  20. - path: /foo
  21. pathType: Exact
  22. backend:
  23. service:
  24. name: whoami
  25. port:
  26. number: 80

Traefik

  1. apiVersion: v1
  2. kind: ServiceAccount
  3. metadata:
  4. name: traefik-ingress-controller
  5. ---
  6. apiVersion: apps/v1
  7. kind: Deployment
  8. metadata:
  9. name: traefik
  10. labels:
  11. app: traefik
  12. spec:
  13. replicas: 1
  14. selector:
  15. matchLabels:
  16. app: traefik
  17. template:
  18. metadata:
  19. labels:
  20. app: traefik
  21. spec:
  22. serviceAccountName: traefik-ingress-controller
  23. containers:
  24. - name: traefik
  25. image: traefik:v3.2
  26. args:
  27. - --entryPoints.websecure.address=:443
  28. - --providers.kubernetesingress
  29. ports:
  30. - name: websecure
  31. containerPort: 443
  32. ---
  33. apiVersion: v1
  34. kind: Service
  35. metadata:
  36. name: traefik
  37. spec:
  38. type: LoadBalancer
  39. selector:
  40. app: traefik
  41. ports:
  42. - protocol: TCP
  43. port: 443
  44. name: websecure
  45. targetPort: 443

Whoami

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: whoami
  5. labels:
  6. app: traefiklabs
  7. name: whoami
  8. spec:
  9. replicas: 2
  10. selector:
  11. matchLabels:
  12. app: traefiklabs
  13. task: whoami
  14. template:
  15. metadata:
  16. labels:
  17. app: traefiklabs
  18. task: whoami
  19. spec:
  20. containers:
  21. - name: whoami
  22. image: traefik/whoami
  23. ports:
  24. - containerPort: 80
  25. ---
  26. apiVersion: v1
  27. kind: Service
  28. metadata:
  29. name: whoami
  30. spec:
  31. ports:
  32. - name: http
  33. port: 80
  34. selector:
  35. app: traefiklabs
  36. task: whoami

Certificates Management

Using a secret

Ingress

  1. apiVersion: networking.k8s.io/v1
  2. kind: Ingress
  3. metadata:
  4. name: foo
  5. namespace: production
  6. spec:
  7. rules:
  8. - host: example.net
  9. http:
  10. paths:
  11. - path: /bar
  12. pathType: Exact
  13. backend:
  14. service:
  15. name: service1
  16. port:
  17. number: 80
  18. # Only selects which certificate(s) should be loaded from the secret, in order to terminate TLS.
  19. # Doesn't enable TLS for that ingress (hence for the underlying router).
  20. # Please see the TLS annotations on ingress made for that purpose.
  21. tls:
  22. - secretName: supersecret

Secret

  1. apiVersion: v1
  2. kind: Secret
  3. metadata:
  4. name: supersecret
  5. data:
  6. tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
  7. tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=

TLS certificates can be managed in Secrets objects.

Info

Only TLS certificates provided by users can be stored in Kubernetes Secrets. Let’s Encrypt certificates cannot be managed in Kubernetes Secrets yet.

Communication Between Traefik and Pods

Routing directly to Kubernetes services

To route directly to the Kubernetes service, one can use the traefik.ingress.kubernetes.io/service.nativelb annotation on the Kubernetes service. It controls, when creating the load-balancer, whether the LB’s children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP.

One alternative is to use an ExternalName service to forward requests to the Kubernetes service through DNS. To do so, one must allow external name services.

Traefik automatically requests endpoint information based on the service provided in the ingress spec. Although Traefik will connect directly to the endpoints (pods), it still checks the service port to see if TLS communication is required.

There are 3 ways to configure Traefik to use HTTPS to communicate with pods:

  1. If the service port defined in the ingress spec is 443 (note that you can still use targetPort to use a different port on your pod).
  2. If the service port defined in the ingress spec has a name that starts with https (such as https-api, https-web or just https).
  3. If the service spec includes the annotation traefik.ingress.kubernetes.io/service.serversscheme: https.

If either of those configuration options exist, then the backend communication protocol is assumed to be TLS, and will connect via TLS automatically.

Info

Please note that by enabling TLS communication between traefik and your pods, you will have to have trusted certificates that have the proper trust chain and IP subject name. If this is not an option, you may need to skip TLS certificate verification. See the insecureSkipVerify setting for more details.

Global Default Backend Ingresses

Ingresses can be created that look like the following:

Ingress

  1. apiVersion: networking.k8s.io/v1
  2. kind: Ingress
  3. metadata:
  4. name: cheese
  5. spec:
  6. defaultBackend:
  7. service:
  8. name: stilton
  9. port:
  10. number: 80

This ingress follows the Global Default Backend property of ingresses. This will allow users to create a “default router” that will match all unmatched requests.

Info

Due to Traefik’s use of priorities, you may have to set this ingress priority lower than other ingresses in your environment, to avoid this global ingress from satisfying requests that could match other ingresses.

To do this, use the traefik.ingress.kubernetes.io/router.priority annotation (as seen in Annotations on Ingress) on your ingresses accordingly.


Using Traefik OSS in Production?

If you are using Traefik at work, consider adding enterprise-grade API gateway capabilities or commercial support for Traefik OSS.

Adding API Gateway capabilities to Traefik OSS is fast and seamless. There’s no rip and replace and all configurations remain intact. See it in action via this short video.