Configuration d'Elasticsearch

Zabbix peut stocker les données d'historique dans Elasticsearch comme alternative à une base de données relationnelle.

La prise en charge d'Elasticsearch est actuellement expérimentale.

Ce guide couvre la configuration des versions prises en charge d'Elasticsearch. Si vous utilisez une version différente, certaines fonctionnalités peuvent ne pas fonctionner comme prévu.

Elasticsearch peut stocker les types de valeurs suivants :

Item value type Database table Elasticsearch type
Numeric (unsigned) history_uint uint
Numeric (float) history dbl
Character history_str str
Log history_log log
Text history_text text
Binary history_bin not supported by Zabbix
JSON history_json json

Elasticsearch n'accepte pas les tableaux JSON. Une valeur JSON doit être soit un objet unique, soit un ensemble d'objets.

Notes importantes

  • Elasticsearch nécessite libcurl. Voir requirements pour plus de détails.
  • Le housekeeper ne supprime pas les données d'Elasticsearch. Pour contrôler la durée de conservation des données, voir Index Lifecycle Management.
  • Zabbix ne calcule ni ne stocke les tendances dans Elasticsearch. Envisagez d'étendre la période de stockage de l'historique afin de conserver les données plus anciennes.
  • Lorsque Elasticsearch est utilisé, les requêtes de plage récupérant des valeurs depuis la base de données sont limitées par l'horodatage de la période de stockage des données.
  • Elasticsearch n'est pas pris en charge pour les proxies Zabbix.

Si Elasticsearch n'est pas encore installé, consultez le guide d'installation officiel avant de continuer.

Configuration d'Elasticsearch

Pour stocker les données d'historique dans Elasticsearch, vous devez :

  • Créer un index pour chaque type de valeur que vous souhaitez stocker — c'est là qu'Elasticsearch stocke les données, de manière similaire à une table dans une base de données relationnelle.
  • Définir un mapping pour chaque index — cela définit la structure des données, de manière similaire au schéma d'une table.
  • Configurer un pipeline d'ingestion pour traiter les valeurs avant leur stockage (requis pour les valeurs JSON et les index basés sur des dates).

Elasticsearch peut stocker les données dans un seul index par type de valeur, ou dans plusieurs index basés sur des dates. Les deux approches sont décrites ci-dessous.

Stockage de l'historique dans un seul index

Dans cette approche, toutes les données d'historique pour un type de valeur donné sont écrites dans un seul index (par exemple, uint ou text).

Pour créer un index pour le type de valeur Numérique (non signé), envoyez la requête suivante (avec /uint dans l'URL) à votre instance Elasticsearch :

curl -X PUT \
 http://localhost:9200/uint \
 -H 'content-type:application/json' \
 -d '{
     "settings": {
      "index": {
         "number_of_replicas": 1,
         "number_of_shards": 5
      }
   },
   "mappings": {
      "properties": {
         "itemid": { "type": "long" },
         "clock": { "format": "epoch_second", "type": "date" },
         "value": { "type": "long" }
      }
   }
}'

Elasticsearch répondra avec une confirmation indiquant que l'index a été créé :

{"acknowledged": true, "shards_acknowledged": true, "index": "uint"}

Des requêtes similaires doivent être envoyées pour chaque type de valeur supplémentaire que vous souhaitez stocker dans Elasticsearch.

Les mappings pour tous les types de valeur sont disponibles dans le dépôt source de Zabbix.

Par exemple, pour créer un index pour le type de valeur Texte :

curl -X PUT \
 http://localhost:9200/text \
 -H 'content-type:application/json' \
 -d '{
   "settings": {
      "index": {
         "number_of_replicas": 1,
         "number_of_shards": 5
      }
   },
   "mappings": {
      "properties": {
         "itemid": { "type": "long" },
         "clock": { "format": "epoch_second", "type": "date" },
         "value": {
            "fields": {
               "analyzed": { "index": true, "type": "text", "analyzer": "standard" }
            },
            "index": false,
            "type": "text"
         }
      }
   }
}'
Type de valeur JSON

Contrairement aux autres types de valeur, les valeurs JSON nécessitent un traitement supplémentaire avant le stockage.

L’index ci-dessous utilise des champs distincts pour les valeurs analysées et brutes ; un pipeline d’ingestion est donc nécessaire pour analyser chaque valeur en tant que JSON et la stocker dans le champ approprié.

Pour créer un index pour le type de valeur JSON, envoyez la requête suivante (avec /json dans l’URL) à votre instance Elasticsearch.

curl -X PUT \
 http://localhost:9200/json \
 -H 'content-type:application/json' \
 -d '{
   "settings": {
      "number_of_shards": 5,
      "number_of_replicas": 1
   },
   "mappings": {
      "dynamic": false,
      "properties": {
         "itemid": { "type": "long" },
         "clock": { "type": "date", "format": "epoch_second" },
         "ns": { "type": "long" },
         "value_parsed": { "type": "flattened" },
         "value_raw": { "type": "keyword", "ignore_above": 1000000 }
    }
  }
}'

Créez ensuite le pipeline d’ingestion :

curl -X PUT \
 http://localhost:9200/_ingest/pipeline/json \
 -H 'content-type:application/json' \
 -d '{
   "processors": [
      {
         "json": {
            "field": "value",
            "target_field": "value_parsed",
            "ignore_failure": true
         }
      },
      {
         "set": {
            "if": "ctx.value_parsed == null",
            "field": "value_raw",
            "value": "{{{ value }}}"
         }
      }
   ],
   "on_failure": [
      {
         "set": {
            "field": "value_raw",
            "value": "{{{ value }}}"
         }
      }
   ]
}'

Elasticsearch répondra par une confirmation indiquant que le pipeline d’ingestion a été créé :

{"acknowledged": true}

Stockage de l'historique dans des index basés sur la date

Au lieu d'écrire toutes les données d'historique dans un seul index (par exemple, uint), Elasticsearch peut répartir ces données sur plusieurs index basés sur la date (par exemple, uint-2026-01-01, uint-2026-01-02). Cela facilite la gestion du volume de données et de la rétention au fil du temps.

Pour activer cette fonctionnalité, vous devez :

  • Créer un modèle d'index pour chaque type de valeur que vous souhaitez stocker — cela indique à Elasticsearch quel mapping appliquer lorsqu'il crée automatiquement un nouvel index basé sur la date.
  • Créer un pipeline d'ingestion pour chaque type de valeur — il traite chaque valeur entrante et l'achemine vers le bon index basé sur la date.
Modèles d’index

Pour créer un modèle pour l’index text, envoyez une requête avec les détails suivants :

  • Utilisez _template/text_template dans l’URL de votre instance Elasticsearch.
  • Utilisez "text*" dans le champ "index_patterns" pour faire correspondre le nom de l’index.
  • Utilisez un mapping pour le type de valeur text (voir les mappings dans le dépôt source de Zabbix).
curl -X PUT \
 http://localhost:9200/_template/text_template \
 -H 'content-type:application/json' \
 -d '{
   "index_patterns": [ "text*" ],
   "settings": {
      "index": {
         "number_of_replicas": 1,
         "number_of_shards": 5
      }
   },
   "mappings": {
      "properties": {
         "itemid": { "type": "long" },
         "clock": { "format": "epoch_second", "type": "date" },
         "value": {
            "fields": {
               "analyzed": { "index": true, "type": "text", "analyzer": "standard" }
            },
            "index": false,
            "type": "text"
         }
      }
   }
}'

Modèle pour l’index json :

curl -X PUT \
 http://localhost:9200/_template/json_template \
 -H 'content-type:application/json' \
 -d '{
   "index_patterns": [ "json*" ],
   "settings": {
      "number_of_shards": 5,
      "number_of_replicas": 1
   },
   "mappings": {
      "dynamic": false,
      "properties": {
         "itemid": { "type": "long" },
         "clock": { "type": "date", "format": "epoch_second" },
         "ns": { "type": "long" },
         "value_parsed": { "type": "flattened" },
         "value_raw": { "type": "keyword", "ignore_above": 1000000 }
      }
   }
}'
Pipelines d’ingestion

Pour créer un pipeline d’ingestion pour l’index text :

  • Utilisez _ingest/pipeline/text-pipeline dans l’URL de votre instance Elasticsearch.
  • Incluez un processeur date_index_name pour acheminer chaque valeur vers l’index basé sur la date correct en fonction de son horodatage.
curl -X PUT \
 http://localhost:9200/_ingest/pipeline/text-pipeline \
 -H 'content-type:application/json' \
 -d '{
   "description": "daily text index naming",
   "processors": [
      {
         "date_index_name": {
            "field": "clock",
            "date_formats": ["UNIX"],
            "index_name_prefix": "text-",
            "date_rounding": "d"
         }
      }
   ]
}'

Pour l’index json, le pipeline doit également analyser la valeur JSON avant de l’acheminer vers l’index correct :

curl -X PUT \
 http://localhost:9200/_ingest/pipeline/json-pipeline \
 -H 'content-type:application/json' \
 -d '{
   "description": "daily json index naming"
   "processors": [
      {
         "json": {
            "field": "value",
            "target_field": "value_parsed",
            "ignore_failure": true
         }
      },
      {
         "script": {
            "source": "if (ctx.value_parsed == null || !(ctx.value_parsed instanceof Map)) { ctx.value_raw = ctx.value; ctx.remove(\"value_parsed\"); }"
         }
      },
      {
         "date_index_name": {
            "field": "clock",
            "date_formats": [ "UNIX" ],
            "index_name_prefix": "json-",
            "date_rounding": "d"
         }
      }
   ]
}'

Configuration du serveur Zabbix

Dans le fichier de configuration de votre serveur Zabbix (zabbix_server.conf), définissez le paramètre HistoryProvider.

Par exemple, pour stocker les valeurs de type Character, Log, Text et JSON dans Elasticsearch (tout en conservant les valeurs Numeric dans une base de données) :

HistoryProvider=elasticsearch;value_types="str,log,text,json",url=http://localhost:9200

Si vous utilisez des index basés sur la date, ajoutez date_index=1 au paramètre :

HistoryProvider=elasticsearch;value_types="str,log,text,json",url=http://localhost:9200,date_index=1

Après avoir effectué les modifications, redémarrez le serveur Zabbix :

systemctl restart zabbix-server

Configuration de l'interface Zabbix

Dans votre fichier de configuration de l'interface Zabbix (zabbix.conf.php), définissez la variable $HISTORY_PROVIDERS de manière à correspondre à la configuration du serveur :

$HISTORY_PROVIDERS[] = [
  'types' => ['str','log','text','json'],
  'provider' => 'elasticsearch',
  'url' => 'http://localhost:9200'
];

Dépannage

Les étapes suivantes peuvent vous aider à résoudre les problèmes liés à votre configuration Elasticsearch :

  1. Vérifiez les journaux d'Elasticsearch ou du serveur Zabbix pour détecter d'éventuelles erreurs.

  2. Pour identifier les requêtes lentes, utilisez l'option log_slow_queries dans le paramètre de configuration du serveur Zabbix HistoryProvider.

  3. Vérifiez qu'Elasticsearch autorise l'accès depuis le serveur Zabbix et l'interface Zabbix.

  4. Vérifiez que auto_create_index est activé :

curl -X GET \
 "http://localhost:9200/_cluster/settings?include_defaults=true&filter_path=**.auto_create_index"

# {"defaults": {"action": {"auto_create_index": "false"} } }

Pour l'activer, envoyez la requête suivante :

curl -X PUT \
 http://localhost:9200/_cluster/settings \
 -H 'content-type:application/json' \
 -d '{
   "persistent": {
      "action.auto_create_index": "true"
   }
}'

# {"acknowledged": true, "persistent": {"action": {"auto_create_index": "true"} }, "transient": {} }
  1. Vérifiez que les mappings, les modèles et les pipelines d'ingestion sont corrects en envoyant des requêtes GET à leurs URL respectives :
curl -X GET http://localhost:9200/json
curl -X GET http://localhost:9200/_template/json*
curl -X GET http://localhost:9200/_ingest/pipeline/json*

Vous pouvez comparer les réponses reçues avec les réponses attendues dans la documentation de l'API Elasticsearch.

  1. Vérifiez si des shards sont dans un état d'échec ; le redémarrage d'Elasticsearch peut résoudre le problème.

  2. Interrogez Elasticsearch pour vérifier si les données collectées par Zabbix sont stockées, par exemple :

curl 'http://localhost:9200/json/_search' \
 -H 'Content-Type: application/json' \
 -d '{
   "query": {
     "term": {
       "itemid": 42269
     }
   }
 }'
  1. Si vous devez réinitialiser votre configuration Elasticsearch et recommencer, vous pouvez supprimer tous les index, modèles et pipelines d'ingestion :
curl -X DELETE "http://localhost:9200/_all"
curl -X DELETE "http://localhost:9200/_template/*"
curl -X DELETE "http://localhost:9200/_ingest/pipeline/*"