Exemple de définition d'architecture pour Kubernetes (v2)

Avant de se lancer tête baissée dans l’expérimentation, tentons de définir la cible et les briques techniques à mettre en oeuvre.

Schéma d'architecture K8S

Un bon schéma valant mieux qu’un grand discours, voici une rapide présentation de ce que je souhaiterais mettre en oeuvre.

Schéma de l'architecture kubernetes cible

Description des éléments

Traitement de la couche stockage

Je souhaiterais exploiter trois types de solutions:

Traitement de la couche compute

J’utiliserais deux serveurs ESXi 7.0U2 pour héberger la totalité des VMs nécessaires au lab. Il serait possible de se simplifier la vie via l'usage de la suite "Tanzu" de l'éditeur. VMWARE propose depuis plusieurs versions maintenant la création assistée d'un cluster Kubernetes sur sa plateforme de virtualisation afin d'offrir directement, depuis le vCenter, la possibilité de traiter aussi bien des VMs que des conteneurs. C'est une offre qui évolue rapidement et propose toujours plus d'intégration de Kubernetes au sein de l'écosystème vSphere. Il faut savoir que VMWARE s'implique assez fortement depuis quelques années maintenant dans le projet K8S et "Tanzu" reste une solution a étudier dans un cas de production, notamment pour le support associé et la simplification des déploiements/mises à jour que cela apporte. Malheureusement, "Tanzu" n'est pas gratuit et dans mon cas, je ne peux me permettre de l'utiliser. Heureusement, beaucoup d'éléments que VMWARE package dans sa suite "Tanzu" est également disponible en open source sur le git de l'éditeur. C'est forcément plus compliqué à mettre en oeuvre, mais ça à le mérite de laisser la possibilité de déployer soit même les briques d'intégration que propose Vmware pour kubernetes. J'adopterais donc une approche "Vanilla" de Kubernetes pour vmware, c'est à dire l'usage des add-ons vmware pour Kubernetes mais sur un cluster déployé indépendament des outils vmware. ( A noter que que je compte tous de meme utiliser un outil d'aide au déploiement du cluster "kubeadm")

Traitement de la couche network

Kubernetes fonctionne sous forme de "briques" qu'il faut assembler pour avoir un cluster fonctionnel. Les binaires de bases de K8S sont centrés sur l'orchestration des conteneurs. Pour les fonctionnalités tierces comme le moteur d'exécution des conteneurs, leur stockage ou leur communication entre eux, Kubernetes laisse le choix d'adopter les technologies de son choix. Ces briques annexes peuvent être confiées à des solutions tiers à partir du moment ou elles respectent un certain standard et se plient à des normes communes. Concernant le réseau, Kubernetes propose la spécification "CNI" pour "Container Network Interface". Différentes solutions ou "plugins" se basent sur "CNI" pour traiter la couche réseau au sein d'un cluster K8S. À chacun de choisir le plug-in qu'il souhaite fonction des caractéristiques qu'il propose : protocole de routage pris en charge, possibilité d'exploiter des politiques d'accès....Me concernant si pendant un temps, j'avais choisi "Calico", j'ai finalement porté mon choix sur "Antrea", mais nous évoquerons ce point plus tard.

Histoire d'avoir une architecture plus représentative de la réalité, je vais également essayer de dédier des noeuds de traitement à des applications en DMZ. j'avoue que sur ce point, j'ai du mal à me faire une idée. Sur le principe Kubernetes est censé offrir un cluster dans lequel on peut encapsuler toutes ses applications et gérer avec précision leur déploiement tout en contrôlant leur trafic avec différents niveaux d'isolation (sous condition qu'on les paramètre). Je vais donc pousser ce concept jusqu'au bout en mixant au sein d'un même cluster, des noeuds sur mon réseau interne et des noeuds en DMZ. Certains risquent de trouver cela dangereux, et préfèreraient certainement dédier un cluster pour le LAN et un cluster pour la DMZ. Je comprends parfaitement cette préférence, mais dans mon cas, je n'ai pas le luxe de pouvoir multiplier les VMs (nouveau cluster signifie nouveau master)

Traitement de la couche Kubernetes

À l'origine, dans la première version de mon cluster, j'étais parti sur l'usage d'Ubuntu 20.04. J'ai pu arriver à une solution pleinement opérationnelle, mais disposant de ressources limitées (2 ESXi seulement) je préférerais maintenant optimiser mon cluster en me basant sur la distribution vmware open source "PhotonOS". À l'image d'autres systèmes dédiés à l'exécution des conteneurs, "PhotonOS" propose une base minimaliste et donc à la fois moins gourmande en ressource et également plus sécurisée, car "nettoyée" des composants superflux pour le bon fonctionnement des conteneurs.  Étant donné qu'elle est proposée par Vmware elle dispose également d'un kernel optimisé pour tourner sur un ESXi (mais on peut très bien l'utiliser ailleurs, notamment sur RPI).

À l'heure de la rédaction de l'article, la version 4.0 de PhotonOS est disponible en GA, elle est donc très récente, mais je préfère partir sur la dernière release et m'assurer une certaine pérennité de ma plateforme. Pour la petite anectode, toutes les appliances vmware comme le vcenter par exemple, tournent désormais sous "PhotonOS".

Mon cluster Kubernetes sera composé dans un premier temps d'un noeud master, d'au moins 2 noeuds Worker sur le LAN et d'au moins 2 noeuds Worker en DMZ.

Les noeuds masters sont essentiels au bon fonctionnement du cluster. Ils vont héberger le serveur API sans lequel il est impossible d’interagir avec le cluster et de nombreux autres rôles critiques. Ils vont aussi stocker la base clef/valeur ETCD dans laquelle toute la configuration du cluster va être stockée. On voit beaucoup d’exemples où l’on exploite un seul master. C’est une très bonne chose pour se former ou pour traiter des environnements non critiques, mais sur des contraintes de production on ne peut se contenter que d’un seul master, car si celui-ci venait à tomber, on impacterait l'interaction avec le Cluster. Avoir un master indisponible ne rend pas les applications déjà en oeuvres sur le cluster inopérantes, par contre il n'y a plus d'orchestration et il devient impossible d'opérer son cluster.

C'est pourquoi, si dans une première phase je débuterais avec un seul master, une étape supplémentaire sera réalisée plus tard pour augmenter le nombre de masters. Cela permettra de décrire les opérations à réaliser pour cela, car si je me suis rendu compte qu'on trouve beaucoup d'aide pour ajouter un worker à son cluster, c'est moins le cas avec le master.

À savoir que deux masters n’est pas supporté pour offrir une solution de HA, car c’est insuffisant pour offrir un consensus  de l’état du cluster, un troisième master est obligatoire pour permettre à l’ensemble des masters de se mettre d’accord entre eux. Le petit schéma si dessous sera plus parlant.

Architecture HA Master K8S (https://kubernetes.io/docs/tasks/administer-cluster/highly-available-master/)

Je vous invite d'ailleur à prendre connaissance de l'article dont est tirée cette illustration et qui explique le principe de HA pour Kubernetes

Cas des applications tierces

L’une des difficultés que je rencontre avec Kubernetes, c’est la capacité à exposer les applications qui y sont hébergées à l’extérieur du cluster. De base, c’est une fonctionnalité, qui si elle est possible nativement, n’est pas très optimisée et assez contraignante.

Il est plutot conseillé de faire appel à des contrôleurs “Ingress”. Ce sont des composants que l’on déploie sur le cluster et qui vont offrir “un équilibrage de charge, une terminaison TLS et un hébergement virtuel basé sur un nom” (definition officielle). Plusieurs produits sont disponibles, personnellement j’ai retenu “Traefik”. C’est une solution OpenSource, française et très appréciée de la communauté.

Traefik va pouvoir se configurer de différentes manières. La première est par l’intermédiaire de “Kubernetes” lui même puisque Traefik va pouvoir interroger le statut des objets au sein du cluster pour fournir la connectivité adéquate. Je souhaite lui ajouter deux autres sources de configuration. La seconde serait donc l’appel à des fichiers de configuration, la troisième serait l’usage de la solution clef/valeur Consul . L’usage de fichier à plat me permettrait d’ajouter des éléments de configurations peu enclin à bouger. “Consul” présente l’intérêt de fournir une interface graphique simple, mais efficace qui me permettrait de compléter une configuration très rapidement et très facilement sous forme de mots clefs associés à une valeur reconnue par traefik. Enfin, “HAproxy” serait utilisé en frontal du cluster Kubernetes  et donc externe à ce dernier (1 VM spécifique) pour assurer un load balancing de niveau 3 uniquement . Dans un cas de prodution, on pourrait imaginer deux instance de HAProxy se partageant une adresse IP virtuelle (VIP) via le protocole VRRP, mais encore une fois mon infra homelab n'est pas extensible à l'infini.

Cette logique serait à reproduire deux fois, l'une pour le LAN, l'autre pour la DMZ.

Il est important de noter que le plus souvent, on parle d'un cluster Kubernetes déployé chez un cloud provider, car plus simple à mettre en oeuvre. Dans ces exemples, la publication des applications à l'extérieur du cluster est le plus souvent traitée dans l'offre du cloud provider. En effet, ces derniers exploitent la notion de "LoadBalancer" des services Kubernetes qui permet d'autoconfigurer les fonctionnalités d'équilibrage de charge du provider.