Méta : prometheus promql vector-matching zettelkasten

📝 PromQL Avancé : Jointures et Opérations Binaires (Vector Matching)

Dans la continuité de vos PromQL Basics, il faut savoir que lorsque vous appliquez un opérateur mathématique (+, -, /, *) ou logique entre deux ensembles de données (vecteurs), Prometheus tente de faire correspondre les éléments de gauche avec ceux de droite uniquement s’ils ont exactement les mêmes labels.

Si les labels diffèrent, la requête échoue ou ne renvoie rien. Le Vector Matching est le mécanisme qui permet de forcer cette correspondance. C’est une notion absolument vitale, notamment dans le cadre du Kubernetes Monitoring, pour croiser des métriques applicatives avec des données d’infrastructure.

1. La Jointure Simple (One-to-One)

Utilisée lorsqu’il y a au maximum un élément de chaque côté correspondant aux critères. Pour forcer la correspondance quand les labels ne sont pas strictement identiques, on utilise les modificateurs on ou ignoring.

  • ignoring(liste_labels) : Demande Ă  Prometheus d’ignorer certains labels lors de la comparaison.

  • on(liste_labels) : Demande Ă  Prometheus de ne se baser que sur ces labels prĂ©cis pour faire la jointure.

Cas d’usage : Calculer un pourcentage d’erreur

On veut diviser les requĂŞtes en erreur (qui ont le label status="500") par le total des requĂŞtes.

  • Le problème : Le numĂ©rateur a un label status="500", mais le dĂ©nominateur regroupe tous les statuts. La jointure naturelle Ă©choue.

  • La solution :

    rate(http_requests_total{status="500"}[5m]) / ignoring(status) rate(http_requests_total[5m])

2. La Jointure Multiple (Many-to-One / One-to-Many)

C’est l’équivalent d’un “LEFT JOIN” ou “RIGHT JOIN” en SQL. Elle est utilisée quand un côté de l’opération possède plusieurs séries temporelles qui doivent correspondre à une seule série temporelle de l’autre côté.

Pour cela, on utilise group_left() ou group_right(). Le mot “left” ou “right” indique de quel côté se trouve la cardinalité la plus forte (le côté “Many”).

Cas d’usage classique : Enrichir une métrique avec des métadonnées

Très courant dans Kubernetes via kube-state-metrics. Imaginons que vous vouliez la consommation mémoire d’un pod, mais vous voulez aussi que le graphique affiche sur quel “node” (nœud) il tourne.

  • MĂ©trique A (Consommation) : container_memory_usage_bytes{pod="api-xyz"} → N’a pas le label “node”.

  • MĂ©trique B (Info Kubernetes) : kube_pod_info{pod="api-xyz", node="worker-1"} → A une valeur de 1, sert juste Ă  stocker des labels.

  • La solution : Multiplier A par B en disant Ă  Prometheus de garder les labels de B.

    container_memory_usage_bytes * on(pod) group_left(node) kube_pod_info

  • Explication :

    • on(pod) : Fait la jointure uniquement sur le nom du pod.

    • group_left(node) : Indique que le cĂ´tĂ© gauche (la mĂ©moire) peut avoir plusieurs conteneurs pour un seul pod (cĂ´tĂ© droit). Le (node) prĂ©cise qu’on veut importer le label “node” depuis la droite vers le rĂ©sultat final Ă  gauche.

3. Les Opérateurs Logiques (Ensembles)

Contrairement aux opérateurs mathématiques (+, -) qui modifient la valeur de la métrique, les opérateurs logiques (and, or, unless) agissent comme des filtres. Ils servent à croiser deux listes de résultats en se basant sur leurs labels (comme une intersection ou une union en mathématiques).

OpérateurComportement (SQL équivalent)Règle de fonctionnement
andINNER JOIN (Intersection)A and B : Renvoie les éléments de A qui ont un jumeau exact (mêmes labels) dans B.
orUNIONA or B : Renvoie tous les éléments de A, plus les éléments de B qui ne sont pas dans A.
unlessNOT IN (Soustraction)A unless B : Renvoie les éléments de A, sauf s’ils ont un jumeau exact dans B.

⚠️ Règle d’or : Le résultat renvoie toujours la valeur et les labels de la métrique située à gauche de l’opérateur.

Le Scénario (Exemple d’application)

Imaginons que nous avons deux requĂŞtes qui renvoient chacune une liste de serveurs :

  • RequĂŞte A (Erreurs) : Les serveurs ayant trop d’erreurs HTTP. (RĂ©sultat : web-01, web-02)

  • RequĂŞte B (Trafic) : Les serveurs recevant un trafic critique (>1000 req/s). (RĂ©sultat : web-02, web-03)

1. L’opérateur and (L’Intersection / Le “ET” strict)

Il renvoie les éléments de gauche uniquement s’ils ont un jumeau exact (mêmes labels) à droite.

  • Dans notre exemple : web-02

  • Cas d’usage (Alerting) : “Je veux dĂ©clencher une alerte critique uniquement sur les serveurs qui ont trop d’erreurs ET qui gèrent un trafic critique.”

    rate(http_errors_total[5m]) > 50 and rate(http_requests_total[5m]) > 1000

2. L’opérateur or (L’Union / Le “OU”)

Il renvoie tous les éléments de gauche, plus les éléments de droite qui n’ont pas de jumeau à gauche.

  • Dans notre exemple : web-01, web-02, web-03

  • Cas d’usage : Combiner deux conditions d’alerte indĂ©pendantes en un seul graphique ou tableau. “Affiche-moi les serveurs qui ont soit trop d’erreurs, soit trop de trafic.”

3. L’opérateur unless (La Soustraction / L’Exclusion)

Il renvoie les éléments de gauche, sauf s’ils existent aussi à droite.

  • Dans notre exemple : web-01 (Car web-02 est Ă©liminĂ© par la prĂ©sence de B).

  • Cas d’usage (Alerting) : “Je veux une alerte pour les serveurs qui ont trop d’erreurs, SAUF si c’est un serveur de test.”

    rate(http_errors_total[5m]) > 50 unless server_status{env="test"}

(Autre cas d’usage courant avec and : Afficher l’utilisation CPU uniquement pour les serveurs dont le disque est rempli à plus de 90% via node_cpu_seconds_total and (node_filesystem_free_bytes < 10000000)).


Ce bloc de connaissance sur le Vector Matching est maintenant parfaitement standardisé !

Es-tu prêt à clôturer ce système avec la toute dernière note sur les fonctions de prédiction et de temps (comme predict_linear() pour anticiper un disque plein, ou changes() / absent()) ?