Spot sur GKE : node pools, scheduling et workloads éligibles
Les Spot VMs sont des instances que GCP peut reprendre à tout moment avec 30 secondes de préavis. En échange elles coûtent 4-5x moins cher qu'une instance standard.
En pratique GCP les reprend rarement et elles conviennent à une majorité de workloads stateless.
Spot VM vs Preemptible
--preemptible est déprécié, durée max 24h. En Terraform c'est spot = true.
2 pools : system + spot
On ne met jamais uniquement des Spot Nodes. Le pattern standard c'est 2 pools :
- Pool
system- On-Demand, pour kube-system, ingress, monitoring, ArgoCD - Pool
spot- Spot VM, pour les workloads applicatifs, batch, CI runners
Le choix du type de machine (machine_type) impacte la capacité réelle allouable, voir GKE - Capacité réelle des nodes pour bien dimensionner.
resource "google_container_node_pool" "system" {
name = "system"
cluster = google_container_cluster.main.name
initial_node_count = 3
autoscaling {
min_node_count = 3
max_node_count = 6
}
node_config {
machine_type = "n2-standard-4"
spot = false
}
}
resource "google_container_node_pool" "spot" {
name = "spot"
cluster = google_container_cluster.main.name
initial_node_count = 0
autoscaling {
min_node_count = 0
max_node_count = 30
}
node_config {
machine_type = "n2-standard-8"
spot = true
taint {
key = "cloud.google.com/gke-spot"
value = "true"
effect = "NO_SCHEDULE"
}
}
}
Scheduler les pods sur Spot
Les nœuds Spot reçoivent automatiquement le taint cloud.google.com/gke-spot=true:NoSchedule. Les pods ont besoin de la tolérance correspondante.
spec:
tolerations:
- key: cloud.google.com/gke-spot
operator: Equal
value: "true"
effect: NoSchedule
nodeSelector:
cloud.google.com/gke-spot: "true"
# GCP donne 30s de préavis max - on reste en dessous
terminationGracePeriodSeconds: 25
containers:
- name: my-app
image: my-app:latest
resources:
requests:
cpu: 500m
memory: 512Mi
Borner les évictions simultanées avec un PDB
Un PDB ne retient pas GCP quand il reprend un nœud Spot, la reprise ne passe pas par l'API d'éviction. Il couvre tout le reste : drain manuel, autoscaler, upgrade de pool.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
spec:
selector:
matchLabels:
app: my-app
minAvailable: 2
Ce qui passe sur Spot, ce qui ne passe pas
Ce nœud détient-il un state critique non répliqué instantanément ? Tout part de là.
Les cas ci-dessous sont les plus courants, ils ne dispensent pas de regarder ce que l'appli garde vraiment en local.
| Workload | Spot OK ? | Pourquoi |
|---|---|---|
| Déploiements stateless (N > 1 + PDB) | ✅ | Aucun state local |
| Jobs batch / workers de queue | ✅ | Retry natif |
| CI/CD runners | ✅ | Job rejoué si interrompu |
| Ingress controllers (N > 1 + PDB) | ✅ | Stateless |
| ArgoCD (HA, composants stateless) | ✅ | Stateless, redémarre proprement |
| DB replica / standby | ✅ | Ne détient pas les écritures actives |
Prometheus avec remote_write | ✅ | State flushé en continu, perte négligeable |
Prometheus sans remote_write | ❌ | Perte de la TSDB locale à la reprise |
| DB primary / leader | ❌ | Failover ~30-60s, GCP donne 30s - fenêtre trop serrée |
| StatefulSet sans réplication | ❌ | State local non répliqué |
Autoscaler : plusieurs pools pour limiter le risque
Si GCP n'a plus de place pour un type d'instance donné, l'autoscaler est bloqué. On crée plusieurs pools Spot avec des types différents :
L'autoscaler utilisera celui qui a de la capacité.
Commandes utiles
Repérer les nœuds Spot du cluster et simuler une reprise pour voir comment l'appli encaisse :
# Voir quels nœuds sont Spot
kubectl get nodes -o custom-columns=\
'NAME:.metadata.name,SPOT:.metadata.labels.cloud\.google\.com/gke-spot'
# Simuler la reprise d'un nœud par GCP
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data --grace-period=25
Voir aussi
- GKE - Capacité réelle des nodes - Dimensionner les nodes pour optimiser le ROI
- GKE Workload Identity - Accorder les bonnes permissions aux pods sur Spot nodes