Infrastructure

Azure Monitor Managed Prometheus : contenir une explosion de cardinalité avant d’augmenter les quotas

Un runbook de production pour isoler métrique, target et labels responsables d’une hausse de séries AKS avant de filtrer la collecte, demander plus de capacité ou rollbacker.

11 sept. 2026 azureazure-monitorprometheusaksobservabilitycardinalitymetricsautomationrunbookrollbackproduction

Les dashboards AKS deviennent lents, certaines métriques présentent des trous et l’Azure Monitor workspace approche de ses limites d’ingestion. La réaction immédiate consiste souvent à demander plus de capacité. Pourtant, une seule release peut avoir ajouté request_id, user_id, une URL non normalisée ou un identifiant de pod éphémère aux labels Prometheus. Chaque nouvelle combinaison crée alors une série et transforme un changement applicatif local en incident d’observabilité partagé.

Le cas fil rouge est une API sur AKS collectée par Azure Monitor Managed Prometheus. Après un déploiement, le nombre de séries actives et les événements ingérés accélèrent, tandis que Grafana répond plus lentement. Ce runbook doit décider s’il faut supprimer un label, réduire un périmètre de scrape, corriger l’instrumentation, répartir la collecte, demander une hausse de limite ou rollbacker la release. L’objectif n’est pas de retrouver un dashboard vert en perdant silencieusement les métriques utiles.

Figer la fenêtre et l’unité de diagnostic

Commencez par borner un workspace, un cluster, une release et une période UTC. Ne mélangez pas une hausse progressive liée à la charge avec une rupture nette après déploiement.

yaml incident-cardinalite-prometheus.yml
incident: inc-20260911-004
workspace: amw-platform-prod
cluster: aks-platform-prod
fenetre_utc:
debut: 2026-09-11T06:30:00Z
fin: 2026-09-11T07:30:00Z
release_candidate: orders-api-2026.09.11.2
symptomes:
- hausse_series_actives
- hausse_evenements_par_minute
- requetes_promql_lentes
- trous_sur_certains_targets

a_preserver:
- utilisation_workspace_avant_et_apres_release
- configuration_scrape_et_relabeling_deployee
- liste_targets_et_etat_up
- metriques_et_labels_ajoutes_par_la_release
- manifest_et_image_precedents
- dashboard_et_regles_affectes

Conservez la configuration réellement chargée, pas seulement celle du dépôt. Un ConfigMap peut être correct dans Git alors que le cluster utilise encore une version précédente, ou qu’un objet de scrape supplémentaire sélectionne deux fois la même cible.

Séparer saturation du workspace et échec de collecte

Une absence de données n’indique pas automatiquement une limite atteinte. Vérifiez d’abord les métriques de plateforme du workspace, puis l’état du DCR et des collecteurs ama-metrics. Les dimensions et noms exacts des métriques peuvent évoluer ; inventoriez-les sur la ressource avant d’automatiser une requête.

bash 01-inventaire-ingestion.sh
az monitor metrics list-definitions \
--resource /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-observability-prod/providers/Microsoft.Monitor/accounts/amw-platform-prod \
--output table

kubectl get pods -n kube-system -o wide
kubectl get configmap ama-metrics-settings-configmap -n kube-system -o yaml
kubectl get configmap ama-metrics-prometheus-config -n kube-system -o yaml

Dans le workspace, comparez au minimum l’utilisation des séries actives, le débit d’événements reçus et les erreurs d’ingestion. Sur le DCR, recherchez les requêtes rejetées et la dimension de code de réponse. Dans le cluster, distinguez quatre classes : target non découvert, scrape en erreur, échantillons produits mais rejetés, ou ingestion acceptée avec requêtes PromQL devenues coûteuses.

N’activez le debug du collecteur que sur une fenêtre courte et avec un propriétaire. Il peut lui-même consommer des ressources. Les logs, la page des targets et les métriques up, scrape_samples_scraped et scrape_series_added suffisent souvent à localiser le job fautif.

Prouver la rupture de cardinalité

Cherchez d’abord le changement de pente, puis réduisez la requête à quelques familles candidates. Une requête globale sur toutes les séries peut aggraver un workspace déjà sous pression.

promql 02-cardinalite-par-metrique.promql
topk(
20,
count by (__name__) (
  {__name__=~"http_.+|rpc_.+|orders_.+"}
)
)

Comparez le résultat avant et après la release avec la même fenêtre et le même pas. Une famille qui passe brutalement de quelques centaines à des dizaines de milliers de séries est un candidat ; ce n’est pas encore la preuve du label responsable.

promql 03-dimensions-candidates.promql
topk(20, count by (route) (http_server_request_duration_seconds_count))

topk(20, count by (status_code) (http_server_request_duration_seconds_count))

count(count by (request_id) (http_server_request_duration_seconds_count))

La dernière requête n’est acceptable que sur une métrique et une fenêtre déjà bornées. Si request_id contient presque une valeur par requête, sa valeur opérationnelle comme label est nulle : cet identifiant appartient aux traces ou aux logs corrélés, pas à l’index de séries temporelles. Appliquez le même raisonnement à user_id, session_id, URL brute, message d’erreur ou hash de commit non borné.

Vérifier la source avant de filtrer

Le même symptôme peut venir de trois endroits : l’application expose trop de labels, la configuration de scrape enrichit les séries, ou plusieurs objets collectent deux fois le même endpoint. Identifiez la première couche qui introduit la dimension.

text arbre-cause-cardinalite.txt
Le label existe sur /metrics
Corriger l’instrumentation applicative
Garder l’identifiant détaillé dans trace ou log
Versionner le changement avec la release

Le label apparaît seulement après découverte ou relabeling
Lire ServiceMonitor, PodMonitor ou configuration custom scrape
Vérifier labelmap, target_label et labels Kubernetes copiés
Supprimer uniquement la règle qui élargit la dimension

La même target apparaît plusieurs fois
Comparer job, instance, endpoint et objets de découverte
Désactiver la collecte dupliquée après preuve
Vérifier que les règles et dashboards utilisent la série conservée

Le volume augmente sans nouveau label
Comparer replicas, targets, fréquence de scrape et métriques exposées
Distinguer croissance attendue et changement de périmètre

Ne filtrez pas un label uniquement parce qu’il a beaucoup de valeurs. pod, namespace ou status_code peuvent être nécessaires à une alerte ou à un diagnostic. La question est : cette dimension soutient-elle une décision d’exploitation, et son domaine de valeurs est-il borné ?

Construire une correction minimale et réversible

La meilleure correction reste souvent dans l’instrumentation : remplacer l’URL brute par une route normalisée et déplacer les identifiants uniques vers les traces. Quand il faut stabiliser l’ingestion avant une release applicative, utilisez un relabeling ciblé sur le job concerné.

yaml 04-relabeling-candidat.yml
scrape_configs:
- job_name: orders-api
  scrape_interval: 30s
  kubernetes_sd_configs:
  - role: pod
  metric_relabel_configs:
  - action: labeldrop
    regex: "request_id|user_id|session_id"
  - source_labels: [__name__]
    action: keep
    regex: "http_server_.+|process_.+|runtime_.+|orders_.+"

Adaptez ce fragment au mécanisme de collecte réellement utilisé ; ne remplacez pas à l’aveugle le ConfigMap complet. Exportez sa version courante, validez le YAML hors production, puis appliquez la correction sur un cluster ou un job canari. Un labeldrop ne supprime pas rétroactivement les anciennes séries et peut fusionner plusieurs échantillons qui ne se distinguaient que par le label retiré. Vérifiez donc l’absence de collisions et le comportement des agrégations.

Réduire la fréquence de scrape peut diminuer les événements par minute, mais ne corrige pas une dimension non bornée. À l’inverse, supprimer le label réduit le nombre de séries futures sans forcément résoudre un débit excessif causé par trop de targets. Traitez chaque limite avec la cause qui lui correspond.

Protéger alertes, dashboards et règles d’enregistrement

Avant la bascule, recherchez les requêtes qui utilisent les labels supprimés ou les métriques filtrées. Une collecte moins coûteuse mais qui casse l’alerte de disponibilité n’est pas une récupération.

yaml contrat-validation-observabilite.yml
consommateurs_a_tester:
- dashboard_service
- alerte_disponibilite
- alerte_saturation
- regles_enregistrement
- rapports_capacite

signaux_a_conserver:
- up_par_job_et_instance
- latence_par_route_normalisee
- erreurs_par_classe_de_statut
- saturation_par_workload
- correlation_trace_id_dans_traces

signaux_a_refuser_comme_labels:
- request_id
- user_id
- session_id
- url_avec_parametres

Rejouez quelques PromQL représentatives avec le même intervalle et comparez résultat, durée et nombre de séries. Les règles d’enregistrement doivent être testées séparément : elles déplacent le coût et peuvent continuer à interroger une dimension retirée.

Décider entre correction, capacité et rollback

Une demande de hausse de limite est cohérente lorsque la croissance est attendue, mesurée et utile. Elle ne doit pas devenir le rollback par défaut d’une instrumentation défectueuse.

text decision-cardinalite-prometheus.txt
Corriger l’instrumentation
Un identifiant non borne est expose comme label
La release responsable est identifiee
La route ou classe bornee de remplacement est connue

Appliquer un filtre de collecte temporaire
Le job et les labels fautifs sont prouves
Les alertes critiques ne dependent pas du label retire
Le manifest precedent est disponible pour rollback

Demander plus de capacite ou repartir la collecte
La croissance correspond a des workloads legitimes
Les labels ont une valeur operationnelle prouvee
La projection reste sous controle apres augmentation

Rollbacker la release
La cardinalite explose immediatement avec la nouvelle instrumentation
Une correction applicative ne tient pas dans la fenetre d’incident
L’image precedente et son schema de metriques sont compatibles

Maintenir le blocage
La source des series reste inconnue
Les donnees sont deja rejetees ou les targets deviennent instables
La correction candidate supprime un signal d’astreinte

Valider sur plusieurs cycles de scrape

Gardez le canari pendant plusieurs intervalles de scrape et sur une charge représentative. La stabilisation attendue n’est pas instantanée : les anciennes séries restent actives un temps, alors que les nouvelles combinaisons doivent cesser d’apparaître.

text gates-validation-prometheus.txt
Conserver la correction
Nombre de nouvelles series revenu a une pente stable
Evenements par minute sous le seuil operationnel
Aucun rejet d’ingestion nouveau
Targets critiques up et scrapes reguliers
Dashboards et alertes critiques valides
Cout et duree des PromQL representatifs ameliores
Identifiants detailles encore accessibles dans traces ou logs

Rollbacker la configuration
Series dupliquees ou collisions apres labeldrop
Alerte critique vide ou aggregation semantiquement fausse
Target disparu apres modification du perimetre
Aucun effet mesurable sur la limite visee
Impossibilite de relier la correction a une cause prouvee

Le rollback consiste à réappliquer le manifest de collecte capturé, puis à vérifier la prise en compte par les collecteurs et le retour des targets. Si la release applicative est rollbackée, confirmez aussi que l’ancien endpoint /metrics n’émet plus le label fautif ; un retour d’image sans validation ne suffit pas.

Conclusion

Une explosion de cardinalité Managed Prometheus est d’abord un problème de modèle de données opérationnel. Bornez le workspace, le cluster et la release, séparez saturation, scrape et requête, puis prouvez la métrique et le label qui créent les séries avant de toucher aux quotas.

La décision finale doit rester réversible : corriger l’instrumentation, filtrer temporairement un label sans valeur, réduire un périmètre dupliqué, dimensionner une croissance légitime ou rollbacker la release. La récupération est validée quand les nouvelles séries se stabilisent sans perte d’alertes, de targets ni de capacité de diagnostic.