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.
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.
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.
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.
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.
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.
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é.
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.
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.
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.
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.