Infrastructure

ELK Stack — Récupération après corruption de translog et pannes en cascade

Retour d'expérience sur la récupération d'un cluster Elasticsearch après corruption de translog suite à un reboot brutal, avec résolution des pannes en cascade sur Kibana et les dashboards Cisco.

Table des matières

Après un reboot non planifié d’un serveur AlmaLinux hébergeant une stack ELK (Elasticsearch + Kibana + Filebeat + Winlogbeat), plusieurs shards se sont retrouvés en état ALLOCATION_FAILED avec des translogs corrompus. Voici le diagnostic complet et la résolution.

Contexte

La stack surveille des logs Windows (Winlogbeat) et des équipements réseau Cisco (Filebeat/rsyslog) sur un serveur AlmaLinux 9.7 en nœud unique.

Symptômes

# Cluster en état RED
curl -sk "https://elastic:PASS@localhost:9200/_cluster/health?pretty"
{
  "status": "red",
  "unassigned_shards": 2,
  "unassigned_primary_shards": 2
}

Deux shards non alloués :

  • .kibana_task_manager_8.x_001ALLOCATION_FAILED
  • .ds-winlogbeat-9.x-2026.xx-000016ALLOCATION_FAILED

Diagnostic

# Identifier la cause exacte de l'échec d'allocation
curl -sk -X POST "https://elastic:PASS@localhost:9200/_cluster/allocation/explain?pretty" \
  -H 'Content-Type: application/json' \
  -d '{"index": ".kibana_task_manager_8.x_001", "shard": 0, "primary": true}'

Réponse révélant la corruption :

{
  "explanation": "failed shard on node",
  "details": "translog truncated - translog-327116.tlog"
}

Le translog a été tronqué lors du reboot brutal (SIGKILL au lieu d’un arrêt propre). Elasticsearch a atteint ses 5 tentatives max et abandonne l’allocation automatique.

Résolution — Forçage de l’allocation

Perte de données

L’allocate_empty_primary réinitialise le shard — toutes ses données sont perdues. Pour le task manager Kibana c’est acceptable (tâches planifiées uniquement). Pour des données de logs, évaluez si un backup est disponible.

ES="https://elastic:PASS@localhost:9200"

# 1. Forcer l'allocation vide sur le task manager (sans données critiques)
curl -sk -X POST "$ES/_cluster/reroute?pretty" \
  -H 'Content-Type: application/json' \
  -d '{
    "commands": [{
      "allocate_empty_primary": {
        "index": ".kibana_task_manager_8.x_001",
        "shard": 0,
        "node": "votre-node",
        "accept_data_loss": true
      }
    }]
  }'

# 2. Vérifier que le shard passe en STARTED
curl -sk "$ES/_cat/shards/.kibana_task_manager*?v&h=index,shard,prirep,state"

Résolution — Conflit de mapping Winlogbeat

Après récupération du cluster, un second problème : les dashboards Winlogbeat affichaient des erreurs de mapping sur le champ host.ip.

Cause : deux templates d’index en conflit de priorité. Le template winlogbeat-ilm (priorité 200) écrasait winlogbeat-9.x (priorité 150), appliquant un type text au champ host.ip au lieu de ip.

# Correction : monter la priorité du bon template
curl -sk -X PUT "$ES/_index_template/winlogbeat-9.x" \
  -H 'Content-Type: application/json' \
  -d '{"priority": 201}'

# Réindexer les indices affectés
curl -sk -X POST "$ES/_reindex" \
  -H 'Content-Type: application/json' \
  -d '{
    "source": {"index": ".ds-winlogbeat-9.x-2026.xx-000007"},
    "dest": {"index": ".ds-winlogbeat-9.x-2026.xx-000007-fixed"}
  }'

Résolution — Dashboards Cisco et basemap OSM

Les dashboards Cisco présentaient deux problèmes :

1. Champs manquants (log.source.address, name, geo.location) — le pipeline Filebeat ne les peuplait pas correctement.

// Ajout dans le pipeline ingest Filebeat Cisco
{
  "set": {
    "field": "source.ip",
    "copy_from": "log.source.address",
    "ignore_empty_value": true
  }
}

2. Basemap OpenStreetMap invisible — la carte Kibana restait vide. Cause : règle pare-feu bloquant l’accès aux tuiles OSM.

# Domaines à autoriser en sortie
a.tile.openstreetmap.org
b.tile.openstreetmap.org
c.tile.openstreetmap.org
Wildcard non supporté

*.openstreetmap.org en wildcard n’était pas supporté sur le pare-feu testé — il a fallu ajouter les trois sous-domaines explicitement.

Mesures préventives

Arrêt propre avant reboot

# Créer un service systemd pour arrêter ES proprement avant le reboot
# /etc/systemd/system/elasticsearch-pre-shutdown.service
[Unit]
Description=Stop Elasticsearch before shutdown
DefaultDependencies=no
Before=shutdown.target reboot.target halt.target

[Service]
Type=oneshot
ExecStart=/bin/systemctl stop elasticsearch
TimeoutStartSec=120

[Install]
WantedBy=shutdown.target reboot.target halt.target

Timeout systemd étendu

mkdir -p /etc/systemd/system/elasticsearch.service.d/
cat > /etc/systemd/system/elasticsearch.service.d/timeout.conf << EOF
[Service]
TimeoutStopSec=120
EOF
systemctl daemon-reload

ILM étendu pour éviter la perte de logs

# Étendre la rétention de 365 à 1095 jours (3 ans)
curl -sk -X PUT "$ES/_ilm/policy/logs-retention" \
  -H 'Content-Type: application/json' \
  -d '{"policy": {"phases": {"delete": {"min_age": "1095d"}}}}'

Clé de chiffrement Kibana persistante

# /etc/kibana/kibana.yml
# Sans cette clé, Kibana en génère une aléatoire à chaque restart
# → sessions invalides après chaque redémarrage
xpack.reporting.encryptionKey: "votre-clé-32-chars-minimum"
xpack.security.encryptionKey: "votre-clé-32-chars-minimum"
xpack.encryptedSavedObjects.encryptionKey: "votre-clé-32-chars-minimum"

Bilan

Problème Cause Fix
Shards ALLOCATION_FAILED Translog corrompu (reboot brutal) allocate_empty_primary
Mapping host.ip en text Conflit priorité templates Priorité template élevée à 201
Dashboards Cisco vides Pipeline ingest incomplet Ajout processors set/copy
Basemap OSM invisible Règle FW bloquante Autorisation 3 sous-domaines OSM
Sessions Kibana invalides Clé chiffrement aléatoire Clé fixe dans kibana.yml

Comments