Les histogrammes natifs passent en bêta et divisent par dix les séries Prometheus
Kubernetes 1.37 active par défaut les histogrammes natifs de Prometheus, qui remplacent les buckets statiques par des buckets exponentiels dynamiques. Les composants restent compatibles via une double exposition : activez scrape_native_histograms puis migrez vos requêtes histogram_quantile.
Kubernetes 1.36. Les histogrammes natifs entrent en alpha sous KEP-5808. Kubernetes 1.37. Ils passent en bêta et s’activent par défaut. Prometheus 3.0. La version du scraper qui sait les lire sans changer toute votre pile. Pourquoi c’est important : la latence de l’API server et du scheduler est enfin mesurée à haute résolution sans faire exploser le nombre de séries temporelles — et c’est exactement le poste qui fait grossir la facture mémoire de Prometheus dans les grands clusters.
Le problème des histogrammes classiques
Depuis les débuts de l’observabilité Kubernetes, les métriques de durée et de latence reposent sur les histogrammes classiques de Prometheus. L’auteur d’une métrique définit une liste statique de bornes cumulatives — les labels le — comme 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10. Ce modèle familier crée trois problèmes structurels.
Le jeu de devinette des buckets. Si le profil de latence d’une charge évolue — vers les microsecondes ou vers une longue traîne au-delà du plus grand bucket — l’histogramme perd toute visibilité. Définir les bornes à l’avance, c’est prétendre connaître la distribution avant de l’avoir observée.
La cardinalité et le coût de stockage. Chaque borne est exportée comme une série temporelle distincte (_bucket{le="…"}). Un histogramme de dix buckets multiplié par ses labels décuple le nombre de séries, augmente la mémoire de Prometheus et gonfle le TSDB.
L’erreur d’interpolation des quantiles. Le calcul des percentiles via histogram_quantile() repose sur une interpolation linéaire entre des bornes statiques. Quand les intervalles sont grossiers, l’estimation du quantile peut être significativement fausse.
Ce que sont les histogrammes natifs
Les histogrammes natifs de Prometheus remplacent les buckets statiques par des buckets exponentiels dynamiques. Au lieu d’émettre une série par borne, un histogramme natif est stocké comme une seule série temporelle contenant un schéma riche de segments positifs et négatifs, de seuils à zéro et de facteurs d’échelle exponentiels.
Trois conséquences directes. Une haute résolution automatique : les buckets exponentiels s’ajustent à n’importe quelle plage de valeurs, de la nanoseconde à l’heure, sans bornes préconfigurées. Jusqu’à 90 % de séries en moins : en consolidant les buckets en segments structurés au sein d’une seule série, la charge de scraping et de stockage s’effondre. Des quantiles exacts : le calcul se fait avec des bornes d’erreur mathématiques — environ 5 % d’erreur relative dans le pire des cas sous les réglages par défaut — sur tout le spectre des observations.
Dans Kubernetes, le support est implémenté directement dans le sous-système de métriques partagé, k8s.io/component-base/metrics. Résultat : tous les composants majeurs du plan de contrôle et des nœuds en héritent automatiquement — kube-apiserver (apiserver_request_duration_seconds, métriques d’authentification et d’autorisation, latences de validation), kube-scheduler (scheduler_plugin_execution_duration_seconds), kubelet, kube-controller-manager et kube-proxy.
La double exposition, ou comment ne rien casser
L’exigence centrale de KEP-5808 était zéro rupture pour les piles d’observabilité existantes. Quand la feature gate NativeHistograms est activée, les composants utilisent une double exposition : les buckets classiques (h.Bucket) sont toujours émis aux côtés des segments natifs, et les segments natifs (h.Schema, h.PositiveSpan) sont inclus dans le même flux Protobuf pour les collecteurs qui les comprennent.
En clair, vos dashboards, règles d’alerte et serveurs Prometheus existants continuent de fonctionner sans modification, pendant que les nouveaux collecteurs profitent des segments natifs. C’est cette coexistence qui rend la migration incrémentale — plutôt qu’un big-bang.
Le réglage par défaut appliqué aux histogrammes mérite d’être connu : BucketFactor: 1.1, qui garantit que chaque bucket est au plus 10 % plus large que le précédent et borne l’erreur relative des quantiles à environ 5 %, et MaxBucketNumber: 160, qui plafonne le nombre de buckets par histogramme pour protéger la mémoire des composants même sous des distributions extrêmes.
Comment scraper et interroger
Côté Prometheus, la configuration dépend de la version. Avec Prometheus 3.0 et plus, on configure par job, sans drapeau global :
scrape_configs:
- job_name: 'kubernetes-apiservers'
scrape_native_histograms: true
always_scrape_classic_histograms: true # recommandé pendant la transition Le drapeau always_scrape_classic_histograms: true est crucial pendant la transition : sans lui, Prometheus n’ingère que le format natif et cesse d’ingérer les séries classiques _bucket, _count et _sum, cassant vos requêtes existantes. Avec Prometheus 2.40 à 2.x, on active la fonctionnalité globalement :
prometheus --enable-feature=native-histograms Une fois les histogrammes ingérés, les requêtes PromQL se simplifient — plus besoin du suffixe _bucket :
# Histogramme classique :
histogram_quantile(0.99, rate(apiserver_request_duration_seconds_bucket[5m]))
# Histogramme natif :
histogram_quantile(0.99, rate(apiserver_request_duration_seconds[5m])) Le chemin de migration, et le gain au bout
La migration se fait en quatre temps. D’abord, activer scrape_native_histograms: true avec always_scrape_classic_histograms: true pour conserver la double ingestion. Ensuite, migrer les requêtes : remplacer les appels histogram_quantile(…_bucket…) par histogram_quantile(…), et les séries _count / _sum par histogram_count(…) et histogram_sum(…). Puis valider en préproduction que dashboards et alertes SLO graphent correctement. Enfin, une fois la migration achevée, passer always_scrape_classic_histograms: false : Prometheus cesse d’ingérer les séries statiques, et le nombre de séries d’histogrammes chute de 90 % — environ dix fois moins de stockage.
Le retour arrière est trivial, et c’est ce qui rend l’adoption peu risquée : un scrape_native_histograms: false fait revenir le collecteur au format classique sans redémarrage de Kubernetes, et la feature gate peut être coupée côté composant avec --feature-gates=NativeHistograms=false (au prix d’un redémarrage).
Verdict
Les histogrammes natifs en bêta sont l’un des gains d’observabilité les plus nets de Kubernetes 1.37 : ils règlent le problème de cardinalité que les histogrammes classiques traînaient depuis des années, sans casser l’existant.
Si votre Prometheus approche ses limites de mémoire ou de stockage sur les métriques d’histogrammes, adoptez la migration complète — le gain de ~90 % de séries est directement récupéré en coût d’infrastructure. Si vos dashboards reposent massivement sur histogram_quantile(…_bucket…), activez la double ingestion avec always_scrape_classic_histograms: true et migrez les requêtes au rythme de votre équipe : c’est une transition que l’on peut étaler. Si vous êtes en Prometheus 2.x, la bascule est tout-ou-rien — testez l’impact en staging avant de l’activer globalement. Dans tous les cas, surveillez la fin de vie des buckets classiques : SIG Instrumentation vise la disponibilité générale, et la dépréciation des buckets statiques suivra.