Cart

    Sorry, we could not find any results for your search querry.

    Installing and using Traefik in Kubernetes

    Helm Charts are updated regularly, so variable names and their locations can change. As a result, we cannot guarantee that every article is always fully up to date. If you notice any information is no longer correct, we’d love to hear from you. 

    Official Traefik Helm repository

     

    Traefik is a popular open-source reverse proxy and load balancer designed for microservices and containerised applications. Traefik can automatically discover the Services running in a Kubernetes cluster and route traffic to those Services using various load-balancing algorithms.

    Traefik sits in front of other Services within your cluster. With Traefik, you can host multiple applications on a Kubernetes cluster and route their traffic through Traefik. Traefik can then act as a single load balancer for all of these applications and can also provision Let’s Encrypt SSL certificates.

    In this guide, we’ll show you how to install and use Traefik. We’ll use a custom (sub)domain name (optional) to connect to Traefik and secure it with an SSL certificate. To log in to the Traefik dashboard, we’ll set up a username and password.

    For this guide you’ll need:

     

     

    Installing Traefik

     

    Step 1

    Add the official Traefik repository and update your Helm repositories so you can use it:

    helm repo add traefik https://helm.traefik.io/traefik
    helm repo update

     

    Step 2

    Traefik can generate Let’s Encrypt certificates for applications that communicate via Traefik. In this guide, we assume you want to use this for your own use case as well. To do so, you’ll use an ACME DNS challenge provider. We support this option via our API. Please note that the provider you choose must support this functionality, and the domains you use must be registered with that provider in the account you use for this guide.

    Create a directory where you’ll store your TransIP API key, for example:

    mkdir transip

    Next, create a file in the directory you just created containing a private key from your TransIP API account, for example:

    cat << EOF > transip/transip.key
    -----BEGIN PRIVATE KEY-----
    MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDKoaYJtbVnJw58
    PYGH8WIJ7ZjWd2lke0IbMV+dNGs=
    -----END PRIVATE KEY-----
    EOF

    This example only includes a small fragment of a private key. Your private key will be much longer.


     

    Step 3

    Create a namespace for Traefik in your cluster:

    kubectl create ns traefik

     

    Step 4

    Generate a Secret based on your API private key that Traefik can use to communicate with the TransIP API. If necessary, replace the following values:

    • -n traefik: Use the name of the namespace you created in step 3.
    • transip/transip.key: Change this to the directory and file name you created in step 2.
    kubectl create -n traefik secret generic transip-key --from-file transip/transip.key

     

    Step 5

    Speaking of Secrets: if you configure Traefik to be accessible via the public internet, by default there is no username and/or password set. So we’ll create another Secret containing a username and password to log in to the Traefik dashboard. 

    Use htpasswd to generate a username and password:

    htpasswd -nb <username> <password> >> htpasswd.txt

    The contents of the htpasswd.txt file will look roughly like this:

    demouser:$2a$13$2QBmxHS5a1hWU9aeyJ.DPNWRFjXcNRNTjcu56QTLhZS.y

    Are you using Windows to follow these steps? Then use our htpasswd tool and generate an htpasswd username and password. Save the output to a file in the folder where you’re running the commands in this guide, for example c:\Users\Administrator\kubernetes\htpasswd.txt

    Then create the Secret based on the contents of the file you just created:

    kubectl create secret generic traefik-dashboard-basicauth --from-file=users=htpasswd.txt -n traefik

     

    Step 6

    To install Traefik, you’ll use the official Helm Chart in the next step. In an additional .yaml file you’ll make a few changes; create a .yaml file for this, for example:

    nano traefik.yaml

    Populate the file with the contents below, adjusting a few values:

    • example@transip.nl: Change this to your email address.
    • jouwaccount: Replace jouwaccount with the name of your TransIP account.
    • /transip/transip.key: Change this (if needed) to the directory and file name you created in step 2.
    • traefik.transip.nl: Change this to the (sub)domain you want to connect to Traefik.
    deployment:
      initContainers:
        - name: volume-permissions
          image: busybox:latest
          command: ["sh", "-c", "touch /data/acme.json; chmod -v 600 /data/acme.json"]
          volumeMounts:
          - mountPath: /data
            name: data
    podSecurityContext:
      fsGroup: 65532
      fsGroupChangePolicy: "OnRootMismatch"
    additionalArguments:
      - "--certificatesresolvers.myresolver.acme.email=shagting@transip.nl"
      - "--certificatesresolvers.myresolver.acme.dnschallenge.provider=transip"
      - "--certificatesresolvers.myresolver.acme.dnschallenge.propagation.delayBeforeChecks=120"
      - "--certificatesresolvers.myresolver.acme.storage=/data/acme.json"
      - "--providers.kubernetescrd.namespaces="
    env:
      - name: TRANSIP_ACCOUNT_NAME
        value: testtransip
      - name: TRANSIP_PRIVATE_KEY_PATH
        value: /transip/transip.key
    volumes:
      - name: transip-key
        mountPath: "/transip"
        type: secret
    persistence:
      enabled: true
      size: 128Mi
    ports:
      websecure:
        tls:
          enabled: true
        expose:
          default: true
        exposedPort: 443
    ingressRoute:
      dashboard:
        enabled: true
        entryPoints:
          - websecure
        matchRule: Host(`traefik.supporttest.nl`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))
        tls:
          certResolver: myresolver
        middlewares:
          - name: "dashboard-auth"
            namespace: "traefik"
    extraObjects:
      - apiVersion: traefik.io/v1alpha1
        kind: Middleware
        metadata:
          name: dashboard-auth
          namespace: traefik
        spec:
          basicAuth:
            secret: "traefik-dashboard-basicauth"
    podAnnotations:
      prometheus.io/port: "8082"
      prometheus.io/scrape: "true"
    providers:
      kubernetesGateway:
        enabled: true
      kubernetesIngress:
        publishedService:
          enabled: true
    priorityClassName: "system-cluster-critical"
    image:
      registry: docker.io
      repository: traefik
    tolerations:
      - key: "CriticalAddonsOnly"
        operator: "Exists"
      - key: "node-role.kubernetes.io/control-plane"
        operator: "Exists"
        effect: "NoSchedule"
      - key: "node-role.kubernetes.io/master"
        operator: "Exists"
        effect: "NoSchedule"
      - key: "node-role.kubernetes.io/master"
        operator: "Exists"
        effect: "NoSchedule"

    Code explanation

    For a full overview of the available options, see the official Helm chart. In a nutshell, the different sections mean the following:

    • deployment.initcontainers: Out of the box, Traefik is configured not to have permission to write SSL certificates to the default file intended for this purpose, /data/acme.json. This section ensures Traefik gets read and write permissions by adjusting the permissions with a chmod command.
    • podsecuritycontext: Ensures each volume has the correct owner (65532).
    • additionalArguments: The values provided specify which email address will receive notifications related to generating SSL certificates, that you use TransIP’s systems (via our API) to generate Let’s Encrypt certificates, how often they are renewed, where they are stored, and that Traefik monitors and can use all namespaces.
    • env: Information related to your TransIP API details (from steps 2 and 4).
    • volumes: Here you configure additional volumes (a kind of disk); in this case, the /transip volume to store your API details.
    • persistence: Controls whether the volume used to store SSL certificates (/data) is retained if you remove your Traefik installation. In this .yaml file, this option is enabled. 
    • ports: The configuration related to using Traefik over SSL (whether it can be used, which port, etc.).
    • ingressRoute: An IngressRoute ensures incoming network requests are routed to the correct Services. 
    • extraObjects: Adds extra components to your Traefik setup. In this setup, you add a Middleware that prompts for a password when you open the Traefik dashboard in your browser, as configured in the traefik-dashboard-basicauth Secret (which you created in step 5).
    • podAnnotations: Additional labels to attach to the Traefik pod, in this case to enable the use of Prometheus in conjunction with Traefik.
    • providers: Enables (a) using Traefik as a Gateway instead of the traditional (end-of-life) Nginx Ingress and (b) Traefik’s option to discover Kubernetes Ingress resources. This option is enabled by default in the official Helm Chart. We’ve included it here anyway, in case Traefik decides to disable it by default at a later date.
    • priorityClassName: Sets a priority class for Traefik. If, for whatever reason, Kubernetes needs to decide which Pods to prioritise when creating them, a Pod with a priority class will be prioritised.
    • image: Which image is used to create the Traefik deployment. 
    • tolerations: Certain pods cannot be placed (i.e. scheduled) on a node with a taint unless the pod has a toleration for that specific taint; see our article on taints & tolerations.
     
     

     

    Step 7

    Install the Traefik Helm Chart using the command below.

    helm install -f traefik.yaml traefik traefik/traefik -n traefik
    • helm install: Installs the Helm Chart.
    • -f traefik.yaml: The file from step 6 that we use to customise the installation.
    • traefik: The name of the Helm ‘release’, which you can check with the ‘helm list’ command.
    • traefik/traefik: Respectively, the name of the repository and the Helm Chart to install.
    • -n traefik: The namespace in which the Helm release is installed; see step 3.

    You’ll now see a confirmation that looks roughly like this:

    NAME: traefik
    LAST DEPLOYED: Wed Feb 12 09:22:05 2025
    NAMESPACE: traefik
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
    NOTES:
    traefik with docker.io/traefik:v3.3.3 has been deployed successfully on traefik namespace !
    🚨 When enabling persistence for certificates, permissions on acme.json can be
    lost when Traefik restarts. You can ensure correct permissions with an
    initContainer. See https://github.com/traefik/traefik-helm-chart/blob/master/EXAMPLES.md#use-traefik-native-lets-encrypt-integration-without-cert-manager

    You can ignore the warning: you addressed this issue at the start of the traefik.yaml file you created in the previous step. 

    Traefik has now been installed successfully, but… what’s next? That brings us to the Traefik dashboard first; see the next section.


     

    The Traefik dashboard

     

    Traefik comes with a web interface that gives you insight into the status of your Kubernetes cluster and the traffic processed by your cluster. It shows information about the routers and Services used to handle traffic, as well as the load-balancing algorithms in use. The dashboard also gives you the ability to view logs and metrics generated by Traefik. In short, the dashboard is a handy tool for monitoring and troubleshooting Traefik.

     

    Step 1

    To use the Traefik dashboard, first find the external IP address of your Traefik LoadBalancer (created automatically):

    kubectl get svc -n traefik

    In the output, under ‘external-IP’, you’ll see an address that looks like: 86-105-245-108.haip.transip.net. Note down the numbers and replace the hyphens with dots, i.e.: 86.105.245.108. 


     

    Step 2

    Want to link Traefik to a (sub)domain? First create an A record for your domain name; see this guide. For example, use the name ‘traefik’ and set its value to the IP address from the previous step.


     

    Step 3

    At the start of this article, we told you that you’ll be using the TransIP API and that you’ll need a key for it. When you created the API key, you were given the option to restrict the key to whitelisted IP addresses only. If you chose this option, also add the IP address from step 1 to your API whitelist; see our API guide again.

    It may take a little while for the DNS and API changes to be picked up. Once they’ve been processed, you can view the Traefik dashboard in a browser via your subdomain, for example https://traefik.voorbeeld.nl/dashboard/, or directly via the IP address at https://<ip-address>:/dashboard/. When prompted for a username and password, use the ones from step 5 of the previous section.


     

    Updating your configuration

     

    It’s advisable to keep the public IP address of your load balancer when you make changes to Traefik’s configuration. So, where possible, don’t remove your entire Traefik installation when making changes. Instead, apply any changes in traefik.yaml and update your Helm installation with:

    helm upgrade -f traefik.yaml traefik traefik/traefik -n traefik

     

    Cert-manager or not

     

    Traefik can generate Let’s Encrypt certificates perfectly well. However, do you use Cert-manager for your use case? If so, you’ll need a few changes in the .yaml file from step 6 of the Traefik installation and configuration. Update traefik.yaml so it looks like the example below (only remove the deployment.initcontainers section if you don’t need /data for your project):

    podSecurityContext:
      fsGroup: 65532
      fsGroupChangePolicy: "OnRootMismatch"
    persistence:
      enabled: true
      size: 128Mi
    ports:
      websecure:
        tls:
          enabled: true
        expose:
          default: true
        exposedPort: 443
    ingressRoute:
      dashboard:
        enabled: true
        entryPoints:
          - websecure
        matchRule: Host(`traefik.supporttest.nl`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))
        tls:
          secretName: traefik-dashboard-tls
        middlewares:
          - name: "dashboard-auth"
            namespace: "traefik"
    extraObjects:
      - apiVersion: traefik.io/v1alpha1
        kind: Middleware
        metadata:
          name: dashboard-auth
          namespace: traefik
        spec:
          basicAuth:
            secret: "traefik-dashboard-basicauth"
    podAnnotations:
      prometheus.io/port: "8082"
      prometheus.io/scrape: "true"
    providers:
      kubernetesGateway:
        enabled: true
      kubernetesIngress:
        publishedService:
          enabled: true
    priorityClassName: "system-cluster-critical"
    image:
      registry: docker.io
      repository: traefik
    tolerations:
      - key: "CriticalAddonsOnly"
        operator: "Exists"
      - key: "node-role.kubernetes.io/control-plane"
        operator: "Exists"
        effect: "NoSchedule"
      - key: "node-role.kubernetes.io/master"
        operator: "Exists"
        effect: "NoSchedule"

    Also use a separate .yaml file (or include the configuration in your existing .yaml) to define the certificate you want to request, e.g. certificate.yaml:

    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: demo-cert
      namespace: demo-setup
    spec:
      secretName: demo-setup-tls
      issuerRef:
        name: letsencrypt-issuer
        kind: ClusterIssuer
      dnsNames:
        - demo.voorbeeld.nl

    Of course, update the name, namespace, secretName, issuerRef.name and dnsNames to match your project.

    Finally, apply the configuration:

    helm upgrade -f traefik.yaml traefik traefik/traefik -n traefik
    kubectl apply -f certificate.yaml

     

    Example of using Traefik

     

    You can now use Traefik to route traffic to your deployments via the Gateway API. Below is an example of how to expose a simple Nginx application through a Traefik Gateway and HTTPRoute, including an HTTP->HTTPS redirect without redirect loops. Note: don’t copy this 1:1—adjust namespaces, hostnames, and secret names to match your use case (e.g. nginx.example.com).

     

    Nginx Deployment and Service:

    The example below deploys a simple Nginx setup that receives traffic on port 80.

    apiVersion: v1
    kind: Namespace
    metadata:
      name: nginx
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
      namespace: nginx
      labels:
        app: nginx
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx:stable-alpine
              ports:
                - containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx
      namespace: nginx
    spec:
      selector:
        app: nginx
      ports:
        - name: http
          port: 80
          targetPort: 80

     

    Certificate (cert-manager):

    cert-manager creates a TLS Secret (for example nginx-example-com-tls). You then attach that Secret to the HTTPS listener in the Gateway via tls.certificateRefs.

    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: nginx-cert
      namespace: nginx
    spec:
      secretName: nginx-example-com-tls
      issuerRef:
        name: letsencrypt-issuer
        kind: ClusterIssuer
      dnsNames:
        - nginx.example.com

     

    Gateway:

    The Gateway defines the “entry point” to your cluster for this hostname. The HTTPS listener uses the certificate from the Secret created by cert-manager. Note: in many Traefik Helm installs the entryPoints listen internally on 8000/8443; make sure your listener ports match your Traefik entryPoints.

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: nginx-gateway
      namespace: nginx
    spec:
      gatewayClassName: traefik
      listeners:
        - name: web
          protocol: HTTP
          port: 8000
          hostname: nginx.example.com
          allowedRoutes:
            namespaces:
              from: Same
        - name: websecure
          protocol: HTTPS
          port: 8443
          hostname: nginx.example.com
          tls:
            mode: Terminate
            certificateRefs:
              - kind: Secret
                name: nginx-example-com-tls
          allowedRoutes:
            namespaces:
              from: Same

     

    HTTPRoute (redirect HTTP -> HTTPS):

    To automatically redirect HTTP to HTTPS without redirect loops, create a separate HTTPRoute that only attaches to the HTTP listener (sectionName: web) and applies a RequestRedirect filter.

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: nginx-route-redirect
      namespace: nginx
    spec:
      parentRefs:
        - name: nginx-gateway
          sectionName: web
      hostnames:
        - nginx.example.com
      rules:
        - matches:
            - path:
                type: PathPrefix
                value: /
          filters:
            - type: RequestRedirect
              requestRedirect:
                scheme: https
                statusCode: 301

     

    HTTPRoute (HTTPS to the Service):

    This route attaches to the HTTPS listener (sectionName: websecure) and forwards traffic to the Nginx Service.

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: nginx-route
      namespace: nginx
    spec:
      parentRefs:
        - name: nginx-gateway
          sectionName: websecure
      hostnames:
        - nginx.example.com
      rules:
        - matches:
            - path:
                type: PathPrefix
                value: /
          backendRefs:
            - name: nginx
              port: 80

    Apply the resources and verify their status:

    kubectl apply -f nginx-deployment-service.yaml
    kubectl apply -f nginx-certificate.yaml
    kubectl apply -f nginx-gateway.yaml
    kubectl apply -f nginx-httproute-redirect.yaml
    kubectl apply -f nginx-httproute.yaml
    
    kubectl get certificate -n nginx
    kubectl describe gateway nginx-gateway -n nginx
    kubectl describe httproute nginx-route-redirect -n nginx
    kubectl describe httproute nginx-route -n nginx

     

     That brings us to the end of our guide on installing and using Traefik in Kubernetes.

    Need help?

    Receive personal support from our supporters

    Contact us