> ## Content Index
> Fetch the complete content index at: https://www.sfeir.dev/llms.txt
> Use this file to discover other available public pages before exploring further.

# Agentic AI at scale : avec Agent Substrate et AX, Google Cloud fait de Kubernetes le socle des agents IA
- URL: https://www.sfeir.dev/cloud/agentic-ai-at-scale-avec-agent-substrate-et-ax-google-cloud-fait-de-kubernetes-le-socle-des-agents-ia/
- Published: 2026-10-07T07:18:13.000Z
- Updated: 2026-10-07T07:42:17.000Z
- Description: Pour exécuter des agents IA à grande échelle, Google a construit AX et Agent Substrate. Leur secret : garder l'ergonomie de Kubernetes tout en le contournant pour stocker l'état des agents et décider de leur placement. Décryptage d'une architecture qui fait de Kubernetes un simple socle.
- Author: Mathieu BODIN
- Tags: Cloud, Kubernetes, Agent AI, GCP, Google, Agent IA

[Boucle agentique](https://www.sfeir.dev/ia/pattern-de-conception-agentique-definition/), frameworks, plateformes d'agents clés en main : quand on parle d'IA agentique, on parle presque toujours de ce que fait l'agent. Beaucoup plus rarement de l'endroit où il tourne. Or, à grande échelle, c'est là que tout se joue. Un agent passe l'essentiel de son temps à attendre, et pendant ce temps, les ressources qu'il immobilise sont payées à ne rien faire. Pour résoudre ce problème, Google propose AX, un orchestrateur d'agents open source, basé sur le runtime Agent Substrate. Leur approche : garder Kubernetes, mais le cantonner au rôle de socle. Il fournit les machines et les pods ; l'état des agents et leur placement se décident ailleurs, à la milliseconde.

**AX : décrire une tâche d'agent comme un manifeste Kubernetes**  
Le projet AX se présente comme un orchestrateur déclaratif : on décrit dans un fichier YAML ce que l'on veut obtenir, et AX se charge du reste. Il met la tâche en sandbox, prépare son espace de travail, verrouille son réseau et l'exécute. Le dépôt [google/ax](https://github.com/google/ax?ref=sfeir.dev) affiche l'ambition de faire tourner des milliards de tâches par cluster. 

L'expérience est volontairement calquée sur *kubectl*, l'outil en ligne de commande de Kubernetes. On retrouve les mêmes verbes, la même structure de manifeste (*apiVersion*, *kind*, *spec*) et une [CLI](https://github.com/google/ax?ref=sfeir.dev#cli-usage) qui suit le contexte de cluster actif. AX repose sur quatre primitives :

- ***Task* :** la plus petite unité d'exécution isolée (image, commande, CPU, mémoire, variables d'environnement). Elle est volontairement petite et jetable ;
- ***Workspace*** : l'environnement de travail de l'agent, avec des dépôts Git clonés, des serveurs [MCP](https://www.sfeir.dev/mcp-model-context-protocol-la-cle-pour-connecter-les-ia-au-monde-reel-2) et des registres de skills. On le déclare une fois, et il est monté dans chaque sandbox ;
- ***Gateway*** : la frontière réseau, avec les ports exposés et une liste blanche d'hôtes sortants. Typiquement, le fournisseur de LLM et le serveur Git, rien d'autre ;
- **Model** : non pas un modèle, mais une configuration (fournisseur, identifiant, paramètres) qui pointe vers le secret contenant la clé d'API. Centralisée, elle se modifie d'un seul *ax apply*, et les composants d'AX eux-mêmes s'en servent, par exemple pour préparer un espace de travail à partir d'un objectif.

Voici à quoi ressemble une tâche minimale, inspirée de l'exemple du [README](https://github.com/google/ax?ref=sfeir.dev#----ax) :

```yaml
apiVersion: ax.io/v1alpha1
kind: Workspace
metadata:
  name: golang
spec:
  git:
    - repo: https://github.com/golang/go.git
      branch: "my-fix"
---
apiVersion: ax.io/v1alpha1
kind: Task
metadata:
  name: test
spec:
  workspaces:
    - name: golang
      goal: "Ensure that Go tool chain is available"
  debug: true # autorise ax ssh
```

Le champ `goal` mérite qu'on s'y arrête : ici, plutôt que de détailler chaque étape d'installation, on formule un objectif en langage naturel, et c'est un agent qui prépare l'espace de travail pour l'atteindre. 

Ensuite, quelques commandes suffisent :

- `ax apply -f task.yaml` crée la tâche.
- `ax watch task test` suit son avancement en direct.
- `ax ssh test` permet de regarder par-dessus l'épaule de l'agent.
- `ax suspend task test` fige l'état de la tâche, et `ax resume task test` la fait repartir exactement là où elle s'était arrêtée.

Jusqu'ici, tout ressemble à du Kubernetes. C'est sous le capot que les choses divergent.

### Pourquoi les agents IA ne rentrent pas dans les cases de Kubernetes

[Kubernetes](https://www.sfeir.dev/kubernetes-definition/), pour faire simple, est un système qui répartit des applications empaquetées en conteneurs sur un parc de machines. L'unité qu'il manipule s'appelle un pod : un ou plusieurs conteneurs qui tournent ensemble sur une même machine. Kubernetes a été conçu autour de deux grandes familles de charges de travail :

- Le **microservice** : sans état, répliqué, toujours allumé. Quand la charge monte, on ajoute des copies.
- Le **job batch** : il démarre, calcule, se termine. On le lance et on attend son code de retour.

[Un agent IA ](https://www.sfeir.dev/ia/llm-qui-assiste-a-des-llm-qui-produisent-comment-integrer-son-equipe-dagent/)n'est ni l'un ni l'autre. Il accumule de l'état au fil de sa session, exécute du code qu'on ne maîtrise pas toujours, appelle des LLM et des serveurs d'outils, et peut consommer du budget en boucle. Surtout, il attend : la réponse du modèle, le résultat d'un outil, la validation d'un humain.

Imaginez un restaurant où chaque client garde sa table réservée toute la journée, même quand il est parti se promener. La salle est pleine, mais personne ne mange. C'est exactement ce qui se passe avec un agent qui occupe un pod pendant qu'il attend : de la capacité payée pour rien. Multipliez par des milliers, puis par des millions d'agents, et vous obtenez le problème qu'Agent Substrate cherche à résoudre.

![Un agent IA ne travaille que par à-coups, entre deux attentes.](https://storage.ghost.io/c/0b/31/0b31478e-a66a-46f1-8c34-d44388e21192/content/images/2026/09/schema-A-trois-profils-de-charge-v2.png)

Un agent IA ne travaille que par à-coups, entre deux attentes.

### Il n'y a pas que ça qui coince dans Kubernetes

Dans un cluster Kubernetes, tout l'état du système est stocké dans etcd, une base de données clé-valeur qui sert de mémoire au cluster. Kubernetes permet d'ajouter ses propres types d'objets, appelés Custom Resource Definitions (CRD). Ils sont eux aussi stockés dans etcd et exposés par l'API server, le point d'entrée unique du cluster.

Le réflexe naturel serait donc de faire de chaque Task une Custom Resource (CR). Le [document de conception d'AX](https://github.com/google/ax/blob/main/DESIGN.md?ref=sfeir.dev) l'écarte explicitement : stocker des millions de tâches courtes sous forme de CR pousse etcd hors de sa zone de confort.

La raison est simple : etcd a été pensé pour des métadonnées, c'est-à-dire peu d'objets, de petite taille, qui changent rarement. Un parc d'agents lui demande exactement l'inverse. Sa capacité est volontairement limitée : [2 Go par défaut, 8 Go au maximum recommandé](https://etcd.io/docs/latest/dev-guide/limit/?ref=sfeir.dev). Et chaque écriture est coûteuse, car elle doit être confirmée par une majorité des serveurs etcd avant d'être validée. Or chaque changement de statut d'un agent est une écriture, et il y en a des millions.

Kubernetes connaît bien ces limites. Sa [documentation sur les grands clusters](https://www.kubernetes.io/docs/setup/best-practices/cluster-large/?ref=sfeir.dev) indique qu'il est conçu pour 150 000 pods au plus par cluster, et conseille déjà d'isoler certains objets très volatils dans une instance etcd dédiée. On est loin du million de tâches, et plus encore du milliard visé par AX et Agent Substrate. Et quand etcd souffre, c'est tout le plan de contrôle qui ralentit, y compris pour les applications qui n'ont rien à voir avec les agents.

AX fait donc un autre choix. Une Task est un simple hash dans Redis, et chaque changement d'état est un événement publié dans un Redis Stream, une sorte de file de messages. Le plan de contrôle est un pipeline court :

- La CLI `ax` parle en gRPC à `ax-server`, une API sans état qui valide la demande, l'enregistre dans Redis et publie un événement.
- Des `ax-controller`, en autant de réplicas que nécessaire, consomment ce flux et font avancer les tâches.
- Ces contrôleurs délèguent l'exécution à Agent Substrate.

Kubernetes, lui, ne voit que les composants d'AX, déployés comme n'importe quelle application, et le secret qui porte la clé d'API. On garde l'ergonomie de Kubernetes sans son stockage. Et Agent Substrate applique exactement le même principe un étage plus bas.

### Agent Substrate : beaucoup d'agents, peu de pods

Si AX est la vitrine, Agent Substrate en est la fondation. Son [README](https://github.com/agent-substrate/substrate?ref=sfeir.dev) résume le principe en une phrase : faire correspondre un grand nombre d'« acteurs » à un petit nombre de « workers » prêts à l'emploi, en misant sur le fait que les agents restent inactifs la plupart du temps. C'est ce qui permet un multiplexage massif : bien plus d'agents qu'il n'y a de pods pour les exécuter.

Le vocabulaire change donc. Un acteur, c'est l'application à faire tourner : un agent IA le plus souvent, mais pas forcément, car le projet se veut peu prescriptif. Un worker, c'est un pod Kubernetes déjà démarré, qui attend dans un pool qu'on lui confie un acteur. Entre les deux, Substrate gère le cycle de vie des acteurs (création, suspension, réveil), les affecte aux workers en temps réel et route le trafic vers eux.

### Endormir, puis réveiller en moins d'une seconde

Un acteur n'occupe un worker que lorsqu'il travaille. Quand il retombe en attente, Substrate prend un instantané complet de son état, mémoire vive et disque compris. Il l'envoie vers un stockage d'objets, comme Google Cloud Storage, puis rend le worker au pool. Au réveil suivant, l'acteur est restauré sur n'importe quel worker disponible, qui n'est pas forcément le même.

Pour que le tout premier réveil soit rapide lui aussi, Substrate utilise des « golden snapshots » : chaque modèle d'acteur est démarré une fois, puis figé. On restaure cette image déjà chaude plutôt que de lancer un conteneur à froid. 

Côté isolation, chaque acteur tourne dans une sandbox [gVisor](https://gvisor.dev/?ref=sfeir.dev) ou dans une [micro-VM](https://blog.stephane-robert.info/docs/virtualiser/type1/firecracker-micro-vm/?ref=sfeir.dev), à partir d'images OCI standard. Les chiffres avancés sont ambitieux :

- une densité dix fois supérieure à celle d'un runtime de conteneurs classique ;
- une reprise en moins de 500 ms ;
- plus de 500 activations par seconde.

La [démonstration officielle](https://www.youtube.com/watch?v=ZEzkCFJkzjY&ref=sfeir.dev) fait jongler environ 250 acteurs avec état sur 8 pods, soit plus de 30 acteurs par pod. Ce sont des chiffres annoncés par les auteurs du projet, et l'équipe vise bien plus haut. Sa [documentation d'architecture](https://github.com/agent-substrate/substrate/blob/main/docs/architecture.md?ref=sfeir.dev#north-star-metrics) fixe trois objectifs de référence : un milliard d'agents par cluster, actifs ou en veille, un réveil en 100 ms pour 95 % des requêtes, et 1 000 réveils par seconde. Ce ne sont encore que des ambitions : la même documentation prévient qu'une grande partie de l'architecture reste à construire.

### Pour aller plus vite : un ordonnancement à deux étages

Dans Kubernetes classique, lancer un pod passe par plusieurs étapes. L'API server enregistre la demande, puis l'ordonnanceur (kube-scheduler) choisit une machine. Cette machine télécharge ensuite l'image et démarre le conteneur. Comptez plusieurs secondes : c'est trop lent pour un agent qui doit se réveiller à chaque sollicitation.

Substrate ne supprime pas cet ordonnanceur, il en ajoute un second, au-dessus. Kubernetes continue de placer les pods workers, rarement et à l'avance, et d'en ajouter via l'autoscaling quand la demande monte. Substrate, lui, décide en temps réel quel acteur occupe quel worker. 

Voici le trajet d'une requête adressée à un agent endormi :

![Réveiller un agent : aucun nouveau pod, juste un worker prêt et un instantané restauré.](https://storage.ghost.io/c/0b/31/0b31478e-a66a-46f1-8c34-d44388e21192/content/images/2026/09/schema-B-trajet-requete-agent-endormi-v2.png)

Réveiller un agent : aucun nouveau pod, juste un worker prêt et un instantané restauré.

- Le client joint l'acteur via le routeur de Substrate, basé sur Envoy. Il le désigne par un nom DNS de la forme `<acteur>.<atespace>.actors.resources.substrate.ate.dev` (un *atespace* est l'équivalent, chez Substrate, d'un namespace Kubernetes), ou par un en-tête HTTP dédié.
- Le routeur met la requête en attente et demande le réveil de l'acteur.
- L'API de Substrate choisit un worker prêt dans le pool. Pas de nouveau pod à planifier, pas d'image à télécharger.
- Sur la machine du worker, un agent local récupère le dernier instantané de l'acteur et restaure sa sandbox.
- La requête d'origine est transmise à l'acteur réveillé.

Si tous les workers sont occupés, le routeur peut « garer » la requête le temps qu'une place se libère, plutôt que de répondre par une erreur 503\. Et comme pour AX, les acteurs et leurs affectations sont stockés hors d'etcd, dans une base de données propre à Substrate.

### Trois étages, trois métiers

Au final, l'ensemble se lit comme un empilement de trois strates, chacune avec un rôle bien distinct :

![Architecture en trois couches : AX exprime l'intention, Agent Substrate place les agents, Kubernetes fournit la capacité](https://storage.ghost.io/c/0b/31/0b31478e-a66a-46f1-8c34-d44388e21192/content/images/2026/09/schema-C-trois-etages-ax-substrate-kubernetes-v2.png)

Architecture en trois couches : AX exprime l'intention, Agent Substrate place les agents, Kubernetes fournit la capacité

- **Kubernetes fournit la capacité.** Il gère les machines, place les pods workers et ajuste leur nombre, ainsi que les secrets et les droits d'accès. En revanche, il ne sait pas quel agent tourne dans quel pod.
- **Agent Substrate décide, en temps réel, qui occupe cette capacité.** Il suspend, réveille, place et route les acteurs, à la milliseconde.
- **AX exprime l'intention.** Il porte la déclaration des tâches, leur espace de travail, leurs règles réseau et l'ergonomie façon `kubectl`.

Le critère de partage est élégant : c'est la fréquence de changement. Ce qui bouge rarement, comme la configuration des pools de workers ou les modèles d'acteurs, reste dans Kubernetes sous forme de CRD, et profite ainsi de ses droits d'accès et de son audit. Ce qui change des milliers de fois par seconde, comme l'affectation d'un acteur à un worker, est confié à la base de données de Substrate, conçue pour encaisser ce rythme sans solliciter etcd.

La conséquence est très concrète pour un développeur : une Task n'est pas un pod. Un `kubectl get pods` affichera des workers anonymes et interchangeables. Pour savoir quel agent tourne où à un instant donné, il faut interroger AX ou Substrate, pas Kubernetes.

### Les gains, et la facture

Sur le papier, les bénéfices sont nets :

- Un agent inactif ne coûte plus de mémoire réservée, seulement du stockage d'objets.
- La reprise se compte en fractions de seconde, et non en secondes.
- L'isolation est active par défaut : noyau *sandboxé*, sorties réseau en liste blanche.
- Les agents partagent le même socle que le reste des charges du cluster, ce qui simplifie la gestion des machines.

Mais la facture existe, et elle est surtout opérationnelle :

- **Deux plans de contrôle de plus** : Redis pour AX, une base de données et une API pour Substrate. Il faut les rendre hautement disponibles et les sécuriser.
- **Une observabilité plus difficile** : un acteur change de worker au fil de ses réveils. Il faut donc recoudre ses logs et ses métriques par acteur, et non par pod.
- **Un problème de données** : des millions d'instantanés à stocker et à faire voyager. Selon la documentation du projet, leur nettoyage (garbage collection) n'est pas encore implémenté.
- **Des outils Kubernetes en partie aveugles** : quotas et règles réseau s'appliquent au pool de workers, pas à chaque agent.
- **Une maturité encore faible** : les API sont instables, et une partie de l'architecture est décrite par ses auteurs comme « aspirationnelle ». Sur le dépôt d'AX, les contributions externes sont en pause le temps que le cœur se stabilise.

AX a aussi une limite très terre à terre : pour ses propres besoins, comme la préparation d'un espace de travail à partir d'un objectif, il ne sait dialoguer qu'avec Gemini, comme le documente une [issue récente](https://github.com/google/ax/issues/375?ref=sfeir.dev). Le code de l'agent, lui, tourne dans l'image de son choix et peut appeler un autre fournisseur si la Gateway l'autorise. Mais pour qui veut tout faire tourner avec un modèle hébergé dans son propre cluster, sans le moindre appel externe, c'est aujourd'hui bloquant.

### Kubernetes, socle plutôt que chef d'orchestre

Ce que montrent AX et Agent Substrate, c'est moins la fin de Kubernetes que sa redéfinition. Kubernetes reste indispensable : il fournit les machines, place les pods et gère leur mise à l'échelle. 

Mais face à une charge qui dort la plupart du temps et doit se réveiller en une fraction de seconde, il n'est plus le bon niveau de décision. L'état des agents quitte etcd, et un second ordonnanceur prend le relais pour placer les agents dans les pods : on garde le socle, et on ajoute la couche qui manque.

Faut-il pour autant se lancer ? Pour un développeur curieux, le README d'AX et la démo de Substrate valent le détour, ne serait-ce que pour comprendre comment l'infrastructure s'adapte aux agents. Pour une équipe plateforme, l'ensemble est prometteur mais jeune : à tester sur un cluster dédié, loin des charges de production.

Reste une question que ces deux projets n'abordent pas : où partent les appels au LLM de ces millions d'agents ? C'est le terrain d'un autre projet de l'écosystème Kubernetes, le [**Gateway API Inference Extension**](https://gateway-api-inference-extension.sigs.k8s.io/?ref=sfeir.dev), que nous décortiquerons dans un prochain article 😉.