Déployer Traefik Proxy dans Kubernetes derrière Cloudflare en TLS Strict
Objectif
Dans cet article, nous allons voir comment installer, sous Kubernetes, Traefik Proxy 2.8 et comment le paramétrer pour qu'il fonctionne correctement avec CloudFlare en mode TLS Strict.
Préambule
Pour les besoins de l'article, j'ai déployé un cluster Kubernetes derrière un Load Balancer HaProxy. Ce point est une "contrainte" de mon infrastructure. Le trafic est donc transmis depuis Cloudflare au HaProxy pour être ensuite redirigé sur Traefik Proxy. J'utilise également MetalLB au sein de mon cluster Kubernetes dans le but d'exposer mes services sur mes différents nœuds.
Tutoriel
Avant de commencer, nous allons voir ensemble la configuration de Cloudflare. J'ai utilisé un compte gratuit pour réaliser le déploiement. Il faut faudra un enregistrement DNS proxied, un certificat Origin Server
. Pensez à bien enregistrer la clé et à télécharger le fichier PEM car nous en aurons besoin pour la suite.
Configuration Cloudflare
La configuration de CloudFlare est assez rapide malgré qu'il y ait beaucoup de paramètres. Je vais donc vous indiquer les principaux. J'ai activé, dans la rubrique SSL/TLS -> Edge Certificates
: Always Use HTTPS
, TLS 1.3
, Automatic HTTPS Rewrites
et la version minimum de TLS est 1.2.
Aussi, j'ai également activé le mode Full (strict)
dans la rubrique SSL/TLS -> Overview
Installation de Traefik
Pour installer simplement Traefik dans Kubernetes, nous allons utiliser Helm. Si ce n'est pas déjà fait, il faut ajouter le chart Traefik
dans Helm, puis nous allons mettre à jour la base de données de Helm :
helm repo add traefik https://helm.traefik.io/traefik
helm repo update
Nous allons installer Traefik, dans le namespace default
en utilisant la commande ci-dessous :
helm install traefik traefik/traefik
Si vous souhaitez déployer Traefik dans un namespace spécifique, il faut ajouter --namespace=traefik --create-namespace
:
helm install traefik traefik/traefik --namespace=traefik --create-namespace
Pour contrôler que l'installation a réussie, vous pouvez lancer la commande kubectl get deploy -n traefik
. Vous devriez avoir le résultat suivant :
NAME READY UP-TO-DATE AVAILABLE AGE
traefik 1/1 1 1 2m
Vous pouvez ajouter l'option -o wide
pour obtenir plus de détail :
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
traefik 1/1 1 1 2m traefik traefik:2.8.0 app.kubernetes.io/instance=traefik,app.kubernetes.io/name=traefik
Activation du dashboard
Par défaut, le dashboard n'est pas actif. Vous pouvez activer le dashboard en déployant une IngressRoute
:
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: dashboard
namespace: traefik
spec:
entryPoints:
- web
routes:
- match: (PathPrefix(`/dashboard`) || PathPrefix(`/api`))
kind: Rule
services:
- name: api@internal
kind: TraefikService
Une fois déployé, avec la commande kubectl apply -f dashboard.yaml
. Avant d'accéder au dashboard, il faut, avec la commande ci-dessous, récupérer l'adresse IP fournie par MetalLb et utilisée par Traefik :
kubectl get svc -n traefik
De mon côté, l'adresse IP est 172.16.0.1. Vous pouvez ouvrir votre navigateur et afficher le dashboard en ouvrant la page http://172.16.0.1/dashboard/
. Le caractère /
est très important à la fin, sans cela, vous aurez une page affichant 404 page not found
.
Déploiement de Nginx
Pour les besoins du test, nous allons déployer Nginx dans un namespace spécifique et avec un service de type ClusterIP, pur ce faire, créer un fichier nommé nginx.yaml
et coller le contenu ci-dessous :
apiVersion: v1
kind: Namespace
metadata:
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: nginx
spec:
selector:
matchLabels:
app: nginx
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: nginx
spec:
type: ClusterIP
selector:
app: nginx
ports:
- protocol: TCP
port: 80
Puis, lancer la commande pour le déploiement :
kubectl apply -f nginx.yaml
Maintenant que nous avons déployé Traefik Proxy et Nginx, nous avons besoin de déployer une IngressRoute dans le but de router le trafic en direction du déploiement Nginx depuis Traefik et suivant un host défini, pour cela, nous allons ajouter le contenu ci-dessous dans le fichier ingress-nginx.yaml
que nous allons créer :
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress-http
namespace: nginx
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web
spec:
rules:
- host: <votre-nom-de-domaine>
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80
Dans ce fichier, nous définissons une annotation pour indiquer le point d'entrée que Traefik devra utiliser pour l'Ingress Route. Puis, dans le bloc spec
, on indique le nom de domaine à utiliser ainsi que le service, puis le port du service.
Veillez bien à modifier la valeur de <votre-nom-de-domaine>
avant de déployer.
Pour vérifier, vous pouvez tester le bon fonctionnement du déploiement à l'aide de la commande curl :
curl -I -H "Host: <votre-nom-de-domaine>" http://<ip-de-traefik>/
Vous devriez avoir une réponse avec un code 200.
Configuration de Haproxy
Comme je l'ai indiqué au début de l'article, j'utilise HaProxy comme point d'entrée de mon infrastructure. Je dois donc paramétrer Haproxy pour qu'il puisse router le trafic venant de CloudFlare vers Traefik.
Avant de paramétrer Haproxy, nous allons modifier la configuration de Traefik afin d'activer le healthcheck. Ceci permettra à Haproxy de réaliser un httpcheck
sur Traefik. Nous allons créer un fichier values.yaml
avec le contenu ci-dessous :
ports:
traefik:
healthchecksPort: 9000
expose: true
La configuration est très simple, nous actions le healthcheck sur le port 9000 et nous exposons le port 9000 de Traefik. Pour déployer la configuration avec Helm sans avoir à désinstaller Traefik, il suffit de lancer la commande ci-dessous :
helm upgrade traefik traefik/traefik -f values.yaml
Lorsque vous souhaitez déployer Traefik avec la bonne configuration, vous devez lancer :
helm install --values=values.yaml traefik traefik/traefik
Si vous souhaitez connaître l'ensemble des valeurs que l'on peut configurer, vous pouvez lancer la commande :
helm show values traefik/traefik
Maintenant que le healthcheck est activé, nous allons remplacer le certificat par défaut de Traefik par le certificat Origin Server
de Cloudflare. Tout d'abord, nous devons créer un secret Kubernetes avec le certificat de Cloudflare :
kubectl create secret generic default-certificate --from-file=tls.crt=cert.pem --from-file=tls.key=cert.key -n kube-system
En exécutant cette commande, nous créeons un secret nommé default-certificate
comprenant les entrées tls.crt
et tls.key
dans le namespace kube-system
avec les valeurs du certificat Cloudflare. Nous allons terminer cette partie avec la création du fichier certificate.yaml
pour indiquer à Traefik le certificat à utiliser par défaut :
apiVersion: traefik.containo.us/v1alpha1
kind: TLSStore
metadata:
name: default
namespace: kube-system
spec:
defaultCertificate:
secretName: default-certificate
Pour déployer cette configuration, lancer la commande :
kubectl apply -f certificate.yaml
Passons désormais à la configuration de Haproxy, nous devons définir un frontend ainsi qu'un backend dans le fichier de configuration, voici ce que j'utilise :
frontend https_frontend
mode http
bind *:443 transparent ssl crt <chemin-vers-votre-certificat-origin-de-cloudflare> verify none
acl kubernetes_acl hdr_dom(host) -i <votre-nom-de-domaine>
use_backend kubernetes_backend if kubernetes_acl
backend kubernetes_backend
mode http
option forwardfor
option httpchk GET /ping
http-check expect status 200
server s1 <ip-de-traefik>:80 check port 9000
Dans ce bloc d'instructions, vous devez modifier 3 variables :
<chemin-vers-votre-certificat-origin-de-cloudflare>
<votre-nom-de-domaine>
<ip-de-traefik>
Concernant la première variable <chemin-vers-votre-certificat-origin-de-cloudflare>
, il faut vous assurer que le certificat Cloudflare est bien présent dans votre machine Haproxy, sans cela, vous aurez une erreur 525 qui sera renvoyée par Cloudflare lorsque vous souhaiterez accéder à votre page web depuis un navigateur. Autre précision, avec Cloudflare, vous ne pouvez pas faire du TLS Strict avec plusieurs niveaux de sous-domaines, vous devez utiliser un seul niveau, par exemple : nginx.kubernetes.domaine.com
ne fonctionnera pas à l'inverse de nginx-kubernetes.domaine.com
qui lui fonctionnera correctement.
Une fois déployé, Haproxy réalisera un healthcheck sur /ping
et sur le port 9000 de Traefik.
Résultat
Vous pouvez visualiser la page en lançant votre navigateur à l'adresse : https://votre-nom-de-domaine
. Vous devriez avoir une page HTML en HTTPS avec un certificat valide.