Blog | WeScale

Le load balancer sous Kubernetes avec Traefik

Rédigé par Maxence Maireaux | 04/09/2017


Une solution que j’affectionne particulièrement est Traefik, car elle est simple à prendre en mains et propose suffisamment d’options pour ce que je veux faire sans être un enfer à configurer.
Je vous propose donc de vous exposer ici la démarche réalisée afin d’installer Traefik dans un cluster Kubernetes.

Les méthodes d’installation de Traefik

J’ai voulu démarrer simplement et utiliser Helm dans l’objectif de déployer rapidement le nécessaire pour Traefik. J’ai cependant réalisé que si celui-ci fonctionne parfaitement, le service créé utilise un nodePort au dessus de 30000, ce qui rend son utilisation moins triviale qu’avec le port http classique.
Si on souhaite définir un nodePort, nous pouvons le faire mais là aussi au dessus des 30000, sinon cela pourrait engendrer des conflits de port qui pourrait affecter par exemple le port 22 et rendre ainsi votre connexion SSH impossible.
Je me suis aussi posé des questions par rapport aux performances de la démarche : passer par un premier service Kubernetes qui va prendre l’ensemble du trafic puis l’envoyer vers de multiples instances Traefik, et pour finir vers les services d’accès au pod, me paraissait un peu lourd. J’ai donc cherché à simplifier le schéma.

Ainsi, j’ai créé un DaemonSet auquel j’ai affecté un hostNetwork pour ouvrir les ports http/https du host directement sans passer par des services.
Mon cluster utilise aussi Role-Based Access Control (RBAC), il faut donc créer un ClusterRole ainsi qu’un ClusterRoleBinding. J’en profite pour créer une règle ingress afin d’accéder au back office de Traefik via une URL, et non par le port 8080 par défaut.

Création des ressources

Création d’un namespace spécifique pour Traefik

apiVersion: v1
kind: Namespace
metadata:
name: traefik
Création d’un ClusterRole
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
 name: traefik-ingress-controller
rules:
 - apiGroups:
     - ""
   resources:
     - pods
     - services
     - endpoints
     - secrets
   verbs:
     - get
     - list
     - watch
 - apiGroups:
     - extensions
   resources:
     - ingresses
   verbs:
     - get
     - list
     - watch
```

Création d’un ClusterRoleBinding

````YML
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
 name: traefik-ingress-controller
roleRef:
 apiGroup: rbac.authorization.k8s.io
 kind: ClusterRole
 name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
 name: traefik-ingress-controller
 namespace: traefik
Création d’un ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
 name: traefik-ingress-controller
 namespace: traefik
```

Création d’un ConfigMap

````YAML
apiVersion: v1
kind: ConfigMap
metadata:
 name: traefik-conf
 namespace: traefik
data:
 traefik.toml: |-
   defaultEntryPoints = ["http","https"]
   [web]
   address = ":8080"
```

Création d’un DaemonSet


````YAML
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
 name: traefik-ingress-controller
 namespace: traefik
 labels:
   k8s-app: traefik-ingress-lb
   kubernetes.io/cluster-service: "true"
spec:
 template:
   metadata:
     labels:
       k8s-app: traefik-ingress-lb
       name: traefik-ingress-lb
   spec:
     hostNetwork: true # workaround
     serviceAccountName: traefik-ingress-controller
     terminationGracePeriodSeconds: 60
     tolerations:
     - key: node-role.kubernetes.io/master
       effect: NoSchedule
     containers:
     - image: traefik:v1.3.1
       name: traefik-ingress-lb
       imagePullPolicy: Always
       volumeMounts:
         - mountPath: "/config"
           name: "config"
       resources:
         requests:
           cpu: 100m
           memory: 20Mi
       args:
       - --kubernetes
       - --configfile=/config/traefik.toml
     volumes:
     - name: config
       configMap:
         name: traefik-conf
```

Création d’un Service

````YAML
apiVersion: v1
kind: Service
metadata:
 name: traefik-web-ui
 namespace: traefik
spec:
 selector:
   k8s-app: traefik-ingress-lb
 ports:
 - port: 80
   targetPort: 8080

Création d’un IngressController

Pensez à modifier la ligne host pour qu’elle corresponde à votre nom de domaine.

```YAML
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
 name: traefik-web-ui
 namespace: traefik
 annotations:
   kubernetes.io/ingress.class: traefik
spec:
 rules:
 - host: "traefik.exemple.tld"
   http:
     paths:
     - backend:
         serviceName: traefik-web-ui
         servicePort: 80

Si vous allez sur l’adresse que vous avez renseignée dans votre IngressController, vous pouvez maintenant accéder à votre backend Traefik !

Conclusion

Vous avez maintenant un beau Traefik qui répondra à l’ensemble de vos requêtes :) Vous n’avez plus qu’à créer de nouveaux IngressController et ainsi accéder à l’ensemble de vos applications via un point d’entrée unique.