Traefik is a simple and eficient load balancer that can be used at any environment, but if is used with docker or kubernetes can use the service discovery funcionality to allow you the deploy your services and it automaticaly discover all of your replicas and where are running

Used with kubernetes, acts as a ingress controller ( version 1.7 ), so you can use the standard ingress manifest to deploy your services

  • Service discovery
  • Path routing
  • Letsencrypt integration

At the last post k3s introduction I told that I was not going to install traefik because is more dificult to make changes on it, so now we are going to learn how to install and use it.

At this point I indicate that to facilitate the dns resolution of the differents deployments we are going to use the nip.io domain, to allow us to call every deployment with dns its name and for that the ingress manifest must have a domain name.

First we are going to install traefik 1.7 at our kubernetes cluster. We can do that with 2 approaches

  • As a Deployment so you can choose how many replicas are running at the cluster.
  • As a DaemonSet so one replica of traefik is running at every node of your cluster.

If you have a large cluster, with high number of requests, you must use DaemonSet because traefik is going to suppport all the requests of your applications, but if you have a small cluster, is possible that you prefer to use Deployment with 1 or 2 replicas. In any case the installation process is the same.

# Create clusterRole
kubectl apply -f https://vmalaga.no-ip.org/examples/traefik/traefik-rbac.yaml
# Install traefik
kubectl apply -f https://vmalaga.no-ip.org/examples/traefik/traefik-ds.yaml

The main diference of my DaemonSet with the one provided by traefik is that with are going to use the NET_BIND_SERVICE capability that permit us to bind at 80 and 443 ports, and use the https entrypoint.

    spec:
      serviceAccountName: traefik-ingress-controller
      terminationGracePeriodSeconds: 60
      containers:
      - image: traefik:v1.7
        name: traefik-ingress-lb
        ports:
        - name: http
          containerPort: 80
          hostPort: 80
        - name: https
          containerPort: 443
          hostPort: 443
        - name: admin
          containerPort: 8080
          hostPort: 8080
        securityContext:
          capabilities:
            drop:
            - ALL
            add:
            - NET_BIND_SERVICE
        args:
        - --api
        - --kubernetes
        - --logLevel=INFO
        - --defaultentrypoints=http,https
        - --entrypoints=Name:https Address::443 TLS
        - --entrypoints=Name:http Address::80
        - --insecureSkipVerify=true

Next we need a SSL certificate to use the https entrypoint, so we are going to use cert-manager to generate a certificate, change 192.168.1.222 with the ip of your server

apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
  name: traefik-cert
  namespace: kube-system
spec:
  secretName: traefik-cert-tls
  issuerRef:
    name: ca-issuer
    kind: ClusterIssuer
  commonName: traefik.192.168.1.222.nip.io
  organization:
  - Tutorial CA
  dnsNames:
  - traefik.192.168.1.222.nip.io
kubectl apply -f https://vmalaga.no-ip.org/examples/traefik/traefik-cert.yaml

Now we have a secret with the ca.crt, tls.crt and tls.key

kubectl -n kube-system describe secrets traefik-cert-tls

Name:         traefik-cert-tls
Namespace:    kube-system
Labels:       <none>
Annotations:  cert-manager.io/alt-names: traefik.192.168.1.222.nip.io
              cert-manager.io/certificate-name: traefik-cert
              cert-manager.io/common-name: traefik.192.168.1.222.nip.io
              cert-manager.io/ip-sans:
              cert-manager.io/issuer-group:
              cert-manager.io/issuer-kind: ClusterIssuer
              cert-manager.io/issuer-name: ca-issuer
              cert-manager.io/uri-sans: 

Type:  kubernetes.io/tls

Data
====
ca.crt:   1688 bytes
tls.crt:  1489 bytes
tls.key:  1679 bytes

Now we need to expose traefik port as NodePort, the Spec externalTrafficPolicy: Local allow as to provide the x-forwarder headers at our backends

kind: Service
apiVersion: v1
metadata:
  name: traefik-ingress-service
  namespace: kube-system
spec:
  externalTrafficPolicy: Local
  selector:
    k8s-app: traefik-ingress-lb
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      name: web
    - protocol: TCP
      port: 443
      targetPort: 443
      name: secure
    - protocol: TCP
      port: 8080
      targetPort: 8080
      name: admin
  type: NodePort

And last, the ingress with the important annotations:

  • kubernetes.io/ingress.class: “traefik”
  • traefik.ingress.kubernetes.io/ssl-redirect: “true”
  • tls.secretName: traefik-cert-tls - the secret generated with the certificate request.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: traefik-dashboard-ingress
  namespace: kube-system
  annotations:
    kubernetes.io/ingress.class: "traefik"
    traefik.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  rules:
  - host: traefik.192.168.1.222.nip.io
    http:
      paths:
      - path: /
        backend:
          serviceName: traefik-ingress-service
          servicePort: 8080
  tls:
  - secretName: traefik-cert-tls
kubectl apply -f https://vmalaga.no-ip.org/examples/traefik/traefik-service-ingress.yaml
kubectl -n kube-system get service,ingress
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
NAME                              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                                     AGE
service/kube-dns                  ClusterIP   10.43.0.10      <none>        53/UDP,53/TCP,9153/TCP                      36d
service/metrics-server            ClusterIP   10.43.141.121   <none>        443/TCP                                     36d
service/traefik-ingress-service   NodePort    10.43.197.168   <none>        80:32667/TCP,443:32691/TCP,8080:31330/TCP   36d

NAME                                           CLASS    HOSTS                          ADDRESS   PORTS     AGE
ingress.extensions/traefik-dashboard-ingress   <none>   traefik.192.168.1.222.nip.io             80, 443   36d

If everything went well, you should be able to see the Trafik admin interface at https://traefik.192.168.1.222.nip.io/dashboard/