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_001—ALLOCATION_FAILED.ds-winlogbeat-9.x-2026.xx-000016—ALLOCATION_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
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
*.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