Une requête humaine envoyée à un agent IA en déclenche en moyenne une vingtaine côté infrastructure — c’est le chiffre cité par Bob Killen et Daniel Krook, tous deux directeurs à la CNCF, dans un entretien repris par The New Stack le 16 octobre 2026. Ces agents attendent une réponse en moins de 200 millisecondes, alors qu’un pod Kubernetes n’est garanti de démarrer qu’en environ une seconde. L’écart entre ces deux chiffres, ce n’est pas un détail de perf : c’est en train de redéfinir ce qui fait tomber un control plane.
Et la réponse n’est pas « trop de nodes ». Joe Betz, tech lead du SIG API Machinery de Kubernetes, a publié via The New Stack une analyse qui mérite d’être lue par quiconque opère un cluster au-delà de quelques centaines de nodes — ou qui commence à y faire tourner des charges d’agents. Son argument : un control plane peut saturer selon trois axes complètement indépendants, et résoudre l’un ne fait strictement rien pour les deux autres.
Le nombre de nodes n’est que la moitié de l’histoire
Le réflexe classique, c’est de dimensionner le control plane en fonction du nombre de nodes attendu. Ça marche pour un type de charge précis, mais pas pour les deux autres que décrit Betz. Voici les trois axes, avec les chiffres qu’il donne pour chacun.
Axe 1 : saturé par les nodes (flottes d’entraînement ML, clusters géants)
Le symptôme classique : les heartbeats des kubelets finissent par noyer le control plane. Le kube-apiserver consomme de plus en plus de mémoire, et etcd commence à peiner. À 100 000 nodes avec un heartbeat toutes les 10 secondes, le simple maintien en vie (« liveness ») représente déjà environ 10 000 écritures par seconde — et dans les mesures de Betz, le renouvellement des leases (les baux de heartbeat) compte pour près de 70% du débit d’écriture total. Autrement dit : sur un très gros cluster, la majorité de la charge d’écriture d’etcd ne sert à rien d’autre qu’à dire « je suis toujours vivant ». C’est typiquement le profil des flottes d’entraînement ML qui pilotent des GPU via la Dynamic Resource Allocation — beaucoup de nodes, du heartbeat classique, pas forcément beaucoup de churn.
Axe 2 : saturé par le churn (plateformes d’agents)
Ici, le nombre de nodes reste modeste, mais le taux de rotation des objets explose. Une session d’agent est une custom resource qu’on crée, suspend, reprend et détruit, potentiellement des milliers de fois par minute. Chaque transition de cycle de vie est une écriture, donc le débit dépend de l’activité des sessions, pas du nombre de machines. C’est précisément l’axe qui devient pertinent avec les plateformes d’agents IA décrites plus haut, même sur un cluster de taille raisonnable.
Axe 3 : saturé par l’état (clusters de plateforme)
Beaucoup de types d’objets différents, et des dizaines de milliers d’objets globalement peu actifs — l’exemple donné par Betz évoque environ 200 opérateurs tournant sur le même cluster. Le piège : chaque kube-apiserver maintient un cache de watch complet en mémoire, donc le coût mémoire total se multiplie par le nombre d’instances d’apiserver. Ajouter des apiservers pour tenir la charge de requêtes — un réflexe courant, y compris dans la configuration par défaut de kOps — augmente donc aussi la consommation mémoire globale, pas seulement la capacité.
Quatre points de découplage, pas une solution miracle
Betz appelle ça des « seams » : des points de découplage entre composants, en général une frontière réseau, qui permettent de changer une pièce sans toucher au reste. Il en identifie quatre, chacun ciblant un axe précis.
| Point de découplage | Ce qu’il contrôle | Axe soulagé | État |
|---|---|---|---|
| Contrat de stockage | Quel etcd stocke quel type de ressource | Churn | Le flag --etcd-servers-overrides existe déjà pour les ressources natives — rien d’équivalent pour les custom resources à ce jour |
| Contrat de liveness des nodes | Comment les heartbeats atteignent le control plane | Nombre de nodes | Une couche dédiée côté nodes absorbe les renouvellements ; le changement côté etcd (rafraîchir les leases en mémoire plutôt que par un commit Raft complet) bénéficie à tous les clusters |
| Axe de sharding | Comment contrôleurs, caches et stockage se répartissent les objets | Les trois à la fois | KEP-5866 propose un filtrage par plage de hash — la coordination entre shards reste un problème ouvert |
| Résidence du cache | Ce que chaque apiserver garde en mémoire | État | Un prototype à deux shards réduit le tas mémoire par shard d’environ moitié — pas encore disponible en amont |
Un point que Betz insiste à corriger : etcd n’est pas le problème et ne doit pas être remplacé. Son argument, c’est qu’un stockage consistant généraliste ne devrait simplement pas absorber du trafic qui n’a pas besoin de durabilité forte — les events et les leases de nodes, typiquement.
L’échelle de recettes, en binaires upstream standards
Au-delà de la théorie, l’article propose une grille concrète de dimensionnement, composée uniquement à partir de briques déjà disponibles dans Kubernetes upstream :
- HA classique — jusqu’à 5 000 nodes, 2 à 3 control planes identiques, aucun point de découplage nécessaire. Configuration mesurée en conditions réelles.
- Role-Split — de 5 000 à 20 000 nodes, des pools de machines séparés pour l’API serving, le scheduler, le controller-manager et etcd. Déjà disponible, bénéfice pas encore formellement mesuré.
- Node Plane — de 20 000 à 65 000 nodes, Role-Split plus une couche dédiée qui absorbe les baux de heartbeat. Mesuré, sur un seul déploiement de référence.
- Partitioned Store — autour de 100 000 nodes, Node Plane plus un découpage des types de ressources sur des stockages indépendants. Démontré en externe.
- Sharded Slice — au-delà, K unités de shard, chacune un contrôleur plus un apiserver épinglé sur une plage de hash. N’existe pas encore en pratique.
Note que cette logique de répartition par unités indépendantes ressemble, à un niveau d’abstraction différent, à ce que fait Karmada pour répartir une charge sur plusieurs clusters plutôt que sur plusieurs shards d’un même control plane — deux réponses distinctes au même problème de fond : un seul control plane ne peut pas tout absorber indéfiniment.
Betz le dit sans détour : aucune recette testée à l’échelle n’a encore été publiée pour les clusters churn-bound ou state-bound. Pour le nombre de nodes, le chemin est balisé ; pour le churn et l’état, c’est encore un terrain de recherche.
Ce que ça change si ton cluster fait 500 nodes, pas 100 000
Sincèrement, si tu gères un cluster de taille courante, l’axe « nombre de nodes » ne te concerne probablement pas avant longtemps — les seuils dont parle Betz sont ceux des hyperscalers et des plus gros clusters d’entraînement ML. Ce qui change la donne, c’est l’axe churn : dès que tu fais tourner une plateforme d’agents IA, même sur un cluster modeste, le taux de création/destruction d’objets peut grimper très vite, et c’est un axe de saturation complètement indépendant de ta taille de cluster. Le réflexe utile ici n’est pas d’ajouter des nodes au control plane, mais de surveiller le débit d’écriture etcd (etcd_server_proposals_committed_total et la latence de etcd_disk_wal_fsync_duration_seconds sont de bons points de départ côté métriques) avant que ça ne devienne un incident. Sur ce terrain, le pattern RBAC strict et l’allowlist d’outils décrits pour les agents kagent valent aussi la peine d’être appliqués à n’importe quel contrôleur custom qui crée des objets à haute fréquence.
FAQ
Mon cluster de 50 nodes peut-il être concerné par ces problèmes ?
Pas par l’axe « node-bound » décrit ici, qui ne devient critique qu’à très grande échelle. Mais l’axe « churn-bound » peut te toucher dès qu’un contrôleur ou une plateforme d’agents crée et détruit des objets à haute fréquence, indépendamment de la taille du cluster.
Faut-il arrêter d’ajouter des instances d’apiserver pour tenir la charge ?
Pas systématiquement, mais il faut savoir ce que ça coûte : chaque apiserver supplémentaire porte son propre cache de watch complet en mémoire. Ça augmente la capacité de traitement des requêtes, mais ça multiplie aussi la consommation mémoire totale du cluster.
Le flag --etcd-servers-overrides est-il utilisable aujourd’hui ?
Oui, il est déjà documenté dans la référence officielle kube-apiserver et permet de router des types de ressources natifs vers des backends etcd séparés. Sa limite actuelle : il ne couvre pas les custom resources, qui nécessitent une configuration de stockage par CRD pas encore disponible.
Où en est KEP-5866 ?
C’est une proposition d’amélioration encore en phase de prototype, qui ajoute un filtrage par plage de hash pour répartir le trafic API. La coordination entre shards et le sharding du controller-manager restent des problèmes non résolus à ce stade.
À retenir avant ton prochain audit de capacité
La prochaine fois qu’un tableau de bord grafana montre un control plane sous tension, résiste à la tentation de regarder uniquement le nombre de nodes. Vérifie le débit d’écriture etcd et sa répartition entre leases, events et objets métier — ça te dira en deux minutes sur quel axe tu es en train de saturer, et donc quel correctif a une chance de fonctionner. Si tu fais déjà tourner une plateforme d’agents ou de CI à forte rotation d’objets sur Kubernetes, ce diagnostic vaut le coup d’être posé maintenant, avant que ça devienne un incident un vendredi soir.

Laisser un commentaire