← Tous les travaux
Kubernetes · reproductible depuis les sourcesSources disponibles

Plateforme de livraison GitOps

Un exercice de cursus devenu la chose la plus utile que j'aie construite pour comprendre la livraison : trois étapes qui mènent de deux machines virtuelles nues à un cluster qui annule vos modifications manuelles, parce que Git ne les a pas demandées.

2 → 1 → 0
VM nécessaires, à mesure qu'on s'approche des conteneurs
1 commande
de la machine vide au cluster synchronisé
prune + self-heal
dérive corrigée sans intervention humaine

Ce que c'est

Trois étapes, chacune retirant une couche de machinerie. La première provisionne deux machines virtuelles et les réunit en un cluster K3s — un serveur, un agent. La deuxième descend à un seul nœud et place trois applications derrière un même ingress, routées par nom d'hôte. La troisième abandonne les machines virtuelles au profit de K3s dans Docker et confie le contrôle à Argo CD, qui surveille un dépôt Git et aligne le cluster dessus.

Une étape bonus remplace GitHub par un GitLab auto-hébergé installé via Helm, avec Postgres, Redis et un stockage objet hors du cluster : le serveur Git dont on se synchronise fait lui-même partie de l'infrastructure.

La partie réellement difficile

Pas Kubernetes. Le réseau. Le tout a été construit sur une machine Apple Silicon, donc avec QEMU et non VirtualBox — et le provider QEMU de Vagrant n'offre aucune primitive réseau de haut niveau : aucun réseau privé déclarable, rien qui attribue une adresse à une VM.

Le réseau privé entre les deux nœuds est donc bâti sur une socket TCP. La deuxième carte réseau de la VM serveur ouvre un écouteur ; celle du worker s'y connecte. La socket est le câble Ethernet. Cela a une conséquence que la plupart des montages Vagrant ne rencontrent jamais : l'ordre de démarrage devient critique, puisque l'écouteur doit exister avant que l'autre extrémité tente de se connecter — le provisionnement parallèle est donc désactivé volontairement, pas par hasard.

Rien ne distribue d'adresses sur ce segment non plus : chaque nœud configure la sienne, depuis un unique modèle rendu par VM, en identifiant l'interface par son adresse MAC et en la renommant, pour que la configuration survive à un ordre d'énumération différent au prochain démarrage.

  • Les adresses sont statiques car aucun serveur DHCP n'existe sur un LAN bâti sur socket — il n'y a que les deux VM.
  • L'analyseur de fichier d'environnement est écrit à la main dans le Vagrantfile, le plugin habituel étant cassé sur les Ruby récents.
  • Argo CD est installé en server-side apply, ses manifestes dépassant la limite de taille d'annotation imposée par l'application côté client.

Prouver que la boucle se referme

Installer Argo CD et croire qu'on fait du GitOps est facile. Le test est de savoir si le cluster suit Git quand Git change, et s'il vous résiste quand vous modifiez le cluster à la main.

La définition d'application active la synchronisation automatique avec élagage et auto-réparation : les ressources que Git cesse de mentionner sont supprimées, et les modifications manuelles sont annulées plutôt que tolérées. L'historique du dépôt surveillé en est la démonstration : une suite de changements de tag d'image, passant à une nouvelle version puis revenant, chacun atterrissant dans le cluster sans que personne lance une commande de déploiement.

Un revirement en cours de projet figure aussi dans cet historique. L'application suivait au départ le tag Git le plus élevé d'une plage de versions, ce qui paraît plus propre que suivre la tête de branche. En pratique, cela obligeait à résoudre un motif de tags pour répondre à « qu'est-ce qui est déployé maintenant ». Retour donc au suivi de la tête : moins astucieux, immédiatement vérifiable.

Ce que je corrigerais avant de parler de production

Mieux vaut être précis sur l'écart entre ceci et un système sur lequel on ferait tourner une activité, car cet écart tient surtout à une chose : rien n'est épinglé en version. Chaque composant s'installe depuis une URL « stable » ou « latest », et les images de conteneurs n'ont pas de tag. Cela fonctionne aujourd'hui sans garantie pour le mois prochain — l'inverse exact de l'objectif d'un provisionnement reproductible.

L'étape bonus est en outre inachevée : elle contient une adresse en dur et un gabarit non substitué dans sa définition d'application. Je préfère le dire plutôt que la présenter comme terminée.

Réalisé avec

  • K3s
  • k3d
  • Argo CD
  • Vagrant
  • QEMU
  • Traefik
  • Helm
  • GitLab

Un exercice de cursus, publié tel quel. Il démontre fidèlement les mécanismes de livraison ; il n'est ni épinglé ni durci pour la production.