Configuration d’Elasticsearch
Zabbix peut stocker les données d’historique dans Elasticsearch comme alternative à une base de données relationnelle.
Ce guide couvre la configuration des versions prises en charge d’Elasticsearch.
Le serveur Zabbix ne démarre pas si votre version d’Elasticsearch est antérieure à la version minimale prise en charge.
Si elle est ultérieure à la version maximale prise en charge, le serveur Zabbix démarre uniquement si le paramètre AllowUnsupportedDBVersions est défini sur 1.
Elasticsearch peut stocker les types de valeurs suivants :
| Type de valeur de l'élément | Table de la base de données | Type Elasticsearch |
|---|---|---|
| Numérique (non signé) | history_uint | uint |
| Numérique (flottant) | history | dbl |
| Caractère | history_str | str |
| Journal | history_log | log |
| Texte | history_text | text |
| Binaire | history_bin | non pris en charge par Zabbix |
| JSON | history_json | json |
Remarques importantes
- Elasticsearch nécessite libcurl. Consultez la section Configuration requise 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, consultez la section Index Lifecycle Management.
- Zabbix ne calcule ni ne stocke les tendances dans Elasticsearch. Envisagez de prolonger 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 proxy Zabbix.
- À partir d'Elasticsearch 8.0, les fonctionnalités de sécurité sont activées par défaut : Elasticsearch nécessite une authentification et utilise HTTPS pour son API HTTP, avec des certificats signés par une autorité de certification générée automatiquement.
Les exemples de cette page utilisent
http://localhost:9200sans authentification. Si la sécurité est activée, utilisez une URLhttps://et transmettez le certificat de l'autorité de certification ainsi que les identifiants dans vos requêtes (par exemple,sudo curl --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic https://localhost:9200; le fichier de certificat de l'autorité de certification ne peut être lu que parrootet le groupeelasticsearch). Pour connecter le serveur Zabbix et l'interface Zabbix à un tel cluster, consultez la section Connexion à un cluster sécurisé.
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 index unique
Avec cette approche, toutes les données d’historique correspondant à un type de valeur donné sont écrites dans un index unique (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 en confirmant 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 que vous souhaitez stocker dans Elasticsearch, c’est-à-dire pour chaque type répertorié dans l’option value_types de la configuration du serveur Zabbix.
Les mappings pour tous les types de valeur sont disponibles dans le dépôt du code 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 valeurs, les valeurs JSON nécessitent un traitement supplémentaire avant leur stockage. L'index du type de valeur JSON stocke chaque valeur dans l'un de deux champs :
value_parsed—objets JSON, stockés dans un champ aplati, afin de pouvoir être recherchés par clé et par valeur ;value_raw—toutes les autres valeurs JSON (tableaux, chaînes, nombres, valeurs booléennes etnull), stockées sous forme de chaîne.
Un pipeline d'ingestion analyse chaque valeur comme du JSON et la stocke dans le champ approprié. Les valeurs qui ne sont pas du JSON valide ne sont pas envoyées à Elasticsearch, car les éléments qui les reçoivent deviennent non pris en charge.
Commencez par créer 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
}
},
{
"script": {
"source": "if (ctx.value_parsed == null || !(ctx.value_parsed instanceof Map)) { ctx.value_raw = ctx.value; ctx.remove(\"value_parsed\"); }"
}
}
]
}'
Elasticsearch répondra en confirmant que le pipeline d'ingestion a été créé :
{"acknowledged": true}
Ensuite, créez un index pour le type de valeur JSON en envoyant la requête suivante (avec /json dans l'URL) à votre instance Elasticsearch.
Le paramètre default_pipeline permet à Elasticsearch de traiter chaque valeur écrite dans cet index avec le pipeline d'ingestion json.
Ce paramètre est requis, car le serveur Zabbix ne spécifie pas de pipeline d'ingestion lors du stockage de l'historique dans un index unique.
curl -X PUT \
http://localhost:9200/json \
-H 'content-type:application/json' \
-d '{
"settings": {
"index": {
"number_of_replicas": 1,
"number_of_shards": 5,
"default_pipeline": "json"
}
},
"mappings": {
"dynamic": false,
"properties": {
"itemid": { "type": "long" },
"clock": { "type": "date", "format": "epoch_second" },
"ns": { "type": "long" },
"value_parsed": { "type": "flattened", "ignore_above": 8191 },
"value_raw": { "type": "keyword", "ignore_above": 8191 }
}
}
}'
Elasticsearch ne peut pas indexer les valeurs keyword et flattened de plus de 32766 octets.
Avec "ignore_above": 8191, les chaînes de plus de 8191 caractères ne sont pas indexées (et ne peuvent pas faire l'objet de recherches), mais elles sont tout de même stockées et renvoyées intégralement à Zabbix.
Sans cette limite, Elasticsearch rejette ces valeurs, qui sont alors perdues.
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
_index_template/text_templatedans l’URL de votre instance Elasticsearch. - Utilisez
"text-*"dans le champ"index_patterns"pour faire correspondre les noms des index basés sur la date. - Dans le champ
"template", spécifiez les paramètres de l’index et un mappage pour le type de valeurtext(voir les mappages dans le dépôt source de Zabbix).
curl -X PUT \
http://localhost:9200/_index_template/text_template \
-H 'content-type:application/json' \
-d '{
"index_patterns": [ "text-*" ],
"template": {
"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"
}
}
}
}
}'
Créez un modèle pour chaque type de valeur que vous souhaitez stocker, en modifiant le nom du modèle, le modèle d’index et le mappage en conséquence.
Par exemple, un modèle pour l’index json (pour plus de détails sur les champs value_parsed et value_raw, voir Type de valeur JSON) :
curl -X PUT \
http://localhost:9200/_index_template/json_template \
-H 'content-type:application/json' \
-d '{
"index_patterns": [ "json-*" ],
"template": {
"settings": {
"number_of_replicas": 1
},
"mappings": {
"dynamic": false,
"properties": {
"itemid": { "type": "long" },
"clock": { "type": "date", "format": "epoch_second" },
"ns": { "type": "long" },
"value_parsed": { "type": "flattened", "ignore_above": 8191 },
"value_raw": { "type": "keyword", "ignore_above": 8191 }
}
}
}
}'
Utilisez des modèles d’index composables (_index_template) comme indiqué ci-dessus.
Les modèles d’index hérités (_template) sont obsolètes, et Elasticsearch rejette les modèles hérités dont les modèles d’index se chevauchent avec ses modèles intégrés (par exemple, un modèle hérité avec le modèle log* pour l’index log).
Pipelines d’ingestion
Pour créer un pipeline d’ingestion pour l’index text :
- Utilisez
_ingest/pipeline/text-pipelinedans l’URL de votre instance Elasticsearch. - Incluez un processeur
date_index_namepour acheminer chaque valeur vers l’index approprié basé sur la date, 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"
}
}
]
}'
Créez un pipeline pour chaque type de valeur que vous souhaitez stocker, en modifiant le nom du pipeline, la description et la valeur de "index_name_prefix" en conséquence.
Le nom du pipeline doit être composé du nom de l’index et du suffixe -pipeline (par exemple, uint-pipeline), car le serveur Zabbix utilise ce nom lors de l’envoi des valeurs à Elasticsearch.
Pour l’index json, le pipeline doit également analyser la valeur JSON avant de l’acheminer vers l’index approprié :
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
Si les fonctionnalités de sécurité d’Elasticsearch sont activées, indiquez une URL https:// avec des identifiants (voir Connexion à un cluster sécurisé).
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 pour qu’elle corresponde à la configuration du serveur :
$HISTORY_PROVIDERS[] = [
'types' => ['str','log','text','json'],
'provider' => 'elasticsearch',
'url' => 'http://localhost:9200'
];
Si les fonctionnalités de sécurité d’Elasticsearch sont activées, spécifiez la même URL https:// avec les identifiants que dans la configuration du serveur (voir Connexion à un cluster sécurisé).
Connexion à un cluster sécurisé
Si les fonctionnalités de sécurité d’Elasticsearch sont activées (par défaut depuis Elasticsearch 8.0), le serveur Zabbix et l’interface Zabbix doivent faire confiance au certificat CA de la couche HTTP d’Elasticsearch et doivent s’authentifier avec un nom d’utilisateur et un mot de passe.
- Créez un rôle et un utilisateur pour Zabbix.
Le rôle suivant permet à Zabbix de récupérer la version d’Elasticsearch (le privilège de cluster
monitor), de créer des index, d’écrire et de lire les données d’historique, et de supprimer les données d’historique lorsque l’historique d’un élément est effacé :
sudo curl -X PUT \
--cacert /etc/elasticsearch/certs/http_ca.crt -u elastic \
https://localhost:9200/_security/role/zabbix_history \
-H 'content-type:application/json' \
-d '{
"cluster": [ "monitor" ],
"indices": [
{
"names": [ "uint", "uint-*", "dbl", "dbl-*", "str", "str-*", "log", "log-*", "text", "text-*", "json", "json-*" ],
"privileges": [ "create_index", "index", "read", "delete" ]
}
]
}'
sudo curl -X PUT \
--cacert /etc/elasticsearch/certs/http_ca.crt -u elastic \
https://localhost:9200/_security/user/zabbix \
-H 'content-type:application/json' \
-d '{
"password": "<password>",
"roles": [ "zabbix_history" ]
}'
- Ajoutez le certificat CA d’Elasticsearch aux certificats approuvés du système d’exploitation sur les hôtes du serveur Zabbix et de l’interface Zabbix.
Si Zabbix s’exécute sur un hôte différent de celui d’Elasticsearch, copiez d’abord le certificat CA (
/etc/elasticsearch/certs/http_ca.crt) sur cet hôte. Par exemple, sur Debian/Ubuntu :
sudo cp /etc/elasticsearch/certs/http_ca.crt /usr/local/share/ca-certificates/elasticsearch-http-ca.crt
sudo update-ca-certificates
Le nom d’hôte dans l’URL doit correspondre au certificat HTTP d’Elasticsearch.
Le certificat généré automatiquement est valide pour localhost, le nom d’hôte et les adresses IP de l’hôte Elasticsearch.
- Indiquez les identifiants dans l’URL, à la fois dans le fichier de configuration du serveur Zabbix et dans le fichier de configuration de l’interface.
Si le mot de passe contient des caractères spéciaux, encodez-les en pourcentage (par exemple,
@en%40,:en%3Aet,en%2C).
HistoryProvider=elasticsearch;value_types="str,log,text,json",url=https://zabbix:<password>@localhost:9200
$HISTORY_PROVIDERS[] = [
'types' => ['str','log','text','json'],
'provider' => 'elasticsearch',
'url' => 'https://zabbix:<password>@localhost:9200'
];
- Redémarrez le serveur Zabbix et PHP-FPM (ou le serveur web, si PHP s’exécute en tant que module du serveur web).
Dépannage
Les étapes suivantes peuvent vous aider à résoudre les problèmes liés à votre configuration Elasticsearch :
- Vérifiez les journaux d’Elasticsearch ou du serveur Zabbix pour rechercher d’éventuelles erreurs. Par exemple, les messages suivants dans le journal du serveur Zabbix indiquent des problèmes de connexion à un cluster sécurisé (voir Connexion à un cluster sécurisé) :
cannot query Elasticsearch: SSL certificate problem: self-signed certificate in certificate chain— le certificat CA d’Elasticsearch n’est pas approuvé ;cannot query Elasticsearch, HTTP error message: The requested URL returned error: 401— les identifiants sont absents ou incorrects ;cannot query Elasticsearch, HTTP error message: The requested URL returned error: 403— l’utilisateur ne dispose pas des privilèges requis.
L’interface Zabbix affiche des erreurs similaires (par exemple, Elasticsearch error: missing authentication credentials for REST request).
-
Pour identifier les requêtes lentes, définissez le paramètre de configuration du serveur Zabbix
LogSlowQueries. Si la lecture de l’historique depuis Elasticsearch prend plus de temps que la durée spécifiée, le serveur Zabbix consigneslow query: <N> sec, "<query>". Lorsqu’il attend une réponse d’Elasticsearch, le serveur Zabbix consigne égalementwaiting for Elasticsearch response <N>secchaque fois que la durée spécifiée s’écoule, ou toutes les 10 secondes siLogSlowQueriesest défini sur 0. -
Vérifiez qu’Elasticsearch autorise l’accès depuis le serveur Zabbix et l’interface Zabbix.
-
Vérifiez que
auto_create_indexest activé (il l’est par défaut) :
curl -X GET \
"http://localhost:9200/_cluster/settings?include_defaults=true&filter_path=**.auto_create_index"
# {"persistent": {"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": {} }
- 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/_index_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.
-
Vérifiez si certains shards sont dans un état d’échec ; le redémarrage d’Elasticsearch peut résoudre ce problème. Dans un cluster à nœud unique, les index avec des réplicas (
"number_of_replicas": 1) ont le statut jaune, car les réplicas ne peuvent pas être alloués au même nœud que les shards primaires ; cela n’affecte pas Zabbix. Pour éviter cela, définissez"number_of_replicas"sur0. -
Interrogez Elasticsearch pour vérifier si les données collectées par Zabbix y sont stockées, par exemple :
curl "http://localhost:9200/json*/_search" \
-H 'Content-Type: application/json' \
-d '{
"query": {
"term": {
"itemid": 42269
}
}
}'
- Si vous devez réinitialiser votre configuration Elasticsearch et recommencer, supprimez les index, les modèles d’index et les pipelines d’ingestion créés pour Zabbix (cette opération supprime toutes les données d’historique stockées dans Elasticsearch).
Par défaut, Elasticsearch n’autorise pas la suppression d’index à l’aide d’expressions génériques. Pour supprimer les index basés sur des dates, modifiez temporairement le paramètre
action.destructive_requires_name. Les modèles d’index et les pipelines d’ingestion doivent être supprimés un par un ; les requêtes concernant des modèles ou des pipelines inexistants renvoient une erreur, qui peut être ignorée.
curl -X DELETE "http://localhost:9200/uint,dbl,str,log,text,json?ignore_unavailable=true"
curl -X PUT \
http://localhost:9200/_cluster/settings \
-H 'content-type:application/json' \
-d '{"persistent": {"action.destructive_requires_name": false}}'
curl -X DELETE "http://localhost:9200/uint-*,dbl-*,str-*,log-*,text-*,json-*"
curl -X PUT \
http://localhost:9200/_cluster/settings \
-H 'content-type:application/json' \
-d '{"persistent": {"action.destructive_requires_name": null}}'
for type in uint dbl str log text json; do
curl -X DELETE "http://localhost:9200/_index_template/${type}_template"
curl -X DELETE "http://localhost:9200/_ingest/pipeline/${type}-pipeline"
done
curl -X DELETE "http://localhost:9200/_ingest/pipeline/json"