Une alerte utile réveille quelqu’un pour une raison qui justifie d’être réveillé — et lui donne assez de contexte pour agir en moins de 5 minutes. C’est la définition complète. Pourtant, la majorité des systèmes d’alerting font l’inverse : ils noient les équipes sous des centaines de notifications inutiles (“CPU à 80 %”, “pod redémarré”, “disque à 70 %”) jusqu’à ce que tout le monde les ignore — y compris la seule alerte qui comptait vraiment. Ce guide vous apprend à construire un système d’alerting symptom-first, calibré sur vos SLO, avec les mécanismes anti-bruit de Prometheus et d’Alertmanager.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Symptom-first : pourquoi alerter sur l’impact utilisateur et pas sur les causes techniques — avec des exemples concrets pour HTTP, batch, queues et bases de données
- Anatomie d’une alerte : les champs obligatoires d’une règle Prometheus pour qu’elle soit actionnable
- Prometheus :
for:— le premier filtre anti-bruit, directement dans les règles d’alerte - Alertmanager : grouping, inhibition, silences — la boîte à outils pour réduire l’alert fatigue côté notification
- Seuils : statiques vs dynamiques, percentiles vs moyennes, et quand utiliser chacun
- SLO-based alerting : le burn rate, le multi-window multi-burn-rate (MWMBR) — la méthode Google SRE pour alerter quand le budget d’erreur se consume trop vite
- Watchdog et absent() : vérifier que la chaîne d’alerting fonctionne et détecter les métriques manquantes
- Règles de qualité : chaque alerte doit avoir un runbook, un owner, une severity — sinon c’est du bruit
- Escalade : qui avertir, quand, par quel canal — et la distinction entre le routing Alertmanager et l’escalade temporelle (PagerDuty, Opsgenie)
- Anti-patterns : les erreurs classiques qui transforment un système d’alerting en machine à épuiser les équipes
Pourquoi la plupart des systèmes d’alerting échouent
Section intitulée « Pourquoi la plupart des systèmes d’alerting échouent »Le problème a un nom : alert fatigue. Quand une équipe reçoit plus de quelques alertes par jour en moyenne, un engrenage se met en place :
- L’équipe commence à ignorer les alertes (surtout les “warning”)
- Pour compenser, elle silence massivement — y compris des alertes utiles
- Un jour, une alerte critique passe inaperçue — et l’incident dure
- Le management réagit en ajoutant des alertes — ce qui aggrave le problème
La cause racine est presque toujours la même : les alertes sont configurées sur les causes (CPU > 80 %, pod CrashLoopBackOff, latence réseau) au lieu des symptômes (les utilisateurs voient des erreurs, le service ne répond plus, le checkout est en panne).
Principe n°1 : alerter sur les symptômes, pas les causes
Section intitulée « Principe n°1 : alerter sur les symptômes, pas les causes »Rob Ewaschuk, ex-SRE chez Google, a formalisé cette idée dans son document “My Philosophy on Alerting” : une alerte doit refléter un problème visible par l’utilisateur, pas un état interne de l’infrastructure.
Exemples symptom-first : services HTTP
Section intitulée « Exemples symptom-first : services HTTP »| Alerte cause (mauvaise) | Alerte symptôme (bonne) | Pourquoi |
|---|---|---|
| ”MySQL down" | "Error rate > 5 % sur le service commandes” | Les utilisateurs voient des erreurs — c’est ça l’impact |
| ”CPU > 90 %" | "Latence p99 > 2 s sur l’API checkout” | Le CPU élevé n’est un problème que s’il dégrade le service |
| ”Pod CrashLoopBackOff" | "Taux de succès < 99 % sur le service paiement” | Le pod qui redémarre n’est un problème que si le service est dégradé |
| ”Disque > 85 %" | "Erreurs d’écriture détectées sur le service logs” | Le disque plein est une cause potentielle, l’échec d’écriture est le symptôme |
| ”Certificat expire dans 7 jours” | (celle-ci est légitime — c’est une alerte préventive) | Exception : les alertes préventives sur des deadlines sont des symptômes “à venir” |
Les alertes cause (CPU, disque, pod) ont leur place dans les dashboards comme aide au diagnostic — mais elles ne doivent pas réveiller quelqu’un. Incluez l’information de cause dans les annotations de l’alerte symptôme pour accélérer le diagnostic.
Symptom-first au-delà du HTTP
Section intitulée « Symptom-first au-delà du HTTP »Le pattern REST/HTTP est le plus courant, mais le principe s’applique à tous les workloads. Voici les symptômes pertinents pour d’autres types de services :
| Type de workload | Alerte cause (mauvaise) | Alerte symptôme (bonne) |
|---|---|---|
| File d’attente / Kafka / RabbitMQ | ”Consumer lag > 10 000" | "Âge du plus vieux message non traité > 5 min” — c’est l’impact sur la fraîcheur des données |
| Batch / cron | ”Job failed" | "Le job n’a pas terminé avec succès dans la fenêtre attendue” — inclut les cas où le job ne s’est jamais lancé |
| Base de données (côté client) | “Connexions MySQL > 80 %" | "Taux d’erreur des requêtes SQL côté application > 1 %” — c’est ce que l’application voit |
| Cache (Redis, Memcached) | “Mémoire Redis > 90 %" | "Cache hit ratio < 80 %” ou “Latence p99 des requêtes cache > 50 ms” |
| Kubernetes | ”Pod CrashLoopBackOff" | "SLO du service dégradé” — un pod qui redémarre n’est un problème que s’il impacte le service |
Anatomie d’une règle d’alerte Prometheus
Section intitulée « Anatomie d’une règle d’alerte Prometheus »Une alerte Prometheus bien construite contient des labels pour le routing et des annotations pour le contexte humain. Voici la structure complète :
groups: - name: payment-service rules: - alert: PaymentErrorRateHigh expr: | ( sum(rate(http_requests_total{service="payment-api", status=~"5.."}[5m])) / clamp_min(sum(rate(http_requests_total{service="payment-api"}[5m])), 1) ) > 0.01 for: 5m labels: severity: critical team: payments service: payment-api annotations: summary: "Taux d'erreur payment-api > 1 %" description: > Le service payment-api retourne {{ $value | humanizePercentage }} d'erreurs 5xx sur les 5 dernières minutes. Impact : les paiements échouent pour les utilisateurs. dashboard_url: "https://grafana.example.com/d/payment-red" runbook_url: "https://wiki.example.com/runbooks/payment-error-rate"Décryptage des champs
Section intitulée « Décryptage des champs »| Champ | Rôle | Règle de qualité |
|---|---|---|
alert | Nom unique de l’alerte | Nom descriptif : ServiceSymptômeSévérité (ex: PaymentErrorRateHigh) |
expr | Requête PromQL — la condition de déclenchement | Toujours basée sur un symptôme, pas une cause. Protéger les divisions avec clamp_min |
for | Durée pendant laquelle la condition doit être vraie avant de déclencher | Fortement recommandé — empêche les alertes sur des pics transitoires (voir exceptions ci-dessous) |
labels.severity | Niveau de sévérité | critical (page), warning (Slack), info (ticket) — 3 niveaux max |
labels.team | Équipe responsable | Chaque alerte a un owner — sinon personne ne se sent responsable |
labels.service | Service concerné | Permet le routing et le grouping dans Alertmanager |
annotations.summary | Résumé en une ligne | Ce qui est affiché dans la notification — clair et concis |
annotations.description | Détail avec impact | Inclure la valeur actuelle ({{ $value }}), l’impact utilisateur, le contexte |
annotations.dashboard_url | Lien vers le dashboard | Le SRE clique et voit immédiatement l’état du service |
annotations.runbook_url | Lien vers le runbook | La procédure de diagnostic et de remédiation — obligatoire pour les critical |
Anti-bruit côté Prometheus : le champ for:
Section intitulée « Anti-bruit côté Prometheus : le champ for: »Le champ for: est le premier filtre anti-bruit, directement dans la
règle d’alerte Prometheus (pas dans Alertmanager). Il impose que la condition
soit vraie en continu pendant la durée spécifiée avant que l’alerte ne
passe de l’état pending à firing.
Sans for:, un pic de latence d’une seconde déclenche l’alerte. Avec
for: 5m, la condition doit être continuellement vraie pendant 5 minutes
avant que l’alerte ne fire. C’est le filtre le plus simple contre les faux
positifs et les flapping alerts (alertes qui oscillent entre OK et
FIRING).
Valeurs recommandées par défaut
Section intitulée « Valeurs recommandées par défaut »| Sévérité | for: recommandé | Logique |
|---|---|---|
critical | 5 min | Assez pour confirmer le problème, assez court pour réagir vite |
warning | 15-30 min | Le problème persiste mais n’est pas urgent — on attend pour confirmer |
info | 1 h+ | Tendance de fond, pas d’urgence |
Exceptions légitimes : quand omettre ou raccourcir for:
Section intitulée « Exceptions légitimes : quand omettre ou raccourcir for: »Le for: est fortement recommandé par défaut, mais certains types
d’alertes sont légitimes avec un for: très court ou absent :
| Type d’alerte | Pourquoi pas de for: |
|---|---|
| Watchdog / Deadman’s switch | L’alerte doit toujours être active — le for: retarderait la détection d’une panne de l’alerting |
| Perte totale de trafic | Si le trafic tombe à zéro, quelques secondes suffisent pour confirmer |
| Certificat / deadline | L’alerte est préventive et basée sur un calcul (expiration dans N jours) — le for: n’apporte rien |
Anti-bruit côté Alertmanager : grouping, inhibition, silences
Section intitulée « Anti-bruit côté Alertmanager : grouping, inhibition, silences »Prometheus évalue les règles et envoie les alertes à Alertmanager, qui est responsable du routing (qui reçoit quoi), du grouping (regrouper les alertes liées), de l’inhibition (supprimer les alertes redondantes) et du silencing (taire les alertes pendant les maintenances).
1. Grouping : regrouper les alertes liées
Section intitulée « 1. Grouping : regrouper les alertes liées »Quand une base de données tombe, 50 services qui en dépendent génèrent chacun une alerte. Sans grouping, le SRE de garde reçoit 50 notifications en rafale. Avec le grouping, il reçoit 1 notification groupée.
# alertmanager.yml — extraitroute: group_by: ['alertname', 'service'] group_wait: 30s group_interval: 5m repeat_interval: 4h| Paramètre | Rôle | Valeur recommandée |
|---|---|---|
group_by | Labels utilisés pour regrouper les alertes | ['alertname', 'service'] — une notification par alerte × service |
group_wait | Délai avant d’envoyer la première notification (attend d’autres alertes du même groupe) | 30 s — assez pour capturer les alertes corrélées |
group_interval | Délai entre les mises à jour d’un groupe existant | 5 min — évite le spam si de nouvelles alertes rejoignent le groupe |
repeat_interval | Délai avant de re-notifier si l’alerte est toujours active | 4 h — rappel régulier sans harcèlement |
2. Inhibition : supprimer les alertes redondantes
Section intitulée « 2. Inhibition : supprimer les alertes redondantes »Si le cluster est down, inutile de recevoir en plus les alertes de chaque service. L’inhibition permet de supprimer automatiquement les alertes de faible priorité quand une alerte de haute priorité est active.
# alertmanager.yml — extraitinhibit_rules: - source_matchers: - severity = critical target_matchers: - severity = warning equal: ['service']Cette règle dit : “si une alerte critical est active pour un service,
supprime toutes les alertes warning du même service”. Le SRE ne voit que
l’alerte la plus grave — il n’est pas distrait par les avertissements
secondaires.
3. Silencing : taire les alertes pendant les maintenances
Section intitulée « 3. Silencing : taire les alertes pendant les maintenances »Avant une maintenance planifiée (mise à jour, migration, redémarrage), créez un silence dans Alertmanager pour les services concernés. Sinon, chaque action de maintenance déclenche des alertes et pollue les canaux.
Un silence se crée via l’interface web d’Alertmanager ou via l’API :
# Silence de 2 h sur le service payment-apiamtool silence add service="payment-api" \ --comment="Maintenance planifiée — mise à jour DB" \ --author="sre-team" \ --duration=2hChoisir ses seuils : statiques, dynamiques, percentiles
Section intitulée « Choisir ses seuils : statiques, dynamiques, percentiles »Le choix du seuil détermine la sensibilité de l’alerte : trop bas = faux positifs (bruit), trop haut = faux négatifs (incidents ratés).
Seuils statiques
Section intitulée « Seuils statiques »Un seuil statique est une valeur fixe : “alerte si error rate > 1 %”, “alerte si latence p99 > 2 s”. C’est simple, compréhensible, et suffisant pour la majorité des cas.
# Seuil statique — error rate > 1 %- alert: PaymentErrorRateHigh expr: | ( sum(rate(http_requests_total{service="payment-api", status=~"5.."}[5m])) / clamp_min(sum(rate(http_requests_total{service="payment-api"}[5m])), 1) ) > 0.01 for: 5mAvantage : facile à comprendre, à expliquer, à auditer.
Limite : un seuil fixe ne s’adapte pas aux variations de trafic. 1 % d’erreurs à 3 h du matin (10 req/s) = 0.1 req/s en erreur. 1 % d’erreurs à 14 h (10 000 req/s) = 100 req/s en erreur — l’impact est radicalement différent.
Percentiles vs moyenne
Section intitulée « Percentiles vs moyenne »Pour les seuils de latence, la même règle que pour les dashboards s’applique : n’alertez jamais sur la moyenne.
| Approche | Problème | Recommandation |
|---|---|---|
| Moyenne > 2 s | 1 requête à 60 s + 99 à 10 ms = moyenne 610 ms — pas d’alerte, mais un utilisateur a attendu 1 min | Ne pas utiliser |
| p99 > 2 s | Le 1 % des requêtes les plus lentes dépasse 2 s — détecte les outliers | Bon pour les alertes critiques |
| p50 > 500 ms | La médiane dépasse 500 ms — l’expérience typique est dégradée | Bon pour les alertes warning |
Combinez les deux : critical sur p99, warning sur p50. Le p99 détecte
les cas extrêmes, le p50 détecte les dégradations généralisées.
Seuils dynamiques (anomaly detection)
Section intitulée « Seuils dynamiques (anomaly detection) »Les seuils dynamiques comparent la valeur actuelle à un historique (moyenne glissante, saisonnalité, bande de prédiction). Ils disent : “alerte si la valeur est anormale par rapport au comportement habituel”.
# Alerte si le taux de requêtes est 50 % inférieur# à la moyenne de la même heure 7 jours avanthttp_requests_total_rate5m < 0.5 * avg_over_time(http_requests_total_rate5m[1h] offset 7d)Les seuils dynamiques demandent une baseline propre (au moins 2-4 semaines de données stables) et une attention particulière aux jours fériés, campagnes marketing, et migrations qui faussent l’historique.
SLO-based alerting : le burn rate multi-window (MWMBR)
Section intitulée « SLO-based alerting : le burn rate multi-window (MWMBR) »L’approche la plus sophistiquée — et la plus fiable — consiste à alerter non pas sur une valeur instantanée, mais sur la vitesse de consommation du budget d’erreur. C’est le burn rate alerting, décrit dans le chapitre 5 du Google SRE Workbook.
Le concept de burn rate
Section intitulée « Le concept de burn rate »Si votre SLO de disponibilité est de 99.9 % sur 30 jours, votre budget d’erreur est de 0.1 % — soit environ 43 minutes d’indisponibilité autorisées par mois.
Le burn rate mesure la vitesse à laquelle ce budget se consume :
| Burn rate | Signification | Budget épuisé en |
|---|---|---|
| 1× | Consommation normale (0.1 % d’erreurs) | 30 jours (toute la fenêtre) |
| 2× | Deux fois plus vite que prévu | 15 jours |
| 10× | Dix fois plus vite | 3 jours |
| 14.4× | Très rapide — alerte critique | ~50 heures |
| 36× | Panne majeure | ~20 heures |
L’idée : au lieu d’alerter sur un taux d’erreur instantané (qui peut être un pic transitoire), on alerte quand le budget d’erreur se consume trop vite pour tenir jusqu’à la fin de la fenêtre SLO.
Multi-window : éviter les faux positifs
Section intitulée « Multi-window : éviter les faux positifs »Un burn rate élevé mesuré sur une seule fenêtre peut être un artefact (pic de 5 minutes qui fait monter la moyenne). La technique multi-window combine deux fenêtres :
- une fenêtre longue pour confirmer la tendance
- une fenêtre courte pour vérifier que le problème est actuel (pas un résidu d’un incident déjà résolu)
L’alerte ne se déclenche que si les deux fenêtres dépassent le seuil.
Le pattern MWMBR standard (Google SRE Workbook)
Section intitulée « Le pattern MWMBR standard (Google SRE Workbook) »Le SRE Workbook recommande deux paires de fenêtres avec des burn rates différents — une pour les incidents rapides (page), une pour les dégradations lentes (ticket) :
| Niveau | Burn rate | Fenêtre longue | Fenêtre courte | for: | Action |
|---|---|---|---|---|---|
| Page (critical) | 14.4× | 1 h | 5 min | 2 min | Intervention immédiate |
| Ticket (warning) | 6× | 6 h | 30 min | 15 min | Action dans les heures ouvrées |
La paire Page détecte les incidents rapides : à 14.4×, le budget serait épuisé en ~50 heures — c’est assez rapide pour justifier une intervention immédiate. La paire Ticket détecte les dégradations lentes : à 6×, le budget serait épuisé en ~5 jours — assez pour créer un ticket, pas pour réveiller quelqu’un la nuit.
Exemple PromQL : MWMBR complet
Section intitulée « Exemple PromQL : MWMBR complet »Pour un SLO de 99.9 % de disponibilité sur 30 jours :
groups: - name: slo-payment-api rules: # Recording rules — pré-calcul du taux d'erreur - record: service:http_error_ratio:rate5m expr: | sum by (service) (rate(http_requests_total{status=~"5.."}[5m])) / clamp_min(sum by (service) (rate(http_requests_total[5m])), 1)
- record: service:http_error_ratio:rate30m expr: | sum by (service) (rate(http_requests_total{status=~"5.."}[30m])) / clamp_min(sum by (service) (rate(http_requests_total[30m])), 1)
- record: service:http_error_ratio:rate1h expr: | sum by (service) (rate(http_requests_total{status=~"5.."}[1h])) / clamp_min(sum by (service) (rate(http_requests_total[1h])), 1)
- record: service:http_error_ratio:rate6h expr: | sum by (service) (rate(http_requests_total{status=~"5.."}[6h])) / clamp_min(sum by (service) (rate(http_requests_total[6h])), 1)
# --- Page (critical) : burn rate 14.4× --- # Fenêtre longue 1h + fenêtre courte 5m - alert: SLOBudgetBurnCritical expr: | service:http_error_ratio:rate1h{service="payment-api"} > (14.4 * 0.001) and service:http_error_ratio:rate5m{service="payment-api"} > (14.4 * 0.001) for: 2m labels: severity: critical team: payments slo: availability annotations: summary: "Burn rate critique — budget d'erreur payment-api se consume 14× trop vite" description: > Le service payment-api consomme son budget d'erreur (SLO 99.9 %) au rythme de {{ $value | humanize }}× la normale. À ce rythme, le budget sera épuisé bien avant la fin de la fenêtre de 30 jours. runbook_url: "https://wiki.example.com/runbooks/slo-budget-burn"
# --- Ticket (warning) : burn rate 6× --- # Fenêtre longue 6h + fenêtre courte 30m - alert: SLOBudgetBurnWarning expr: | service:http_error_ratio:rate6h{service="payment-api"} > (6 * 0.001) and service:http_error_ratio:rate30m{service="payment-api"} > (6 * 0.001) for: 15m labels: severity: warning team: payments slo: availability annotations: summary: "Burn rate élevé — budget d'erreur payment-api se consume 6× trop vite" runbook_url: "https://wiki.example.com/runbooks/slo-budget-burn"Quand utiliser le burn rate vs les seuils statiques
Section intitulée « Quand utiliser le burn rate vs les seuils statiques »| Situation | Approche recommandée |
|---|---|
| Service sans SLO défini | Seuils statiques (error rate > X %, latence p99 > Y s) |
| Service avec SLO mais trafic faible (< 100 req/min) | Seuils statiques — le burn rate est instable sur peu de données |
| Service avec SLO et trafic significatif (> 100 req/min) | MWMBR — c’est la méthode la plus fiable |
| Alerte préventive (certificat, disque) | Seuils statiques — pas de notion de SLO |
Santé de la chaîne d’alerting : Watchdog et absent()
Section intitulée « Santé de la chaîne d’alerting : Watchdog et absent() »Un système d’alerting qui ne fonctionne plus sans que personne ne le sache est pire qu’un système sans alerting — il donne une fausse impression de sécurité. Deux mécanismes permettent de détecter ces pannes silencieuses.
Watchdog (Deadman’s switch)
Section intitulée « Watchdog (Deadman’s switch) »Le Watchdog est une alerte qui doit toujours être en état firing. Si elle disparaît, c’est que la chaîne d’alerting est cassée (Prometheus ne scrape plus, Alertmanager ne reçoit plus rien, le receiver est en panne).
groups: - name: meta-alerting rules: - alert: Watchdog expr: vector(1) labels: severity: info annotations: summary: "Watchdog — chaîne d'alerting OK" description: > Cette alerte doit toujours être en firing. Si elle disparaît, c'est que Prometheus, Alertmanager ou le receiver est en panne.Configurez votre outil d’astreinte (PagerDuty, Opsgenie, Grafana OnCall) pour recevoir un heartbeat du Watchdog. Si le heartbeat cesse pendant plus de 5 minutes, l’outil d’astreinte page automatiquement — c’est le filet de sécurité ultime.
Alertes d’absence : absent() et no-data
Section intitulée « Alertes d’absence : absent() et no-data »Un cas classique : votre exporter tombe, les métriques disparaissent, et vos alertes basées sur ces métriques ne se déclenchent plus (pas de données = pas de condition remplie = pas d’alerte). C’est le piège du “no data means no alert”.
La fonction absent() de Prometheus détecte la disparition d’une série
temporelle :
groups: - name: scrape-health rules: # Détecte si un node-exporter ne remonte plus de métriques - alert: NodeExporterDown expr: absent(up{job="node-exporter"} == 1) for: 5m labels: severity: warning team: platform annotations: summary: "node-exporter ne remonte plus de métriques" description: > Le job node-exporter n'a plus de target avec up=1 depuis 5 min. Cause probable : exporter crashé, pod non schedulé, ou scrape config incorrecte. runbook_url: "https://wiki.example.com/runbooks/exporter-down"
# Détecte si aucune métrique HTTP n'arrive pour un service critique - alert: NoHTTPMetrics expr: absent(http_requests_total{service="payment-api"}) for: 10m labels: severity: critical team: payments annotations: summary: "Aucune métrique HTTP reçue pour payment-api" description: > Aucune série http_requests_total n'existe pour le service payment-api depuis 10 min. Soit l'application est down, soit l'instrumentation est cassée.| Situation | Ce que vous voyez | Ce que absent() détecte |
|---|---|---|
| Exporter down | La cible disparaît de Prometheus | absent(up{job="..."} == 1) — la série up n’existe plus |
| Application non instrumentée | Pas de métriques applicatives | absent(http_requests_total{service="..."}) — la série n’a jamais existé ou a disparu |
| Pipeline de collecte cassé | Les métriques s’arrêtent d’arriver | absent() sur les métriques clés du pipeline (ex: logs/s, spans/s) |
Règles de qualité : chaque alerte doit être complète
Section intitulée « Règles de qualité : chaque alerte doit être complète »Une alerte sans runbook, c’est un réveil à 3 h du matin suivi de 30 minutes de “qui sait ce que c’est ?”. Chaque alerte critical doit respecter 5 critères avant d’être mise en production :
Les 5 critères d’une alerte production-ready
Section intitulée « Les 5 critères d’une alerte production-ready »| Critère | Question | Si la réponse est “non” |
|---|---|---|
| Owner | Quelle équipe est responsable ? | L’alerte ne sera jamais traitée — personne ne se sent concerné |
| Runbook | Un lien runbook_url vers la procédure de diagnostic existe-t-il ? | Le SRE de garde perd du temps à chercher quoi faire |
| Severity | Le niveau (critical/warning/info) est-il justifié ? | Tout en critical = plus rien n’est critical |
| Actionnable | Le destinataire peut-il faire quelque chose ? | L’alerte est du bruit — transformez-la en métrique de dashboard |
| Testée | L’alerte a-t-elle été testée dans un environnement dédié ? | Risque de faux positifs ou de non-déclenchement |
Convention de nommage
Section intitulée « Convention de nommage »Adoptez une convention de nommage systématique pour que chaque alerte soit identifiable au premier coup d’œil :
Format : ServiceSymptômeSévéritéExemples : PaymentErrorRateHigh → critical PaymentLatencyDegraded → warning CheckoutAvailabilityLow → critical CertificateExpiresIn7Days → warningLe label severity : 3 niveaux, pas plus
Section intitulée « Le label severity : 3 niveaux, pas plus »| Severity | Action | Canal | Horaire |
|---|---|---|---|
critical | Intervention immédiate — le SRE de garde est paginé | PagerDuty / Opsgenie / Grafana OnCall | 24/7 |
warning | Action requise dans les heures qui viennent | Slack / Teams / email | Heures ouvrées |
info | À traiter quand possible — ticket automatique | Jira / GitLab Issues | Backlog |
Escalade : routing Alertmanager + outil d’astreinte
Section intitulée « Escalade : routing Alertmanager + outil d’astreinte »L’escalade a deux composantes distinctes qu’il ne faut pas confondre :
- Alertmanager gère le routing : quelle alerte va vers quel receiver (PagerDuty, Slack, Jira) en fonction des labels (severity, team)
- L’outil d’astreinte (PagerDuty, Opsgenie, Grafana OnCall) gère l’escalade temporelle : si personne ne répond en 15 min, on page le secondaire, puis le manager
Alertmanager ne fait pas d’escalade temporelle — il envoie la notification initiale au bon receiver, point. L’escalade (T+15, T+30) est configurée dans l’outil d’astreinte.
Structure d’escalade type (côté outil d’astreinte)
Section intitulée « Structure d’escalade type (côté outil d’astreinte) »| Délai | Action | Destinataire |
|---|---|---|
| T+0 | Page (notification push + appel) | SRE de garde (primaire) |
| T+15 min | Re-page si non acquittée | SRE de garde (secondaire) |
| T+30 min | Escalade | Engineering Manager |
| T+1 h | Escalade | VP Engineering / incident commander |
Configuration du routing Alertmanager
Section intitulée « Configuration du routing Alertmanager »Le routing dans Alertmanager utilise un arbre de correspondance : chaque alerte descend dans l’arbre selon ses labels jusqu’à trouver le receiver approprié.
# alertmanager.yml — routingroute: receiver: 'default-slack' group_by: ['alertname', 'service'] group_wait: 30s group_interval: 5m repeat_interval: 4h
routes: # Alertes critical → PagerDuty (l'escalade est gérée côté PagerDuty) - matchers: - severity = critical receiver: 'pagerduty-critical' repeat_interval: 1h routes: # Sous-route : équipe payments - matchers: - team = payments receiver: 'pagerduty-payments'
# Alertes warning → Slack canal équipe - matchers: - severity = warning receiver: 'slack-warnings' repeat_interval: 4h
# Alertes info → webhook vers Jira - matchers: - severity = info receiver: 'jira-tickets' repeat_interval: 24h
receivers: - name: 'default-slack' slack_configs: - channel: '#alerts-general'
- name: 'pagerduty-critical' pagerduty_configs: - service_key: '<PD_SERVICE_KEY>'
- name: 'pagerduty-payments' pagerduty_configs: - service_key: '<PD_PAYMENTS_KEY>'
- name: 'slack-warnings' slack_configs: - channel: '#alerts-warnings'
- name: 'jira-tickets' webhook_configs: - url: 'https://jira.example.com/api/alertmanager-webhook'Anti-patterns : ce qu’il ne faut pas faire
Section intitulée « Anti-patterns : ce qu’il ne faut pas faire »| Anti-pattern | Pourquoi c’est un problème | Solution |
|---|---|---|
| Alerter sur les causes (CPU, RAM, pod restart) | Bruit — ces métriques fluctuent sans impact utilisateur | Alerter sur les symptômes (error rate, latence, disponibilité) |
Pas de for: (sauf Watchdog) | Un pic d’1 seconde déclenche l’alerte | Minimum 5 min pour critical, 15 min pour warning |
| Tout en critical | Le mot perd son sens, l’équipe ignore | 3 niveaux (critical, warning, info) avec des critères stricts |
| Pas de runbook | Le SRE de garde ne sait pas quoi faire | Chaque critical a un lien runbook_url dans les annotations |
| Pas de grouping | 50 notifications pour le même incident | group_by: ['alertname', 'service'] dans Alertmanager |
| Pas d’inhibition | Alertes warning + critical en parallèle — confusion | Inhiber les warning quand un critical est actif sur le même service |
| Alerter sur la moyenne | Masque les outliers, fausse impression de normalité | Alerter sur p99 (critical) et p50 (warning) |
| Seuils jamais revus | Les seuils de 2022 ne correspondent plus au trafic de 2026 | Revue trimestrielle des seuils et des alertes |
| Silences permanents | Masque des problèmes réels | Durée maximale d’un silence = durée de la maintenance + 30 min |
| Escalade manuelle | ”Appelle le manager si c’est grave” — personne ne le fait à 3 h du matin | Escalade automatique configurée dans PagerDuty/Opsgenie |
| Alertes non versionnées | Modifications non traçables, pas de review | Alertes as code dans Git, déployées via CI/CD |
| Pas de Watchdog | Si l’alerting tombe, personne ne le sait | Toujours avoir un Watchdog + heartbeat côté outil d’astreinte |
| Division sans clamp_min | NaN si trafic = 0, alerte imprévisible | clamp_min(dénominateur, 1) sur tous les ratios |
Métriques d’alerting : mesurer la santé du système
Section intitulée « Métriques d’alerting : mesurer la santé du système »Un système d’alerting a besoin d’être observé lui-même. Suivez ces métriques pour savoir si vos alertes sont utiles ou si elles dérivent :
| Métrique | Cible | Si hors cible |
|---|---|---|
| Alertes critical / semaine | 2-3 max | Trop de bruit → revoir les seuils ou passer en warning |
| % d’alertes actionnables | > 80 % | Trop de faux positifs → revoir les conditions et les for: |
| MTTA (Mean Time To Acknowledge) | < 15 min | L’équipe ne réagit pas → problème d’escalade ou d’alert fatigue |
| Taux de flapping | < 5 % | Seuils trop proches du comportement normal → ajouter de l’hystérésis |
| Alertes silencées (%) | < 10 % | Trop d’alertes inutiles que l’équipe silence au lieu de corriger |
| Alertes sans runbook (%) | 0 % pour les critical | Un critical sans runbook est un billet de loterie |
Revue périodique
Section intitulée « Revue périodique »Chaque trimestre, passez en revue votre système d’alerting :
- Quelles alertes ont sonné le plus ? — Si une alerte sonne 20 fois par semaine, elle est soit mal calibrée, soit un symptôme d’un problème de fond non résolu
- Quelles alertes n’ont jamais sonné ? — Après 6 mois sans trigger, l’alerte est peut-être obsolète ou son seuil est trop haut
- Quelles alertes ont été systématiquement silencées ? — C’est un signe qu’elles sont du bruit — corrigez-les ou supprimez-les
- Les runbooks sont-ils à jour ? — Un runbook périmé est pire que pas de runbook (il donne de fausses instructions)
Workflow : construire votre système d’alerting
Section intitulée « Workflow : construire votre système d’alerting »-
Listez vos services critiques et leurs SLO
Identifiez les 3-5 services dont l’indisponibilité a le plus d’impact métier. Si vous n’avez pas encore de SLO, définissez des cibles initiales (ex: 99.9 % de disponibilité, latence p99 < 500 ms).
-
Écrivez les alertes symptom-first
Pour chaque service : une alerte sur le taux d’erreur (symptôme principal) et une alerte sur la latence (dégradation). Pas plus de 2-3 alertes critical par service pour commencer.
-
Ajoutez les annotations et les runbooks
Chaque alerte doit avoir : summary, description avec impact, lien
dashboard_url, lienrunbook_url. Pas de runbook = pas de mise en production de l’alerte. -
Configurez le Watchdog et les alertes absent()
Déployez le Watchdog + heartbeat côté outil d’astreinte. Ajoutez
absent()sur les exporters et métriques critiques. C’est le filet de sécurité qui détecte les pannes silencieuses. -
Configurez Alertmanager
Routing par severity et par équipe, grouping (
group_by: ['alertname', 'service']— ajoutezcluster/envsi multi-cluster), inhibition (critical supprime warning), silencing (procédure documentée pour les maintenances). -
Configurez l’escalade dans l’outil d’astreinte
Dans PagerDuty/Opsgenie/Grafana OnCall : primaire → secondaire → manager avec des délais explicites (15 min, 30 min). Alertmanager route vers l’outil, l’outil escalade si personne ne répond.
-
Testez de bout en bout
Simulez un incident (inject error rate) et vérifiez : l’alerte se déclenche ? La notification arrive au bon canal ? Le lien dashboard fonctionne ? Le runbook est accessible ? Le Watchdog heartbeat est actif ?
-
Mesurez et itérez
Après 2 semaines, consultez les métriques d’alerting (MTTA, % actionnable, flapping). Ajustez les seuils, les
for:, le routing. L’alerting est un système vivant — il doit évoluer avec votre infrastructure.
Pièges courants
Section intitulée « Pièges courants »| Piège | Conséquence | Solution |
|---|---|---|
| Commencer par 50 alertes | Alert fatigue immédiate — l’équipe ignore tout | Commencer par 5-10 alertes sur les services les plus critiques |
| Copier les alertes d’un article de blog | Seuils non adaptés à votre contexte | Calibrer chaque seuil sur vos données réelles (baseline 2 semaines) |
| Alerter depuis le dashboard Grafana | Les alertes dépendent de Grafana — si Grafana tombe, plus d’alertes | Alertes = rules Prometheus + Alertmanager, indépendants de Grafana |
| Pas de distinction critical/warning | Tout se mélange, rien n’est priorisé | 3 niveaux max, critères stricts pour chaque niveau |
| Runbook = “regarder le dashboard” | Ce n’est pas un runbook, c’est un post-it | Un runbook = symptôme → diagnostic → remédiation → escalade |
À retenir
Section intitulée « À retenir »-
Alertez sur les symptômes (impact utilisateur), pas sur les causes (CPU, RAM, pod restart) — les causes ont leur place dans les dashboards, pas dans les alertes. Le pattern s’applique aussi aux queues (âge du message), batch (échec dans la fenêtre attendue) et bases de données (taux d’erreur côté client)
-
Le champ
for:(côté Prometheus) est votre premier anti-bruit : 5 min par défaut pour les critical, 15-30 min pour les warning — exceptions : Watchdog, perte totale de trafic, deadlines -
Côté Alertmanager, utilisez grouping (une notification par incident, pas 50), inhibition (critical supprime warning) et silencing (maintenances) — ajoutez
cluster/envaugroup_byen multi-cluster -
Pour les services avec des SLO et un trafic suffisant, le MWMBR (multi-window multi-burn-rate) est la méthode la plus fiable : page à 14.4× (1 h + 5 min), ticket à 6× (6 h + 30 min)
-
Chaque alerte critical doit avoir un owner, un
runbook_url, une severity justifiée et être testée — sinon c’est du bruit -
Déployez un Watchdog (alerte toujours firing + heartbeat) et des alertes
absent()sur vos exporters critiques — sans eux, une panne de l’alerting passe inaperçue -
L’escalade temporelle (T+15, T+30) se configure dans l’outil d’astreinte (PagerDuty, Opsgenie), pas dans Alertmanager — Alertmanager fait le routing, l’outil fait l’escalade
-
Revoyez vos alertes chaque trimestre : alertes trop fréquentes, jamais déclenchées, systématiquement silencées — chacune est un signal que le système doit évoluer
- Rob Ewaschuk — My Philosophy on Alerting : docs.google.com/document/d/199PqyG3UsyXlwieHaqbGiWVa8eMWi8zzAn0YfcApr8Q — le document fondateur de l’alerting symptom-first (ex-Google SRE)
- Google SRE Workbook — Alerting on SLOs : sre.google/workbook/alerting-on-slos — chapitre 5, burn rate et multi-window multi-burn-rate
- Google SRE Book — Practical Alerting : sre.google/sre-book/practical-alerting — principes fondamentaux
- Prometheus — Alertmanager : prometheus.io/docs/alerting/latest/alertmanager — documentation officielle (grouping, inhibition, silencing, routing)
- Grafana — Multi-window multi-burn-rate alerts : grafana.com/blog/how-to-implement-multi-window-multi-burn-rate-alerts-with-grafana-cloud — implémentation pratique