Traefik, c’est quoi ?#
Je vous ai déjà parlé de Traefik comme étant un super proxy inversé (reverse proxy) que j’utilisais pour mes configurations avec docker-compose qui permettait en plus de générer des certificats TLS pour un accès HTTPS sans certificat auto-signé.
Le produit évolue toujours, il est actuellement en version 2.8 à la rédaction de cet article.
Pour une présentation plus complète du fonctionnement interne, je vous redirige vers cet article où j’ai présenté en détail le fonctionnement de ce proxy.
L’objectif de cet article est de voir l’intégration de Traefik au sein de l’écosystème Kubernetes.
Traefik avec Kubernetes#
Introduction#
Dans Kubernetes, pour rendre vos ressources accessibles de l’extérieur (généralement HTTP ou HTTPS), il est nécessaire d’utiliser (et d’installer) ce que l’on appelle un Ingress Controller afin d’utiliser des objets Ingress
.
Si vous souhaitez plus d’informations à ce sujet, la documentation officielle regroupe beaucoup d’informations.
Des Ingress Controller il en existe un paquet ! Que ce soit ceux des services managés du Cloud, nginx, HAProxy, etc.
Alors, pourquoi choisir Traefik ?
- Très simple à déployer sur un cluster avec un chart Helm configurable ;
- Très léger et pour cause, K3S, le Kubernetes allégé utilise Traefik en tant qu’Ingress Controller par défaut ;
- Génération de certificats TLS avec Let’s Encrypt et gestion automatique du renouvellement ce qui évite d’utiliser cert-manager en parallèle ;
- Permet de faire de l’équilibrage de charge HTTP, mais aussi TCP ;
- Beaucoup de fonctionnalités disponibles (dashboard, plugins, etc.).
Pour ce qui concerne Traefik, il y a deux manières de l’utiliser dans ce type d’orchestrateur :
- Soit en utilisant un objet
Ingress
classique qui est nativement inclus sur Kubernetes ; - Soit en utilisant un objet
IngressRoute
qui est un objet personnalisé fourni par Traefik en tant que Custom Resource Definition (CRD).
Pourquoi ces deux possibilités ?
Après avoir utilisé l’objet Ingress
, la communauté a voulu créer un objet personnalisé (IngressRoute
) au sein de Kubernetes pour éviter d’utiliser les annotations pour l’ensemble des fonctionnalités souhaitées par l’utilisateur afin de ne pas surcharger l’objet Ingress
et d’avoir une structure plus claire et lisible.
En résumé, la première solution est simple et rapide, la deuxième est pour des cas d’utilisation avancées.
Installation#
Pour ceux qui souhaitent installer le Chart Traefik avec Ansible, voici le bout de code pour y parvenir :
- hosts: client # Machine sur laquelle vous souhaitez jouer le playbook
gather_facts: true
become: true
vars:
traefik_chart_version: 10.24.0 # Version du Chart Helm de Traefik
tasks:
- name: Install traefik chart
kubernetes.core.helm:
release_name: traefik
chart_ref: traefik
chart_version: "{{ traefik_chart_version }}"
chart_repo_url: https://helm.traefik.io/traefik
release_namespace: traefik-ingress
create_namespace: true
values:
globalArguments:
deployment:
kind: DaemonSet # Déploiement en mode DaemonSet
providers:
kubernetesCRD:
enabled: true # Active la création des CRD pour les objets personnalisés
service:
type: LoadBalancer # Type de service à utiliser pour Traefik
ingressRoute:
dashboard:
enabled: false # Désactive la création d'une IngressRoute pour accéder au dashboard
become: false
C’est la configuration que j’utilise quand je déploie Traefik sur mon projet kubeadm-automation
que vous pouvez retrouver ici. De plus, il ne faut pas oublier de déployer MetalLB pour utiliser le type LoadBalancer sur ce type d’installation.
N’oubliez pas non plus d’exécuter ansible-galaxy collection install kubernetes.core
avant de jouer ce playbook afin d’utiliser la collection core de Kubernetes avec Ansible.
Il est possible d’installer l’Ingress Controller Traefik de manière traditionnelle avec Helm avec les commandes suivantes :
# Ajoute le repository à Helm
helm repo add traefik https://helm.traefik.io/traefik
# Permet de mettre à jour l'ensemble des repo
helm repo update
# Crée le namespace traefik-ingress
kubectl create ns traefik-ingress
# Crée le fichier traefik-values.yaml
cat > traefik-values.yaml <<EOF
globalArguments:
deployment:
kind: DaemonSet
providers:
kubernetesCRD:
enabled: true
service:
type: LoadBalancer
ingressRoute:
dashboard:
enabled: false
EOF
# Installe Traefik
helm install --namespace=traefik-ingress traefik traefik/traefik --values=./traefik-values.yaml
Vérifier l’installation#
Plusieurs commandes permettent de vérifier le bon déploiement de Traefik.
Tout d’abord, est-ce que le ou les Pod
sont Ready ?
$ kubectl -n traefik-ingress get pod
NAME READY STATUS RESTARTS AGE
traefik-xfz57 1/1 Running 0 3m18s
Oui !
Traefik a été configuré en mode DaemonSet
, ce qui veut dire que chaque noeud du cluster doit avoir un Pod
associé :
$ k -n traefik-ingress get ds
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
traefik 1 1 1 1 1 <none> 5m4s
Est-ce que le service de type LoadBalancer
dispose d’une EXTERNAL-IP ?
$ kubectl -n traefik-ingress get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
traefik LoadBalancer 10.106.241.64 172.16.254.1 80:30648/TCP,443:31371/TCP 9m29s
Tout est bon ! Traefik est totalement fonctionnel !
Créer son premier Ingress#
Maintenant que l’installation est terminée, il est possible de créer un objet de type Ingress
avec un exemple très simple.
Tout d’abord, il est impératif de créer un Pod
et un service associé à ce Pod
:
kubectl run nginx --image=nginx
kubectl expose pod nginx --port=80
et ensuite de créer l’Ingress
se basant sur le service préalablement créé :
cat <<EOF | kubectl create -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ing-traefik
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80
EOF
Pour vérifier le fonctionnement de l’Ingress
, il suffit de prendre l’EXTERNAL-IP du service Traefik. Ce qui donne :
$ curl 172.16.254.1
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
</head>
<body>
...
</body>
</html>
Simple non ? En même temps, c’est une fonctionnalité très basique que l’ensemble des Ingress Controllers ont.
Utiliser l’objet IngressRoute et obtenir un certificat TLS#
On vient de configurer un Ingress
classique, le but est maintenant de faire la même chose tout en ayant une génération de certificat automatique pour un nom de domaine. Pour cela, il est nécessaire d’utiliser l’IngressRoute
de Traefik.
Tout d’abord, il est impératif d’ajouter un bloc (au niveau du fichier traefik-values.yaml
avant de déployer notre Chart) qui est requis pour configurer letsencrypt
et permettre à Traefik de générer des certificats TLS.
certResolvers:
letsencrypt:
email: # Insérer ici une adresse email qui permettra d'associer vos certificats à celle-ci
httpChallenge: # Utilisation du challenge HTTP
entryPoint: "web"
storage: /data/acme.json # Espace de stockage des certificats sur les masters Kubernetes
L’ensemble des Challenges est disponible à cette adresse afin de vérifier que le nom de domaine vous appartient.
Une chose important à savoir avant de réaliser ces étapes, c’est que vous devez disposer d’une IP publique qui pointe sur votre cluster avec un nom de domaine associé à cette IP publique.
Et voici la configuration à avoir si on reprend l’exemple du dessus :
kubectl run nginx --image=nginx
kubectl expose pod nginx --port=80
cat <<EOF | kubectl create -f -
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ing-traefik-tls
spec:
entryPoints:
- websecure
routes:
- match: Host(\`ingress.filador.fr\`)
kind: Rule
services:
- name: nginx
port: 80
tls:
certResolver: letsencrypt
EOF
La configuration est un peu différente d’un Ingress
classique, ce qui change surtout c’est la partie tls
avec le certResolver
à spécifier (qui a été défini au préalable dans le Chart Helm).
La création d’un certificat peut prendre plus ou moins de temps, pas de panique ici, Traefik met à disposition son certificat par défaut (CN=TRAEFIK DEFAULT CERT
) le temps de la génération du certificat TLS.
Par ailleurs, les certificats ont une durée de vie de 90 jours et sont renouvelés 30 jours avant leur expiration.
Pour aller plus loin, il peut être intéressant de rediriger le trafic HTTP vers le HTTPS. C’est ce qui est fait ici :
cat <<EOF | kubectl create -f -
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ing-traefik
spec:
entryPoints:
- web
routes:
- match: Host(\`ingress.filador.fr\`)
kind: Rule
services:
- name: nginx
port: 80
middlewares:
- name: https-redirect
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: https-redirect
spec:
redirectScheme:
scheme: https
permanent: true
EOF
Un nouvel objet est créé, ici Middleware
qui permet de mettre en place une redirection vers le HTTPS.
Beaucoup d’options peuvent être positionnées au niveau du Middleware
notamment pour ajuster la sécurité au niveau des Headers HTTPS.
Fractionner le trafic#
Dans les utilisations avancées de Traefik, il est possible de fractionner le trafic en créant un TraefikService
permettant d’associer des poids à chaque route.
C’est ce qui va être effectué dans cet exemple :
On crée un Pod
nginx et un autre httpd avec pour chacun un service de type ClusterIP
.
kubectl run nginx --image=nginx
kubectl expose pod nginx --port=80
kubectl run httpd --image=httpd
kubectl expose pod httpd --port=80
On crée par la suite, un TraefikService
avec le poids de chaque service : 5 pour nginx et 1 pour httpd.
cat <<EOF | kubectl create -f -
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
name: weightedroundrobin
spec:
weighted:
services:
- name: nginx
port: 80
weight: 5
- name: httpd
port: 80
weight: 1
EOF
Enfin, on associe le TraefikService
avec un objet IngressRoute
avec un nom de domaine associé.
cat <<EOF | kubectl create -f -
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingress-weightedroundrobin
spec:
entryPoints:
- web
routes:
- match: Host(\`traefik-wrr.local\`)
kind: Rule
services:
- name: weightedroundrobin
kind: TraefikService
EOF
Pour tester, il ne faut pas oublier d’ajouter le nom de domaine associé à l’IngressRoute
dans votre fichier /etc/hosts
avec l’adresse IP externe lié au LoadBalancer
de Traefik (dans le cas où vous testez avec le projet kubeadm.
Une fois sur 5 (à peu près), on peut visualiser le <html><body><h1>It works!</h1></body></html>
d’httpd au lieu de la page de nginx.
Cette fonctionnalité a le mérite d’être très utile dans le cas où on souhaite tester une nouvelle version d’application avec une petite portion de trafic qui lui est associée.
Le mot de la fin#
Traefik se révèle comme l’Ingress Controller
facile à mettre en place avec un large panel de fonctionnalités. Son intégration directe avec Let’s Encrypt permet la génération de certificats à la volée plutôt que de passer par des outils intermédiaires.
Enfin, les objets personnalisés permettent de réaliser des configurations avancées qui sont intéressantes à mettre en oeuvre en fonction du cas d’utilisation rencontré.