Ballast et Attune : automatiser le dimensionnement vertical sans redémarrer vos pods
Le VPA natif tue les pods pour les redimensionner. Ballast lisse les recommandations, Attune applique le redimensionnement à chaud. Installation, réglage et garde-fous d'une chaîne qui récupère 30 à 40 % de ressources.
Le constat est universel : sur n'importe quel cluster de production, les demandes de ressources déclarées dépassent largement la consommation réelle. Un facteur de trois à cinq n'a rien d'exceptionnel. Un développeur qui ne sait pas combien son service consomme demande large — et personne ne revient corriger.
Le Vertical Pod Autoscaler répond à ce problème, mais il souffre d'un défaut rédhibitoire en production : pour appliquer une nouvelle taille, il supprime le pod. Sur un service à état ou une charge à session longue, c'est inacceptable.
Deux composants changent la donne. Ballast lisse et sécurise les recommandations. Attune les applique à chaud, en s'appuyant sur le redimensionnement des ressources sans redémarrage, stabilisé depuis Kubernetes 1.33.
Pourquoi le VPA seul ne suffit pas
| Problème | Effet observé |
|---|---|
| Éviction pour appliquer | Coupure de service sur les charges à état |
| Réaction aux pics | Une pointe unique gonfle durablement la recommandation |
| Pas de notion de marge | Recommandation collée à la consommation, sans réserve |
| Conflit avec le HPA | VPA et HPA sur le processeur se contredisent |
| Aveugle au budget | Aucun plafond global |
Ballast traite les quatre premiers points, Attune le premier.
Installer la chaîne
Le prérequis tient en une ligne : la fonctionnalité InPlacePodVerticalScaling doit être active. Depuis 1.33, elle est activée par défaut en bêta.
kubectl get --raw='/readyz?verbose' | grep -i inplace
# à défaut, vérifier le plan de contrôle :
# --feature-gates=InPlacePodVerticalScaling=true# valeurs Ballast, gérées par ArgoCD
recommandeur:
source: prometheus
prometheusUrl: http://prometheus.observabilite.svc:9090
fenetre: 14d # deux semaines couvrent le cycle hebdomadaire
quantileProcesseur: 0.90 # p90 : on ignore les pointes rares
quantileMemoire: 0.98 # mémoire : presque le maximum, un dépassement tue
margeProcesseur: 1.15
margeMemoire: 1.25
lissage:
actif: true
methode: ewma # moyenne mobile exponentielle
alpha: 0.25
variationMax: 0.30 # jamais plus de 30 % d'écart par ajustement
periodeMin: 6h # délai minimal entre deux ajustements
gardeFous:
processeurMin: 50m
memoireMin: 64Mi
processeurMax: "8"
memoireMax: 32Gi
ratioLimiteSurDemande: 2.0Les deux quantiles différenciés constituent le réglage le plus important. Le processeur se comprime : un service bridé ralentit. La mémoire ne se comprime pas : un dépassement tue le conteneur. D'où le p90 sur l'un et le p98 sur l'autre.
# valeurs Attune
application:
mode: in-place
repliQueue: true # un pod à la fois par déploiement
attendreDisponibilite: true
respecterPDB: true
fenetres:
- jours: ["Mon","Tue","Wed","Thu"]
debut: "10:00"
fin: "16:00" # heures ouvrées : l'équipe est là si ça dérape
timezone: "Europe/Paris"
repli:
surEchecInPlace: differer # jamais d'éviction automatique
tentativesMax: 3Le repli: differer mérite qu'on insiste. Si le redimensionnement à chaud échoue — ce qui arrive quand la mémoire diminue au-delà de ce que le noyau accepte —, Attune reporte plutôt que d'évincer. Une éviction automatique nocturne sur un service critique, c'est l'incident garanti.
Déclarer une politique
apiVersion: ballast.io/v1alpha1
kind: RightSizingPolicy
metadata:
name: api-commandes
namespace: production
spec:
cible:
apiVersion: apps/v1
kind: Deployment
name: api-commandes
mode: Auto
conteneurs:
- nom: application
controle: [cpu, memory]
minAutorise: { cpu: 200m, memory: 512Mi }
maxAutorise: { cpu: "4", memory: 8Gi }
- nom: sidecar-proxy
controle: [memory] # le processeur du proxy suit le trafic, pas la taille
contraintes:
respecterHPA: true # le HPA garde la main sur le processeur
variationMaxParPas: 0.25
ajustementsMaxParJour: 3
observation:
dureeMin: 7d # aucune décision avant une semaine d'historiqueLa contrainte respecterHPA évite le conflit classique. Quand un HPA règle le nombre de répliques sur le processeur, laisser le VPA toucher au processeur crée une boucle instable : le VPA réduit la demande, l'utilisation relative monte, le HPA ajoute des répliques, la charge par pod baisse, le VPA réduit encore.
La règle : HPA sur le processeur, Ballast sur la mémoire. Ou HPA sur une métrique métier, et Ballast sur les deux.
Vérifier avant d'automatiser
Ne passez jamais en Auto directement. Le mode Recommend produit les recommandations sans les appliquer.
# Gaspillage processeur : demandé moins consommé, par espace de noms
sum by (namespace) (
kube_pod_container_resource_requests{resource="cpu"}
) -
sum by (namespace) (
rate(container_cpu_usage_seconds_total{container!=""}[7d])
)
# Écart entre la recommandation et la demande actuelle
(
ballast_recommendation_cpu_cores
/
on(namespace, pod, container) kube_pod_container_resource_requests{resource="cpu"}
) < 0.5La seconde requête liste les conteneurs qui demandent plus du double de leur besoin. Commencez par ceux-là : gain maximal, risque minimal.
Les garde-fous que j'impose
Un plafond global par espace de noms. Ballast ajuste vers le haut aussi bien que vers le bas. Sans plafond, une charge anormale peut faire gonfler les demandes jusqu'à saturer le cluster.
apiVersion: v1
kind: ResourceQuota
metadata:
name: plafond-production
namespace: production
spec:
hard:
requests.cpu: "400"
requests.memory: 1600GiUne exclusion explicite pour les charges sensibles. Bases de données, files de messages, tout ce qui a une consommation en dents de scie.
metadata:
annotations:
ballast.io/exclude: "true"
ballast.io/exclude-reason: "consommation irrégulière, dimensionnement manuel validé"L'annotation de motif n'est pas décorative : six mois plus tard, personne ne se souvient pourquoi l'exclusion existe.
Une alerte sur les ajustements en rafale.
- alert: AjustementsBallastEnRafale
expr: sum(increase(attune_resize_total[1h])) by (namespace) > 20
for: 15m
labels: { severity: warning }
annotations:
summary: "{{ $value }} redimensionnements en une heure sur {{ $labels.namespace }}"
description: "Le lissage ne fait pas son travail : vérifier alpha et periodeMin."Ce que cela rapporte
Sur un cluster de production de taille moyenne — cent cinquante déploiements, huit cents pods —, la mise en place complète a récupéré 34 % du processeur demandé et 28 % de la mémoire en six semaines, sans un seul incident lié au redimensionnement.
Le gain n'est pas immédiat. La première semaine sert à l'observation, la deuxième à la validation en mode recommandation, et l'ajustement progressif s'étale sur un mois. C'est précisément ce que le lissage impose — et c'est ce qui rend l'opération sûre.
Un dernier point : ce gain se dissipe si personne ne surveille. Les nouvelles charges arrivent avec leurs demandes surdimensionnées. Ballast ne tient que parce qu'il tourne en continu.