Aller au contenu
Outils medium

Exporters Prometheus

21 min de lecture

Prometheus ne sait faire qu'une chose pour collecter : envoyer une requête HTTP et lire un texte au format qu'il attend. Un exporter est le programme qui produit ce texte à partir d'une source qui l'ignore, système d'exploitation, base de données, équipement réseau. Ce guide vous aide à choisir le bon outil et à comprendre comment les pièces s'articulent.

L'exporter n'envoie jamais rien de lui-même : c'est Prometheus qui vient lire son endpoint /metrics à intervalle régulier, une opération appelée scrape. Cette inversion explique l'essentiel du reste de la page, notamment le fait que l'exporter doit être joignable en réseau depuis le serveur Prometheus, et non l'inverse.

Flux d'un exporter : la source envoie les métriques à l'exporter qui les expose pour Prometheus

[SOURCE] → (exporter / instrumentation) → /metrics ──scrape──▶ Prometheus
  • Source : OS, DB, service réseau, application…
  • Exporter : interroge la source et publie le résultat sur /metrics
  • Prometheus : collecte, stocke, interroge, alerte

Le choix se décide sur un seul critère, la possession du code. Instrumenter consiste à faire produire ses propres métriques à l'application, ce qui donne accès à des indicateurs métier qu'aucun outil externe ne pourra déduire. L'exporter, lui, observe de l'extérieur ce qu'un composant veut bien exposer.

SituationSolutionPourquoi
J'ai le code de l'appInstrumentation (client libs, OTel)Métriques métier précises, moins d'approximation
Produit tiers, pas de codeExporter dédiéMySQL, PostgreSQL, Redis, Nginx
Système d'exploitationAgent (Node/Windows Exporter)CPU, RAM, disque, réseau
Vérifier la disponibilité externeBlackbox ExporterProbes HTTP, DNS, TCP, ICMP

C'est la distinction à comprendre avant de configurer quoi que ce soit, parce qu'elle change la façon d'écrire le scrape_config. Le critère de tri est simple : combien de cibles un exemplaire de l'exporter peut-il observer, et où tourne-t-il par rapport à elles. Les deux premières familles se configurent avec une liste de cibles ordinaire ; la troisième impose de passer par le relabeling, détaillé plus bas.

Un exporter = une machine/service. L'exporter tourne sur ou près de la cible.

ExempleUsage
Node ExporterMétriques système Linux
Windows ExporterMétriques système Windows

Configuration Prometheus (simple) :

scrape_configs:
- job_name: node
static_configs:
- targets: ['server1:9100', 'server2:9100']

Chaque target est directement l'exporter.

L'exporter se connecte à un service (MySQL, PostgreSQL, Redis…) via TCP + credentials, puis expose /metrics.

ExempleUsage
mysqld_exporterMySQL/MariaDB
postgres_exporterPostgreSQL
redis_exporterRedis
mongodb_exporterMongoDB

Points d'attention :

  • Droits minimum (read-only quand possible)
  • Latence de collecte → ajuster scrape_timeout
  • Cardinalité des labels

Un seul exporter peut monitorer N cibles via un paramètre target=.... C'est le pattern multi-target exporter.

ExempleUsage
Blackbox ExporterProbes HTTP, DNS, TCP, ICMP
SNMP ExporterÉquipements réseau SNMP

Pourquoi c'est différent ?

  • L'exporter ne connaît pas les cibles à l'avance
  • Prometheus passe la cible en paramètre via relabeling
  • Un seul exporter peut sonder des centaines d'URLs

Ce tableau part de l'intention et non de l'outil : formulez d'abord ce que vous voulez savoir, la colonne « famille » vous indique ensuite le type de configuration à prévoir. La dernière ligne fait exception, cAdvisor n'étant pas un exporter au sens strict, comme l'explique l'encadré qui suit.

IntentionOutilFamilleCe que ça mesure
Santé machine LinuxNode ExporterACPU, RAM, disque, réseau
Santé Windowswindows_exporterAPerformance counters
Disponibilité HTTP/DNS/TCP/ICMPBlackbox ExporterCProbes externes, SSL expiry
Santé MySQL/MariaDBmysqld_exporterBConnexions, requêtes, réplication
Santé PostgreSQLpostgres_exporterBConnexions, locks, bloat
Santé Redisredis_exporterBMémoire, keys, ops/sec
Métriques conteneurscAdvisor / kubeletSourceCPU, RAM, I/O par conteneur

Liste complète des exporters officiels

C'est l'exporter à déployer en premier : il collecte les métriques système d'une machine Linux, CPU, mémoire, disques, interfaces réseau. Il s'installe sur chaque serveur à surveiller et écoute par défaut sur le port 9100. Aucune configuration n'est nécessaire pour démarrer, les réglages servent uniquement à activer ou désactiver des collecteurs.

Le binaire est le mode recommandé sur une machine physique ou virtuelle, car l'exporter doit voir le système hôte. La variante Docker existe mais réclame plusieurs options de partage avec l'hôte, détaillées dans son onglet.

  1. Télécharger l'archive et le fichier de sommes

    Fenêtre de terminal
    cd /tmp
    VERSION="1.12.1"
    BASE="https://github.com/prometheus/node_exporter/releases/download/v${VERSION}"
    wget "${BASE}/node_exporter-${VERSION}.linux-amd64.tar.gz"
    wget "${BASE}/sha256sums.txt"
  2. Vérifier l'empreinte avant d'extraire

    Fenêtre de terminal
    sha256sum --ignore-missing -c sha256sums.txt

    La sortie doit afficher la ligne de l'archive suivie de OK. Si elle affiche ÉCHEC ou FAILED, l'archive est corrompue ou altérée : supprimez-la sans l'extraire.

  3. Installer

    Fenêtre de terminal
    tar xvfz node_exporter-${VERSION}.linux-amd64.tar.gz
    sudo cp node_exporter-${VERSION}.linux-amd64/node_exporter /usr/local/bin/
    sudo useradd --no-create-home --shell /usr/sbin/nologin node_exporter
  4. Créer le service

    /etc/systemd/system/node_exporter.service
    [Unit]
    Description=Node Exporter
    Wants=network-online.target
    After=network-online.target
    [Service]
    User=node_exporter
    Group=node_exporter
    Type=simple
    ExecStart=/usr/local/bin/node_exporter
    Restart=always
    # Hardening
    NoNewPrivileges=true
    ProtectSystem=strict
    ProtectHome=true
    [Install]
    WantedBy=multi-user.target
  5. Démarrer

    Fenêtre de terminal
    sudo systemctl daemon-reload
    sudo systemctl enable node_exporter
    sudo systemctl start node_exporter

Côté Prometheus, rien de particulier : chaque serveur est déclaré comme une cible ordinaire, avec son port d'exporter. Le nom du job devient un label attaché à toutes les métriques collectées, choisissez-le explicite.

prometheus.yml
scrape_configs:
- job_name: 'node'
static_configs:
- targets:
- 'server1:9100'
- 'server2:9100'

Node Exporter publie plusieurs centaines de séries ; celles-ci suffisent à couvrir la surveillance courante. Notez le suffixe _total, qui signale un compteur cumulatif : sa valeur brute n'a aucun intérêt, seule sa variation dans le temps en a, d'où l'usage de rate() dans les requêtes suivantes.

MétriqueDescription
node_cpu_seconds_totalTemps CPU par mode (idle, user, system)
node_memory_MemAvailable_bytesMémoire disponible
node_filesystem_avail_bytesEspace disque disponible
node_network_receive_bytes_totalBytes reçus par interface
node_load1, node_load5, node_load15Load average

Ces trois requêtes reposent sur le même principe : Node Exporter ne fournit pas de pourcentage d'utilisation, il faut le calculer. Pour le processeur, on part du temps passé en mode idle et on le soustrait à 100 ; pour la mémoire et le disque, on rapporte l'espace disponible à l'espace total.

# CPU utilisé (%)
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# Mémoire utilisée (%)
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
# Disque utilisé (%)
(1 - node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100

Surveille la disponibilité depuis l'extérieur : HTTP, DNS, TCP, ICMP. C'est du synthetic monitoring (probes), pas de la télémétrie interne.

Blackbox ne tourne pas sur les cibles qu'il surveille. Un seul Blackbox Exporter peut sonder des centaines d'URLs, parce que la cible ne fait pas partie de sa configuration : Prometheus la lui transmet à chaque scrape, dans le paramètre target de la requête HTTP.

Prometheus scrappe:
GET /probe?target=https://example.com&module=http_2xx
Blackbox répond:
probe_success 1
probe_duration_seconds 0.234

Un seul exemplaire suffit pour l'ensemble des cibles. Placez-le là d'où vous voulez mesurer la disponibilité : une sonde exécutée depuis le même datacenter que le service ne dira rien de ce que vivent vos utilisateurs.

Fenêtre de terminal
docker run -d \
--name blackbox_exporter \
-p 9115:9115 \
-v $(pwd)/blackbox.yml:/config/blackbox.yml:ro \
prom/blackbox-exporter:v0.28.0 \
--config.file=/config/blackbox.yml

Le fichier de configuration ne contient aucune cible : il déclare des modules, c'est-à-dire des manières de sonder. Chaque module porte un nom qui sera réclamé par Prometheus au moment du scrape. Le module http_2xx illustre le point important : ce sont les valid_status_codes qui décident si la sonde est un succès, un code 404 correctement renvoyé sera compté comme un échec.

blackbox.yml
modules:
http_2xx:
prober: http
timeout: 5s
http:
valid_http_versions: ["HTTP/1.1", "HTTP/2.0"]
valid_status_codes: [200, 201, 204]
follow_redirects: true
tcp_connect:
prober: tcp
timeout: 5s
icmp:
prober: icmp
timeout: 5s
dns_resolve:
prober: dns
dns:
query_name: "example.com"
query_type: "A"

Le relabeling transforme une liste d'URLs en paramètres pour Blackbox :

prometheus.yml
scrape_configs:
- job_name: 'blackbox-http'
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets:
- https://example.com
- https://api.example.com/health
- https://docs.example.com
relabel_configs:
# 1. L'URL devient le paramètre ?target=
- source_labels: [__address__]
target_label: __param_target
# 2. L'URL est aussi copiée dans le label "instance"
- source_labels: [__param_target]
target_label: instance
# 3. L'adresse réelle de scrape devient Blackbox Exporter
- target_label: __address__
replacement: blackbox-exporter:9115

Ce qui se passe :

  1. Prometheus voit https://example.com dans targets
  2. Relabeling transforme en GET blackbox-exporter:9115/probe?target=https://example.com
  3. Le label instance garde l'URL d'origine pour identifier les métriques

Toutes les sondes produisent le même petit ensemble de métriques, quel que soit le module utilisé, ce qui rend les alertes uniformes. La dernière ligne est celle qu'on oublie de surveiller : elle donne la date d'expiration du certificat et permet d'être prévenu avant la coupure plutôt qu'après.

MétriqueDescription
probe_success1 si probe réussie, 0 sinon
probe_duration_secondsDurée totale de la probe
probe_http_status_codeCode HTTP retourné
probe_ssl_earliest_cert_expiryDate d'expiration du certificat SSL

Ces deux règles couvrent l'essentiel de ce qu'apporte Blackbox. Le for: 2m de la première évite de réveiller quelqu'un pour un incident réseau passager : la condition doit rester vraie deux minutes d'affilée. La seconde compare la date d'expiration du certificat à l'heure courante et déclenche trente jours avant l'échéance, ce qui laisse le temps d'un renouvellement.

rules/blackbox.yml
groups:
- name: blackbox
rules:
- alert: EndpointDown
expr: probe_success == 0
for: 2m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} is down"
- alert: SSLCertExpiringSoon
expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 30
for: 1h
labels:
severity: warning
annotations:
summary: "SSL cert for {{ $labels.instance }} expires in < 30 days"

Ces exporters ont tous le même fonctionnement : ils ouvrent une connexion au moteur avec un compte dédié, interrogent ses vues statistiques internes et en publient le résultat. Deux points de vigilance en découlent. Le compte utilisé doit disposer du minimum de privilèges nécessaires à la lecture des statistiques, jamais des droits d'administration. Et la chaîne de connexion contient un mot de passe : elle n'a rien à faire dans un dépôt Git, passez-la par une variable d'environnement ou un fichier protégé.

Les droits PROCESS, REPLICATION CLIENT et SELECT suffisent à alimenter toutes les métriques exposées. Remplacez le mot de passe de l'exemple avant toute exécution.

  1. Créer l'utilisateur MySQL (droits minimum)

    CREATE USER 'exporter'@'localhost' IDENTIFIED BY 'password';
    GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'localhost';
    FLUSH PRIVILEGES;
  2. Lancer l'exporter

    Fenêtre de terminal
    export DATA_SOURCE_NAME='exporter:password@(localhost:3306)/'
    ./mysqld_exporter

    Ou via Docker :

    Fenêtre de terminal
    docker run -d \
    --name mysqld_exporter \
    -p 9104:9104 \
    -e DATA_SOURCE_NAME='exporter:password@(mysql:3306)/' \
    prom/mysqld-exporter
  3. Configuration Prometheus

    - job_name: 'mysql'
    static_configs:
    - targets: ['localhost:9104']

Métriques clés :

MétriqueDescription
mysql_upMySQL accessible (1/0)
mysql_global_status_threads_connectedConnexions actives
mysql_global_status_slow_queriesRequêtes lentes
mysql_global_status_questionsRequêtes exécutées

La configuration tient dans une seule variable d'environnement au format URI. Le sslmode=disable de l'exemple suppose que l'exporter tourne sur la même machine que la base ; dès que la connexion traverse le réseau, exigez require ou mieux.

Fenêtre de terminal
export DATA_SOURCE_NAME='postgresql://exporter:password@localhost:5432/postgres?sslmode=disable'
./postgres_exporter

Métriques clés :

MétriqueDescription
pg_upPostgreSQL accessible
pg_stat_activity_countConnexions par état
pg_stat_database_deadlocksDeadlocks
pg_stat_database_tup_fetchedLignes lues

L'adresse de l'instance se passe en option de ligne de commande. Si votre Redis demande un mot de passe, fournissez-le par la variable d'environnement prévue à cet effet plutôt que dans la commande, où il serait visible dans la liste des processus.

Fenêtre de terminal
docker run -d \
--name redis_exporter \
-p 9121:9121 \
oliver006/redis_exporter:v1.86.0 \
--redis.addr=redis://localhost:6379

Pour des métriques d'un système tiers non couvert, créez un exporter.

La bibliothèque cliente officielle fait tout le travail de format et de service HTTP : start_http_server ouvre l'endpoint /metrics, il ne reste qu'à mettre à jour les valeurs. Attention à la boucle finale, l'intervalle de rafraîchissement doit rester inférieur au scrape_interval de Prometheus, sinon la même valeur sera collectée deux fois.

my_exporter.py
from prometheus_client import start_http_server, Gauge
import requests
import time
# Définir les métriques
ORDERS_PENDING = Gauge('orders_pending_total', 'Pending orders count')
ORDERS_VALUE = Gauge('orders_pending_value_euros', 'Value of pending orders')
def collect_metrics():
"""Collecte depuis une API externe."""
response = requests.get('https://api.internal/orders/stats')
data = response.json()
ORDERS_PENDING.set(data['pending_count'])
ORDERS_VALUE.set(data['pending_value'])
if __name__ == '__main__':
start_http_server(8000)
print("Exporter running on :8000/metrics")
while True:
collect_metrics()
time.sleep(15)

Le type se choisit à la déclaration et ne se change pas ensuite sans casser les requêtes existantes. La distinction fondamentale oppose le Counter, qui ne fait que croître et se remet à zéro au redémarrage du processus, et la Gauge, qui représente une valeur instantanée pouvant monter comme descendre.

TypeUsageExemple
CounterValeur croissante uniquementRequêtes, erreurs
GaugeMonte et descendMémoire, connexions
HistogramDistribution avec bucketsLatence
SummaryQuantiles côté clientLatence (moins recommandé)

Le nom d'une métrique est public et durable : le renommer casse tous les tableaux de bord et toutes les alertes qui l'utilisent. Deux règles suffisent, préfixer par le nom du composant et terminer par l'unité de mesure, en unités de base (secondes et octets, jamais millisecondes ni mégaoctets).

namespace_name_unit_suffix
  • myapp_http_requests_total
  • myapp_request_duration_seconds
  • requestCount ❌ (pas de namespace, pas d'unité)

Deux de ces pièges méritent une attention particulière. Un endpoint /metrics laissé ouvert renseigne un attaquant sur votre parc, versions et volumétrie comprises, sans qu'aucune authentification ne soit requise. Et la cardinalité, c'est-à-dire le nombre de combinaisons de labels distinctes, est la première cause de saturation d'un Prometheus : mettre un identifiant d'utilisateur ou une URL complète en label crée une série temporelle par valeur rencontrée.

PiègeImpactSolution
/metrics exposé sans authFuite d'infosFirewall, TLS, basic auth
Trop de labelsExplosion cardinalitéLabels faible cardinalité uniquement
Scrape interval trop courtSurcharge exporter15s-60s selon criticité
Scrape timeout trop courtTargets "DOWN"Ajuster scrape_timeout

Le premier réflexe consiste à interroger l'endpoint /metrics à la main, depuis la machine qui héberge Prometheus et non depuis votre poste : la plupart des cibles marquées DOWN le sont pour une raison de filtrage réseau. Si la réponse arrive mais que les métriques attendues manquent, le problème s'est déplacé vers les droits du compte utilisé par l'exporter.

SymptômeCause probableSolution
Exporter non accessibleFirewall/réseaucurl http://exporter:port/metrics
Métriques videsPas de permissionsVérifier droits DB/système
Scrape timeoutExporter lentAugmenter scrape_timeout
Target "DOWN"DNS/réseauVérifier résolution + ping

Commandes de debug :

Fenêtre de terminal
# Vérifier l'endpoint
curl -s http://localhost:9100/metrics | head -20
# Vérifier dans Prometheus
# Status → Targets
# Pour Blackbox, tester la probe manuellement
curl "http://localhost:9115/probe?target=https://example.com&module=http_2xx"
  • 3 familles : single-target (Node), service (MySQL), multi-target (Blackbox)
  • Instrumentation > Exporter si vous avez le code
  • Blackbox = synthetic monitoring (disponibilité externe)
  • Relabeling : essentiel pour le pattern multi-target
  • Sécurité : ne jamais exposer /metrics sans protection réseau

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn