Configurazione di Elasticsearch

Zabbix può memorizzare i dati storici in Elasticsearch come alternativa a un database relazionale.

Il supporto di Elasticsearch è attualmente sperimentale.

Questa guida illustra la configurazione delle versioni supportate di Elasticsearch. Se stai usando una versione diversa, alcune funzionalità potrebbero non funzionare come previsto.

Elasticsearch può memorizzare i seguenti tipi di valore:

Tipo di valore dell'item Tabella del database Tipo Elasticsearch
Numerico (senza segno) history_uint uint
Numerico (float) history dbl
Carattere history_str str
Log history_log log
Testo history_text text
Binario history_bin non supportato da Zabbix
JSON history_json json

Elasticsearch non accetta array JSON. Un valore JSON deve essere un singolo oggetto oppure un insieme di oggetti.

Note importanti

  • Elasticsearch richiede libcurl. Vedi requirements per i dettagli.
  • Il housekeeper non elimina i dati da Elasticsearch. Per controllare per quanto tempo i dati vengono conservati, vedi Index Lifecycle Management.
  • Zabbix non calcola né memorizza le trend in Elasticsearch. Valuta di estendere il periodo di conservazione della history per preservare i dati più vecchi.
  • Quando viene usato Elasticsearch, le query di intervallo che recuperano valori dal database sono limitate dal timestamp del periodo di conservazione dei dati.
  • Elasticsearch non è supportato per i proxy Zabbix.

Se Elasticsearch non è ancora installato, consulta la guida ufficiale all'installazione prima di procedere.

Configurazione di Elasticsearch

Per memorizzare i dati di storico in Elasticsearch, è necessario:

  • Creare un indice per ogni tipo di valore che si desidera memorizzare: è qui che Elasticsearch archivia i dati, in modo simile a una tabella in un database relazionale.
  • Definire una mappatura per ogni indice: questa definisce la struttura dei dati, in modo simile allo schema di una tabella.
  • Configurare una pipeline di ingest per elaborare i valori prima della memorizzazione (necessaria per i valori JSON e per gli indici basati sulla data).

Elasticsearch può memorizzare i dati in un singolo indice per tipo di valore oppure in più indici basati sulla data. Entrambi gli approcci sono descritti di seguito.

Archiviazione della cronologia in un singolo indice

In questo approccio, tutti i dati di cronologia per un determinato tipo di valore vengono scritti in un singolo indice (ad esempio, uint o text).

Per creare un indice per il tipo di valore Numeric (unsigned), invia la seguente richiesta (con /uint nell'URL) alla tua istanza 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 risponderà con una conferma che l'indice è stato creato:

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

Richieste simili devono essere inviate per ogni ulteriore tipo di valore che si desidera memorizzare in Elasticsearch.

Le mappature per tutti i tipi di valore sono disponibili nel repository sorgente di Zabbix.

Ad esempio, per creare un indice per il tipo di valore Text:

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"
         }
      }
   }
}'
Tipo di valore JSON

A differenza degli altri tipi di valore, i valori JSON richiedono un'elaborazione aggiuntiva prima dell'archiviazione.

L'indice seguente utilizza campi separati per i valori analizzati e grezzi, quindi è necessaria una pipeline di ingest per analizzare ogni valore come JSON e memorizzarlo nel campo corretto.

Per creare un indice per il tipo di valore JSON, invia la seguente richiesta (con /json nell'URL) alla tua istanza 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 }
    }
  }
}'

Quindi, crea la pipeline di ingest:

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 risponderà con una conferma della creazione della pipeline di ingest:

{"acknowledged": true}

Archiviazione della history in indici basati sulla data

Invece di scrivere tutti i dati della history in un unico indice (ad esempio, uint), Elasticsearch può distribuire questi dati su più indici basati sulla data (ad esempio, uint-2026-01-01, uint-2026-01-02). Questo semplifica la gestione del volume dei dati e della retention nel tempo.

Per abilitarlo, è necessario:

  • Creare un index template per ogni tipo di valore che si desidera archiviare: questo indica a Elasticsearch quale mapping applicare quando crea automaticamente un nuovo indice basato sulla data.
  • Creare un ingest pipeline per ogni tipo di valore: elabora ogni valore in ingresso e lo indirizza al corretto indice basato sulla data.
Template di indice

Per creare un template per l'indice text, invia una richiesta con i seguenti dettagli:

  • Usa _template/text_template nell'URL della tua istanza Elasticsearch.
  • Usa "text*" nel campo "index_patterns" per corrispondere al nome dell'indice.
  • Usa una mappatura per il tipo di valore text (vedi le mappature nel repository sorgente di 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"
         }
      }
   }
}'

Template per l'indice 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 }
      }
   }
}'
Pipeline di ingestione

Per creare una pipeline di ingestione per l'indice text:

  • Usa _ingest/pipeline/text-pipeline nell'URL della tua istanza Elasticsearch.
  • Includi un processore date_index_name per instradare ogni valore all'indice basato sulla data corretto in base al relativo timestamp.
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"
         }
      }
   ]
}'

Per l'indice json, la pipeline deve anche analizzare il valore JSON prima di instradarlo all'indice corretto:

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"
         }
      }
   ]
}'

Configurazione di Zabbix server

Nel file di configurazione di Zabbix server (zabbix_server.conf), impostare il parametro HistoryProvider.

Ad esempio, per archiviare i valori di tipo Character, Log, Text e JSON in Elasticsearch (mantenendo i valori Numeric in un database):

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

Se si utilizzano indici basati sulla data, aggiungere date_index=1 al parametro:

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

Dopo aver apportato le modifiche, riavviare Zabbix server:

systemctl restart zabbix-server

Configurazione del frontend di Zabbix

Nel file di configurazione del frontend di Zabbix (zabbix.conf.php), impostare la variabile $HISTORY_PROVIDERS in modo che corrisponda alla configurazione del server:

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

Risoluzione dei problemi

I seguenti passaggi possono aiutarti a risolvere i problemi con la configurazione di Elasticsearch:

  1. Controlla i log di Elasticsearch o del server Zabbix per individuare eventuali errori.

  2. Per identificare le query lente, usa l'opzione log_slow_queries nel parametro di configurazione del server Zabbix HistoryProvider.

  3. Verifica che Elasticsearch consenta l'accesso dal server Zabbix e dal frontend Zabbix.

  4. Verifica che auto_create_index sia abilitato:

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

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

Per abilitarlo, invia la seguente richiesta:

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. Verifica che mapping, template e ingest pipeline siano corretti inviando richieste GET ai rispettivi URL:
curl -X GET http://localhost:9200/json
curl -X GET http://localhost:9200/_template/json*
curl -X GET http://localhost:9200/_ingest/pipeline/json*

Puoi confrontare le risposte ricevute con le risposte attese nella documentazione API di Elasticsearch.

  1. Controlla se qualche shard si trova in stato di errore; il riavvio di Elasticsearch potrebbe risolvere il problema.

  2. Interroga Elasticsearch per verificare se i dati raccolti da Zabbix sono stati memorizzati, ad esempio:

curl 'http://localhost:9200/json/_search' \
 -H 'Content-Type: application/json' \
 -d '{
   "query": {
     "term": {
       "itemid": 42269
     }
   }
 }'
  1. Se devi reimpostare la configurazione di Elasticsearch e ricominciare da zero, puoi eliminare tutti gli indici, i template e le ingest pipeline:
curl -X DELETE "http://localhost:9200/_all"
curl -X DELETE "http://localhost:9200/_template/*"
curl -X DELETE "http://localhost:9200/_ingest/pipeline/*"