Un système de traitement de commandes tourne avec 6 pods depuis des semaines. La charge CPU moyenne ? À peine 8 %. Pourtant, les messages Kafka s'accumulent dans la file, le lag grimpe, et les délais de traitement s'allongent. L'autoscaling traditionnel basé sur le CPU ne voit rien — et ne fait rien.
C'est exactement le problème que KEDA (Kubernetes Event-Driven Autoscaling) résout.
Le problème que le CPU ne voit pas
L'Horizontal Pod Autoscaler natif de Kubernetes est une excellente primitive pour les charges CPU-bound. Mais dans les architectures événementielles — traitement de messages Kafka, files d'attente, jobs batch — le CPU n'est pas le goulot d'étranglement. Les pods attendent des messages, consomment peu de ressources, mais le travail s'accumule.
Ce décalage entre la métrique observée (CPU) et la charge réelle (messages en attente) crée un angle mort : le système scale trop tard, ou pas du tout. Et quand il finit par réagir, le lag a déjà impacté les SLOs.
KEDA : scaler sur l'événement, pas sur la ressource
KEDA s'installe sur le cluster comme un opérateur et étend l'API Kubernetes avec un CRD :
le ScaledObject. Il agit comme un adaptateur de métriques externe pour le HPA,
mais expose des sources que Kubernetes ne connaît pas nativement : Kafka, Pub/Sub, Redis,
Cloud Monitoring, RabbitMQ, et bien d'autres.
Avantage clé : KEDA peut scaler à zéro. Quand il n'y a pas de messages, les pods disparaissent. Quand le lag augmente, ils réapparaissent. C'est un scaling piloté par la demande réelle.
Le signal choisi ici : le retard de consommation Kafka
Le consumer lag Kafka mesure l'écart entre le dernier message produit et le dernier message consommé. C'est le signal le plus fidèle de la charge réelle d'un consumer group.
Avec KEDA, on configure un ScaledObject qui :
- observe le lag du consumer group sur les topics concernés
- déclenche le scale-up quand le lag dépasse un seuil (
lagThreshold) - permet le scale-down jusqu'à zéro quand le lag est nul
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: orders-processor
namespace: production
spec:
scaleTargetRef:
name: orders-processor-deployment
minReplicaCount: 0
maxReplicaCount: 20
triggers:
- type: kafka
metadata:
bootstrapServers: kafka-broker:9092
consumerGroup: orders-group
topic: orders
lagThreshold: "100"
offsetResetPolicy: latest
Avec ce manifeste, le déploiement orders-processor scale de 0 à 20 pods
selon le lag réel du consumer group orders-group.
Comment ça s'assemble sur GCP
Sur GCP, la combinaison naturelle est Cloud Monitoring + Workload Identity.
Si le broker Kafka est managé (Confluent Cloud ou Kafka auto-hébergé sur GKE), KEDA s'y
connecte directement. Mais si le lag est exposé via des métriques custom dans Cloud Monitoring
— pattern courant dans les architectures GCP — KEDA peut utiliser le scaler
gcp-stackdriver :
triggers:
- type: gcp-stackdriver
authenticationRef:
name: keda-workload-identity
metadata:
projectId: "my-gcp-project"
filter: |
resource.type="k8s_container"
metric.type="custom.googleapis.com/kafka/consumer_lag"
targetValue: "100"
Workload Identity permet à KEDA d'interroger Cloud Monitoring sans secret ni clé de service — un pattern natif GKE qui élimine toute gestion manuelle de credentials.
Ce que ça change concrètement
- Scale to zero : entre deux batchs de commandes, aucun pod ne tourne. Réduction directe des coûts compute.
- Réactivité sur signal métier : le scaling commence quand le lag dépasse le seuil, pas quand le CPU a saturé depuis plusieurs minutes.
- Pas de sur-provisionnement permanent : exit le "garde 6 pods en permanence au cas où".
- Observabilité native : le lag Kafka est une métrique directement corrélable aux SLOs de traitement.
Le CPU reste une métrique utile pour les workloads CPU-bound. Mais pour les architectures événementielles, il est temps de scaler sur ce qui compte vraiment : le travail en attente.