Supervision Kubernetes : Prometheus, Grafana, alertes

Installer kube-prometheus-stack sur un cluster de PME : rétention, coût réel, les 8 règles d'alerte qui servent vraiment et celles à désactiver.

Homme de dos dans une salle de contrôle devant des écrans de supervision et un mur d'affichage

Réponse courte : sur un cluster Kubernetes de PME, la supervision utile tient en trois décisions, pas en trois cents tableaux de bord. Installer kube-prometheus-stack (le chart communautaire qui embarque Prometheus, Alertmanager, Grafana et les règles kubernetes-mixin), dimensionner la rétention à 15 jours sur un volume de 50 Gi — soit environ 2 à 5 € par mois de block storage chez OVHcloud ou Scaleway —, puis supprimer 80 % des règles d'alerte livrées par défaut pour n'en garder qu'une dizaine qui décrivent un symptôme ressenti par un utilisateur. Une alerte qui ne déclenche pas d'action est un bug de configuration, pas une précaution.

Nous reprenons régulièrement des clusters où Prometheus tourne depuis un an. Le pattern est toujours le même : un canal Slack #alerts muet depuis huit mois parce que personne ne supporte plus les notifications, un Grafana avec quarante tableaux de bord dont trois ouverts au moins une fois, et une rétention à 10 jours sur un disque qui déborde tous les quinze jours. Pendant ce temps, l'incident réel — une base PostgreSQL saturée en connexions, un pod tué par l'OOM killer toutes les nuits à 2 h — passe inaperçu. Cet article décrit l'installation que nous posons par défaut et, surtout, le tri des alertes.

Homme de dos dans une salle de contrôle devant des écrans de supervision et un mur d'affichage

Ce qu'il faut mesurer avant de choisir un outil

Découpons le besoin. Sur un cluster qui sert les sites et applications d'une PME, la supervision répond à quatre questions distinctes, et elles n'ont pas le même outil.

QuestionNature de la donnéeOutil
Le service répond-il, et vite ?métriques de latence et de taux d'erreur HTTPPrometheus + ingress/Gateway metrics
Le cluster a-t-il encore des ressources ?métriques nœuds, pods, PVCPrometheus + node-exporter, kube-state-metrics
Pourquoi ce pod a-t-il échoué ?journaux applicatifsLoki, ou la plateforme de logs du fournisseur
Quelle requête a ralenti ce parcours ?traces distribuéesOpenTelemetry + Tempo ou Jaeger

La confusion la plus coûteuse consiste à vouloir tout faire avec Prometheus. Prometheus est une base de séries temporelles à faible cardinalité : il stocke des métriques numériques agrégées, pas des événements individuels. Mettre un identifiant de requête ou un e-mail d'utilisateur dans un label fait exploser la mémoire — la documentation Prometheus sur les bonnes pratiques de nommage et celle sur l'instrumentation le répètent : chaque combinaison de labels crée une série distincte.

Notre recommandation pour un cluster de PME, sur un périmètre de 3 à 10 nœuds :

  • Métriques : kube-prometheus-stack, autohébergé dans le cluster. Rétention courte, agrégation claire.
  • Journaux : Loki avec un bucket objet, ou le service de logs du fournisseur si le cluster est managé. Les journaux sont volumineux et rarement consultés : l'object storage à 0,01 € le Go-mois les rend indolores.
  • Traces : à ajouter seulement quand une application a plus de deux services qui s'appellent entre eux. Avant, c'est du temps perdu.

Installer kube-prometheus-stack sans se tromper sur les valeurs

Le chart kube-prometheus-stack est maintenu par la communauté prometheus-community. Il embarque le Prometheus Operator, Prometheus, Alertmanager, Grafana, node-exporter, kube-state-metrics et un jeu complet de règles issues du projet kubernetes-mixin. En une commande, on obtient une supervision qui fonctionne — et qui crie beaucoup trop.

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install monitoring prometheus-community/kube-prometheus-stack \
  --namespace monitoring --create-namespace \
  -f values.yaml

Le fichier values.yaml est là où tout se joue. Voici le squelette que nous utilisons, en adaptant la storageClassName au fournisseur (csi-cinder-high-speed chez OVHcloud, scw-bssd chez Scaleway) :

prometheus:
  prometheusSpec:
    retention: 15d
    retentionSize: 40GiB
    scrapeInterval: 30s
    evaluationInterval: 30s
    resources:
      requests:
        cpu: 200m
        memory: 2Gi
      limits:
        memory: 4Gi
    storageSpec:
      volumeClaimTemplate:
        spec:
          storageClassName: csi-cinder-high-speed
          accessModes: ["ReadWriteOnce"]
          resources:
            requests:
              storage: 50Gi
    # ne récupérer que les ServiceMonitor explicitement étiquetés
    serviceMonitorSelectorNilUsesHelmValues: false

alertmanager:
  alertmanagerSpec:
    storage:
      volumeClaimTemplate:
        spec:
          storageClassName: csi-cinder-high-speed
          accessModes: ["ReadWriteOnce"]
          resources:
            requests:
              storage: 5Gi

grafana:
  adminPassword: ""        # injecté depuis un Secret externe
  persistence:
    enabled: true
    size: 5Gi
  defaultDashboardsTimezone: Europe/Paris

Trois réglages méritent une explication, parce qu'ils sont la cause de la majorité des incidents de supervision que nous dépannons.

retention et retentionSize ensemble, toujours

retention: 15d seul ne protège pas le disque : si la cardinalité augmente (nouveau service, nouveaux labels), le volume se remplit avant les 15 jours et Prometheus s'arrête. retentionSize fixe un plafond dur. On le règle à environ 80 % de la taille du volume — 40 GiB pour un PVC de 50 Gi — pour laisser la place aux blocs en cours de compaction.

Pour dimensionner, la règle de grandeur de la documentation Prometheus sur le stockage reste utilisable : espace ≈ durée de rétention × nombre d'échantillons par seconde × taille moyenne d'un échantillon (de l'ordre de 1 à 2 octets après compression). Sur nos clusters de 5 nœuds avec une trentaine de services instrumentés, on observe en pratique 15 à 25 Gi pour 15 jours. Un PVC de 50 Gi laisse donc deux fois la marge nécessaire, pour quelques euros par mois.

Une limite mémoire, jamais de limite CPU

Prometheus consomme de la mémoire proportionnellement au nombre de séries actives, avec des pics pendant la compaction et les requêtes lourdes des tableaux de bord. Une limits.memory évite qu'il emporte un nœud entier ; une limits.cpu au contraire le fait throttler pendant la compaction et déclenche de faux positifs partout. C'est la même logique que pour les applications décrite dans notre article sur l'autoscaling de Next.js sur Kubernetes avec HPA et KEDA.

Le scrapeInterval à 30 s, pas à 15 s

Doubler l'intervalle divise par deux le volume stocké et la charge CPU. Pour des sites et applications de PME, détecter une saturation en 30 secondes plutôt qu'en 15 ne change rien : l'alerte comporte de toute façon un for: 5m pour éviter le bruit. Les 15 s par défaut ne se justifient que si vous construisez des SLO à la seconde.

Les huit alertes qui méritent une notification

Le jeu de règles kubernetes-mixin livré avec le chart compte plus de cent alertes. Beaucoup décrivent des états internes du plan de contrôle — inexploitables sur un cluster managé OVHcloud, Scaleway ou EKS, où ce plan de contrôle n'est pas le vôtre. La première action après l'installation consiste donc à couper ce qui ne vous concerne pas :

defaultRules:
  create: true
  rules:
    etcd: false
    kubeApiserverAvailability: false
    kubeApiserverBurnrate: false
    kubeApiserverSlos: false
    kubeControllerManager: false
    kubeSchedulerAlerting: false
    kubeProxy: false

Ensuite, on applique un principe simple, repris de la philosophie d'alerting documentée par Google dans le chapitre « Monitoring Distributed Systems » du SRE Book : n'alerter que sur les symptômes visibles par l'utilisateur, ou sur les causes qui deviendront inévitablement un symptôme. Tout le reste va dans un tableau de bord, pas dans une notification.

Voici la liste que nous gardons sur un cluster de PME, avec la raison d'être de chacune.

AlerteDéclencheurPourquoi elle justifie une notification
TargetDownune cible de scrape injoignable > 10 minsans elle, toutes les autres alertes deviennent silencieuses
KubePodCrashLoopingredémarrages répétés > 15 minun déploiement cassé, souvent juste après une mise en production
KubePodNotReadypod non prêt > 15 minimage introuvable, probe mal réglée, PVC non monté
KubeDeploymentReplicasMismatchréplicas désirés ≠ disponibles > 15 mincapacité réduite silencieusement
KubePersistentVolumeFillingUpPVC prévu plein < 4 joursla panne la plus prévisible et la plus destructrice
KubeNodeNotReadynœud non prêt > 15 minperte de capacité, risque de pods non replaçables
KubeMemoryOvercommitsomme des requests mémoire > capacitéplus aucun pod ne pourra être replacé en cas de perte de nœud
CertificateExpiringSooncertificat TLS < 14 joursune expiration = site inaccessible, et cert-manager échoue silencieusement

À cette base, nous ajoutons systématiquement une alerte applicative par service exposé, celle qui remplace à elle seule vingt règles d'infrastructure : le taux d'erreurs HTTP 5xx vu par l'ingress ou la Gateway. Le PrometheusRule ressemble à ceci, sur des métriques exposées par un contrôleur compatible Gateway API :

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: app-availability
  namespace: monitoring
  labels:
    release: monitoring
spec:
  groups:
    - name: app-availability
      rules:
        - alert: HighHttp5xxRate
          expr: |
            sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
            /
            sum(rate(http_requests_total[5m])) by (service)
            > 0.02
          for: 5m
          labels:
            severity: critical
          annotations:
            summary: "Plus de 2 % d'erreurs 5xx sur {{ $labels.service }}"
            runbook: "https://wiki.interne/runbooks/http-5xx"

Deux détails font la différence. Le label release: monitoring est indispensable pour que l'Operator ramasse la règle quand le chart est installé sous ce nom de release — c'est la cause n°1 des PrometheusRule appliqués qui ne déclenchent jamais. Et l'annotation runbook : une alerte sans procédure associée sera traitée différemment par chaque astreinte, donc mal.

Salle de supervision : adultes devant des écrans de tableaux de bord et un grand mur d'affichage

Router les alertes : deux sévérités, pas cinq

Alertmanager permet des arbres de routage arbitrairement complexes. Sur un cluster de PME, deux niveaux suffisent, et toute sévérité intermédiaire finit ignorée.

alertmanager:
  config:
    route:
      receiver: chat-info
      group_by: ['alertname', 'namespace']
      group_wait: 30s
      group_interval: 5m
      repeat_interval: 12h
      routes:
        - matchers: [severity="critical"]
          receiver: astreinte
          repeat_interval: 1h
    inhibit_rules:
      - source_matchers: [alertname="KubeNodeNotReady"]
        target_matchers: [severity="warning"]
        equal: ['node']
    receivers:
      - name: chat-info
        webhook_configs:
          - url: https://chat.example/hooks/monitoring
      - name: astreinte
        webhook_configs:
          - url: https://oncall.example/hooks/critical
  • critical → notification qui réveille, avec un runbook. Un symptôme utilisateur, ou une panne imminente.
  • warning → message dans un canal lu en heures ouvrées, revu une fois par semaine.

Les inhibit_rules évitent le scénario classique : un nœud tombe, et trente alertes de pods non prêts arrivent en même temps que l'alerte de nœud. On n'en veut qu'une. Pensez aussi aux time_intervals pour les tâches planifiées qui font monter la charge la nuit — mieux vaut une fenêtre de silence explicite qu'une alerte que l'équipe apprend à ignorer.

Un point souvent oublié : testez le chemin de notification, pas seulement la règle. Une URL de webhook révoquée se comporte exactement comme un cluster en bonne santé. Nous déclenchons une alerte factice Watchdog (livrée par le chart, elle est toujours active) vers un service de « dead man's switch » : si le ping cesse d'arriver, c'est la supervision elle-même qui est tombée. Même raisonnement que pour une sauvegarde jamais restaurée — un sujet que nous détaillons dans notre guide des sauvegardes Kubernetes avec Velero.

Combien ça coûte réellement

C'est la question qui tranche entre auto-hébergé et service managé. Les tarifs publics suivants sont ceux affichés par les fournisseurs à l'automne 2026 ; vérifiez-les avant de budgéter, ils bougent.

PosteDimensionCoût mensuel indicatif
Block storage Prometheus (OVHcloud, Scaleway)50 Gi haute performance~4 à 6 € HT
Block storage Alertmanager + Grafana10 Gi~1 € HT
CPU/RAM consommés dans le cluster~0,5 vCPU, 3 à 5 Giéquivalent à un petit nœud partagé
Object storage pour les journaux (Loki)100 Go~1 à 2 € HT

En pratique, sur les clusters que nous exploitons, la supervision complète coûte moins de 10 € HT par mois de stockage, et consomme l'équivalent d'un tiers de nœud. Le vrai coût est ailleurs : les quelques jours de réglage initial, puis l'heure mensuelle de ménage dans les alertes.

Les offres SaaS d'observabilité facturent à l'hôte ou au volume ingéré. Elles deviennent pertinentes dès que vous avez plusieurs clusters, une astreinte formalisée et besoin de corréler métriques, journaux et traces dans la même interface. En dessous, kube-prometheus-stack fait le travail — avec la même logique de comparaison que celle appliquée au choix entre PostgreSQL sur Kubernetes et une base managée : le prix du service, c'est le temps d'exploitation qu'il vous rend.

Console d'administration avec écran, clavier et souris devant des baies de serveurs dans un centre de données

Les erreurs que nous voyons le plus souvent

  • Prometheus sans volume persistant. Le chart démarre volontiers en emptyDir. Chaque redémarrage de pod efface l'historique, donc toute analyse post-incident.
  • Grafana en source de vérité. Les tableaux de bord créés à la main dans l'interface disparaissent avec le PVC. Les stocker en ConfigMap avec le label grafana_dashboard: "1", versionnés dans Git, les rend reproductibles — exactement comme les manifestes déployés par le pipeline GitLab CI/CD.
  • Cardinalité non surveillée. Un label user_id ou path non normalisé multiplie les séries par mille. On surveille prometheus_tsdb_head_series et on alerte au-delà d'un seuil choisi (par exemple 1 million de séries pour les ressources ci-dessus).
  • Aucune alerte sur les certificats. cert-manager échoue silencieusement quand un challenge DNS casse. L'alerte arrive alors des utilisateurs, trois semaines plus tard.
  • Des alertes sans for:. Une règle qui déclenche sur un unique point de mesure produit du bruit à chaque pic de 30 secondes. En dessous de for: 5m, posez-vous la question.

Si vous reprenez un cluster existant, le premier exercice utile n'est pas d'ajouter des tableaux de bord : c'est d'exporter les alertes déclenchées sur les 90 derniers jours et de supprimer toutes celles qui n'ont jamais donné lieu à une action. C'est typiquement ce que nous faisons en début de mission sur les prestations d'infogérance et d'infrastructure, avant d'ajouter la moindre règle. Un canal d'alerte crédible vaut mieux que mille métriques.

Questions fréquentes

Faut-il Prometheus si le cluster est managé chez OVHcloud ou Scaleway ?

Oui. Les fournisseurs supervisent le plan de contrôle (API server, etcd, scheduler) et vous en montrent la santé, mais pas vos applications : ni vos taux d'erreur 5xx, ni vos PVC qui se remplissent, ni vos pods en CrashLoopBackOff. Le périmètre managé s'arrête à la frontière de vos namespaces. En revanche, cela vous autorise à désactiver toutes les règles etcd, kubeApiserver*, kubeControllerManager et kubeScheduler : vous ne pouvez rien y faire, et elles génèrent des faux positifs.

Quelle rétention choisir pour Prometheus ?

15 jours couvrent les besoins d'investigation post-incident et de comparaison semaine sur semaine. Au-delà, le besoin change de nature : il s'agit de tendances (capacité, saisonnalité), pas de diagnostic. Pour cela, on ne rallonge pas la rétention locale — on ajoute un remote_write vers Thanos, Mimir ou un service managé, avec des métriques déjà agrégées. Garder 12 mois de données brutes à 30 secondes d'intervalle coûte en stockage et en mémoire sans rien apporter.

Loki ou le service de logs du fournisseur ?

Loki est cohérent si vous voulez tout dans Grafana et un coût au Go d'object storage. Il demande du réglage (rétention, index, limites par tenant) et un bucket S3 à gérer. Les services de logs intégrés aux Kubernetes managés évitent cette exploitation, au prix d'une facture à l'ingestion qui surprend quand une application se met à journaliser en boucle. Dans les deux cas : plafonnez le débit par namespace, sinon un seul console.log dans une boucle fait exploser le budget.

Peut-on alerter sur la latence sans instrumenter l'application ?

Partiellement. Les contrôleurs d'ingress et les implémentations de Gateway API exposent des histogrammes de latence par route, ce qui suffit pour un seuil sur le 95e centile. C'est d'ailleurs un argument de plus pour le passage à la Gateway API en remplacement d'ingress-nginx. En revanche, savoir où le temps est passé demande des traces, donc de l'instrumentation applicative — généralement avec les SDK OpenTelemetry.

Combien d'alertes critiques par semaine est-ce normal ?

Zéro, la plupart des semaines. Sur les clusters de PME que nous exploitons, une alerte critical est un événement, pas une routine. Si votre astreinte en reçoit plusieurs par semaine sans qu'une action corrective suive, le problème n'est pas la fréquence : ce sont les seuils. Le bon indicateur de santé d'une supervision n'est pas le nombre d'alertes, c'est le pourcentage d'alertes qui ont déclenché une action.

En résumé

  • kube-prometheus-stack installe en une commande Prometheus, Alertmanager, Grafana et les règles kubernetes-mixin ; tout le travail est dans les values.yaml et le tri des règles.
  • Fixez toujours retention et retentionSize (≈ 80 % du volume), avec un PVC de 50 Gi pour 15 jours sur un cluster de 3 à 10 nœuds.
  • Une limits.memory sur Prometheus, jamais de limits.cpu : le throttling pendant la compaction génère des faux positifs.
  • Sur un cluster managé, désactivez les règles du plan de contrôle (etcd, kubeApiserver*, kubeScheduler, kubeControllerManager) : vous ne pouvez pas agir dessus.
  • Gardez une dizaine d'alertes d'infrastructure plus une règle de taux d'erreur 5xx par service exposé, chacune avec un for: et une annotation runbook.
  • Deux sévérités suffisent : critical qui réveille, warning revue en heures ouvrées. Plus de niveaux = niveaux ignorés.
  • Testez le chemin de notification avec un dead man's switch sur l'alerte Watchdog : une supervision tombée ressemble à un cluster en bonne santé.
  • Comptez moins de 10 € HT par mois de stockage et environ un tiers de nœud en ressources ; le coût réel est le temps de réglage.
  • Besoin d'un regard extérieur sur la supervision d'un cluster existant ? Parlez-en à notre équipe ou contactez-nous.