Elasticsearch-Einrichtung

Zabbix kann Verlaufsdaten in Elasticsearch als Alternative zu einer relationalen Datenbank speichern.

Die Unterstützung von Elasticsearch ist derzeit experimentell.

Diese Anleitung beschreibt die Einrichtung der unterstützten Versionen von Elasticsearch. Wenn Sie eine andere Version verwenden, funktioniert möglicherweise nicht alles wie vorgesehen.

Elasticsearch kann die folgenden Werttypen speichern:

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 akzeptiert keine JSON-Arrays. Ein JSON-Wert muss entweder ein einzelnes Objekt oder eine Menge von Objekten sein.

Wichtige Hinweise

  • Elasticsearch erfordert libcurl. Weitere Informationen finden Sie unter Anforderungen.
  • Der Housekeeper löscht keine Daten aus Elasticsearch. Um zu steuern, wie lange Daten aufbewahrt werden, siehe Index Lifecycle Management.
  • Zabbix berechnet oder speichert Trends in Elasticsearch nicht. Erwägen Sie, den Speicherzeitraum für Historien zu verlängern, um ältere Daten zu erhalten.
  • Wenn Elasticsearch verwendet wird, sind Bereichsabfragen, die Werte aus der Datenbank abrufen, durch den Zeitstempel des Datenspeicherzeitraums begrenzt.
  • Elasticsearch wird für Zabbix Proxies nicht unterstützt.

Wenn Elasticsearch noch nicht installiert ist, lesen Sie vor dem Fortfahren die offizielle Installationsanleitung.

Elasticsearch konfigurieren

Um Verlaufsdaten in Elasticsearch zu speichern, müssen Sie:

  • Für jeden Werttyp, den Sie speichern möchten, einen Index erstellen – dort speichert Elasticsearch die Daten, ähnlich wie in einer Tabelle in einer relationalen Datenbank.
  • Für jeden Index ein Mapping definieren – dieses legt die Struktur der Daten fest, ähnlich wie ein Tabellenschema.
  • Eine Ingest-Pipeline einrichten, um Werte vor der Speicherung zu verarbeiten (erforderlich für JSON-Werte und datumsbasierte Indizes).

Elasticsearch kann Daten in einem einzelnen Index pro Werttyp oder über mehrere datumsbasierte Indizes hinweg speichern. Beide Ansätze werden unten beschrieben.

Verlauf in einem einzelnen Index speichern

Bei diesem Ansatz werden alle Verlaufsdaten für einen bestimmten Werttyp in einen einzelnen Index geschrieben (z. B. uint oder text).

Um einen Index für den Werttyp Numerisch (vorzeichenlos) zu erstellen, senden Sie die folgende Anfrage (mit /uint in der URL) an Ihre Elasticsearch-Instanz:

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 antwortet mit einer Bestätigung, dass der Index erstellt wurde:

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

Ähnliche Anfragen müssen für jeden zusätzlichen Werttyp gesendet werden, den Sie in Elasticsearch speichern möchten.

Mappings für alle Werttypen sind im Zabbix source repository verfügbar.

Zum Beispiel, um einen Index für den Werttyp Text zu erstellen:

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"
         }
      }
   }
}'
JSON-Werttyp

Im Gegensatz zu anderen Werttypen erfordern JSON-Werte vor der Speicherung eine zusätzliche Verarbeitung.

Der unten stehende Index verwendet separate Felder für geparste und rohe Werte, daher wird eine Ingest-Pipeline benötigt, um jeden Wert als JSON zu parsen und im richtigen Feld zu speichern.

Um einen Index für den Werttyp JSON zu erstellen, senden Sie die folgende Anfrage (mit /json in der URL) an Ihre Elasticsearch-Instanz.

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

Erstellen Sie dann die Ingest-Pipeline:

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 antwortet mit einer Bestätigung, dass die Ingest-Pipeline erstellt wurde:

{"acknowledged": true}

Speicherung von History in datumsbasierten Indizes

Anstatt alle History-Daten in einen einzelnen Index zu schreiben (z. B. uint), kann Elasticsearch diese Daten auf mehrere datumsbasierte Indizes verteilen (z. B. uint-2026-01-01, uint-2026-01-02). Dadurch lassen sich Datenvolumen und Aufbewahrung im Laufe der Zeit einfacher verwalten.

Um dies zu aktivieren, müssen Sie:

  • Für jeden Werttyp, den Sie speichern möchten, eine Indexvorlage erstellen - diese teilt Elasticsearch mit, welches Mapping angewendet werden soll, wenn automatisch ein neuer datumsbasierter Index erstellt wird.
  • Für jeden Werttyp eine Ingest-Pipeline erstellen - sie verarbeitet jeden eingehenden Wert und leitet ihn an den richtigen datumsbasierten Index weiter.
Index-Vorlagen

Um eine Vorlage für den text-Index zu erstellen, senden Sie eine Anfrage mit den folgenden Details:

  • Verwenden Sie _template/text_template in der URL Ihrer Elasticsearch-Instanz.
  • Verwenden Sie "text*" im Feld "index_patterns", um den Index-Namen abzugleichen.
  • Verwenden Sie ein Mapping für den Werttyp text (siehe Mappings im Zabbix-Quellcode-Repository).
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"
         }
      }
   }
}'

Vorlage für den json-Index:

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 }
      }
   }
}'
Ingest-Pipelines

Um eine Ingest-Pipeline für den Index text zu erstellen:

  • Verwenden Sie _ingest/pipeline/text-pipeline in der URL Ihrer Elasticsearch-Instanz.
  • Fügen Sie einen Prozessor date_index_name hinzu, um jeden Wert anhand seines Zeitstempels an den korrekten datumsbasierten Index weiterzuleiten.
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"
         }
      }
   ]
}'

Für den Index json muss die Pipeline den JSON-Wert vor der Weiterleitung an den korrekten Index außerdem parsen:

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

Konfigurieren des Zabbix-Servers

Setzen Sie in der Konfigurationsdatei Ihres Zabbix-Servers (zabbix_server.conf) den Parameter HistoryProvider.

Um beispielsweise Werte der Typen Character, Log, Text und JSON in Elasticsearch zu speichern (während Numeric-Werte in einer Datenbank verbleiben):

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

Wenn Sie datumsbasierte Indizes verwenden, fügen Sie dem Parameter date_index=1 hinzu:

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

Starten Sie nach den Änderungen den Zabbix-Server neu:

systemctl restart zabbix-server

Konfigurieren des Zabbix-Frontends

Setzen Sie in Ihrer Konfigurationsdatei des Zabbix-Frontends (zabbix.conf.php) die Variable $HISTORY_PROVIDERS so, dass sie mit der Serverkonfiguration übereinstimmt:

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

Fehlerbehebung

Die folgenden Schritte können Ihnen bei der Fehlerbehebung Ihrer Elasticsearch-Konfiguration helfen:

  1. Prüfen Sie die Protokolle von Elasticsearch oder dem Zabbix-Server auf Fehler.

  2. Um langsame Abfragen zu identifizieren, verwenden Sie die Option log_slow_queries im Zabbix-Server-Konfigurationsparameter HistoryProvider.

  3. Vergewissern Sie sich, dass Elasticsearch den Zugriff vom Zabbix-Server und vom Zabbix-Frontend erlaubt.

  4. Vergewissern Sie sich, dass auto_create_index aktiviert ist:

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

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

Um es zu aktivieren, senden Sie die folgende Anfrage:

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. Vergewissern Sie sich, dass Mappings, Vorlagen und Ingest-Pipelines korrekt sind, indem Sie GET-Anfragen an die jeweiligen URLs senden:
curl -X GET http://localhost:9200/json
curl -X GET http://localhost:9200/_template/json*
curl -X GET http://localhost:9200/_ingest/pipeline/json*

Sie können die empfangenen Antworten mit den erwarteten Antworten in der Elasticsearch-API-Dokumentation vergleichen.

  1. Prüfen Sie, ob sich Shards in einem fehlgeschlagenen Zustand befinden; ein Neustart von Elasticsearch kann das Problem möglicherweise beheben.

  2. Fragen Sie Elasticsearch ab, um zu prüfen, ob die von Zabbix gesammelten Daten gespeichert wurden, zum Beispiel:

curl 'http://localhost:9200/json/_search' \
 -H 'Content-Type: application/json' \
 -d '{
   "query": {
     "term": {
       "itemid": 42269
     }
   }
 }'
  1. Wenn Sie Ihre Elasticsearch-Konfiguration zurücksetzen und neu beginnen müssen, können Sie alle Indizes, Vorlagen und Ingest-Pipelines löschen:
curl -X DELETE "http://localhost:9200/_all"
curl -X DELETE "http://localhost:9200/_template/*"
curl -X DELETE "http://localhost:9200/_ingest/pipeline/*"