Supervision complète avec Prometheus & Grafana
Ceci met en place une stack Prometheus + Grafana qui scrape de vraies cibles, alerte sur des symptômes réellement ressentis par les utilisateurs plutôt que sur des métriques de ressources brutes comme le CPU% par défaut, et provisionne le dashboard en tant que code.
Scraper les cibles avec prometheus.yml
Prometheus va chercher les métriques plutôt que de les recevoir passivement, donc l'essentiel de la configuration se résume à : où regarder, et à quelle fréquence.
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: "checkout-api"
metrics_path: /metrics
kubernetes_sd_configs:
- role: pod
namespaces:
names: ["payments"]
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_app]
regex: checkout-api
action: keep
- source_labels: [__meta_kubernetes_pod_name]
target_label: pod
- source_labels: [__meta_kubernetes_namespace]
target_label: namespace
- job_name: "node-exporter"
static_configs:
- targets: ["node-exporter:9100"]
rule_files:
- "alert.rules.yml"
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:9093"]kubernetes_sd_configs fait de la découverte de service, pour ne pas avoir à maintenir une liste de cibles à la main à chaque fois qu'un pod est reprogrammé ailleurs, et le bloc relabel_configs filtre cette découverte pour ne garder que l'application ciblée, sans lui, Prometheus scrape tous les pods du namespace. L'action keep couplée à un regex sur un label de pod est le pattern que j'utilise en premier réflexe.
Choisir quoi alerter : les méthodes RED et USE
Le moyen le plus rapide de se retrouver avec de la fatigue d'alerte, c'est d'alerter sur tout ce que l'exporter expose par défaut. Deux frameworks corrigent ça :
- RED (pour les services orientés requêtes) : Rate (débit), Errors (erreurs), Duration (latence). Si un service traite des requêtes, ces trois métriques couvrent ce que l'utilisateur vit réellement.
- USE (pour les ressources) : Utilization, Saturation, Errors. À utiliser pour l'infrastructure sous-jacente : nodes, disques, files d'attente.
L'utilisation CPU est une métrique USE qui concerne le node. « Les requêtes timeout » est une métrique RED qui concerne l'expérience de l'utilisateur. Alertez sur le second, et servez-vous du premier comme contexte de debug une fois que vous êtes déjà en train d'intervenir.
Si vous ne pouvez pas terminer « un utilisateur est actuellement en train de subir X » à partir du nom d'une alerte, c'est probablement une métrique de cause, pas de symptôme. Gardez-la comme panneau de dashboard, pas comme page d'astreinte.
Une vraie règle d'alerte : taux d'erreur avec for:
Voici l'alerte que je déploie pour un service HTTP, construite autour du taux d'erreur de RED :
groups:
- name: checkout-api.rules
rules:
- alert: CheckoutAPIHighErrorRate
expr: |
sum(rate(http_requests_total{job="checkout-api", status=~"5.."}[5m]))
/
sum(rate(http_requests_total{job="checkout-api"}[5m]))
> 0.02
for: 10m
labels:
severity: page
team: payments
annotations:
summary: "Taux d'erreur de checkout-api au-dessus de 2% pendant 10 minutes"
description: "{{ $value | humanizePercentage }} des requêtes vers checkout-api renvoient un 5xx sur les 5 dernières minutes."
runbook_url: "https://runbooks.internal/checkout-api-errors"Le champ for: 10m est le plus sous-utilisé de l'alerting Prometheus. Sans lui, l'alerte se déclenche à l'instant où l'expression dépasse 2%, même pour un pic isolé de 30 secondes pendant un déploiement, puis se résout aussitôt. Exiger que la condition tienne dix minutes d'affilée filtre ce bruit transitoire tout en gardant la détection de ce qui est durable. J'ajuste la durée par alerte : 2-3 minutes pour quelque chose d'urgent, 10-15 minutes pour tout ce qui s'auto-résout par un comportement normal de retry/backoff.
for: échange de la vitesse de détection contre de la qualité de signal. Le régler trop court recrée de la fatigue d'alerte ; le régler trop long retarde une vraie page.
Routage et regroupement dans Alertmanager
Prometheus décide si une alerte doit se déclencher ; Alertmanager décide qui en entend parler et à quelle fréquence. Routez en vous basant sur les labels que vos règles définissent déjà :
route:
receiver: "default-slack"
group_by: ["alertname", "team"]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
- match:
severity: page
team: payments
receiver: "payments-oncall-pagerduty"
continue: false
receivers:
- name: "default-slack"
slack_configs:
- channel: "#alerts-general"
- name: "payments-oncall-pagerduty"
pagerduty_configs:
- routing_key: "{{ .PaymentsPagerDutyKey }}"group_by est ce qui empêche un déploiement défaillant de vous envoyer quinze notifications pour quinze pods du même rollout. group_wait laisse une courte fenêtre aux alertes liées pour arriver ensemble avant la première notification ; repeat_interval contrôle la fréquence de relance d'une alerte non résolue, qui doit être suffisamment longue pour que l'astreinte ne soit pas re-sollicitée toutes les quelques minutes.
Provisionner le dashboard Grafana en code
Le dashboard qui compte est celui qui est livré avec le service, pas celui que quelqu'un construit à la main dans l'interface. Le provisioning permet ça :
apiVersion: 1
providers:
- name: "checkout-api"
orgId: 1
folder: "Payments"
type: file
disableDeletion: false
updateIntervalSeconds: 30
options:
path: /etc/grafana/provisioning/dashboards/checkout-api
foldersFromFilesStructure: true
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: trueAssociez ça à un fichier JSON de dashboard (généré une première fois depuis l'interface, puis versionné dans le dépôt), et le dashboard, sa source de données et les règles d'alerte se déploient tous ensemble via le même pipeline que le service. Sautez cette étape et le dashboard dérive dès que quelqu'un retouche un panneau à la main, en silence, jusqu'à devenir le panneau cassé auquel plus personne ne fait confiance.
Comment les pièces s'assemblent
Pour conclure
Une configuration de scraping, une règle d'alerte, un arbre de routage, un dashboard provisionné. Ce qui distingue une équipe qui fait confiance à ses alertes de celle qui finit par couper le canal, c'est si chaque alerte répond à « un utilisateur est-il affecté en ce moment », soutenue par une fenêtre for: assez longue pour ignorer le bruit.
Envie de faire tourner ça en production ?
Ce tutoriel couvre les concepts et l'architecture. Si vous voulez l'implémenter dans votre propre infrastructure, ou monter en compétence pour posséder ce sujet durablement, je propose du mentorat individuel construit autour de votre environnement réel, pas une formation générique.
Ce tutoriel
- Concepts clés et architecture principale
- Extraits de code illustratifs
- Le raisonnement derrière chaque décision
Mentorat individuel
- Des sessions de travail sur votre propre environnement
- Des réponses directes aux cas particuliers que vous rencontrez
- Un retour sur votre implémentation réelle
- Un accompagnement continu pendant que vous la construisez