Introduction : la fatigue d'alerte, le cancer des ops
Combien d'alertes votre équipe reçoit-elle chaque jour ? Dix ? Cent ? Mille ?
90 % des alertes sont ignorées. Ce n'est pas une statistique alarmiste — c'est une réalité documentée par des études de l'industrie. Quand un on-call reçoit 200 notifications par jour, son cerveau se déconnecte. L'alerte qui devrait déclencher une intervention devient un bruit de fond, une nuisance parmi tant d'autres.
C'est ce phénomène qu'on appelle l'alert fatigue, et c'est l'ennemi public numéro un du monitoring moderne. Non seulement elle rend vos équipes sourdes aux vrais problèmes, mais elle détruit aussi leur qualité de vie — et par extension, la stabilité de votre infrastructure.
Dans cet article, nous explorons comment construire une stratégie d'alerting qui réduit le bruit tout en accélérant la réponse aux véritables incidents. Pas de théorie creuse : des pratiques concrètes, du code, des patterns testés en production.
Plan de l'article
- Le problème de l'alert fatigue — chiffres, conséquences réelles
- Taxonomie des alertes — comment catégoriser pour clarifier
- Hiérarchiser symptômes et causes — alerter sur ce que les utilisateurs voient
- Alertmanager — routing, grouping, inhibition
- Réduction du bruit — déduplication, fenêtres temporelles, maintenance
- Escalation et on-call — rotations, PagerDuty, runbooks
- Alertes SLO-based — burn rate, multi-window, error budget
- Templates et runbooks — annotations, standardisation
- Anti-patterns à éviter — les pièges courants
- Perspectives complémentaires — lectures et stacks connexes
Le problème de l'alert fatigue
Statistiques et impact
Selon le Google SRE Book, l'alert fatigue est une cause majeure de défaillances opérationnelles :
- 90 % des alertes ignorées dans les environnements mal configurés
- 70 % des incidents auraient pu être évités avec une meilleure stratégie d'alerting
- Temps moyen de réaction multiplié par 3 quand le ratio signal/bruit est mauvais
Cas réels
Un incident célèbre : une infrastructure critique a connu une panne de 2 heures parce que l'alerte appropriée était noyée dans 10 000 alertes quotidiennes. Personne ne l'a vue.
Autre exemple : une équipe DevOps était alertée toutes les 30 secondes pour une métrique non-critique. Résultat ? Les vrais problèmes passaient sous le radar, et les on-call quittaient l'équipe par frustration.
Coût réel
- Bruit cognitif → décisions plus lentes
- Attrition → burn-out des équipes ops
- MTTR (Mean Time To Resolution) → dégradé
- Confiance envers le monitoring → perdue
Taxonomie des alertes
Avant de réduire le bruit, il faut le comprendre. Catégorisez vos alertes :
Par sévérité
P1 (Critical) : Service down, data loss risk, SLA breach imminent
P2 (High) : Feature degraded, performance impacted, intervention < 2h
P3 (Medium) : Minor issues, can wait until business hours
P4 (Low) : Informational, cosmetic issues, can be batched
Par nature
Symptôme-based : "Users see errors" (ce que l'utilisateur expérimente) Cause-based : "Disk at 95%" (diagnostic, contexte pour engineers) Threshold-based : "CPU > 80%" (simple mais souvent trop bruyant) Anomaly-based : "Requêtes 50% plus lentes que d'habitude" (ML-driven)
Critère d'actionabilité
Une bonne alerte répond à ces questions :
- Quelqu'un peut-il agir sur cette alerte ?
- Y a-t-il une runbook documentée ?
- Quel est le SLA de réponse ?
- Peut-on l'automatiser ? (auto-remediation)
Hiérarchiser : symptômes vs causes
Alerte sur les symptômes, pas les causes
❌ Mauvais : "Disk usage at 85%" ✅ Bon : "Less than 24 hours of disk space remaining"
❌ Mauvais : "CPU > 80%" ✅ Bon : "Response time for checkout endpoint > 2s"
❌ Mauvais : "Memory usage > 70%" ✅ Bon : "API error rate > 1%"
Pourquoi ?
L'on-call doit savoir immédiatement s'il y a un impact utilisateur. Les métriques internes sont un contexte pour comprendre le symptôme, pas des alertes en soi.
Exemple concret
Vous avez une baisse soudaine de CPU. Est-ce un problème ?
- Si le service répond toujours rapidement → non, c'est normal
- Si les requêtes ralentissent → oui, escalade
Donc alertez sur la latence, pas le CPU. Le CPU devient métrique de diagnostic.
Alertmanager : routing et grouping
Concept central
Alertmanager prend les alertes brutes de Prometheus et les transforme via trois mécanismes :
- Grouping : regrouper par labels (ex: par service, tenant, cluster)
- Routing : dispatcher vers les bons canaux (Slack, PagerDuty, email)
- Inhibition : supprimer les alertes redondantes
Configuration YAML
global:
resolve_timeout: 5m
route:
receiver: 'default'
group_by: ['service', 'cluster']
group_wait: 30s
group_interval: 5m
repeat_interval: 12h
routes:
- match:
severity: 'P1'
receiver: 'pagerduty-critical'
group_wait: 5s
repeat_interval: 5m
continue: true
- match:
severity: 'P2'
receiver: 'slack-ops'
group_wait: 2m
- match:
service: 'billing'
receiver: 'slack-billing'
receivers:
- name: 'default'
slack_configs:
- channel: '#alerts'
- name: 'pagerduty-critical'
pagerduty_configs:
- service_key: '{{ env "PAGERDUTY_KEY" }}'
description: '{{ .GroupLabels.alertname }}'
- name: 'slack-ops'
slack_configs:
- channel: '#ops'
inhibit_rules:
- source_matchers:
- severity: 'P1'
target_matchers:
- severity: 'P2|P3|P4'
equal: ['service', 'cluster']
- source_matchers:
- alertname: 'ClusterDown'
target_matchers:
- alertname: 'PodDown'
equal: ['cluster']
Points clés
- group_by : regroupe les alertes avant envoi → réduit le bruit
- group_wait : attend 30s pour laisser les alertes s'accumuler
- inhibit_rules : si ClusterDown est active, supprime automatiquement PodDown (cause vs symptôme)
- repeat_interval : relance l'alerte toutes les 12h (important pour les alertes longue-durée)
Réduction du bruit
Technique 1 : Grouping intelligent
route:
group_by: ['service', 'instance_type']
group_wait: 30s
Plutôt que 50 alertes "DiskFull" sur 50 serveurs, recevez une seule notification « DiskFull on web servers (50 instances) ».
Technique 2 : Déduplication
Prometheus envoie parfois la même alerte deux fois. Utilisez un label fingerprint ou les templates Alertmanager pour dédupliquer.
Technique 3 : Fenêtres temporelles
route:
routes:
- match:
severity: 'P3'
receiver: 'slack-ops'
repeat_interval: 24h
group_wait: 1h
Les P3 ne sortent qu'une fois par jour, durant les heures de bureau. Les P1 sortent chaque 5 minutes.
Technique 4 : Maintenance windows
inhibit_rules:
- source_matchers:
- alertname: 'MaintenanceMode'
target_matchers: []
equal: ['cluster']
Lors de déploiements ou maintenances : postez une alerte "MaintenanceMode" qui supprime toutes les autres durant 1h.
Technique 5 : Seuils dynamiques
Au lieu de "Disk > 90%", utilisez "Time until disk full < 24h" calculé depuis les trends.
- alert: DiskFillingSoon
expr: |
predict_linear(node_filesystem_avail_bytes[1h], 86400) < 1073741824
Escalation et on-call
Concept : rotation structurée
Alert P1 → PagerDuty immediately
Alert P2 → Slack #ops + email if unacknowledged after 30m
Alert P3 → Summary email end of day
Alert P4 → Archived, available on dashboard
Intégration PagerDuty
- name: 'pagerduty-critical'
pagerduty_configs:
- service_key: '{{ env "PAGERDUTY_KEY" }}'
description: '{{ .CommonAnnotations.summary }}'
details:
firing: '{{ template "pagerduty.default.instances" .Alerts.Firing }}'
resolve_key: '{{ .GroupLabels.alertname }}:{{ .GroupLabels.service }}'
client: 'Alertmanager'
client_url: '{{ .ExternalURL }}'
links:
- href: '{{ .CommonAnnotations.runbook_url }}'
text: 'Runbook'
Rotation on-call
Gérez les rotations via :
- PagerDuty : schedules, overrides, rotations implicites
- Opsgenie : escalation policy, rotation fine-grained
- Grafana OnCall : gratuit, auto-hébergé
Clés d'une bonne rotation :
- Durée claire : 1 semaine, pas 3 mois
- Sur-call défini : sur-appel après 3 escalations
- Handoff documenté : notes le lundi matin
Alertes SLO-based
Concept : burn rate alerts
Au lieu d'alerter sur des métriques brutes, alertez sur la consommation du budget d'erreur.
Si votre SLA est 99.9%, vous pouvez vous permettre :
Downtime budget = (1 - 0.999) × 30 jours = 43.2 secondes/jour = ~25.9 minutes/mois
Multi-window approach
Rob Ewaschuk a popularisé une approche à deux fenêtres :
- alert: SLOBurnRateCritical
expr: |
(
sum(rate(requests_total{status=~"5..|0"}[5m]))
/
sum(rate(requests_total[5m]))
) > (14.4 * 0.001)
for: 5m
annotations:
summary: 'SLO burn rate 14.4x'
- alert: SLOBurnRateHigh
expr: |
(
sum(rate(requests_total{status=~"5..|0"}[30m]))
/
sum(rate(requests_total[30m]))
) > (6 * 0.001)
for: 30m
annotations:
summary: 'SLO burn rate 6x'
Interprétation :
- 14.4x burn rate sur 5m → vous consommerez votre budget mensuel en ~2 heures → escalade immédiate
- 6x burn rate sur 30m → vous consommerez le budget en ~5 heures → escalade rapide
- < 1x burn rate → aucune action, c'est normal
Avantages
✅ Basé sur le SLA, pas sur des seuils arbitraires ✅ Réduit le bruit (alertes seulement si vraie dérive) ✅ Aligne ops sur business objectives
Templates et runbooks
Annotations enrichies
- alert: ApiLatencyHigh
expr: histogram_quantile(0.95, request_duration_seconds) > 2
for: 5m
labels:
severity: 'P2'
service: 'api'
annotations:
summary: '{{ $labels.service }} P95 latency > 2s'
description: |
Service {{ $labels.service }} on {{ $labels.instance }} has P95 latency of {{ $value }}s
Current timestamp: {{ humanize $value }}
runbook_url: 'https://wiki.internal/runbooks/api-latency-high'
dashboard_url: 'https://grafana.internal/d/abc123'
slack_channel: '#api-oncall'
Structure d'une runbook
# API Latency High
## Symptoms
- P95 latency > 2s for more than 5 minutes
## Impact
- Users experience slow API responses
- SLA 99.9% at risk if sustained
## Troubleshooting
1. Check Grafana dashboard (link in alert)
2. Look at error logs: `journalctl -u api -n 100`
3. Check resource usage: `htop`
4. If CPU-bound: trigger scaling policy
5. If DB-bound: check slow query logs
6. Escalate to database team if persisted
## Escalation
If not resolved in 15 minutes: page @api-lead
Templates standards
Définissez des templates Alertmanager globaux :
templates:
- '/etc/alertmanager/templates/*.tmpl'
Fichier /etc/alertmanager/templates/slack.tmpl :
{{ define "slack.default.text" }}
{{ range .Alerts }}
*{{ .Labels.severity }}* | {{ .Labels.alertname }}
{{ .Annotations.summary }}
{{ if .Annotations.runbook_url }}Runbook: <{{ .Annotations.runbook_url }}|here>{{ end }}
{{ end }}
{{ end }}
Anti-patterns à éviter
❌ Pattern 1 : Alerte sur tout
- alert: MetricTooHigh
expr: any_metric > 50
Problème : Nous alertons sur chaque métrique > 50. Mais 50 signifie quoi pour une latence ? Différent d'un nombre d'erreurs.
Solution : Seulement les métriques métier-relevantes avec des seuils justifiés.
❌ Pattern 2 : Pas de runbook
Une alerte sans runbook → on-call googling la solution → résolution lente.
Solution : Chaque alerte P1/P2 a une runbook préparée.
❌ Pattern 3 : Alert tout le temps
- alert: DiskSpace
expr: node_filesystem_avail_bytes / node_filesystem_size_bytes < 0.2
for: 0m
Déclenche toutes les secondes pendant le cronjob. Absorbée immédiatement.
Solution : for: 5m minimum, grouping agressif.
❌ Pattern 4 : CPU > 80% comme alerte
CPU élevé ≠ problème. Si le service répond bien, c'est normal.
Solution : Alertez sur latence, pas CPU.
❌ Pattern 5 : Alertes sans contexte
Alert: HighCPU
Description: CPU is high
Solution : Ajoutez contexte (instance, service, valeur exacte, cause probable).
Perspectives complémentaires
Cette stratégie d'alerting s'insère dans une stack monitoring plus large. Pour approfondir :
- Prometheus + Grafana + Alertmanager — stack open-source production-ready
- SLO, SLI et error budget — théorie et implémentation
- Uptime monitoring avec Uptime Kuma — surveillance externe
- Logging structuré et correlation IDs — diagnostic rapide
Ces articles complètent votre stratégie globale de reliability.
Sources
- Google SRE Book, chapitre "Monitoring Distributed Systems" : https://sre.google/books/
- Rob Ewaschuk, "My Philosophy on Alerting" : https://docs.google.com/document/d/199PqyG3UsyXlwieHaqbGiWVa8eMWi8zzAn0YfcABiQA/
- PagerDuty, "Incident Response" : https://response.pagerduty.com/
- Prometheus, documentation officielle : https://prometheus.io/docs/alerting/
- Grafana, best practices : https://grafana.com/docs/alerting/latest/
Conclusion
Une bonne stratégie d'alerting n'est pas compliquée, mais elle demande de la discipline :
- Alertez sur les symptômes que les utilisateurs vivent
- Catégorisez par sévérité (P1 → immédiat, P4 → summary)
- Réduisez le bruit avec Alertmanager (grouping, inhibition, fenêtres)
- Versionnez vos runbooks (une par alerte P1/P2)
- Mesurez votre SLO, alertez sur le burn rate
En pratique, chez SHPV par exemple, où le SLA cible est 99.9%+ avec un GTI (Garantie de Temps d'Intervention) de 2h, une telle stratégie assure que les alertes réelles remontent rapidement sans saturer l'équipe infogérance. Le bruit est réduit, la réaction accélérée.
Commencez simple : une douzaine d'alertes bien pensées vaut mieux que deux cents mal configurées.
Prochain pas : prendre votre plus gros système, appliquer cette taxonomie, et réduire vos alertes quotidiennes par 80%. Vous verrez la différence en une semaine.


