Pour finaliser le cluster Kubernetes, nous allons y déployer un Ingress Controller.
De base, K8S propose l’objet Ingress dont le rôle est de gérer les accès externes aux services hébergés au sein du cluster. Il définit les règles de routage pour diriger le trafic vers les services appropriés en fonction du chemin de l’URL appelée ou d’autres paramètres.
L’Ingress Controller va permettre la surveillance de ces objets et va les exploiter pour fournir un service de reverse proxy.
Il existe plusieurs Ingress Controller, chacun apportant son lot de fonctionnalités. On peut citer NGINX, ou encore HAProxy que nous utilisons déjà en tant que load balancer externe.
Pour cet article, c’est Traefik que l’on va retenir.
Conçu par Émile Vaugue, fondateur de la société française "Containous" devenu "Traefik Labs", le projet a été initié en 2015 pour répondre aux besoins de gestion du trafic dans des environnements dynamiques, notamment les conteneurs.
Disponible dans une version gratuite et à l’heure de cet article dans sa troisième version, Traefik connait une adoption grandissante et s’intègre parfaitement dans une architecture Kubernetes.
Traefik se déploie sous forme de conteneurs directement sur le cluster Kubernetes.
Il est important de rappeler que dans notre cas, nous allons avoir besoin de déployer deux instances constituées de plusieurs itérations de Traefik. Une dédiée aux applications exposées dans le LAN, l’autre pour les applications exposées en DMZ.
En effet, l’architecture que je vous propose exploite les capacités de segmentation logique d’un cluster Kubernetes pour héberger au sein d’un même cluster des applications destinées à être accessibles à travers deux zones réseau.
N’oubliez pas qu’on n’a précédemment déployé deux serveurs HAproxy externes, le premier prdk8snlb501 configuré pour renvoyer vers les control planes, et prdk8snlb511 configuré pour renvoyer vers les nodes en DMZ.
Comme K8S autorise plusieurs class d’Ingress Controller, nous allons tous simplement installer une classe traefik-lan et une classe traefik-dmz.
Chacune de ces classes dispose de son propre compte de service.
C’est ainsi que Traefik dialogue avec l’API de K8S , surveille les objets Ingress provisionnés et applique les règles de routage en conséquence.
Cliquez sur l'image pour l'agrandir.
Enfin, il est important de noter que si Traefik peut se contenter des objets Ingress basiques, il fournit également ses propres objets qu’il est possible d’installer ou pas.
Ces objets additionnels étendent l’API Kubernetes et permettent à Traefik de proposer des fonctions supplémentaires, comme la réécriture d’URL ou la protection d’accès par mot de passe.
S’il est souvent conseillé de rester au plus proche des objets natifs de l’API, pour s’assurer une réversibilité maximum, nous aurons également à traiter avec les objets Traefik pour certains besoins.
Avant de démarrer, on s’assure toujours de la santé du cluster avec la commande:
kubectl get pod
Cliquez sur l'image pour l'agrandir.
Si tous les nœuds sont opérationnels, on peut poursuivre.
En prérequis, nous allons labéliser nos control plane avec l’étiquette traefik-lan=yes. Ceci afin de permettre le déploiement des pods Traefiks dédié au LAN automatiquement et seulement sur ces deniers.
kubectl label nodes prdk8sctp501 traefik-lan=yes
kubectl label nodes prdk8sctp502 traefik-lan=yes
kubectl label nodes prdk8sctp503 traefik-lan=yes
Cliquez sur l'image pour l'agrandir.
Il est d’usage de ne pas donner plus de rôle qu’ils n’ont déjà dans un cluster aux Control Plane.
Mais pour une petite infrastructure comme la mienne, ne pas optimiser les ressources attribuées à ces nodes serait dommage.
Comme affiché lors de la définition de l’architecture, les control plane serviront également de points d’entrée pour l’instance Traefik en LAN (et pas en DMZ bien sûr).
On poursuit avec la déclaration d’un namespace dédié.
kubectl create ns inf-traefik-lan
Cliquez sur l'image pour l'agrandir.
Puis on y inscrit le compte de service réservé à cette instance de Traefik.
Pour cela on se place dans le dossier ~/kub.coolcorp.priv/traefik du premier control plane créé lors du lancement du playbook Ansible et dans lequel ont été provisionnés tous les fichiers de configuration de Traefik.
Cliquez sur l'image pour l'agrandir.
Le compte de service est décrit dans le fichier svc-traefik-lan.yaml:
apiVersion: v1
kind: ServiceAccount
metadata:
name: "svc-prd-traefik"
namespace: "inf-traefik-lan"
C’est très basique, on n’a besoin de préciser que très peu de choses en dehors du nom du compte de service svc-prd-traefik.
On applique le compte avec la commande:
kubectl apply -f svc-traefik-lan.yaml
Cliquez sur l'image pour l'agrandir.
Ensuite, on enregistre le repo Helm de Traefik, puisque c’est de de cette manière qu’on va installer le produit.
Pour rappel Helm est un gestionnaire de package pour Kubernetes, on n’a déployé le binaire Helm automatiquement avec Ansible.
Les commandes à passer sont les suivantes:
helm repo add traefik https://helm.traefik.io/traefik
helm repo update
Cliquez sur l'image pour l'agrandir.
C’est maintenant que l’on procède à l’installation de l’instance Traefik du LAN avec la commande:
helm install --namespace=inf-traefik-lan traefik-lan traefik/traefik -f traefik-config-lan.yaml --set nodeSelector.traefik-lan=yes --set tolerations[0].key=node-role.kubernetes.io/control-plane --set tolerations[0].operator=Exists --set tolerations[0].effect=NoSchedule
Cliquez sur l'image pour l'agrandir.
La commande permet de préciser le namespace et le fichier de configuration traefik-config-lan.yaml à utiliser pour surcharger les paramètres par défaut.
Le reste des arguments permet le déploiement sur les control plane. L’usage du label n’est pas suffisant, car par défaut les control plane sont marqués avec certaines caractéristiques qui vont devoir être tolérées par les pods pour s’exécuter sur les serveurs associés.
Le contenu du fichier traefik-config-lan.yaml est le suivant:
image:
name: traefik
tag: "3.0.1"
pullPolicy: IfNotPresent
deployment:
enabled: true
kind: DaemonSet
labels:
network: lan
podLabels:
network: lan
providers:
kubernetesIngress:
labelSelector: network=lan
kubernetesCRD:
enabled: true
allowCrossNamespace: false
allowExternalNameServices: false
allowEmptyServices: false
namespaces:
- inf-traefik-lan
serviceAccount:
name: "svc-prd-traefik"
logs:
level: ERROR
hostNetwork: true
ports:
web:
port: 80
ports.web.redirectTo.port: websecure
websecure:
port: 443
securityContext:
capabilities:
drop: [ALL]
add: [NET_BIND_SERVICE]
readOnlyRootFilesystem: true
runAsGroup: 0
runAsNonRoot: false
runAsUser: 0
updateStrategy:
rollingUpdate:
maxSurge: 0
maxUnavailable: 1
type: RollingUpdate
additionalArguments:
- "--providers.kubernetesingress.ingressclass=traefik-lan"
- "--serversTransport.insecureSkipVerify=true"
Rappelez vous que son contenu a été généré depuis un template via Ansible.
Je ne vais pas détailler chaque ligne, mais certains points sont importants à comprendre.
tag: "3.0.1"
: C’est la version de Traefik à déployerkind: DaemonSet
: Un DeamonSet est un type de Deployment spécifique. Cela correspond pour le cluster à exécuter une instance d’un pod sur chaque node qui répond aux caractéristiques demandées. Dans notre cas, un control plane. Cela permet d’ajouter automatiquement un pod Traefik sur un nouveau control plane qui serait ajouté au cluster par la suite.labelSelector: network=lan
: C’est ici qu’on indique à traefik de considérer tout objet de type Ingress qui sera labélisé network=lan. Si ce n’est pas le cas, il l’ignorera.kubernetesCRD: enabled: true
: CRD pour Custom Ressource Definition. On active l’usage des objets additionnels de Traefik en demandant à les inscrire dans l’API K8S.name: "svc-prd-traefik"
: Le nom du compte de service à utiliser que l'on a déployé précédemment.hostNetwork: true
: Indique qu’on va mapper Traefik au réseau du serveur. Les pods Traefik sont effectivement, hors exceptions, les seuls pod à pouvoir être exposés directement à travers les ports du serveur.
ports:
web:
port: 80
ports.web.redirectTo.port: websecure
websecure:
port: 443
Ces lignes sont importantes. Elles définissent tous les points d’entrée sur lesquels Traefik doit écouter. Ici le point web sur le port 80 et le point websecure sur le port 443. On n’en profite pour mettre une redirection automatique du port 80 vers le port 443 via l’option ports.web.redirectTo.port: websecure
Taefik n’est pas limité au port HTTP et HTTPS, il peut également travailler sur des ports plus exotiques et sur la couche trois du modèle OSI. On peut donc ajouter autant de ports que l’on souhaite et les nommer à notre convenance (web et websecure ont été choisis de manière totalement arbitraire, mais c’est souvent ainsi que vous les retrouverez dans les exemples Traefik)
- "--providers.kubernetesingress.ingressclass=traefik-lan"
: Permet de nommer la classe d’Ingress Controller rattachée à cette instance Traefik.Si tout va bien, on peut vérifier le statut du déploiement avec la commande:
kubectl get pod -n inf-traefik-lan -o wide
Cliquez sur l'image pour l'agrandir.
Chaque control plane dispose d’un pod Traefik (déploiement via DaemonSet).
Avant de passer à la DMZ, on va ajouter à Traefik la capacité d’exposer un dashboard de suivi.
C’est une option bien pratique. Le dashboard ne permet aucune action, mais affiche le statut de Traefik et surtout décrit le routage proposé par ce dernier.
Pour des raisons de sécurité, on va souhaiter protéger l’accès au dashboard par un mot de passe. Ce qui va nous permettre d’exploiter un premier objet custom de Traefik : le Middelware.
celui-ci va se baser sur un objet Secret contenant un login/mot de passe au format apache pour demander une authentification avant l’affichage de la page.
Vous pouvez utiliser l’outil htpasswd pour générer le nom d’utilisateur et le password.
Par exemple en passant par votre instance WSL et votre terminal Windows.
Sinon il existe des sites en ligne pour cela (mais attention ce n’est jamais bon d’utiliser un site web pour générer des password critiques…sans être parano, vous n’êtes jamais certains de l’usage qui en ai fait derrière).
La commande de l’outil est:
htpasswd -Bbn vote_login votre_password
Cliquez sur l'image pour l'agrandir.
Il suffit de placer le contenu de la sortie de cette commande dans un fichier sec-traefik-dashboard-lan-password au niveau du premier control plane.
Cliquez sur l'image pour l'agrandir.
Puis de lancer la commande suivante pour générer un Secret à partir du fichier.
kubectl create secret generic sec-traefik-dashboard-lan-password --from-file=traefik-dashboard-lan-password --namespace inf-traefik-lan
Cliquez sur l'image pour l'agrandir.
Il est conseillé de supprimer le fichier ensuite.
Le dashboard étant accessible via HTTPS, il est également nécessaire de lui associer un certificat.
Plusieurs démarches sont possibles, et tout va dépendre de ce que vous avez à disposition pour générer des certificats.
Me concernant, j’ai ma propre PKI interne (sous Windows) intégrée à mon domaine, qui me permet de générer des certificats reconnus sur l’ensemble de mes devices internes.
Vous pouvez vous inspirer de ce que je propose et l’adapter à vos usages, l’idée n’étant pas ici de faire un tutoriel sur les certificats.
Mais dans l’ensemble j’utilise la logique standard:
Depuis mon instance WSL sur mon poste de travail, je génère ma clef privée (sur 4096 bits) et ma demande de certificat (un csr), à l’aide de openssl.
openssl req -new -nodes -sha256 -keyout traefik-k8s-lan.coolcorp.priv.key -out traefik-k8s-lan.coolcorp.priv.csr -newkey rsa:4096 -subj "/C=FR/ST=Ile-de-France/L=Paris/O=OFI/OU=Infrastructure/CN=traefik-k8s-lan.coolcorp.priv" -reqexts SAN -config <(printf "[req]\ndistinguished_name = req_distinguished_name\n[req_distinguished_name]\n[SAN]\nsubjectAltName=DNS:traefik-k8s-lan.coolcorp.priv")
Cliquez sur l'image pour l'agrandir.
Cliquez sur l'image pour l'agrandir.
Je copie mon csr sur ma PKI et je demande à cette dernière l’obtention d’un certificat calqué sur un template TPL-SRV-WEB-DEFAULT (regroupe les caractéristiques d’un certificat utilisé par un service web)
Cliquez sur l'image pour l'agrandir.
certreq -attrib "CertificateTemplate:TPL-SRV-WEB-DEFAULT" -submit traefik-k8s-lan.coolcorp.priv.csr
Cliquez sur l'image pour l'agrandir.
J’obtiens à la fin un certificat et une clef privée.
Cliquez sur l'image pour l'agrandir.
Ces deux composants vont être copiés sur le premier control plane (leur contenu est copiable sans difficulté, c’est du texte).
Cliquez sur l'image pour l'agrandir.
Cliquez sur l'image pour l'agrandir.
Ces deux fichiers vont servir à créer un autre Secret.
kubectl create secret generic sec-certif-traefik-k8s-lan --from-file=tls.crt=traefik-k8s-lan.coolcorp.priv.cer --from-file=tls.key=traefik-k8s-lan.coolcorp.priv.key --namespace inf-traefik-lan
Cliquez sur l'image pour l'agrandir.
Maintenant qu’on dispose d’un secret sec-traefik-dashboard-lan-password contenant les informations d’authentification pour l’accès au dashboardet d’un secret sec-certif-traefik-k8s-lan pour le certificat, on peut lancer la commande suivante:
kubectl apply -f traefik-lan-dashboard.yaml
Cliquez sur l'image pour l'agrandir.
On se base sur le fichier traefik-lan-dashboard.yaml dont le contenu est le suivant:
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: traefik-lan-dashboard
namespace: "inf-traefik-lan"
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`traefik-k8s-lan.coolcorp.priv`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))
services:
- name: api@internal
kind: TraefikService
middlewares:
- name: traefik-dashboard-lan-auth # Referencing the BasicAuth middleware
namespace: inf-traefik-lan
tls:
secretName: sec-certif-traefik-k8s-lan
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: traefik-dashboard-lan-auth
namespace: inf-traefik-lan
spec:
basicAuth:
secret: sec-traefik-dashboard-lan-password
On y retrouve deux objets. Tous les deux propres à Traefik et ajoutés à l’API K8S dans la branche traefik.io/v1alpha1
Le premier est nommé IngressRoute. C’est un peu un Ingress amélioré. On y’ retrouve le point d’entrée attendu (websecure) et l’URL associée (traefik-k8s-lan.coolcorp.priv) avec l’obligation d’y ajouter le préfix /api ou /dashboard.
Si une requête venant de l’extérieur répond à ces règles, alors elle sera redirigée vers un service interne à Traefik api@internal, soit le dashboard.
On n’y trouve également la référence au middleware pour l’accès sécurisé ainsi qu’au secret sec-certif-traefik-k8s-lan dans la section TLS pour l’association du certificat.
Le second objet est le fameux Middleware lui-même référencé dans l’objet précédent. Il prend simplement comme entrée le secret contenant le login/password.
Si on résume, lorsqu’on va taper https://traefik-k8s-lan.coolcorp.priv/dashboard/ on va arriver sur l’entrée websecure, et l’URL va matcher avec la règle de routage.
Traefik va y appliquer le certificat contenu dans le secret sec-certif-traefik-k8s-lan, mais avant d’exposer le dashboard, il va d’abord faire appel au Middleware qui lui, va demander une authentification.
Si l’authentification correspond aux informations de connexion présente dans le secret sec-traefik-dashboard-lan-password, alors, la requête est redirigée vers le service api@internal.
Voyons si cela se produit réellement. Bien entendu avant, il faudra s’assurer d’avoir un alias DNS qui renvoie le nom traefik-k8s-lan.coolcorp.priv vers le loabalancer HAProxy du LAN (prdk8snlb501), qui lui-même relayera vers l’un ou l’autre des control plane pour être ensuite intercepté par l’instance Traefik qui s’y exécute.
Cliquez sur l'image pour l'agrandir.
Pour rappel HAproxy a été configuré lors d'une étape précédente
On n’a bien un prompt d’authentification, et lorsque qu’on rentre le bon login et le bon password, on n’arrive bien sur le dashboard Traefik.
Cliquez sur l'image pour l'agrandir.
Cliquez sur l'image pour l'agrandir.
Si on descend un peu dans l’affichage, on retrouve bien l’activation des CRD dans la liste des providers, en plus des objets Ingress natif (KubernetesIngress). Traefik va donc pouvoir s'appuyer sur les deux types d'objets, natifs et custom pour gérer le routage. On n’aura l’occasion de parcourir davantage ce dashboard un peu plus loin dans l’article.
Cliquez sur l'image pour l'agrandir.
Concernant l’installation de l’instance en DMZ, on va répéter exactement les mêmes opérations. Je ne vais pas donc forcément redonner le même niveau de détail.
On démarre de la même manière, à savoir labéliser les nodes qui exécuteront les pods traefik.
Je vous invite à revoir la définition de l’infrastructure, mais pour la DMZ ce sont les deux workers qui y sont présents qui vont avoir cette charge.
On les labélise donc de la manière suivante
kubectl label nodes prdk8snod511 traefik-dmz=yes
kubectl label nodes prdk8snod512 traefik-dmz=yes
Cliquez sur l'image pour l'agrandir.
Puis on créer le namespace dédié
kubectl create ns inf-traefik-dmz
Cliquez sur l'image pour l'agrandir.
Toujours sur le premier control plane dans le dossier ~/kub.coolcorp.priv/traefik on trouve le fichier svc-traefik-dmz.yaml généré durant le playbook Ansible.
Son contenu est le suivant:
apiVersion: v1
kind: ServiceAccount
metadata:
name: "svc-prd-traefik-dmz"
namespace: "inf-traefik-dmz"
Comme pour le LAN, Traefik va utiliser un compte de service, mais différent de celui créé précédemment.
On applique le yaml avec la commande suivante:
kubectl apply -f svc-traefik-dmz.yaml
Cliquez sur l'image pour l'agrandir.
On passe à l’installation de Traefik, toujours via Helm. Les repos étant déjà ajoutés, il faut utiliser la commande suivante:
helm install --namespace=inf-traefik-dmz traefik-dmz traefik/traefik -f traefik-config-dmz.yaml --set nodeSelector.traefik-dmz=yes --set tolerations[0].key=node-role.kubernetes.io/worker-dmz --set tolerations[0].operator=Exists --set tolerations[0].effect=NoSchedule
Cliquez sur l'image pour l'agrandir.
On joue sur la notion de label, pour faire en sorte que cette fois-ci les pods ne s’exécutent plus sur les control plane, mais bien sûr les workers en DMZ.
Le fichier de configuration utilisé pour surcharger les paramètres, et créer via un template au moment de l’exécution d’Ansible, est pratiquement identique à celui utilisé pour le LAN.
image:
name: traefik
tag: "3.0.1"
pullPolicy: IfNotPresent
deployment:
enabled: true
kind: DaemonSet
labels:
network: dmz
podLabels:
network: dmz
providers:
kubernetesIngress:
labelSelector: network=dmz
kubernetesCRD:
enabled: true
allowCrossNamespace: false
allowExternalNameServices: false
allowEmptyServices: false
namespaces:
- inf-traefik-dmz
serviceAccount:
name: "svc-prd-traefik-dmz"
logs:
level: ERROR
hostNetwork: true
ports:
web:
port: 80
ports.web.redirectTo.port: websecure
websecure:
port: 443
securityContext:
capabilities:
drop: [ALL]
add: [NET_BIND_SERVICE]
readOnlyRootFilesystem: true
runAsGroup: 0
runAsNonRoot: false
runAsUser: 0
updateStrategy:
rollingUpdate:
maxSurge: 0
maxUnavailable: 1
type: RollingUpdate
additionalArguments:
- "--providers.kubernetesingress.ingressclass=traefik-dmz"
- "--serversTransport.insecureSkipVerify=true"
Hormis le namespace d’exécution, le nom du compte de service utilisé et l’usage du mot clef « dmz » pour définir à la fois la classe de l’Ingress Controller et le label des Ingress à contrôler, c’est exactement la même logique que pour le LAN.
On peut vérifier l’installation via la commande suivante:
kubectl get pod -n inf-traefik-dmz -o wide
Cliquez sur l'image pour l'agrandir.
Cette fois-ci les pod Traefik sont bien déployés sur les worker en DMZ.
Toujours dans la même logique que précédemment, on va déployer le dashboard.
On commence donc par créer une combinaison login/password avec la commande htpasswd qu’on pourra retrouver sur son installation WSL.
htpasswd -Bbn votre_login votre_password
Cliquez sur l'image pour l'agrandir.
On exploite la sortie de la commande pour la recopier sur le premier control plane dans un fichier nommé traefik-dashboard-dmz-password
Cliquez sur l'image pour l'agrandir.
Puis on génère le secret à partir de ce fichier via la commande:
kubectl create secret generic sec-traefik-dashboard-dmz-password --from-file=traefik-dashboard-dmz-password --namespace inf-traefik-dmz
Cliquez sur l'image pour l'agrandir.
Un nouveau certificat est nécessaire et on rejoue donc la logique de création de clef, de génération d’un CSR et de l’obtention d’un certificat auprès d’une PKI.
openssl req -new -nodes -sha256 -keyout traefik-k8s-dmz.coolcorp.priv.key -out traefik-k8s-dmz.coolcorp.priv.csr -newkey rsa:4096 -subj "/C=FR/ST=Ile-de-France/L=Paris/O=OFI/OU=Infrastructure/CN=traefik-k8s-dmz.coolcorp.priv" -reqexts SAN -config <(printf "[req]\ndistinguished_name = req_distinguished_name\n[req_distinguished_name]\n[SAN]\nsubjectAltName=DNS:traefik-k8s-dmz.coolcorp.priv")
Cliquez sur l'image pour l'agrandir.
certreq -attrib "CertificateTemplate:TPL-SRV-WEB-DEFAULT" -submit traefik-k8s-dmz.coolcorp.priv.csr
Cliquez sur l'image pour l'agrandir.
Cliquez sur l'image pour l'agrandir.
La clef privée et le certificat doivent être recopiés sur le premier control plane, puis à partir de ces deux fichiers on génère le secret sec-certif-traefik-k8s-dmz.
Cliquez sur l'image pour l'agrandir.
Cliquez sur l'image pour l'agrandir.
kubectl create secret generic sec-certif-traefik-k8s-dmz --from-file=tls.crt=traefik-k8s-dmz.coolcorp.priv.cer --from-file=tls.key=traefik-k8s-dmz.coolcorp.priv.key --namespace inf-traefik-dmz
Cliquez sur l'image pour l'agrandir.
Il ne reste plus qu’à jouer le yaml traefik-dmz-dashboard.yaml généré par Ansible dans ~/kub.coolcorp.priv/traefik sur le premier control plane pour déployer le dashboard.
kubectl apply -f traefik-dmz-dashboard.yaml
Cliquez sur l'image pour l'agrandir.
Le contenu est le suivant:
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dmz-dashboard
namespace: "inf-traefik-dmz"
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`traefik-k8s-dmz.coolcorp.priv`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))
services:
- name: api@internal
kind: TraefikService
middlewares:
- name: traefik-dashboard-dmz-auth # Referencing the BasicAuth middleware
namespace: inf-traefik-dmz
tls:
secretName: sec-certif-traefik-k8s-dmz
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: traefik-dashboard-dmz-auth
namespace: inf-traefik-dmz
spec:
basicAuth:
secret: sec-traefik-dashboard-dmz-password
Hormis les références à la DMZ plutôt qu’au LAN, le fichier est exactement le même que pour le LAN.
On peut tester l’accès au dashboard via l’URL https://traefik-k8s-dmz.coolcorp.priv/dashboard/.
Bien entendu, la aussi il faut un alias DNS correctement renseigné, mais qui cette fois ci va pointer l’IP du LoadBalancer HAProxy en DMZ prdk8snlb511 (paramétré dans une étape précédente pour renvoyer les requêtes vers l’un ou l’autre des nœuds en DMZ).
Cliquez sur l'image pour l'agrandir.
Comme pour le dashboard en LAN, on n'a d'abord un prompt d'authentification puis ensuite on n'accède au dashboard, mais cette fois-ci propre à l'instance traefik en DMZ.
Cliquez sur l'image pour l'agrandir.
Cliquez sur l'image pour l'agrandir.
Comme nous l’avons fait lors du déploiement de la couche de storage persistant via le CSI vSphere, nous allons tester le bon fonctionnement de nos opérations avec une application de test.
Toujours comme j’ai l’habitude de le faire, je créer un dossier du nom du namespace que je vais utiliser pour y stocker mes fichiers.
Cliquez sur l'image pour l'agrandir.
Je créer ce même namespace dev-demotraefik-lan de manière déclarative via la commande:
kubectl create ns dev-demotraefik-lan
Cliquez sur l'image pour l'agrandir.
Le premier fichier YAML est 01-deploy-demotraefik-front.yaml.
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-demotraefik-front
namespace: dev-demotraefik-lan
labels:
environment: dev
network: lan
application: demotraefik
spec:
strategy:
type: Recreate
selector:
matchLabels:
environment: dev
network: lan
application: demotraefik
template:
metadata:
labels:
environment: dev
network: lan
application: demotraefik
spec:
nodeSelector:
network: lan
containers:
- name: demo-nginx-traefik-lan
image: nginx:1.27
resources:
requests:
memory: "8Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: 1
livenessProbe:
initialDelaySeconds: 5
periodSeconds: 5
exec:
command:
- ls /usr/share/nginx/html
ports:
- containerPort: 80
Il permet la création d’un objet Deployment nommé deploy-demotraefik-front qui va lui-même s’occuper de déployer un pod demo-nginx-traefik-lan basé sur l’image nginx 1.27.
Le pod va donc contenir un seul conteneur qui écoute sur le port 80.
Une fois le fichier appliqué avec la commande:
kubectl apply -f 01-deploy-demotraefik-front.yaml
Cliquez sur l'image pour l'agrandir.
On peut vérifier que le déploiement est correcte avec la commande:
kubectl get pod -n dev-demotraefik-lan -o wide
Cliquez sur l'image pour l'agrandir.
On peut passer au second fichier 02-svc-demotraefik-front.yaml.
---
kind: Service
apiVersion: v1
metadata:
name: svc-demotraefik-front
namespace: dev-demotraefik-lan
labels:
environment: dev
network: lan
application: demotraefik
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
environment: dev
network: lan
application: demotraefik
C’est un objet Service qui y décrit. Je ne rentre pas dans le détail à ce niveau, mais cet objet va permettre d’exposer au sein du cluster, le pod créé précédemment, et donc le conteneur NGINX qui s’y trouve.
Pour cela le service relaye les requêtes qu’il reçoit sur le port 80, vers le port 80 de tout pod qui correspond au label contenu dans la section selector.
Si vous revenez sur le fichier précédent, vous verrez qu’il s’agit des labels positionnés sur le pod rattaché au Deployment.
On exécute la création du service avec la commande:
kubectl apply -f 02-svc-demotraefik-front.yaml
Cliquez sur l'image pour l'agrandir.
On controle que le service est bien créé avec la commande:
kubectl get svc -n dev-demotraefik-lan -o wide
Cliquez sur l'image pour l'agrandir.
Avant de passer au dernier fichier, on va d’avoir à nouveau générer un certificat. Notre but est de tester l’exposition du conteneur NGINX à l’extérieur du cluster via une URL de test. Il faut donc un certificat si l’on veut exposer l’application en HTTPS.
Je ne réexplique pas la logique, mais comme pour les dashboards en DMZ et en LAN, on génère une clef, avec un CSR, on soumet le CSR à une PKI et on récupère un certificat.
openssl req -new -nodes -sha256 -keyout demotraefik-lan.coolcorp.priv.key -out demotraefik-lan.coolcorp.priv.csr -newkey rsa:4096 -subj "/C=FR/ST=Ile-de-France/L=Paris/O=OFI/OU=Infrastructure/CN=demotraefik-lan.coolcorp.priv" -reqexts SAN -config <(printf "[req]\ndistinguished_name = req_distinguished_name\n[req_distinguished_name]\n[SAN]\nsubjectAltName=DNS:demotraefik-lan.coolcorp.priv")
Cliquez sur l'image pour l'agrandir.
certreq -attrib "CertificateTemplate:TPL-SRV-WEB-DEFAULT" -submit demotraefik-lan.coolcorp.priv.csr
Cliquez sur l'image pour l'agrandir.
La clef et le certificat sont copiés sur le premier control plane:
Cliquez sur l'image pour l'agrandir.
Cliquez sur l'image pour l'agrandir.
On génère le secret associé avec la commande:
kubectl create secret generic sec-certificate-demotraefik-lan --from-file=tls.crt=demotraefik-lan.coolcorp.priv.cer --from-file=tls.key=demotraefik-lan.coolcorp.priv.key --namespace dev-demotraefik-lan
Cliquez sur l'image pour l'agrandir.
On peut maintenant passer au dernier fichier, 03-ing-demotraefik-front.yaml.
Son contenu est le suivant:
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ing-nginxnfs-default
namespace: dev-demotraefik-lan
labels:
environment: dev
network: lan
application: demotraefik
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
ingressClassName: traefik-lan
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik-lan
tls:
- hosts:
- demotraefik-lan.coolcorp.priv
secretName: sec-certificate-demotraefik-lan
rules:
- host: demotraefik-lan.coolcorp.priv
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: svc-demotraefik-front
port:
number: 80
Contrairement aux dashboards Traefik, on n’utilise cette fois-ci un objet Ingress natif à l’API K8S.
En effet, il n’y a pas besoin de fonctions avancées comme précédemment et on ne redirige pas vers l’API interne de Traefik.
L’objet Ingress est donc suffisant.
C’est grâce à ce qui figure dans les annotations que Traefik va pouvoir savoir comment se comporter.
Pour le reste du fichier, on reste sur la définition d’un Ingress telle que décrite dans l’API Kubernetes.
On spécifie la classe d’Ingress Controller qu’on souhaite exploiter, ici traefik-lan.
Puis on donne l’URL rattachée, le service à utiliser ainsi que le port vers lequel renvoyer les requêtes.
Dans cet exemple, on n’a donc un Ingress ing-nginxnfs-default faisant appel à l’Ingress Controller traefik-lan qui va permettre de rediriger tous flux reçu avec l’URL demotraefik-lan.coolcorp.priv vers le port 80 du service svc-demotraefik-front en y appliquant le certificat contenu dans le secret sec-certificate-demotraefik-lan.
On applique la configuration avec la commande:
kubectl apply -f 03-ing-demotraefik-front.yaml
Cliquez sur l'image pour l'agrandir.
Comme toute objet K8S on veut vérifier le statut du déploiement de l'Ingress:
kubectl get ing -n dev-demotraefik-lan
Cliquez sur l'image pour l'agrandir.
Vérifions maintenant que le site est accessible. Pour cela, il faut qu’un alias DNS existe afin que l’URL de test renvoi vers l’IP du loadbalancer du LAN, afin que celui-ci relaye sur l’un ou l’autre des contrôles plane pour l’instance Traefik qui s’y trouve puisse traiter la demande.
Cliquez sur l'image pour l'agrandir.
Tentons un accès.
On n’a bien un certificat rattaché et reconnu.
Cliquez sur l'image pour l'agrandir.
Si maintenant on se connecte sur le dashboard Traefik de l’instance du LAN, on va pouvoir retrouver dans le menu HTTP, le détail de notre configuration.
Cliquez sur l'image pour l'agrandir.
Tout le chemin de routage est visible. La présence du bouclier indique qu’on n’est bien en TLS avec un certificat.
Cliquez sur l'image pour l'agrandir.
Cliquez sur l'image pour l'agrandir.
Notez que cet exemple tire parti du Traefik en LAN, mais on pourrait très bien appliquer la même chose pour la DMZ, il suffirait juste de changer les références à traefik-lan vers traefik-dmz .
On pourrait même se passer dans ce cas du certificat, car en DMZ, l’applicatif est accessible depuis le WEB.
Ce qui implique qu’on peut utiliser des services externes de demandes automatiques de certificat basésur le protocole ACME et supporté par Traefik, comme Let’s encrypt par exemple.
Dans ce cas, tout se fait automatiquement, mais nous verrons ce point dans un autre article quand nous détaillerons vraiment le déploiement d’une application. (Et finalement même en LAN, on pourrait arriver à ce niveau d’automatisation…mais on verra ça plus tard).
Nous voila arrivé à la fin de cet article. J’espère qu’il vous aura permis de comprendre comment déployer un Ingress Controller, principalement Traefik.
L’idée était aussi de vous montrer comment exploiter à la fois un objet Ingress classique et des objets customisés ajoutés à l’API K8S.
Encore une fois, rester au plus proche des objets de base est une bonne pratique, mais parfois, on n’est obligé d’étendre l’API pour bénéficier de fonctionnalités avancées.
À noter que les objets Ingress tendent à être remplacés par des objets Gateway qui peuvent reprendre des fonctions justement assurées par des objets custom de Traefik. À la date de cet article, je n’ai pas suffisamment d’expérience pour en parler davantage, mais je ne manquerais pas d’écrire sur le sujet une fois que j’en saurais un peu plus de mon côté.
Par contre on peut maintenant dire que le cluster est pleinement opérationnel et capable de répondre à de nombreux usages.
Il ne reste plus qu’à déployer une véritable application…mais ça, c’est pour l’article final de ce Cookbook. Mais avant, je vous propose de parler Certificat.