Dans mon [précédent article](https://www.doit.com/blog/instant-on-scaling-eliminating-node-provisioning-delays-in-gke-with-active-buffer), j'expliquais comment l'[Active Buffer](https://docs.cloud.google.com/kubernetes-engine/docs/concepts/capacity-buffer) de GKE résolvait l'un des points les plus douloureux de l'exploitation Kubernetes : la latence de provisionnement des nœuds. En déclarant une ressource [`CapacityBuffer`](https://docs.cloud.google.com/kubernetes-engine/docs/reference/crds/capacitybuffer), l'Active Buffer maintient des nœuds préchauffés prêts à absorber instantanément les pics de trafic — fini les démarrages à froid de plusieurs minutes, les balloon pods et les acrobaties manuelles autour des `PriorityClass`.
Mais comme tout pattern architectural qui laisse tourner des nœuds on-demand à vide, les active buffers ont un coût. C'est certes moins cher que de surprovisionner aveuglément un cluster entier, mais vous payez quand même le prix fort pour faire tourner des machines virtuelles complètes 24h/24, 7j/7. Si vous voulez un filet de sécurité conséquent — disons 50 CPU et 50 Gio de RAM en réserve — vous payez le plein tarif compute pour des nœuds qui ne font rien.
Google a livré la réponse en juin 2026 : les **[Standby Buffers](https://docs.cloud.google.com/kubernetes-engine/docs/concepts/capacity-buffer#standby_buffer)**, une nouvelle `provisioningStrategy` pour l'API `CapacityBuffer` qui permet à GKE de pré-provisionner et d'initialiser entièrement des nœuds dans un état suspendu. Disponibles à partir de la version GKE `1.36.0-gke.2253000`, les standby buffers offrent un scheduling en moins d'une seconde pour des workloads imprévisibles, tout en réduisant les coûts d'infrastructure inactive jusqu'à 90 % par rapport à un surprovisionnement complet.
> **Note :** les standby buffers sont actuellement en **Preview** et soumis aux "Pre-GA Offerings Terms". Consultez les [exigences et limitations](https://docs.cloud.google.com/kubernetes-engine/docs/concepts/capacity-buffer#requirements_and_limitations) avant toute utilisation en production.
## L'évolution : Active vs Standby Buffers
Pour saisir l'intérêt des standby buffers, il est utile de comparer la manière dont chaque stratégie traite l'infrastructure compute :
**Active Buffers (`buffer.x-k8s.io/active-capacity`) :** GKE crée des pods placeholders légers pour représenter la demande à venir. Le Cluster Autoscaler les intercepte et provisionne de véritables VM, entièrement opérationnelles. Les nœuds sont actifs, les DaemonSets chargés, et les instances facturées au plein tarif. Lorsque les pods de workload réels montent en charge, ils reprennent instantanément cette capacité préchauffée.
**Standby Buffers (`buffer.gke.io/standby-capacity`) :** GKE provisionne et initialise entièrement les nœuds — démarrage des DaemonSets et fenêtre de préchargement des images de conteneur — puis **suspend les instances de compute sous-jacentes**. L'état du système d'exploitation est conservé sur disque, la facturation du compute et de la mémoire s'arrête, et vous ne payez plus que le disque persistant et l'adresse IP. Lors d'un pic de demande, ces nœuds suspendus redémarrent **2 à 3 fois plus vite** que le provisionnement d'une VM partant de zéro, puisque les étapes de bootstrap de l'OS et de Kubernetes sont déjà faites.
**Les benchmarks :** dans les [premiers benchmarks](https://cloud.google.com/blog/products/containers-kubernetes/gke-standby-buffers-speed-up-autoscaling-for-less-spend) publiés par Google, un cluster utilisant des standby buffers a obtenu une latence de scheduling sous la seconde pour des workloads dynamiques (comme les AI Agent Sandboxes), à un coût jusqu'à 90 % inférieur à celui du surprovisionnement classique.

gke-cluster-3-nap-n4-highcpu-4-1b5c18-fb0115cd-mrfm True
```
Les trois états possibles sont :
- `` — le nœud est actif et n'a jamais été suspendu (par exemple un nœud de cluster classique ou un nœud d'active buffer)
- `False` — le nœud a déjà été suspendu mais a été repris pour servir des workloads
- `True` — le nœud est actuellement suspendu (standby buffer, facturation limitée au disque et à l'IP)
## Préchargement des images : à ne pas négliger
Un nœud suspendu redémarre plus vite qu'un démarrage à froid, mais les images de vos workloads doivent toujours être présentes sur le nœud quand un pod réel y atterrit. L'annotation `standby-capacity-init-time` accorde au nœud une fenêtre de démarrage avant suspension, mais les images ne seront pas tirées automatiquement sans une demande explicite pendant cette fenêtre.
L'approche supportée par GKE consiste à déployer un [DaemonSet](https://docs.cloud.google.com/kubernetes-engine/docs/how-to/configure-capacity-buffer#preload-images) de préchargement d'images qui s'exécute durant la fenêtre d'init. Le détail clé : la tolération du taint `buffer.gke.io/standby-node-suspended` — c'est elle qui garantit que le DaemonSet sera bien planifié sur les nœuds de standby buffer, qui seraient ignorés sans cela. Un init container tire ensuite votre image cible, forçant containerd à mettre les couches d'image en cache sur le disque local avant la suspension du nœud.
Lorsqu'un événement de scaling survient, le nœud sort du standby avec l'image déjà disponible en stockage local — le pod démarre immédiatement, sans attendre un pull depuis le registry.
## Synthèse
Le standby buffer vient compléter l'histoire des capacity buffers GKE. L'active buffer règle la latence de provisionnement des nœuds en maintenant une capacité chaude et opérationnelle. Le standby buffer règle le coût du maintien de ce filet de sécurité à grande échelle.
En adoptant une stratégie déclarative à deux niveaux combinant active et standby capacity buffers, vous bâtissez une infrastructure auto-réparatrice qui répond à la demande utilisateur en millisecondes, tout en faisant le bonheur de votre équipe FinOps.
Démarrez avec un petit standby buffer associé à un active buffer, observez comment vos patterns de trafic interagissent avec la fenêtre de reprise, puis ajustez à partir de là. Google propose également un [simulateur de dimensionnement de buffer](https://github.com/gke-labs/buffers-simulator), vraiment utile pour calibrer les buffers en fonction de vos objectifs de performance. La référence complète de configuration se trouve dans la [documentation des capacity buffers GKE](https://docs.cloud.google.com/kubernetes-engine/docs/concepts/capacity-buffer).
Source : Google Cloud Blog
Dans des tests de latence menés sous des charges de trafic identiques, un cluster sans buffers affichait des latences de scheduling P95 et P99 bloquées entre 4 et 6 minutes. Le cluster équipé de standby buffers a maintenu un P50 de l'ordre de quelques secondes, avec des P95/P99 culminant brièvement à une minute avant un retour complet à la normale. Source : Google Cloud Blog
## Choisir la bonne stratégie de buffer Si votre application exige la latence de scheduling de pods la plus faible possible, ne misez pas tout sur les standby buffers. La reprise d'un nœud suspendu a beau être rapide (environ 30 secondes, contre plusieurs minutes pour un démarrage à froid), elle introduit tout de même une brève fenêtre de latence face à des pics immédiats et imprévisibles. Le pattern architectural ultime est un système hybride à deux niveaux : 1. **Active Buffer (l'amortisseur) :** un petit pool de nœuds totalement opérationnels et à capacité réservée absorbe le pic immédiat et imprévisible avec une latence de scheduling sous la seconde. 2. **Standby Buffer (le réservoir profond) :** un pool plus large de nœuds suspendus se réveille en une trentaine de secondes pour couvrir les montées de trafic prolongées. À mesure que les unités d'active buffer sont consommées, les nœuds standby qui se réveillent réalimentent le niveau actif. ```text [ Pic de trafic entrant ] │ ▼ ┌──────────────────────────────────────┐ │ Niveau 1 : Active Buffer (Instant) │ ──► Absorbe le pic immédiat └──────────────────────────────────────┘ │ (Quand le niveau 1 s'épuise...) ▼ ┌──────────────────────────────────────┐ │ Niveau 2 : Standby Buffer (~30s) │ ──► Se réveille pour couvrir la montée prolongée └──────────────────────────────────────┘ ``` **Philosophie de dimensionnement :** gardez un active buffer compact et économique — juste assez large pour combler les 30 secondes nécessaires au réveil des nœuds standby. Dimensionnez le standby buffer pour couvrir le volume total et prolongé d'un pic de trafic soutenu. ## Configuration déclarative : comment implémenter les Standby Buffers Le changement de configuration par rapport à un active buffer est minime. Il suffit d'ajouter le champ `provisioningStrategy` à votre spec CapacityBuffer, de lui donner la valeur `buffer.gke.io/standby-capacity`, et éventuellement d'ajuster deux nouvelles annotations qui pilotent la temporisation de la suspension et la fréquence de rafraîchissement. ### Prérequis Pour profiter des standby buffers, vérifiez que votre cluster GKE Standard tourne en version `1.36.0-gke.2253000` ou ultérieure. Le node auto-provisioning est **requis** pour les standby buffers. Consultez la [documentation officielle](https://docs.cloud.google.com/kubernetes-engine/docs/concepts/capacity-buffer#requirements_and_limitations) pour la liste complète des exigences et limitations. ### Étape 1 : créer un Namespace et une ComputeClass Si vous souhaitez configurer des priorités de compute de repli, définissez une [`ComputeClass`](https://docs.cloud.google.com/kubernetes-engine/docs/concepts/about-custom-compute-classes) : ```YAML apiVersion: v1 kind: Namespace metadata: name: platform-scaling --- apiVersion: cloud.google.com/v1 kind: ComputeClass metadata: name: high-perf-compute namespace: platform-scaling spec: priorities: - machineFamily: n4 - machineFamily: n4d - machineFamily: c4 - machineFamily: c4d nodePoolAutoCreation: enabled: true ``` ### Étape 2 : définir l'unité de buffer Créez un `PodTemplate` qui reflète le profil de ressources des workloads que vous comptez scaler. GKE s'en sert pour déterminer la capacité compute requise par unité de buffer. ```YAML apiVersion: v1 kind: PodTemplate metadata: name: app-buffer-template namespace: platform-scaling template: spec: terminationGracePeriodSeconds: 0 containers: - name: buffer-container image: registry.k8s.io/pause:3.9 resources: requests: cpu: "1" memory: "1Gi" limits: cpu: "1" memory: "1Gi" nodeSelector: cloud.google.com/compute-class: high-perf-compute ``` ### Étape 3 : créer le Standby Buffer Le champ `provisioningStrategy` est le seul vrai ajout par rapport à un active buffer. Les deux [annotations](https://docs.cloud.google.com/kubernetes-engine/docs/how-to/configure-capacity-buffer#customize-standby-behavior) contrôlent la durée pendant laquelle un nœud reste actif avant suspension, ainsi que la fréquence à laquelle les nœuds suspendus sont rafraîchis pour rester à jour avec les versions des DaemonSets et les couches d'image. ```yaml apiVersion: autoscaling.x-k8s.io/v1beta1 kind: CapacityBuffer metadata: name: my-standby-buffer namespace: platform-scaling annotations: # Durée pendant laquelle un nœud reste actif après init avant suspension (défaut : 5m) # À augmenter si votre workload doit précharger des images lourdes ou des modèles ML buffer.gke.io/standby-capacity-init-time: "5m" # Fréquence à laquelle les nœuds suspendus sont recréés pour rester à jour (défaut : 1d) buffer.gke.io/standby-capacity-refresh-frequency: "1d" spec: podTemplateRef: name: app-buffer-template limits: cpu: "50" memory: "50Gi" provisioningStrategy: "buffer.gke.io/standby-capacity" ``` ### Étape 4 : associer un petit active buffer (recommandé) Un active buffer de 5 CPU et 5 Go de RAM ```yaml apiVersion: autoscaling.x-k8s.io/v1beta1 kind: CapacityBuffer metadata: name: my-active-buffer namespace: platform-scaling spec: podTemplateRef: name: app-buffer-template limits: cpu: "5" memory: "5Gi" provisioningStrategy: "buffer.x-k8s.io/active-capacity" ``` ### Étape 5 : vérifier les nœuds suspendus Vous pouvez vérifier que votre capacity buffer gère bien les nœuds suspendus nativement via `kubectl`. Les nœuds suspendus se repèrent à la condition Suspended. ```bash kubectl get nodes -o custom-columns=\ 'NAME:.metadata.name,SUSPENDED:.status.conditions[?(@.type=="Suspended")].status' ``` Exemple de sortie : ```yaml NAME SUSPENDED gke-cluster-3-nap-n4-highcpu-2-nm9ieq-586f2c73-4v2z False gke-cluster-3-nap-n4-highcpu-2-nm9ieq-586f2c73-pdbs