ELK Architecture : Shards, ILM et Query DSL expliqués simplement

Image

ELK Architecture : Shards, ILM et Query DSL expliqués simplement

Temps de lecture : 14 min | Niveau : Intermédiaire | Mis à jour : Février 2026

Vous avez installé la stack ELK, vos logs arrivent dans Elasticsearch et Kibana affiche des dashboards. Mais dès que le volume de données augmente, des questions se posent : pourquoi mon cluster ralentit ? Comment gérer la rétention des anciens index ? Comment écrire des requêtes efficaces ?

La réponse se trouve dans l'architecture interne d'Elasticsearch. Ce guide vous explique les trois mécanismes essentiels que tout ingénieur DevOps, administrateur système ou développeur doit maîtriser pour exploiter ELK en production.

Besoin d'un rappel sur les fondamentaux ? Consultez d'abord notre guide complet ELK : Elasticsearch, Logstash & Kibana

Shards et Replicas : comprendre le système de distribution

Quand vous indexez un document dans Elasticsearch, il n'est pas stocké "en vrac" dans un seul fichier. Elasticsearch découpe chaque index en morceaux appelés shards (partitions). Chaque shard est en réalité une instance complète du moteur Apache Lucene, capable d'indexer et de rechercher des données de manière autonome.

Primary shards vs Replica shards

Elasticsearch distingue deux types de shards :

Type Rôle Modifiable après création ?
Primary shard Contient une portion des données de l'index. Gère l'indexation (écriture) des documents. Non (fixé à la création de l'index)
Replica shard Copie exacte d'un primary shard. Sert à la haute disponibilité et à répartir la charge de lecture. Oui (ajustable à tout moment)

Comment les shards sont distribués

Elasticsearch répartit automatiquement les shards sur les nœuds disponibles du cluster. Une règle fondamentale : un replica ne réside jamais sur le même nœud que son primary shard. Si un nœud tombe, le replica sur un autre nœud prend le relais sans perte de données.

Exemple concret : un index avec 3 primary shards et 1 replica, sur un cluster de 3 nœuds

Nœud 1 : P0 R1

Nœud 2 : P1 R2

Nœud 3 : P2 R0

P = primary, R = replica. Si le Nœud 1 tombe, R0 sur le Nœud 3 devient le nouveau primary.

Ce qui se passe lors d'une recherche

Quand vous lancez une recherche, Elasticsearch envoie la requête à tous les shards de l'index (primaries et replicas). Chaque shard exécute la recherche localement, puis les résultats sont fusionnés et triés par le nœud coordinateur. C'est ce mécanisme de scatter-gather qui rend Elasticsearch si rapide : la recherche est parallélisée sur toutes les partitions.

Dimensionner ses shards : les règles pratiques

Un mauvais dimensionnement des shards est la cause numéro 1 de problèmes de performance en production. Trop de shards surchargent le cluster (overhead mémoire, ralentissement). Trop peu de shards empêchent la parallélisation.

Règle Recommandation Pourquoi
Taille cible par shard Entre 10 Go et 50 Go En dessous de 10 Go, l'overhead domine. Au-dessus de 50 Go, la récupération après panne est trop lente.
Nombre de shards par nœud Max ~20 shards par Go de heap Chaque shard consomme de la mémoire. Un nœud avec 16 Go de heap ne devrait pas dépasser 300-400 shards.
Nombre de primary shards 1 shard pour les petits index, adapter au volume pour les gros Depuis Elasticsearch 7, le défaut est 1 primary shard (contre 5 avant). Ne surdimensionnez pas.
Replicas 1 replica minimum en production Garantit la haute disponibilité. 0 replica = perte de données si un nœud tombe.

Pour vérifier le nombre et l'état de vos shards, utilisez l'API _cat/shards :

GET _cat/shards?v

# Résultat :
# index             shard  prirep  state    docs   store  node
# logs-2026.02.22   0      p       STARTED  50000  45mb   node-1
# logs-2026.02.22   0      r       STARTED  50000  45mb   node-2

ILM : automatiser le cycle de vie des index

En production, les index de logs grossissent continuellement. Sans gestion automatisée, le cluster finit par manquer d'espace disque et les performances se dégradent. L'Index Lifecycle Management (ILM) résout ce problème en automatisant la gestion de vos index à travers 5 phases.

Les 5 phases du cycle de vie

Phase Description Actions typiques Type de disque
Hot L'index est en cours d'écriture et fréquemment interrogé Rollover (créer un nouvel index quand le seuil est atteint) SSD rapide
Warm L'index n'est plus écrit mais encore consulté régulièrement Shrink (réduire les shards), Force merge (optimiser les segments) SSD standard
Cold L'index est rarement consulté, mais doit rester accessible Réduction des replicas, searchable snapshots HDD / stockage économique
Frozen L'index est quasi jamais consulté, tolérance aux requêtes lentes Searchable snapshots depuis stockage froid Stockage objet (S3, etc.)
Delete L'index est supprimé définitivement Suppression de l'index et de ses données

Pourquoi ILM est indispensable en production

Sans ILM, vous devez gérer manuellement la rotation et la suppression de vos index. Avec un flux de logs continu, cela devient vite ingérable. ILM vérifie automatiquement (toutes les 10 minutes par défaut) si un index doit passer à la phase suivante, en fonction de critères que vous définissez : âge de l'index, taille des shards ou nombre de documents.

Configurer une politique ILM : exemple complet

Voici un exemple réaliste de politique ILM pour des logs applicatifs. L'objectif : conserver les logs récents sur du stockage rapide, les archiver après 7 jours, et les supprimer après 90 jours.

PUT _ilm/policy/logs-policy
{
  "policy": {
    "phases": {
      "hot": {
        "actions": {
          "rollover": {
            "max_primary_shard_size": "50gb",
            "max_age": "1d"
          }
        }
      },
      "warm": {
        "min_age": "7d",
        "actions": {
          "shrink": {
            "number_of_shards": 1
          },
          "forcemerge": {
            "max_num_segments": 1
          }
        }
      },
      "cold": {
        "min_age": "30d",
        "actions": {
          "allocate": {
            "number_of_replicas": 0
          }
        }
      },
      "delete": {
        "min_age": "90d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

Ce que fait cette politique :

  • Hot : un nouvel index est créé (rollover) quand le shard dépasse 50 Go ou quand l'index a 1 jour
  • Warm (après 7 jours) : l'index est compacté en 1 seul shard et les segments Lucene sont fusionnés pour optimiser l'espace
  • Cold (après 30 jours) : les replicas sont supprimés pour économiser de l'espace disque
  • Delete (après 90 jours) : l'index est définitivement supprimé

Pour appliquer cette politique à un index template :

PUT _index_template/logs-template
{
  "index_patterns": ["logs-*"],
  "template": {
    "settings": {
      "number_of_shards": 1,
      "number_of_replicas": 1,
      "index.lifecycle.name": "logs-policy"
    }
  }
}

Tous les index dont le nom commence par "logs-" seront automatiquement gérés par cette politique ILM.

Query DSL : le langage de requêtes d'Elasticsearch

Le Query DSL (Domain Specific Language) est le langage JSON utilisé pour interroger Elasticsearch. C'est l'équivalent du SQL pour les bases de données relationnelles, mais adapté à la recherche full-text et aux agrégations sur des données distribuées.

Query context vs Filter context

Elasticsearch distingue deux contextes d'exécution pour les requêtes. Comprendre cette distinction est essentiel pour écrire des requêtes performantes :

Contexte Question posée Score de pertinence ? Mise en cache ? Performance
Query « À quel point ce document correspond-il à la requête ? » Oui (calcul du _score) Non Plus lent
Filter « Ce document correspond-il, oui ou non ? » Non (binaire) Oui (automatique) Plus rapide

Les types de requêtes essentiels

Requête Usage Exemple
match Recherche full-text (avec analyse du texte) Trouver les logs contenant "connection timeout"
term Correspondance exacte (sans analyse) Filtrer par status code "500"
range Plage de valeurs (dates, nombres) Logs des 24 dernières heures
bool Combiner plusieurs critères (must, should, must_not, filter) Erreurs 500 sur le service "api" cette semaine
match_phrase Recherche d'une expression exacte dans l'ordre Trouver "out of memory"
wildcard Recherche avec jokers (* et ?) Trouver tous les champs commençant par "err*"
exists Vérifier qu'un champ existe Documents qui ont un champ "error_message"

Exemples de requêtes courantes

1. Recherche full-text simple

Trouver tous les documents contenant "connection refused" dans le champ message :

GET logs-*/_search
{
  "query": {
    "match": {
      "message": "connection refused"
    }
  }
}

La requête match analyse le texte : elle cherche "connection" OU "refused". Pour une expression exacte, utilisez match_phrase.

2. Requête combinée avec bool

Trouver les erreurs 500 du service "api-gateway" survenues dans les dernières 24 heures :

GET logs-*/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "service": "api-gateway" } }
      ],
      "filter": [
        { "term": { "status_code": 500 } },
        { "range": {
            "@timestamp": {
              "gte": "now-24h",
              "lte": "now"
            }
          }
        }
      ]
    }
  }
}

Le must influence le score de pertinence. Le filter filtre sans calculer de score (plus performant). C'est la structure la plus utilisée en production.

3. Agrégation : top 5 des erreurs par service

Compter le nombre d'erreurs par service et afficher les 5 services avec le plus d'erreurs :

GET logs-*/_search
{
  "size": 0,
  "query": {
    "term": { "level": "error" }
  },
  "aggs": {
    "errors_par_service": {
      "terms": {
        "field": "service.keyword",
        "size": 5
      }
    }
  }
}

"size": 0 signifie qu'on ne veut pas les documents eux-mêmes, uniquement le résultat de l'agrégation. Le champ .keyword est utilisé pour les termes exacts (non analysés).

4. Recherche avec date range et tri

Dernières 100 entrées de logs, triées par date décroissante :

GET logs-*/_search
{
  "size": 100,
  "sort": [
    { "@timestamp": { "order": "desc" } }
  ],
  "query": {
    "range": {
      "@timestamp": {
        "gte": "now-7d"
      }
    }
  }
}

Bonnes pratiques architecture ELK

Domaine Bonne pratique Erreur fréquente
Shards Viser 10-50 Go par shard, 1 primary shard par défaut Mettre 5 shards sur un index de 1 Go (overhead inutile)
Replicas Toujours au moins 1 replica en production 0 replica = perte de données si un nœud tombe
ILM Activer ILM dès le premier index. Définir une politique de rétention claire. Laisser les index grandir sans limite et supprimer manuellement
Rollover Utiliser le rollover automatique (ILM + data streams) Créer un index par jour manuellement avec un cron
Requêtes Utiliser filter pour les critères exacts, query pour le full-text Tout mettre dans must (calcul de score inutile)
Mapping Définir un mapping explicite pour les champs importants Se fier uniquement au mapping dynamique (types incorrects)
Cluster Minimum 3 nœuds pour la haute disponibilité Un seul nœud en production (single point of failure)

Envie de maîtriser l'architecture ELK en profondeur ?

La formation ELK de Lenidit couvre les shards, ILM, Query DSL, Logstash, Kibana et le déploiement en production. Exercices pratiques inclus.

19€/mois pour cette formation et tout le catalogue (Docker, Kubernetes, CI/CD, cybersécurité). Attestation incluse.

Accéder à la formation ELK

FAQ

Qu'est-ce qu'un shard dans Elasticsearch ?
Un shard est une partition d'un index Elasticsearch. Chaque shard est une instance autonome du moteur Lucene, capable d'indexer et de rechercher des données. Les index sont découpés en shards pour distribuer les données sur plusieurs nœuds et paralléliser les opérations de recherche.
Peut-on modifier le nombre de shards d'un index existant ?
Non, le nombre de primary shards est fixé à la création de l'index et ne peut pas être modifié ensuite. Pour changer le nombre de shards, vous devez réindexer vos données dans un nouvel index ou utiliser l'action Shrink d'ILM pour réduire le nombre de shards. Le nombre de replicas, en revanche, est modifiable à tout moment.
Qu'est-ce que l'ILM (Index Lifecycle Management) ?
L'ILM est une fonctionnalité d'Elasticsearch qui automatise la gestion du cycle de vie des index. Elle permet de définir des règles pour déplacer automatiquement les index à travers 5 phases (hot, warm, cold, frozen, delete) en fonction de critères comme l'âge ou la taille. Cela optimise les coûts de stockage et les performances sans intervention manuelle.
Quelle est la différence entre query et filter dans Elasticsearch ?
Une query calcule un score de pertinence pour chaque document (utile pour la recherche full-text). Un filter répond par oui ou non sans calcul de score, ce qui le rend plus rapide et automatiquement mis en cache. En pratique, utilisez filter pour les critères exacts (dates, statuts, ID) et query pour la recherche textuelle.
Quelle taille recommandée pour un shard Elasticsearch ?
Elastic recommande de viser entre 10 Go et 50 Go par shard. Des shards trop petits créent un overhead de gestion inutile. Des shards trop gros ralentissent la récupération après une panne et les opérations de merge. Le dimensionnement optimal dépend de votre cas d'usage et du volume de données.
Comment débuter avec le Query DSL d'Elasticsearch ?
Commencez par les requêtes match (recherche textuelle) et term (correspondance exacte), puis apprenez la requête bool qui permet de combiner des critères avec must, should, must_not et filter. La console Dev Tools de Kibana est l'endroit idéal pour tester vos requêtes. La documentation officielle Elastic fournit des exemples complets pour chaque type de requête.
Qu'est-ce que le rollover dans ILM ?
Le rollover est une action ILM qui crée automatiquement un nouvel index quand l'index actif atteint un seuil défini (taille maximale des shards, âge de l'index ou nombre de documents). Les écritures sont alors redirigées vers le nouvel index. Cela évite que les index deviennent trop volumineux et maintient des performances optimales.

Quiz Architecture Elasticsearch (2 minutes)

Testez vos connaissances sur les shards, ILM et Query DSL. 8 questions. Résultat + recommandation à la fin.