glossaire

Cardinalité des métriques (Prometheus)

La cardinalité d’un système de métriques est le nombre de séries temporelles uniques qu’il stocke. Dans Prometheus, chaque combinaison distincte de nom de métrique et de valeurs de labels crée une série : une même métrique http_requests_total déclinée sur 10 routes, 5 codes HTTP et 20 pods pèse 1 000 séries, pas une. C’est la grandeur qui dimensionne réellement un serveur Prometheus — bien plus que le nombre de métriques déclarées.

Pourquoi elle explose

La cardinalité est multiplicative : ajouter un label multiplie le nombre de séries par le nombre de ses valeurs possibles. Le piège classique est le label à valeurs non bornées — identifiant de requête, adresse IP client, chemin d’URL contenant un identifiant. Chaque nouvelle valeur crée une série qui ne sera peut-être plus jamais mise à jour, mais que le serveur garde en mémoire tant qu’elle est considérée active. Sur Kubernetes, le renouvellement des pods produit le même effet : chaque redéploiement génère de nouveaux noms de pods, donc de nouvelles séries pour toutes les métriques qui portent ce label. Un histogramme aggrave le tout, puisqu’il émet une série par bucket.

Ce que ça coûte

Chaque série active occupe de la mémoire dans la tête de la TSDB (index, symboles, échantillons récents) — c’est le premier poste de consommation RAM d’un Prometheus. Au-delà de la mémoire, une cardinalité élevée ralentit les requêtes qui agrègent sur beaucoup de séries, alourdit les recording rules et, sur les offres managées ou mutualisées facturées à la série active, se paie directement sur la facture.

La mesurer et la contenir

Prometheus s’observe lui-même : prometheus_tsdb_head_series donne le total de séries actives, et l’API TSDB (/api/v1/status/tsdb) liste les métriques et labels les plus coûteux. En PromQL, topk(10, count by (__name__)({__name__=~".+"})) identifie les métriques les plus grosses. Les leviers habituels : supprimer ou réécrire des labels au scrape via metric_relabel_configs, abandonner les métriques jamais requêtées, plafonner les dérives avec sample_limit par cible, et pré-agréger par recording rules ce qui est consulté sous forme agrégée. Le garde-fou le plus rentable reste en amont : au moment d’instrumenter, refuser tout label dont on ne sait pas borner les valeurs.