Installer un système d’exploitation sur un serveur loué ressemble à un problème résolu depuis longtemps. Poser Talos Linux, un OS immuable, piloté par API et sans SSH, sur du bare metal qu’un fournisseur cloud démarre en réseau comme bon lui semble, s’est révélé être une semaine entière de post-mortems. Nous construisions une plateforme Kubernetes bare metal, et la seule étape d’installation a traversé cinq approches distinctes avant qu’un nœud n’atteigne l’état Ready. Talos Linux est pourtant populaire et stable : 10,7k étoiles GitHub, plus de 330 contributeurs et une ligne de version stable v1.13.x (siderolabs/talos, 2026). Voici la version honnête de ce qui s’est passé entre « provisionner un serveur » et « rejoindre le cluster ».
À retenir
- Le bare metal réduit la facture de 30 à 70 % pour des charges Kubernetes stables et durables (OpenMetal, 2025), ce qui justifie la douleur du provisioning d’OS immuables et sans SSH comme Talos.
- Notre script d’installation est passé par iPXE, kexec et un
ddsur disque à chaud avant que le rescue mode couplé à une préparation en RAM ne produise enfin un nœud reproductible et sans kernel panic.- La mise en route au plus près du matériel est impérative et brouillonne : nous l’avons volontairement sortie de Pulumi pour qu’un humain puisse la relancer contre un serveur à moitié provisionné.
- Chaque correctif « évident » faisait surgir une nouvelle panne : l’effacement de disque cassait le netboot du fournisseur, les doubles VLAN cassaient l’adhésion au cluster. La simplicité a gagné à chaque fois.
Pourquoi faire tourner Kubernetes sur du bare metal en 2026 ?
Le bare metal l’emporte sur le coût pour les charges stables et prévisibles : OpenMetal (2025) rapporte 30 à 70 % d’économies face aux instances des hyperscalers pour des flottes Kubernetes durables, et cite 37signals économisant 1,3 M$ par an en quittant AWS. Pour les bases de données, les runners de CI et les labs qui tournent en continu, le matériel dédié est tout simplement moins cher que la location.
La même analyse d’OpenMetal évoque environ 50 % de réduction sur la facture des charges lors de migrations vers du cloud privé, et ce n’est pas un pari tout ou rien. Environ 70 % des organisations mènent aujourd’hui des stratégies d’infrastructure hybride, mêlant cloud et matériel dédié (Unihost, 2025). Les équipes européennes se tournent vers le bare metal pour la souveraineté numérique et la prévisibilité des coûts, dans un contexte où des cadres comme SecNumCloud placent la maîtrise des données au cœur des choix d’infrastructure ; les équipes nord-américaines misent de plus en plus sur la colocation pour échapper aux frais de sortie de données et aux marges sur les instances. C’est la même discipline de platform engineering qui fait de Kubernetes le bon control plane par-dessus : les charges qui ont leur place sur le métal sont les plus ennuyeuses et les plus régulières, bases de données, runners de CI et environnements de lab qui tournent toute la journée, tous les jours.
Qu’est-ce qui distingue Talos Linux d’un nœud classique ?
Talos est un système d’exploitation dédié à Kubernetes, sans shell, sans SSH et sans gestionnaire de paquets : on le configure entièrement via une API déclarative et un fichier de machine-config signé. Cette immuabilité est toute la raison d’être du projet. InfoQ (octobre 2025) le situe aux côtés de Bottlerocket et Flatcar dans la tendance des OS minimaux, et le décrit comme le plus tranché.
Il fait une seule chose, faire tourner Kubernetes, et retire tout le reste. Ce parti pris a de vrais adeptes. InfoQ cite des entreprises comme la SNCF et SGX, ainsi que des déploiements en périphérie, en distribution et sur ligne de production, où un nœud verrouillé et reproductible compte plus que le confort de l’opérateur. Sidero vend Talos comme un chemin allant « du bare metal à Kubernetes en moins d’une minute », mais c’est une promesse commerciale mesurée dans des conditions idéales, pas ce que vous obtenez lors d’un premier provisioning contre du matériel que vous ne connaissez pas.
Le piège dont personne ne vous prévient : quand l’OS n’a ni SSH ni shell de secours, chaque erreur pendant l’installation reste invisible jusqu’à ce que le nœud rejoigne le cluster ou, silencieusement, échoue à le faire. On débogue en redémarrant, pas en se connectant. Cela inverse la façon dont la plupart d’entre nous avons appris à dépanner un serveur.
Retour de terrain nº 1 : pourquoi iPXE plus cloud-init a échoué dès le premier jour
La première tentative est morte sur une erreur de validation, pas sur un kernel panic. Nous avons essayé l’option « Custom install » du fournisseur en passant un script iPXE via le champ CloudInit. Scaleway valide ce champ soit comme du YAML cloud-init, soit comme un script shell, et un script iPXE qui commence par #!ipxe ne correspond à aucun des deux, si bien que l’API l’a rejeté d’emblée, avant même qu’un octet ne démarre.
La leçon transposable est ennuyeuse mais coûteuse : lisez ce que les champs de boot de votre fournisseur acceptent réellement avant de concevoir un flux autour d’eux. Nous avions supposé que « custom install » signifiait « payload de boot arbitraire ». Cela signifiait « cloud-init, ou un script shell, et rien d’autre ». Une après-midi de templating iPXE est partie directement à la poubelle.
Piège : le mode d’installation « custom » ou « avancé » d’un fournisseur cloud reste bordé par une validation d’entrée.
#!ipxen’est ni du YAML cloud-init ni un script shell, il échoue donc au contrôle de schéma avant le boot. Confirmez le format accepté avec un payload trivial d’abord.
Retour de terrain nº 2 : l’impasse kexec
La deuxième approche paraissait élégante et n’a mené nulle part. Nous avons démarré une image Ubuntu classique, puis utilisé un script cloud-init pour faire un kexec directement vers un noyau et un initramfs Talos téléchargés, en sautant un redémarrage complet. Le kexec a fonctionné. Fournir ensuite sa configuration à Talos, non.
Le problème, c’est le timing. Après le kexec, la machine récupère un nouveau bail DHCP, et le serveur HTTP éphémère qui servait la machine-config, tournant à l’intérieur de la session Ubuntu désormais remplacée, a disparu. Talos démarre sans source de configuration atteignable. Nous avons tenté d’intégrer la configuration dans la ligne de commande du noyau, et nous avons heurté la limite de taille du cloud-init du fournisseur. Sans hôte de configuration persistant et joignable, il n’y avait pas de passation propre : nous avons abandonné en cours de session, sans résolution.
Le kexec est séduisant parce qu’il paraît plus rapide et plus propre qu’un redémarrage. Mais il détruit silencieusement tout état en mémoire sur lequel vous vous appuyiez, y compris l’identité réseau et le moindre service local. Si votre mécanisme de livraison de configuration vit dans l’OS que vous remplacez, le kexec supprime votre issue de secours à l’instant précis où vous en avez besoin.
Retour de terrain nº 3 : comment le rescue mode a amené le premier nœud à Ready
Le rescue mode a été la première chose qui a réellement fonctionné. Nous avons redémarré le serveur Elastic Metal dans le Linux de secours du fournisseur, démarré en réseau et résident en RAM (boot-type=rescue), nous nous y sommes connectés en SSH pendant que les disques physiques restaient entièrement démontés, écrit l’image Talos directement sur le disque, puis redémarré en boot normal. Cela a amené notre premier nœud, appelons-le bm-1, à l’état Ready.
Talos a démarré proprement depuis un disque jamais monté à chaud pendant l’écriture. L’intuition qui a tout débloqué : le moment sûr pour écrire une image OS brute, c’est quand rien n’est monté depuis le disque cible. Le rescue mode vous offre exactement cela, un espace utilisateur Linux complet tournant entièrement depuis la RAM, avec les vrais disques passifs et accessibles en écriture.
# Reboot the metal server into the provider's RAM-resident rescue OS
scw baremetal server reboot "$SERVER_ID" boot-type=rescue
# ...once it is up, SSH in: physical disks are unmounted and safe to write...
curl -fsSL "$TALOS_IMAGE_URL" | zstd -d > /dev/shm/talos.raw
dd if=/dev/shm/talos.raw of=/dev/sda bs=4M oflag=direct status=progress
# Back to normal boot; Talos starts from a disk that was never live-mounted
scw baremetal server reboot "$SERVER_ID" boot-type=normal
Retour de terrain nº 4 : à la poursuite des kernel panics jusque dans un disque RAM
Plus tard, nous avons régressé, et les panics nous ont appris pourquoi le rescue mode importait. Pour itérer plus vite, quelqu’un est passé à l’installation de Debian depuis le catalogue, à une connexion SSH, puis à un curl | dd de l’image Talos directement sur le disque à chaud. Résultat : des kernel panics aléatoires, des ports SSH figés et un serveur d’un lot qui rejoignait le cluster pendant qu’un jumeau identique échouait.
Il n’y avait aucun motif reproductible, et c’était le signal. Cause racine, documentée dans un post-mortem : écrire des blocs disque bruts sous un système de fichiers à chaud, alors que d’autres processus comme curl et zstd conservent encore des références dessus, provoque une course qui envoie le noyau dans un panic. Le correctif est arrivé par couches. Préparer l’image entière en RAM (/dev/shm) d’abord, mettre au repos les I/O de fond, puis faire le dd de la RAM vers le disque afin que le système de fichiers à chaud ne soit jamais lu pendant l’écriture. Remplacer le redémarrage propre par une réinitialisation matérielle SysRq, car redémarrer un système de fichiers en pleine mutation peut lui-même provoquer un panic.
curl -fsSL "$TALOS_IMAGE_URL" | zstd -d > /dev/shm/talos.raw
swapoff -a
echo 3 > /proc/sys/vm/drop_caches
dd if=/dev/shm/talos.raw of=/dev/sda bs=4M oflag=direct status=progress
echo b > /proc/sysrq-trigger || true # SysRq reset; || true absorbs the dropped SSH
Le signal, c’était le non-déterminisme : matériel identique, script identique, résultats différents. Cette signature, « ça marche sur l’un, ça panic sur le suivant », pointe presque toujours vers une course, pas vers un bug de configuration, la même classe de panne non déterministe que nous avons appris à traquer dans la fiabilité des contrôleurs Kubernetes. Nous avons cessé de chercher le « mauvais serveur » une fois cela accepté.
Retour de terrain nº 5 : la saga de l’effacement de disque, RAID, iPXE et un GPT vierge
Le second disque nous a coûté trois faux départs, chaque correctif exposant une panne sans rapport. Tentative une : effacer à zéro le disque secondaire pour que Longhorn puisse le revendiquer. Cela a fait planter le bootloader iPXE du fournisseur sur une erreur d’I/O, parce que son firmware de boot veut une signature de bootloader valide sur chaque disque physique.
Tentative deux : écrire Talos sur les deux disques. Cela a supprimé le plantage iPXE mais a provoqué une collision d’étiquettes GPT, des partitions TALOS-STATE et TALOS-EPHEMERAL en double, ce qui a fait planter kubelet. Le correctif qui a tenu : Talos sur le disque primaire uniquement, et le secondaire reçoit un wipefs -a, un petit effacement à zéro et un GPT vierge doté d’un MBR de protection. Cette signature satisfait le scan de boot du firmware tout en laissant le disque vide pour que Talos le formate nativement pour Longhorn. Un dernier grain de sable : le fournisseur livre les serveurs avec un RAID 1 logiciel s’étendant sur les deux disques, qui maintient le secondaire sous un verrou exclusif, si bien que le script doit d’abord marquer en échec et retirer ces membres du tableau avant de pouvoir effacer quoi que ce soit.
# Release the secondary disk from the provider's default software RAID 1
for part in $(lsblk -nlo NAME /dev/sdb | tail -n +2); do
mdadm --fail /dev/md0 "/dev/$part" 2>/dev/null || true
mdadm --remove /dev/md0 "/dev/$part" 2>/dev/null || true
done
# A blank GPT + protective MBR: enough of a signature to keep iPXE booting,
# empty enough for Talos to format the disk for Longhorn
wipefs -a /dev/sdb
dd if=/dev/zero of=/dev/sdb bs=1M count=10
parted -s /dev/sdb mklabel gpt
Piège : le firmware de netboot de certains fournisseurs refuse de démarrer un serveur en iPXE si un disque attaché ne possède pas de signature de bootloader valide. Un disque « vide » n’est pas neutre ; il peut casser complètement le boot. Un GPT vierge avec un MBR de protection est le minimum qui contente le firmware.
Qu’est-ce que la couche de bootstrap Pulumi nous a appris ?
Tout ce qui précède se situe délibérément en dehors de Pulumi. Pulumi détient la couche convergente et déclarative : le VPC, le réseau privé, la passerelle NAT, les VM Talos et le bootstrap du cluster, avec Cilium comme CNI. Une séquence d’installation fragile et dépendante du matériel est impérative et exige des boucles de débogage serrées, nous l’avons donc scriptée au lieu de la forcer à travers pulumi up.
Cette couche déclarative a été vérifiée de bout en bout, un LoadBalancer a reçu une vraie IP externe, un PVC s’est lié et un pod y a écrit, et elle avait tout de même ses propres pièges. Le bucket d’état Pulumi avait le versionnement d’objets activé par défaut, si bien que dev.json a accumulé en silence plus de 10 000 versions jusqu’à ce que le stockage objet refuse toute nouvelle écriture ; une règle de cycle de vie a réglé le problème. Les ressources Kubernetes managées par le cloud avaient besoin de RetainOnDelete pour qu’un teardown interrompu ne bloque pas une release Helm. L’affectation du providerID par le cloud controller manager échoue silencieusement sans cloud-provider: external, mais ajouter ce flag avant que le CCM n’existe teinte chaque nœud et bloque le CNI : l’ordonnancement compte.
Piège : le cloud controller manager de Scaleway n’a pas de flag
--cluster-id, malgré une surface qui ressemble à uncloud-controller-managerstandard.HasClusterID()est codé en dur àfalse, donc--allow-untagged-cloudest obligatoire sinon le CCM échoue fatalement au démarrage. Le nommage du cluster passe par la variable d’environnementSCW_CCM_PREFIXà la place.
Quand l’isolation réseau devient-elle trop maligne ?
Nous avions conçu une séparation réseau propre en deux, un réseau privé de plateforme pour le control plane et les workers d’infra, et un réseau isolé distinct pour les nœuds worker de lab non fiables, puis nous l’avons supprimée. Attacher un serveur bare metal aux deux réseaux privés introduisait un bug de correspondance de VLAN dans la génération de la machine-config Talos. Le nœud n’a jamais rejoint le cluster.
Le correctif fut la soustraction. Nous avons retiré entièrement le second sous-réseau et placé le worker bare metal sur le même réseau de plateforme que tout le reste, éliminant la gestion des doubles VLAN. Tel que construit, il n’y a aucune isolation au niveau réseau entre les types de nœuds ; si les charges de lab ont besoin d’isolation, elle vit au niveau Kubernetes à la place. D’expérience, une topologie élégante qui empêche les nœuds de rejoindre le cluster vaut moins qu’une topologie plate qui fonctionne. La simplicité a gagné, encore une fois.
Que nous enseignent ces retours de terrain sur l’infrastructure immuable ?
L’infrastructure immuable déplace la partie difficile vers le provisioning. Quand un nœud ne peut être ni patché, ni accédé en SSH, ni réparé à la main, chaque once de complexité est repoussée vers le moment où vous le construisez, et ce moment doit être reproductible sinon rien ne l’est. C’est pour cela que nous avons poursuivi les panics jusque dans un disque RAM et codifié une astuce de GPT vierge.
Nous l’avons fait non par élégance, mais pour que le centième nœud démarre exactement comme le premier. Le motif récurrent à travers ces sept histoires, c’est que chaque correctif assuré exposait une panne sans rapport. La validation iPXE, puis la config perdue du kexec, puis les panics sur disque à chaud, puis l’exigence de signature disque du firmware, puis un bug d’adhésion VLAN. La mise en route au plus près du matériel récompense l’itération empirique guidée par les post-mortems plus que l’idée de tout réussir du premier coup. Écrivez le script pour qu’il soit idempotent, rejouable contre un nœud à moitié cassé, et honnête sur ses hypothèses. L’immuabilité que vous obtenez à l’exécution se paie intégralement en amont.
Conclusion
Kubernetes bare metal avec Talos est un compromis réellement bon pour les bonnes charges de travail : de vraies économies, la souveraineté des données et un OS verrouillé et reproductible qui fait exactement une seule chose. Mais l’argument marketing du « moins d’une minute » décrit le chemin idéal, pas la première semaine de provisioning contre du matériel inconnu.
Le chemin honnête passe par des scripts iPXE rejetés, une impasse kexec, des kernel panics, un combat en trois manches sur l’effacement de disque, et un bug de VLAN résolu en supprimant le réseau. Si vous ne retenez qu’une chose de ces retours de terrain, retenez celle-ci : l’infrastructure immuable ne supprime pas la douleur opérationnelle, elle la relocalise vers le provisioning, là où elle a sa place. Investissez dans un chemin d’installation idempotent et rejouable, documentez vos échecs sous forme de post-mortems, et préférez la topologie plate et ennuyeuse qui fonctionne à la topologie maligne qui échoue.
Ismail Kaboubi dirige l’ingénierie cloud et plateforme chez Edixos.
Réponses directes
Questions fréquentes
Talos Linux est-il prêt pour la production sur du bare metal ?
Oui. Talos dispose d'une ligne stable v1.13.x, de 10,7k étoiles GitHub et de plus de 330 contributeurs (siderolabs/talos, 2026), avec des entreprises adoptantes comme la SNCF et SGX citées par InfoQ (octobre 2025). Le chemin de provisioning est délicat, mais l'OS en fonctionnement est stable et largement déployé en périphérie et en environnement industriel.
Pourquoi ne pas simplement se connecter en SSH et installer Talos de façon classique ?
Parce que Talos n'a ni SSH ni shell, par conception. On le configure via une API de machine-config déclarative, pas une session interactive. Cette immuabilité est la fonctionnalité de sécurité et de reproductibilité, mais elle implique que tout votre débogage se déroule pendant le provisioning, à travers redémarrages et logs, plutôt qu'en vous connectant à un nœud en marche.
Le bare metal fait-il réellement économiser de l'argent face au cloud ?
Pour des charges stables et durables, oui. OpenMetal (2025) rapporte 30 à 70 % d'économies et cite 37signals économisant 1,3 M$ par an en quittant AWS. Les économies fondent ou s'inversent pour des charges irrégulières et imprévisibles, où vous descendriez sinon à zéro. Environ 70 % des organisations mènent des stratégies hybrides (Unihost, 2025) pour cette raison.
L'installation de Talos doit-elle vivre dans mon outil d'IaC ou dans un script séparé ?
D'expérience, gardez-la séparée. Les outils déclaratifs comme Pulumi excellent sur l'infrastructure convergente, mais une installation fragile, multi-phases et dépendante du matériel a besoin d'un scripting impératif et rejouable, avec des boucles de débogage serrées. Nous avons laissé Pulumi détenir le cluster et le VPC, et piloté l'installation et l'adhésion du bare metal depuis un script idempotent autonome.