Aller au contenu principal
TECH

Anatomie d'un cluster Kubernetes de production : HA, multi-tenant et GitOps en une dizaine d'heures

Publié le12 min de lecture

Le détail complet d'un cluster Kubernetes bare-metal de production : Talos, Cilium, Gateway API partagée, GitOps app-of-apps, bases de données opérées, monitoring et backups chiffrés. Pourquoi la qualité — pas la vitesse — est le vrai sujet.

Il y a quelques mois, j'ai raconté ici comment j'avais monté un cluster Kubernetes sur du bare metal pour un client. À l'époque, ça m'avait pris trois semaines. Mes propres projets, eux, tournaient encore sur de bons vieux VPS en Docker Compose. Depuis, j'ai franchi le pas pour moi-même : j'ai construit mon cluster et j'y ai migré l'ensemble de mes produits — le blog que vous lisez, un CRM, une académie de formation, des bases de données, du monitoring, des backups chiffrés. Et reconstruire le tout, aujourd'hui, me prend une dizaine d'heures de travail effectif.

Ce chiffre ne veut rien dire si je ne décris pas ce qu'il y a sous le capot. N'importe qui peut « monter un cluster Kubernetes en une journée » — un cluster qui tombe au premier serveur en panne, qui n'héberge qu'une seule application, dont les secrets traînent en clair dans Git et qu'on ne sait pas restaurer après un sinistre. L'intérêt de l'histoire n'est pas la vitesse. C'est ce que la vitesse permet quand elle s'appuie sur une vraie exigence de qualité. Voici donc l'anatomie complète.

Trois semaines, puis dix heures : ce qui a changé

Petit repère temporel, parce qu'il est éclairant. Il y a un an, monter une infrastructure de ce type demandait facilement trois mois à deux SRE. Il y a six mois, avec de l'IA de complétion classique, un développeur senior y arrivait en trois semaines — c'est exactement le chiffre que je donnais dans mon précédent article. Aujourd'hui, avec de l'IA agentique et l'expérience accumulée, le travail humain effectif tient dans une dizaine d'heures.

Soyons précis sur ce que recouvrent ces dix heures, parce que c'est là que beaucoup d'articles trichent. Ce sont dix heures de temps homme : écrire les configurations, piloter les agents, vérifier, corriger, valider. Le temps d'horloge, lui, est plus long — quelques jours au maximum. Mais ces jours, ce n'est pas du travail : c'est de l'attente. OVH qui livre et provisionne les serveurs, les tests de réinstallation pour vérifier qu'une machine repart proprement de zéro, la vérification que le BIOS est à jour, la propagation DNS, l'émission des certificats. De l'attente incompressible qui n'occupe pas mes mains.

Et surtout : ces dix heures ne sont accessibles qu'à quelqu'un qui sait ce qu'il fait. L'IA ne remplace pas l'expertise infrastructure, elle l'amplifie — j'en ai fait un article entier parce que c'est le cœur du sujet. Sans bagage, l'IA vous produit un cluster qui a l'air de marcher et qui s'effondre au premier incident réel. La preuve la plus honnête que je puisse en donner, ce sont les galères que j'ai traversées pour arriver là. Elles sont disséminées dans cet article, et ce sont elles qui font la différence entre une démo et une production.

La stack, en un coup d'œil

BriqueRôlePourquoi ce choix
Talos LinuxOS des nœudsImmutable, sans SSH, API déclarative — du « bétail »
CiliumRéseau (CNI) + Gateway + L2Remplace kube-proxy, Gateway API native, annonce L2 d'IP
ArgoCDDéploiement GitOpsApp-of-apps, sync-waves, tout l'état du cluster dans Git
Sealed SecretsSecrets dans GitSecrets chiffrés versionnés, déchiffrables par le seul cluster
cert-managerCertificats TLSLet's Encrypt DNS-01, wildcards renouvelés automatiquement
LonghornStockage répliquéVolumes persistants distribués, backups S3 intégrés
MongoDB / RabbitMQ / TypesenseDonnéesBases opérées par des operators, pas bricolées à la main
Prometheus / Loki / GrafanaObservabilitéMétriques, logs, alerting par sévérité

Chacune de ces briques mérite qu'on s'y attarde, parce que c'est dans les détails d'intégration que se joue la différence entre « ça tourne » et « ça tient en production ».


Talos : un OS qu'on ne touche jamais à la main

Talos Linux est un système d'exploitation entièrement dédié à Kubernetes. Pas de shell, pas de SSH, pas de gestionnaire de paquets. On ne se connecte pas à un nœud Talos : on lui parle via une API déclarative, on lui pousse une configuration, et c'est tout. Cette contrainte, qui déroute au début, est en réalité une bénédiction. La surface d'attaque est minuscule. La dérive de configuration — ce moment où un serveur finit par être différent des autres parce que quelqu'un a bidouillé un truc en SSH un soir de production — devient littéralement impossible.

Le revers, c'est que quand le bootstrap se passe mal, on ne peut pas « aller voir » à l'ancienne. Et il s'est mal passé. Lors d'une de mes tentatives de reconstruction, le service etcd refusait de démarrer sur le premier nœud. Les logs finissaient par lâcher la vraie cause : error writing kubelet PKI: read-only file system — le répertoire /etc/kubernetes n'était même pas monté. Diagnostiquer ça sur un OS sans shell, en mode rescue OVH, en remontant la partition système pour comprendre qu'un résidu d'installation précédente bloquait le montage : voilà le genre de problème que l'IA ne résout pas à votre place. Elle aide à formuler des hypothèses, à lire des traces, à se souvenir d'une option obscure. Mais c'est l'expérience qui sait par où commencer à creuser.

L'autre vertu de Talos, c'est qu'il rend concrète la philosophie du « bétail, pas des animaux de compagnie ». Quand un de mes serveurs a eu une défaillance matérielle, je n'ai rien réparé : j'ai demandé un remplacement à l'hébergeur, repoussé la configuration, et le nœud a rejoint le cluster comme si de rien n'était. Un serveur n'est plus un objet précieux qu'on bichonne. C'est une ressource interchangeable. C'est exactement ce qu'on attend d'une infrastructure résiliente, et c'est ce qui permet de dormir tranquille.


Cilium : un seul réseau, une seule IP, tous les projets

Le réseau est l'endroit où la plupart des clusters maison montrent leurs limites. J'ai choisi Cilium, qui remplace à la fois le CNI (le réseau interne des pods), kube-proxy (le routage des services), et fournit nativement la Gateway API ainsi que l'annonce d'adresses IP en couche 2. Une seule brique pour ce qui demande souvent trois ou quatre composants empilés.

Le point d'architecture dont je suis le plus satisfait, c'est la Gateway unique partagée. Dans le modèle Gateway API, la Gateway appartient à l'infrastructure, et les routes (les HTTPRoute) appartiennent aux applications. Concrètement, j'ai une seule porte d'entrée pour tout le cluster, sur une seule IP, et le routage se fait par nom de domaine via SNI. Ajouter un nouveau projet — une nouvelle application, un nouvel environnement — ne consiste jamais à commander une IP supplémentaire. C'est ajouter un listener et une route. Quand on sait qu'une IP de failover par projet et par environnement serait à la fois absurde et coûteuse, ce design fait toute la différence pour la suite.

Cette IP unique est annoncée par Cilium en couche 2, par un mécanisme d'élection : un nœud porte l'adresse, et si ce nœud tombe, un autre la reprend en envoyant un ARP gratuit pour rediriger le trafic. J'ai testé le basculement en conditions réelles — quinze requêtes sur quinze servies pendant la ré-élection. Mais y arriver proprement m'a coûté une vraie panne. En refondant cette partie, un nœud a été élu sans la route réseau adéquate et a englouti le trafic dans un trou noir pendant environ trois minutes. La leçon est précieuse : sur ce genre de mécanisme, le chemin nominal est facile, ce sont les cas limites du basculement qui font mal.

J'ai aussi appris à mes dépens une subtilité de l'implémentation Cilium de la Gateway API. Pour rediriger le HTTP vers le HTTPS, il faut un listener HTTP par domaine, avec un nom d'hôte explicite : un listener « attrape-tout » sans hostname renvoie un 404 au lieu de la redirection attendue. Pire, un listener HTTP générique ne sert pas un domaine déjà réclamé par un listener HTTPS exact. Le symptôme — des redirections qui marchent en staging mais cassent en production — n'a aucun sens tant qu'on n'a pas compris la règle sous-jacente. C'est typiquement le genre de piège qu'on ne trouve dans aucune documentation et qu'on paye en heures de débogage.


GitOps : si ce n'est pas dans Git, ça n'existe pas

Tout l'état du cluster est décrit dans un dépôt Git, et ArgoCD se charge de faire converger le cluster vers cette description. Aucun kubectl apply manuel en production. Aucun hotfix appliqué à la main qu'on oublie de versionner. Un déploiement, c'est un commit ; un rollback, c'est un revert. Cette discipline n'est pas un confort esthétique : c'est ce qui rend le cluster reconstructible. Si tout part en fumée, je recrée les nœuds Talos, ArgoCD resynchronise depuis Git, et l'infrastructure se reconstitue d'elle-même.

L'organisation suit le modèle app-of-apps : une application racine qui décrit toutes les autres, déployées dans un ordre maîtrisé grâce aux sync-waves. Le stockage avant les bases de données, les certificats avant les routes, et ainsi de suite. Cet ordonnancement n'est pas un détail. Installer Longhorn via ArgoCD, par exemple, m'a confronté à deux pièges connus mais bloquants : un hook de pré-installation qui réclamait un compte de service pas encore créé, et le fait que Talos refuse par défaut les pods privilégiés dont le stockage a besoin. Les deux se règlent — désactiver le hook, forcer les labels de sécurité du namespace — mais il faut savoir que le problème existe avant de perdre une soirée dessus.

Pour les secrets, j'utilise Sealed Secrets : les secrets sont chiffrés et versionnés dans Git, et seul le cluster, avec sa clé privée, peut les déchiffrer. Élégant, sauf qu'il y a un point critique souvent négligé. Cette clé maîtresse, si elle change, rend illisibles tous les secrets déjà chiffrés. Lors d'une reconstruction, il faut donc impérativement restaurer l'ancienne clé avant de démarrer le contrôleur, sinon il en génère une neuve et tous les pods se retrouvent en erreur de configuration. C'est le genre de séquence qu'on n'apprend qu'en se l'étant fait une fois.

Les données : des bases opérées, pas bricolées

C'est là que beaucoup de clusters maison déraillent. Faire tourner une base de données dans Kubernetes n'est pas trivial : il faut de la réplication, de la persistance, des sauvegardes, et une stratégie de mise à jour qui ne perde pas de données. J'ai fait le choix d'operators dédiés plutôt que de StatefulSets bricolés à la main, parce qu'un operator encode le savoir-faire opérationnel d'une base — comment elle se réplique, comment elle bascule, comment elle se met à jour.

MongoDB tourne en replica set à trois membres, opéré par l'operator officiel, avec une version de compatibilité épinglée pendant les montées de version pour ne jamais se retrouver coincé. RabbitMQ et Typesense sont gérés de la même manière. Chacun a ses subtilités — Typesense, par exemple, exige que son service réseau publie les adresses des pods avant même qu'ils soient prêts, sans quoi le consensus Raft ne s'établit jamais, un classique problème d'œuf et de poule. Côté stockage, Longhorn fournit deux classes : une répliquée pour les volumes critiques uniques, une à réplica unique pour les bases qui se répliquent déjà elles-mêmes au niveau applicatif. Doubler la réplication serait du gâchis.

Et surtout, les sauvegardes. Une base sans sauvegarde testée n'est pas une base, c'est une bombe à retardement. Un CronJob exporte chaque nuit les bases vers un stockage objet S3 chez un autre hébergeur, et Longhorn fait de même pour ses volumes. Le point important : j'ai testé la restauration, pas seulement la sauvegarde. Plusieurs centaines de documents restaurés, comptages identiques à la source. Tant qu'on n'a pas restauré pour de vrai, on ne sait pas si on a une sauvegarde — on a juste un fichier dont on espère qu'il est bon. Si le choix d'une base vous intéresse au-delà du réflexe SQL, j'en ai parlé dans un autre article.


Observabilité : voir ce qui se passe, être prévenu quand ça casse

Un cluster qu'on ne surveille pas est un cluster dont on apprend les pannes par ses utilisateurs. J'ai installé la pile classique : Prometheus pour les métriques, Loki pour les logs, Grafana pour les tableaux de bord. Mais l'observabilité utile ne se résume pas à collecter des chiffres ; c'est savoir lesquels regarder et être alerté au bon moment.

Les alertes partent vers mon téléphone, avec une priorité calée sur la sévérité : une alerte critique sonne, une information passe en silence. Les tableaux de bord eux-mêmes sont versionnés dans Git et déployés par GitOps, comme le reste — un dashboard n'est pas quelque chose qu'on clique à la main et qu'on perd à la prochaine reconstruction. J'ai ajouté des sondes externes qui vérifient en continu que chaque service répond et que les certificats ne vont pas expirer, ainsi qu'une alerte qui se déclenche si une sauvegarde de base venait à manquer. Parce que le pire scénario, ce n'est pas la panne : c'est la panne silencieuse qu'on découvre le jour où on a besoin du backup.

Résister à la catastrophe : la stratégie de survie

C'est le critère qui sépare une infrastructure sérieuse d'un projet de week-end. Que se passe-t-il si je perds tout ? Pas un nœud — tout. Le cluster entier, et mon Mac de travail avec.

J'ai conçu la réponse autour de deux secrets qui ne peuvent pas se régénérer : la clé maîtresse qui déchiffre les secrets du cluster, et le certificat TLS, parce que Let's Encrypt limite le nombre d'émissions par semaine — une limite que j'ai d'ailleurs atteinte en enchaînant les reconstructions, ce qui force à sauvegarder le certificat valide plutôt que d'en redemander un. Ces éléments sont sauvegardés, et le script de reconstruction les réinjecte automatiquement dans le bon ordre. Au-delà, tout mon coffre de secrets est archivé chiffré chez un fournisseur cloud distinct de mon hébergeur, et la clé qui ouvre ce coffre vit uniquement dans mon trousseau, sur un troisième fournisseur encore. Trois acteurs différents, aucune dépendance circulaire : je peux tout reconstituer même si mon Mac et le cluster disparaissent le même jour. J'ai écrit la procédure de reprise noir sur blanc, justement pour qu'elle soit exécutable sous stress, le jour où le pire arrive.

Multi-tenant en pratique : un nouveau projet en deux heures

Toute cette architecture n'aurait qu'un intérêt théorique si ajouter un projet restait compliqué. La meilleure preuve que le design tient, c'est la facilité avec laquelle on l'étend. Récemment, j'ai eu besoin de mettre en ligne un petit projet personnel — un site statique, chiffré côté client, sans backend. Le développement m'a pris deux heures. Le déploiement sur le cluster : quelques minutes. Un conteneur servant les fichiers statiques, un listener et une route ajoutés à la Gateway partagée, un certificat dédié émis automatiquement. Aucune nouvelle IP, aucune nouvelle infrastructure, aucune décision d'architecture à reprendre.

C'est exactement le retour sur investissement d'une plateforme bien pensée. Le premier projet coûte cher en réflexion et en mise en place. Tous les suivants deviennent presque gratuits. C'est la différence entre bricoler une machine par application et construire une plateforme qui accueille des projets. Et c'est précisément ce qui rend le bare metal viable pour un indépendant qui jongle entre plusieurs produits : la mutualisation.


Alors, dix heures, vraiment ?

Oui — mais maintenant vous savez ce qu'il y a derrière, et pourquoi le chiffre seul est trompeur. Dix heures de travail humain pour reconstruire une plateforme haute disponibilité, multi-tenant, avec des bases répliquées et sauvegardées, du GitOps de bout en bout, de l'observabilité et une stratégie de survie au sinistre. Ce résultat n'est pas accessible à n'importe qui en dix heures. Il est accessible à quelqu'un qui a vingt ans de métier, qui a déjà rencontré la plupart de ces pièges, et qui sait reconnaître le moment où l'IA propose une solution plausible mais fausse.

L'IA est un multiplicateur formidable. Elle m'a fait passer de trois semaines à dix heures. Mais elle multiplie une expertise ; elle ne la crée pas. Donnez le même outillage à quelqu'un sans les fondamentaux, et vous obtiendrez un cluster qui passe la démo et meurt au premier vrai incident — un nœud qui tombe, un certificat qui expire, une clé qu'on n'a pas su restaurer. Toutes ces galères que j'ai racontées, ce ne sont pas des anecdotes : ce sont les endroits exacts où l'expertise fait la différence, et où l'IA seule vous aurait laissé en plan.

Pour qui, et quand

Soyons honnêtes : cette infrastructure n'est pas pour tout le monde, et certainement pas pour tout de suite. Pour une startup qui démarre son produit, un simple conteneur sur un VPS à vingt euros reste le bon choix. Passer à Kubernetes par anticipation ou par effet de mode est une erreur que je vois régulièrement. La question du cloud public ou du bare metal ne se tranche qu'au regard d'un besoin réel de haute disponibilité ou de maîtrise des coûts.

Mais quand ce besoin arrive — un SLA à tenir, un produit qui ne tolère pas l'interruption, une facture cloud qui devient déraisonnable — le calcul a basculé. Ce qui exigeait une équipe SRE dédiée et des mois de travail est désormais à la portée d'un profil expérimenté outillé d'IA, en une fraction du temps et pour une fraction du coût. Ce n'est pas une raison pour se passer de compétences infra à terme. C'est une raison pour ne plus reporter indéfiniment une vraie infrastructure résiliente sous prétexte qu'elle serait trop chère ou trop longue à mettre en place.

C'est tout l'enjeu, finalement. La barrière n'est plus la vitesse ni le coût. C'est l'expertise — et c'est justement ce qui, à l'heure de l'IA, reprend de la valeur.

Envie d'en discuter ?

Réservez un créneau de 30 minutes pour un premier échange. Je vous aiderai à y voir plus clair sur votre situation.

Prendre rendez-vous