Kubernetes : pourquoi un orchestrateur est devenu plus important que les serveurs eux-mêmes
Réflexions techniques sur l’évolution de l’administration système, des VPS traditionnels vers les infrastructures distribuées.
Ce texte n’est ni une introduction à Kubernetes ni un plaidoyer pour l’installer partout. Il décrit les problèmes opérationnels qui rendent l’orchestration utile, les abstractions qu’elle apporte, et surtout les endroits où Linux, le réseau, le stockage et l’humain reprennent leurs droits.
Le jour où le serveur a cessé d’être le centre du système#
Le premier VPS donne une impression de maîtrise presque parfaite. Une adresse IP, une clé SSH, un Nginx proprement configuré, quelques unités systemd, un pare-feu lisible. On sait où sont les logs, où vit la configuration, quel processus écoute sur quel port. Quand quelque chose casse, on entre sur la machine et on regarde. Cette proximité est rassurante parce que le modèle mental tient dans une seule tête.
Puis Docker arrive, souvent pour de bonnes raisons. L’application ne dépend plus du Python ou du Node installé sur l’hôte. PostgreSQL, Redis, l’API et le worker rejoignent un compose.yaml. Le déploiement ressemble enfin à quelque chose de reproductible : une image, des variables d’environnement, quelques volumes et un reverse proxy. À ce stade, docker compose up -d paraît résoudre l’essentiel du problème.
Pendant quelque temps, il le résout vraiment.
La difficulté ne commence pas lorsque le trafic explose. Elle commence bien avant, avec l’accumulation. Un certificat doit être renouvelé. Une image de base contient une vulnérabilité et oblige à reconstruire trois services. Le redémarrage de l’hôte révèle qu’un conteneur dépendait implicitement d’un montage NFS arrivé trop tard. Le port 8080 déjà occupé force une exception dans un fichier Compose. Une migration de base prend plus longtemps que prévu et l’ancienne API redémarre contre un schéma qu’elle ne comprend plus. Un volume a bien été sauvegardé, mais personne n’a rejoué la restauration depuis six mois.
Le serveur reste simple à dessiner. Son exploitation ne l’est déjà plus.
J’ai souvent vu le même basculement psychologique. Au début, on administre une application. Ensuite, on administre les conditions qui permettent à l’application de survivre : ordre de démarrage, rotation des secrets, capacité disque, dépendances réseau, compatibilité de schéma, certificats, sauvegardes, fenêtres de maintenance. Le code métier n’est plus la principale source d’incertitude. La machine, son histoire et toutes les décisions manuelles accumulées deviennent le risque.
On peut tenir longtemps ainsi. Un excellent administrateur peut faire fonctionner dix services sur un VPS avec systemd, Nginx et des scripts de déploiement très propres. Il ne faut pas mépriser ce modèle : il est direct, économique et remarquablement efficace quand son périmètre reste stable. Mais sa qualité dépend d’une discipline humaine constante. Le serveur possède une biographie. Quelqu’un a modifié /etc/sysctl.conf un soir d’incident. Un certificat intermédiaire a été ajouté manuellement. Le volume de données a été déplacé, puis un bind mount est resté. La machine fonctionne, mais elle n’est plus entièrement décrite ailleurs qu’en elle-même.
Le vrai seuil n’est donc pas un nombre de requêtes ou de conteneurs. Il apparaît quand la somme des états implicites dépasse la capacité de l’équipe à les connaître, les reproduire et les réparer sans improviser.
D’une machine précieuse à une capacité remplaçable#
L’ancienne administration construisait autour du serveur. On choisissait sa distribution, on le durcissait, on le nommait, on le surveillait, puis on évitait de le toucher. Beaucoup de machines de production portaient des noms parce qu’elles avaient réellement une identité. Quand atlas ou db-master-01 tombait, toute l’équipe savait quelle nuit elle allait passer.
Le changement le plus profond des infrastructures modernes n’a pas été le conteneur. Il a été l’abandon progressif de cette fidélité à la machine.
Un nœud ne devrait plus être l’endroit où vit une application. Il devrait être une quantité de CPU, de mémoire, de réseau et éventuellement de stockage que la plateforme peut employer, vider puis remplacer. Ce principe ressemble au vieux contraste pets versus cattle, mais l’expression est parfois comprise trop littéralement. Il ne s’agit pas de traiter le matériel sans soin. Il s’agit d’éviter qu’une propriété métier dépende de l’histoire secrète d’un hôte particulier.
L’infrastructure immuable pousse cette logique jusqu’au bout. On ne corrige pas un serveur en production ; on produit une nouvelle image, on remplace la capacité et on détruit l’ancienne une fois le service stabilisé. L’Infrastructure as Code décrit les réseaux, machines, règles et identités. GitOps ajoute une discipline opérationnelle : la version approuvée dans Git devient la référence que la plateforme doit rejoindre. Aucun de ces termes ne garantit la qualité. Un mauvais manifeste versionné reste un mauvais manifeste. Mais ils déplacent la vérité depuis la mémoire d’un administrateur et le disque d’un serveur vers une description relisible, diffable et rejouable.
Cette transition paraît abstraite jusqu’au premier remplacement réussi d’un nœud en production. On draine la machine, les charges sont recréées ailleurs, les contrôles passent, puis l’instance disparaît. Personne ne se connecte pour « sauver » l’hôte. À cet instant, le serveur est devenu un consommable au sens opérationnel : important comme ressource, secondaire comme identité.
Cela change également la nature d’un incident. Sur un VPS traditionnel, la question est souvent : « qu’est-il arrivé à cette machine ? » Dans une plateforme déclarative, elle devient : « pourquoi l’état observé ne converge-t-il pas vers l’état demandé ? » La seconde question n’est pas plus facile, mais elle est plus industrialisable. Elle peut être traitée par des contrôleurs, des politiques, des événements et des audits plutôt que par une succession de sessions SSH.
Les conteneurs ne sont que la matière première#
Réduire Kubernetes à un gestionnaire de conteneurs revient à décrire systemd comme un outil qui lance des binaires. C’est vrai, mais cela manque le mécanisme qui donne sa valeur à l’ensemble.
Le cœur du système est un écart : d’un côté, ce que l’opérateur a demandé ; de l’autre, ce que le cluster observe. Entre les deux tournent des boucles de réconciliation. Elles ne suivent pas un script linéaire en supposant que chaque étape réussira. Elles examinent continuellement le monde et tentent de le ramener vers l’état désiré.
Un manifeste ne dit pas « démarre trois conteneurs, puis quitte ». Il dit en substance « trois répliques de cette charge doivent être disponibles sous ces contraintes ». Si un processus meurt, si un nœud disparaît ou si une réplique est supprimée, la déclaration reste vraie et le contrôleur recrée ce qui manque. L’intention survit à l’exécution qui l’a matérialisée.
Quelques lignes suffisent à montrer ce déplacement :
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-facturation
spec:
replicas: 3
strategy:
type: RollingUpdate
template:
spec:
containers:
- name: api
image: registry.internal/facturation:2026.07.22
readinessProbe:
httpGet:
path: /ready
port: 8080
La partie intéressante n’est pas la syntaxe YAML. C’est ce qu’elle permet d’éviter d’écrire : la boucle de surveillance, la décision de redémarrage, la conservation du nombre de répliques, l’exclusion du trafic tant que l’instance n’est pas prête et la progression du déploiement.
L’API Server fournit le point de coordination. Les objets y sont validés, persistés, observés et modifiés. Les contrôleurs réagissent à ces objets. Le scheduler cherche un placement compatible avec les ressources, affinités, taints, volumes et politiques. Les agents de nœud transforment ensuite cette décision en processus réels. Aucun composant ne « possède » toute l’opération comme le ferait un script de déploiement. Le comportement émerge de plusieurs acteurs qui convergent sur un modèle commun.
C’est pourquoi l’analogie avec un système d’exploitation distribué est plus utile que celle d’un Docker Compose géant. Un système d’exploitation arbitre des ressources et offre des abstractions plus stables que le matériel sous-jacent. Ici, l’unité arbitrée n’est plus un seul processeur ni une seule mémoire, mais un ensemble de machines, de réseaux et de volumes. L’API devient une sorte d’interface système pour le datacenter.
Nomad suit une philosophie plus compacte : planifier des charges avec beaucoup moins de surface conceptuelle et une excellente lisibilité opérationnelle. Pour certaines équipes, c’est exactement le bon équilibre. systemd reste supérieur lorsqu’un service appartient réellement à un hôte. Docker Compose reste imbattable pour assembler clairement quelques processus sur une machine. Kubernetes prend l’avantage quand l’état doit survivre au placement, au remplacement des nœuds et à la croissance du nombre d’équipes. Ce n’est pas une hiérarchie absolue ; ce sont des périmètres de contrôle différents.
La vraie valeur n’est presque jamais le scaling#
Les démonstrations commerciales aiment montrer un autoscaler qui passe de trois à cinquante pods. C’est visuel, immédiat et facile à vendre. En production, la valeur quotidienne se trouve ailleurs : dans les opérations ordinaires que la plateforme rend prévisibles.
La plupart des applications ne passent pas leur journée à multiplier leur capacité par vingt. Elles passent leur vie à être déployées, redémarrées, déplacées, mises à jour, inspectées et réparées. Elles rencontrent des nœuds saturés, des processus bloqués, des dépendances lentes, des erreurs de configuration et des images imparfaites. L’intérêt de l’orchestrateur est de transformer ces événements en transitions normales plutôt qu’en interventions exceptionnelles.
Prenons une mise à jour banale. Sur deux VPS derrière un load balancer, l’opération peut être parfaitement automatisée. On retire un serveur de la rotation, on met à jour, on teste, on le réintroduit, puis on recommence. Cette procédure fonctionne, mais chaque équipe finit par reconstruire sa propre version. Avec un Deployment, le déploiement progressif, les contraintes de disponibilité et le retour à une révision antérieure appartiennent au comportement standard de la plateforme.
kubectl rollout status deployment/api-facturation
kubectl rollout undo deployment/api-facturation
Ces commandes ne sont rassurantes que si les sondes sont honnêtes. Une livenessProbe ne doit pas redémarrer un processus simplement parce que PostgreSQL répond lentement. Une readinessProbe doit répondre à la question précise : cette instance peut-elle recevoir du trafic maintenant ? Une startupProbe protège un démarrage long contre une liveness trop impatiente. Mal conçus, ces contrôles créent des pannes cycliques. Bien conçus, ils donnent à la plateforme les signaux nécessaires pour agir sans attendre un humain.
L’auto-réparation n’a rien de magique. Kubernetes recrée ; il ne guérit pas un bug. Si une image plante au démarrage, elle sera relancée avec une remarquable constance. Si une fuite mémoire remplit chaque pod, le contrôleur déplacera le symptôme. Si le service dépend d’un tiers indisponible, ajouter des répliques peut seulement amplifier la pression. La résilience vient du contrat entre l’application et l’orchestrateur : terminaisons propres, timeouts, idempotence, files de travail récupérables, sessions externalisées, migrations compatibles, budgets de perturbation raisonnables.
Mais ce contrat change la manière de concevoir. On cesse de supposer que le processus vivra plusieurs mois. On accepte qu’il soit interrompu, replacé et reconstruit. On teste la perte d’une instance comme une condition normale. La disponibilité ne repose plus sur la survie d’un processus exceptionnellement stable, mais sur la capacité collective à perdre des éléments sans perdre le service.
Le scaling arrive ensuite. Il est utile, parfois indispensable, mais il s’appuie sur tout le reste : métriques fiables, démarrage suffisamment rapide, dépendances capables d’absorber la concurrence, capacité disponible, limites de ressources cohérentes. Sans cette base, l’autoscaling est seulement une boucle supplémentaire susceptible de prendre de mauvaises décisions plus vite qu’un opérateur.
À mesure que l’application se simplifie, le réseau se révèle#
Un conteneur qui démarre est rarement le vrai problème. Le problème est de déterminer qui doit pouvoir lui parler, sous quel nom, par quel chemin, avec quelle identité et ce qui doit arriver pendant son remplacement.
Sur un VPS, le modèle est visible. Nginx écoute sur 443, transmet vers le port 8080 de l’interface de bouclage, PostgreSQL écoute sur une interface privée, et quelques règles nftables ferment le reste. Dans un cluster, les adresses des pods sont éphémères. Un Service fournit une identité stable à un ensemble mouvant d’endpoints. Le DNS interne résout cette identité. ClusterIP offre une adresse virtuelle. Ingress ou Gateway traite l’entrée HTTP. Un LoadBalancer demande souvent une ressource au fournisseur. Les NetworkPolicies expriment les communications autorisées. Le CNI doit rendre tout cela vrai sur des nœuds différents.
Chaque couche répond à une bonne question. Ensemble, elles forment un chemin assez long pour que le diagnostic devienne une discipline.
Lorsqu’une requête échoue, il faut distinguer la résolution DNS, la sélection du Service, les endpoints prêts, la traduction ou le routage, l’overlay, les règles réseau, le proxy d’entrée, le certificat et enfin l’application. Un curl depuis son poste ne voit qu’une extrémité de ce chemin. Un curl depuis un pod de debug peut produire une réponse différente. Le paquet traverse parfois VXLAN ou Geneve, parfois du routage natif BGP, parfois une pile eBPF, parfois des règles iptables dont personne ne souhaite réellement lire la totalité pendant un incident.
Le choix du CNI n’est donc pas cosmétique. Il détermine une partie du modèle de routage, de politique, de chiffrement, d’observabilité et parfois de load balancing. Une NetworkPolicy déclarée mais non appliquée par le plugin donne un dangereux sentiment de sécurité. Un MTU incorrect dans l’overlay produit ces incidents pénibles où les petits paquets passent et les réponses TLS volumineuses se figent. Une plage Pod CIDR qui chevauche le réseau d’un site distant transforme une future interconnexion en chantier.
Beaucoup d’administrateurs entrent dans Kubernetes pour les conteneurs et découvrent qu’ils exploitent surtout un réseau distribué. C’est logique. Dès que le placement devient dynamique, le réseau doit absorber la disparition de la relation fixe entre une adresse, un processus et une machine. Le Service Discovery n’est pas un confort ajouté au-dessus des pods ; c’est ce qui permet à leur volatilité d’être acceptable.
Le stockage refuse de devenir abstrait#
Le calcul se recrée facilement parce qu’une image de conteneur est, par construction, copiable. Les données ont une autre personnalité. Elles possèdent un ordre, une durabilité, une localisation, un historique et parfois plusieurs téraoctets qu’on ne déplace pas parce qu’un scheduler a trouvé un nœud plus élégant.
Persistent Volumes, StorageClasses et CSI donnent une interface cohérente pour demander, attacher et monter du stockage. C’est une amélioration majeure. Mais cette interface ne transforme pas automatiquement un disque réseau en système distribué sûr. Elle masque les différences jusqu’au moment où elles redeviennent importantes : latence d’attachement, mode d’accès, topologie de zone, comportement au fencing, cohérence d’un snapshot, capacité réelle de restauration.
Un StatefulSet stabilise les identités et l’ordre de certains workloads. Il ne réplique pas les données à la place de PostgreSQL. Un volume persistant conserve des octets après la mort d’un pod. Il ne garantit ni leur cohérence applicative ni leur présence dans une autre région. Un snapshot peut capturer un volume exactement au mauvais moment. Une sauvegarde réussie dans un tableau de bord ne prouve rien tant qu’une restauration complète n’a pas été testée.
Le simple PostgreSQL d’un VPS devient soudainement une conversation à plusieurs dimensions. Où se trouve le primaire ? Comment l’élection est-elle protégée contre le split brain ? Qui possède le volume après une panne réseau ? Les replicas sont-ils synchrones ou asynchrones ? Les sauvegardes WAL quittent-elles le cluster ? Quel est le temps de reconstruction ? Que se passe-t-il si la zone entière disparaît ?
On peut exploiter PostgreSQL sur Kubernetes avec d’excellents opérateurs. Ils automatisent les tâches répétitives, formalisent le failover, gèrent les replicas et rendent les procédures plus cohérentes. Ils ne suppriment pas la nécessité de comprendre PostgreSQL. Ils déplacent une partie du runbook dans un contrôleur. C’est très précieux, à condition de savoir quel runbook a réellement été encodé.
Dans de nombreuses plateformes, le choix raisonnable consiste à orchestrer les applications stateless dans le cluster et à conserver les bases sur un service managé, des VM dédiées ou un cluster bare metal spécialisé. Ce n’est pas un échec du cloud native. C’est la reconnaissance que le cycle de vie du calcul et celui des données ne sont pas identiques.
Une plateforme qui récompense les frontières propres#
Kubernetes n’impose pas les microservices. On peut y déployer un monolithe, et c’est souvent une excellente décision. Un binaire bien structuré, répliqué derrière un Service, avec une base externe et quelques workers, reste plus facile à raisonner que quarante services séparés uniquement pour suivre une mode architecturale.
En revanche, la plateforme récompense les composants dont le cycle de vie est explicite. Une API peut être répliquée indépendamment des workers. Un consumer peut évoluer selon la profondeur d’une queue. Un traitement batch peut devenir un Job avec une fin observable. Une tâche périodique peut être portée par un CronJob plutôt que par un crontab caché sur worker-03. Un composant gourmand en mémoire peut recevoir sa propre classe de nœuds. Une fonction sensible peut être isolée par des politiques réseau et des comptes de service dédiés.
Cette récompense pousse naturellement vers la modularité, mais la bonne granularité reste une décision d’ingénierie. Séparer deux composants a un coût : protocole réseau, authentification, compatibilité de versions, retries, observabilité, ownership, déploiements coordonnés. Le monolithe paie ses dépendances à l’intérieur du processus. Les microservices les paient sur le réseau et dans l’organisation.
Docker Compose rend cette réalité très visible : tous les services tiennent dans un fichier et leur proximité reste évidente. Kubernetes permet à chaque équipe de posséder ses objets, ses pipelines et ses politiques, ce qui devient puissant à grande échelle mais peut aussi cacher le système global. Nomad offre une voie médiane intéressante lorsque l’on souhaite différents types de workloads et un scheduler robuste sans adopter tout l’écosystème de contrôleurs. systemd conserve un avantage décisif pour un agent lié au matériel, un proxy local ou un service qui doit démarrer avant la plateforme elle-même.
L’orchestrateur ne décide pas de l’architecture. Il rend certaines qualités moins coûteuses : processus jetables, configuration externe, endpoints stables, travail idempotent, séparation du batch et du service permanent. Il rend aussi les mauvaises frontières immédiatement visibles, généralement sous forme de timeouts, de dépendances circulaires et de déploiements qui ne peuvent pas évoluer indépendamment.
Le cluster fonctionne ; maintenant, expliquez pourquoi l’utilisateur souffre#
Installer un cluster fiable est un projet fini. L’observer correctement ne l’est jamais.
La difficulté d’exploitation vient du fait que plusieurs couches peuvent sembler saines tout en produisant un service dégradé. Les nœuds sont Ready, les pods sont Running, les probes passent, mais le percentile élevé d’une API se détériore. Une queue accumule du retard. Un pool de connexions est saturé. Le DNS répond avec une latence irrégulière. Une dépendance externe ralentit et les retries doublent le trafic. Aucun voyant isolé ne raconte l’histoire.
Prometheus fournit les séries temporelles et les alertes. Grafana permet de construire les vues. Loki centralise des logs sans obliger à monter chaque nœud. OpenTelemetry aide à transporter métriques, traces et journaux avec un contexte commun. Le tracing distribué révèle qu’une requête apparemment lente passe la majorité de son temps dans un service secondaire. Tout cela est utile, mais aucun outil ne choisit les bons signaux à la place de l’équipe.
Une plateforme peut collecter des millions de métriques et rester aveugle. Le travail consiste à relier la santé technique à l’expérience réellement servie. Taux d’erreur, latence, saturation et trafic restent une base solide, mais il faut aussi regarder l’âge du plus ancien message, le temps d’une opération métier, le nombre de paiements en attente ou la fraîcheur d’un index. Une alerte PodRestarting peut être du bruit. Une absence de redémarrage n’est pas une preuve de santé.
Le diagnostic est souvent plus difficile que la maintenance parce que Kubernetes répare rapidement les symptômes. Le pod fautif a disparu avant que l’ingénieur ne se connecte. Son filesystem éphémère aussi. Le scheduler l’a replacé ailleurs. Sans logs centralisés, événements conservés, profils et traces, l’auto-réparation efface une partie de la scène de crime.
J’accorde beaucoup de valeur à une commande très simple pendant un incident :
kubectl get events --all-namespaces --sort-by=.lastTimestamp
Elle ne remplace pas l’observabilité, mais elle rappelle que le cluster raconte ses décisions. Il faut conserver ce récit au-delà de la faible rétention native, le corréler aux changements Git et aux déploiements Helm, puis permettre à l’astreinte de passer d’un symptôme utilisateur à un pod, un nœud, une route ou un volume sans ouvrir quinze tableaux de bord sans lien.
Helm lui-même illustre le problème. Il apporte le packaging et le paramétrage qui manquent aux manifests bruts. Mais une commande comme :
helm upgrade --install paiements ./chart --atomic --timeout 10m
ne rend pas le changement sûr par nature. Elle rend son application cohérente et son échec plus gérable. La sûreté vient des sondes, de la compatibilité des schémas, des budgets de disponibilité, des métriques de déploiement et de la capacité à comprendre pourquoi --atomic a déclenché un retour arrière.
Un cluster n’est pas une propriété magique de haute disponibilité#
Le mot cluster rassure parfois trop vite. Trois machines ne forment pas automatiquement un service hautement disponible. Elles peuvent partager le même switch, la même alimentation, la même baie, le même stockage et le même domaine d’administration. Elles multiplient alors les nœuds sans multiplier réellement les domaines de panne.
Le control plane mérite d’être traité comme un système distribué à part entière. Les anciens « master nodes » — terme encore présent dans beaucoup de conversations — hébergent les composants qui portent l’API, le scheduling et l’état du cluster. Les workers exécutent les charges. En production, la haute disponibilité du control plane demande plusieurs instances, un datastore correctement opéré, des certificats gérés, une stratégie d’upgrade et surtout des sauvegardes restaurables. Un cluster dont etcd n’a jamais été restauré possède une hypothèse de sauvegarde, pas une sauvegarde.
Les rolling updates permettent de maintenir les nœuds sans interrompre le service, à condition d’avoir assez de capacité, des PodDisruptionBudgets réalistes et des applications capables de terminer proprement. Le drain d’un nœud est une excellente revue d’architecture : il révèle les pods non réplicables, les volumes trop attachés à une zone, les daemons oubliés et les services qui confondaient encore disponibilité et longévité d’un processus.
Le multi-région rend le dessin séduisant et l’exploitation sévère. La latence affecte les consensus et les bases. Les dépendances globales deviennent des points de couplage. Le routage des utilisateurs, la réplication des données et la gestion des secrets doivent être pensés ensemble. Étendre un seul cluster sur plusieurs régions est rarement le meilleur premier choix. Plusieurs clusters limitent le blast radius et clarifient certains domaines de panne, mais ils ajoutent distribution de configuration, identité, observabilité fédérée et procédures de bascule.
Le failover géographique ne se résume jamais à « démarrer les pods ailleurs ». La partie facile est souvent le calcul. Les questions difficiles concernent la fraîcheur des données, l’autorité d’écriture, le DNS ou l’anycast, les sessions actives, les files non répliquées et le retour vers la région principale. Une plateforme sérieuse documente non seulement comment basculer, mais comment éviter deux régions actives qui pensent chacune être la seule autorité.
Kubernetes et la virtualisation ne répondent pas à la même question#
Il est étonnant de voir encore opposer Kubernetes aux hyperviseurs. KVM, Proxmox, VMware, Hyper-V et les conteneurs système LXC travaillent à des frontières différentes.
La virtualisation construit des machines avec un noyau, une mémoire, des périphériques et un domaine d’isolation propres. L’orchestration de conteneurs organise des processus qui partagent le noyau de leur hôte. Une VM convient lorsqu’on a besoin d’un autre OS, d’une frontière de sécurité plus forte, d’un cycle de maintenance indépendant ou d’un environnement hérité. Un pod convient lorsqu’on souhaite empaqueter et replacer rapidement une charge conçue pour ce modèle.
Les deux coexistent parce que leurs propriétés se complètent. De très nombreux clusters tournent dans des VM. Le fournisseur peut remplacer un hôte physique, migrer une instance, attacher un disque et exposer une API d’infrastructure stable. Kubernetes voit alors des nœuds Linux ; l’équipe de virtualisation voit des invités. Sur Proxmox ou VMware, cette séparation permet de conserver les pratiques de sauvegarde, de segmentation et de gestion matérielle tout en offrant aux développeurs une plateforme déclarative.
Sur bare metal, on gagne en densité, en performance prévisible et en accès direct au matériel. On récupère aussi toute la responsabilité : provisionnement PXE, firmware, RAID ou Ceph, remplacement de carte, isolation de panne, automatisation du système de base. Ce choix est parfaitement valable lorsque l’échelle, les accélérateurs ou les contraintes de coût le justifient. Il exige simplement de ne pas confondre absence d’hyperviseur et absence de couche d’infrastructure.
LXC occupe encore un autre espace. Pour héberger plusieurs environnements Linux durables sur un serveur Proxmox, avec des adresses stables et une administration proche d’une machine, il reste extrêmement efficace. systemd-nspawn ou LXC peuvent être plus honnêtes qu’un cluster complet quand le besoin est de compartimenter des services d’infrastructure plutôt que d’orchestrer des applications éphémères.
Le cloud ne supprime aucune loi de Linux#
Un cluster managé sur AWS, Azure ou GCP réduit une charge importante : construction et disponibilité du control plane, intégration des identités, load balancers, volumes, upgrades encadrés, parfois autoscaling des nœuds. Cette valeur est réelle. Elle permet à une équipe de se concentrer davantage sur la plateforme consommée par ses applications.
Mais sous l’API se trouvent toujours des machines Linux, des routes, des MTU, des tables de connexion, des quotas, des disques et des processus. Le cloud remplace la manipulation directe par des contrats de service. Il ne suspend pas les contraintes physiques.
Un volume a toujours une latence et une topologie. Une adresse privée doit toujours être routée. Un load balancer possède des health checks et des timeouts. Un nœud peut manquer d’inodes. Le conntrack peut se remplir. Une région peut perdre un service dépendant. Les permissions peuvent empêcher le contrôleur de créer une ressource. Simplement, la frontière de diagnostic se déplace : une partie est visible par kubectl, une autre par l’API cloud, une dernière appartient au fournisseur.
L’illusion devient dangereuse quand l’équipe ne sait plus descendre d’une abstraction. Les bons ingénieurs de plateforme peuvent partir d’un objet Kubernetes, retrouver le pod, le nœud, l’interface, la route, le volume et l’événement cloud correspondant. Ils n’effectuent pas ce parcours tous les jours. Ils savent seulement qu’il existe et maintiennent les accès, les métriques et les runbooks nécessaires pour l’emprunter sous pression.
Kubernetes masque de la complexité comme un filesystem masque un disque. Cette abstraction est extraordinairement utile. Personne n’en conclut pourtant que les disques ne tombent plus en panne. Le cloud et l’orchestrateur fonctionnent de la même manière : ils donnent des interfaces plus stables que les composants sous-jacents, sans abolir leurs modes de défaillance.
Quand il vaut mieux ne pas construire de cluster#
Il existe des projets pour lesquels choisir Kubernetes est une dépense d’attention sans retour suffisant. Une application unique, un trafic faible, une petite équipe et un VPS fiable constituent souvent ce cas. Le déploiement peut tenir dans une image, une unité systemd, un reverse proxy et une sauvegarde externalisée. La solution est observable, compréhensible et réparable avec peu de couches.
Docker Compose devient pertinent lorsqu’il faut assembler plusieurs services sur ce même hôte. Il donne un réseau, des volumes, des dépendances lisibles et un format de déploiement partagé. Avec un pipeline correct, des healthchecks, une stratégie de sauvegarde et une supervision externe, il peut soutenir une production sérieuse. Sa limite n’est pas un manque de respectabilité. Sa limite est le domaine d’orchestration : une machine.
systemd reste mon choix naturel pour les services fondamentaux liés au nœud : VPN, agents matériels, stockage, exporters, bootstrap ou applications simples dont le packaging en conteneur n’apporte rien. Ses dépendances, politiques de redémarrage, sandboxing et intégration au journal sont souvent sous-utilisés.
Nomad mérite une évaluation honnête lorsque l’équipe veut un scheduler multi-nœuds plus simple, capable d’exécuter des conteneurs ou des binaires, et accepte un écosystème moins vaste. Il réduit le nombre de concepts à exploiter. En contrepartie, beaucoup d’intégrations et de contrôleurs disponibles nativement autour de Kubernetes devront être choisis, assemblés ou développés autrement.
LXC convient lorsque le besoin ressemble davantage à de petites machines Linux persistantes qu’à des workloads réconciliés. Pour un hébergeur classique, un laboratoire ou une plateforme interne de taille modeste, cette stabilité peut être une qualité et non un retard technologique.
La mauvaise raison d’adopter Kubernetes est la peur de ne pas paraître moderne. Une meilleure raison serait qu’au moins plusieurs des problèmes suivants sont déjà concrets : déploiements fréquents par plusieurs équipes, besoin de placement multi-nœuds, exigences de disponibilité, environnements reproductibles, politiques communes, diversité de workloads, autoservice interne, remplacement régulier de capacité. Le cluster doit payer son loyer opérationnel.
Il faut aussi compter l’équipe plateforme. Un service managé réduit la charge du control plane, pas celle des manifests, du réseau, des politiques, des upgrades d’API, de l’observabilité, des coûts et de la sécurité. Si personne ne possède ces sujets, le cluster devient une dépendance critique administrée à temps partiel. Un bon VPS automatisé est alors plus résilient qu’une plateforme sophistiquée comprise par personne.
L’orchestrateur est devenu plus important parce que les serveurs sont devenus insuffisants comme unité de raisonnement#
Les entreprises n’ont pas adopté Kubernetes uniquement parce qu’elles avaient des milliers de conteneurs. Beaucoup n’en avaient pas. Elles avaient surtout dépassé le point où une collection de serveurs, même bien administrés, pouvait offrir une interface cohérente à des dizaines d’équipes et à des changements quotidiens.
Le serveur reste indispensable. Il exécute toujours les instructions, porte le noyau, reçoit les paquets et attache les volumes. Mais il ne suffit plus comme unité de décision. Une application moderne existe à travers plusieurs machines, plusieurs versions pendant un déploiement, plusieurs zones de panne et plusieurs dépendances. Sa réalité opérationnelle n’est contenue dans aucun hôte isolé.
L’orchestrateur devient alors plus important non parce qu’il remplace les serveurs, mais parce qu’il porte l’intention qui leur manque. Il sait combien de répliques doivent exister, quelles contraintes elles doivent respecter, quels endpoints sont prêts, quelle version doit progresser et quelles ressources sont demandées. Les serveurs fournissent la capacité ; la plateforme fournit la continuité.
Ce déplacement a une conséquence organisationnelle forte. L’opération manuelle n’est plus le chemin nominal. L’humain décrit, révise et améliore les mécanismes qui opèrent. Il intervient sur les exceptions, mais cherche ensuite à transformer l’exception comprise en politique, en contrôleur, en test ou en alerte. Le bon résultat d’un incident n’est pas seulement un service rétabli. C’est une classe d’incidents devenue plus difficile à reproduire.
Il ne faut pas idéaliser cette automatisation. Un contrôleur exécute fidèlement une mauvaise intention. GitOps propage rapidement une configuration erronée. Un opérateur de base de données peut automatiser un failover destructeur. La plateforme augmente autant la portée de la rigueur que celle de l’erreur. C’est pourquoi les validations, les politiques d’admission, les déploiements progressifs, les environnements de préproduction et les limites de blast radius comptent davantage à mesure que l’automatisation gagne en pouvoir.
Après des années d’exploitation, on finit par regarder différemment la fiabilité. Le matériel échoue, mais de façon relativement compréhensible. Les processus meurent. Les réseaux perdent des paquets. Les disques ralentissent avant de disparaître. Ces pannes sont inévitables, donc les plateformes apprennent à les absorber.
L’humain, lui, échoue de manière créative. Il oublie une étape uniquement sur le troisième serveur. Il applique une commande dans le mauvais contexte. Il retarde une mise à jour parce que la machine est trop précieuse pour être redémarrée. Il copie un secret dans un fichier temporaire. Il suit un runbook devenu faux après deux évolutions. Il prend une bonne décision locale qui rompt un invariant global invisible.
À partir d’une certaine taille, l’humain devient effectivement le composant le moins fiable de l’infrastructure — non parce qu’il serait incompétent, mais parce qu’on lui demande de maintenir mentalement un système trop vaste, trop dynamique et trop interconnecté. Kubernetes répond à ce problème en donnant une forme exécutable à l’intention et en répétant sans fatigue les opérations de convergence.
La leçon la plus utile n’est donc pas qu’il faut tout migrer vers Kubernetes. Elle est que l’exploitation moderne doit être conçue autour de la perte, du remplacement et de la répétition. Un bon système suppose qu’un nœud disparaîtra, qu’un déploiement échouera, qu’un certificat expirera, qu’un opérateur se trompera et qu’une dépendance ralentira. Il ne cherche pas à empêcher absolument ces événements. Il réduit leur portée et rend le retour à un état connu plus rapide, plus observable et moins dépendant d’un héros disponible à deux heures du matin.
Dans les petites infrastructures, cette philosophie peut être appliquée avec systemd, Ansible, Docker Compose et d’excellentes sauvegardes. Dans les plateformes plus vastes, Kubernetes fournit un langage commun et une mécanique de réconciliation suffisamment générale pour que des équipes différentes partagent les mêmes invariants. Le choix de l’outil dépend de l’échelle. La direction, elle, est la même : décrire l’état, automatiser sa restauration, observer les écarts et considérer les machines comme remplaçables.
Le serveur n’a pas perdu son importance technique. Il a perdu son statut de centre narratif. Ce qui compte désormais, ce n’est plus la machine qui héberge le service à cet instant, mais la capacité du système à continuer de produire le service quand cette machine, ce processus ou cette zone ne sera plus là.
RN 005 · Carnet d’infrastructureL’état désiré survit aux machines qui le matérialisent.
Toutes les publications