Kubernetes sur BareMetal

de | novembre 6, 2020

J’ai récemment eu à installer un Cluster Kubernetes sur une grappe de VM managées sur OpenStack. Le OpenStack en question n’avait aucune capacité particulière activée pour le support de Kubernetes. J’étais donc comme sur un environnement BareMetal.

K8s dans le cloud

La documentation d’installation de Kubernetes et les différents tutoriels que j’ai pu trouver sur le net partent toujours du principe que le cluster est déployé dans un Cloud type AWS ou GCP. La différence entre ces plateformes et une installation BareMetal est la présence d’un LoadBalancer capable de dialoguer avec notre cluster K8s pour attribuer dynamiquement des IPs aux services de type LoadBalancer.

Sur ce magnifique schéma, on peut voir que nous avons un service de type LoadBalancer comme porte d’entrée de notre cluster K8s. C’est ce service qui va récupérer une IP externe depuis le NetworkLoadBalancer (NLB) de la plateforme. Pour faire des économies, les adresses IPs n’étant pas gratuites, on va mettre un IngressController qui n’est autre qu’un reverse proxy pour K8s. Cet IngressController va ensuite se servir des Ingress pour router les flux vers les bons services.

Problème

Sur du BareMetal si on applique cette configuration cela donne ça :

La conséquence, outre le problème de stockage que nous verrons plus tard, est l’impossibilité pour notre service de type LoadBalancer d’obtenir une IP. Son statut restera indéfiniment à « pending ». Par la même occasion l’ensemble de notre cluster sera indisponible depuis internet.

Solution 1 : NodePort

La première solution que vous trouverez partout sur internet, car la plus simple à mettre en oeuvre, est d’utiliser des services de type NodePort. Ces services ont la particularité d’exposer les pods qu’ils gèrent directement sur l’IP externe du cluster sur une plage de port comprise entre 30000 et 32767.

Cependant cette solution à plusieurs gros inconvénients:

  • Vos services sont accessibles directement sur le net. Pas de possibilité de filtrage par reverse-proxy.
  • Des ports par vraiment sexy à ajouter à la fin de votre IP/nom de domaine
  • Une fois un port attribué, il est attribué sur l’ensemble des nœuds du cluster. Deux services ne pourront pas utiliser le même port même si chacun des services n’exposent qu’un seul pod sur un cluster de plusieurs noeuds.

Solution 2 : MetalLB

MetalLB est une solution développée par Google, pour permettre à une installation BareMetal de fonctionner comme une plateforme Cloud. C’est en quelque sorte une implémentation d’un NLB déployable sur K8s.

Cette solution à pour avantage de corriger effectivement le problème de l’absence de NLB. Cependant pour fonctionner MetalLB doit avoir un pool d’adresses IPs externes disponibles pour attribution. MetalLB utilise soit le mode Layer 2 ou BGP pour négocier l’attribution d’adresses IPs.

Si comme moi vous êtes sur un OpenStack où l’attribution d’un pool d’IP n’est pas possible, cela ne fonctionnera pas.

Solution 3 : Reverse Proxy Externe

La troisième solution vous permet de vous abstraire de la plateforme sur laquelle est déployé le cluster. La seule chose nécessaire est une unique adresse IP externe. C’est cette solution que j’ai mis en place.

Cette solution est aussi la plus complexe à mettre en œuvre. Elle repose sur un système de double reverse proxy. Le premier sur le noeud master du cluster sur lequel pointe l’IP externe est chargé de rediriger le flux HTTP/TCP sur le service de type ClusterIP de l’IngressController. Ce service est accessible, car il dispose d’une IP locale au réseau de VM du cluster.

Le second Reverse proxy est chargé de rediriger le flux vers les différents services en fonction du nom de domaine ou d’autres règles propre au cluster et définies dans les Ingress.

L’avantage par rapport à la solution NodePort est que les flux peuvent être contrôlés par un reverse proxy avant d’atteindre les pods. De plus chaque pod peut déclarer le port qui lui convient. Les services faisant dynamiquement le mapping port-pod <=> port-cluster.

Il reste néanmoins un point à soulever. Que se passe-t-il en cas de redémarrage du Service du IngressController? Son adresse IP locale risque fort de changer et dans ce cas le reverse proxy ne pourra plus rediriger le flux HTTP/TCP vers le cluster. Autrement dit, l’accès au cluster sera interrompu. Une solution pour cela est de créer un script se positionnant en écoute de l’API Kubernetes pour détecter ce changement d’IP et modifier la configuration du reverse proxy en conséquence.

[EDIT] : Après plusieurs redémarrages du cluster, il semble que l’adressage IP soit conservé. Cela est certainement sauvegardé dans la base etcd du cluster.

Solution de stockage.

Reste maintenant la solution de stockage. Si vous avez de la chance, vous avez à disposition une solution fournie par la plateforme. Pour OpenStack c’est Cinder. Malheureusement, je n’ai pas eu cette chance. Pour palier à cela et fournir un stockage persistant à mes pods, j’ai choisi de monter un disque NFS sur le Noeud Master de cette manière :

Mon stockage NFS est ainsi accessible à l’ensemble de mes pods. Un provider dynamique pour NFS est disponible permettant l’attribution à la volée d’un espace de stockage aux pods qui en ont le besoin.

Conclusion

Avec la solution 3, j’ai maintenant une solution BareMetal fonctionnelle. Le regret est d’avoir perdu beaucoup de temps pour la mettre en place. La documentation officiel de K8s ne mettant pas assez en avant cette problématique à mon sens.

00

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.