📝 Logs Centralisés avec Promtail + Loki : Adieu les SSH sur 50 Serveurs !

🟢 Niveau : Débutant à Intermédiaire | ⏱️ Lecture : 14 min | 🛠️ Mise en œuvre : 2-3 heures

📚 Prérequis

  • Stack Prometheus + Grafana + Loki installée (voir article 02)
  • Docker installé sur les serveurs à monitorer
  • Compréhension basique des fichiers de logs Linux

Vous connaissez ce scénario : un bug en production, et vous voilà à vous connecter en SSH à 10 serveurs différents, à lancer des grep et tail -f en cascade pour trouver l’erreur. C’est inefficace, stressant et source d’erreurs. La solution ? Centraliser tous vos logs avec Promtail et Loki.


😫 Le Problème des Logs Distribués

Dans une architecture moderne, les logs sont éparpillés :

  • Logs applicatifs sur chaque serveur
  • Logs Docker de chaque conteneur
  • Logs système (syslog, auth.log)
  • Logs de reverse proxy (Nginx, HAProxy)
  • Logs de bases de données

Résultat :

  • ❌ Impossible de corréler les événements entre services
  • ❌ Les logs disparaissent quand un conteneur redémarre
  • ❌ Pas de recherche efficace
  • ❌ Pas de rétention contrôlée

🌟 Loki : Le Prometheus des Logs

Loki, développé par Grafana Labs, est conçu pour être le pendant « logs » de Prometheus. Sa philosophie est radicalement différente d’Elasticsearch :

Loki vs Elasticsearch

AspectLokiElasticsearch
IndexationLabels uniquementFull-text de tout le contenu
RessourcesLéger (~10x moins de RAM)Gourmand
Coût de stockageFaibleÉlevé
ComplexitéSimpleNécessite expertise
RecherchePar labels puis grepFull-text instantané

Philosophie Loki : « Like grep on steroids » – On filtre d’abord par labels (service, environnement, host), puis on fait un grep sur les lignes filtrées.

📤 Promtail : L’Agent de Collecte

Architecture de collecte de logs avec Promtail et Loki
Architecture de centralisation des logs avec Promtail et Loki

Promtail est l’agent qui tourne sur chaque serveur et envoie les logs à Loki. Il peut lire :

  • Des fichiers de logs (/var/log/*.log)
  • Les logs Docker via l’API
  • Le journal systemd

Configuration Type

server:
  http_listen_port: 9080

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  # Logs système
  - job_name: system
    static_configs:
      - targets:
          - localhost
        labels:
          job: varlogs
          host: ${HOSTNAME}
          __path__: /var/log/*.log

  # Logs applicatifs
  - job_name: app
    static_configs:
      - targets:
          - localhost
        labels:
          job: myapp
          host: ${HOSTNAME}
          __path__: /var/log/myapp/*.log

🏷️ L’Importance des Labels

Les labels sont la clé de Loki. Ils permettent de filtrer rapidement les logs pertinents.

Bons Labels
  • job : Type de service (nginx, api, worker)
  • host : Nom du serveur
  • env : Environnement (prod, staging, dev)
  • namespace : En Kubernetes
Mauvais Labels (à éviter)
  • user_id : Cardinalité trop élevée
  • request_id : Unique par requête
  • timestamp : Déjà géré par Loki

Règle d’or : Si un label a potentiellement des milliers de valeurs différentes, ne l’utilisez pas comme label. Mettez-le dans le contenu du log.


🔍 LogQL : Le Langage de Requête

LogQL est le langage de requête de Loki, inspiré de PromQL. Voici les bases :

Sélection par Labels
# Tous les logs du job "nginx"
{job="nginx"}

# Logs nginx en production
{job="nginx", env="prod"}

# Logs de tous les jobs sauf "debug"
{job!="debug"}

# Logs d'un host spécifique avec regex
{host=~"web-.*"}
Filtrage du Contenu
# Logs nginx contenant "error"
{job="nginx"} |= "error"

# Logs ne contenant PAS "healthcheck"
{job="nginx"} != "healthcheck"

# Regex : erreurs 5xx
{job="nginx"} |~ "HTTP/1.1\" 5[0-9]{2}"

# Plusieurs filtres
{job="nginx"} |= "error" != "timeout"
Parsing et Agrégations
# Parser un format JSON et filtrer
{job="api"} | json | level="error"

# Parser les logs Nginx en format combined
{job="nginx"} | pattern `<ip> - - [<_>] "<method> <uri> <_>" <status> <_>`

# Compter les erreurs par host
count_over_time({job="nginx"} |= "error" [5m]) by (host)

# Taux d'erreurs par minute
rate({job="nginx"} |= "error" [1m])

📊 Corrélation Métriques + Logs dans Grafana

La vraie puissance de la stack Prometheus + Loki apparaît dans Grafana :

  1. Un dashboard montre un pic de latence sur votre API
  2. Vous sélectionnez la période suspecte
  3. Vous cliquez sur « Explore » → Loki
  4. Grafana pré-filtre les logs sur la même période et le même service
  5. Vous voyez immédiatement les erreurs correspondantes

Cette corrélation est possible grâce aux labels partagés entre Prometheus (métriques) et Loki (logs).

🔔 Alerting sur les Logs

Grafana permet de créer des alertes basées sur les logs :

# Alerte si plus de 10 erreurs en 5 minutes
count_over_time({job="api"} |= "error" [5m]) > 10

# Alerte sur des patterns critiques
{job="app"} |= "FATAL" or {job="app"} |= "OutOfMemoryError"

Configurez des notifications vers Slack, email, PagerDuty, etc.


🐳 Cas Spécial : Logs Docker

Promtail peut collecter les logs Docker de deux façons :

1. Via les Labels Docker

Ajoutez des labels à vos conteneurs :

services:
  api:
    image: myapi:latest
    labels:
      logging: "promtail"
      job: "api"

Promtail peut utiliser Docker service discovery pour détecter automatiquement ces conteneurs.

2. Via les Fichiers de Logs

Si vous utilisez le driver json-file de Docker :

scrape_configs:
  - job_name: docker
    static_configs:
      - targets:
          - localhost
        labels:
          job: docker
          __path__: /var/lib/docker/containers/*/*.log

🚀 Déployer la Stack en Production

Notre rôle Ansible grafana_prometheus_loki simplifie le déploiement :

Mode Server

Déploie Grafana + Prometheus + Loki sur un serveur dédié :

  • ✅ Loki configuré avec rétention
  • ✅ Datasources Grafana préconfigurées
  • ✅ AlertManager optionnel

Mode Client

Déploie les agents de collecte sur chaque serveur :

  • ✅ Promtail pour les logs
  • ✅ Node Exporter pour les métriques système
  • ✅ cAdvisor pour les métriques Docker

La configuration de prometheus.yml est mise à jour automatiquement avec les nouveaux targets.

Prêt à centraliser vos logs ? Découvrez notre rôle Ansible grafana_prometheus_loki.


📖 Glossaire

  • LogQL : Langage de requête de Loki, inspiré de PromQL, pour filtrer et analyser les logs
  • Labels : Métadonnées attachées aux logs (job, host, env) permettant le filtrage rapide
  • Cardinalité : Nombre de valeurs uniques d’un label. Une cardinalité trop élevée dégrade les performances
  • Positions File : Fichier où Promtail enregistre sa progression de lecture pour ne pas relire les mêmes logs
  • Scrape Config : Configuration définissant quels logs collecter et quels labels leur attribuer
  • Docker Service Discovery : Mécanisme permettant à Promtail de détecter automatiquement les conteneurs Docker

Le prochain article partagera nos 10 meilleures pratiques pour écrire des rôles Ansible maintenables et réutilisables. Restez connectés !