8 Configuração do Elasticsearch

O Zabbix pode armazenar dados históricos no Elasticsearch como uma alternativa ao banco de dados relacional.

O suporte ao Elasticsearch atualmente é experimental.

Este guia cobre a configuração para o Elasticsearch 7.X. Se você estiver usando uma versão diferente, algumas funcionalidades podem não funcionar conforme o esperado.

A configuração envolve criar um local de armazenamento no Elasticsearch para cada tipo de valor, configurar o pré-processamento (se necessário) e conectar o Zabbix à sua instância do Elasticsearch.

O Elasticsearch pode armazenar os seguintes tipos de valores:

Tipo de valor do item Tabela do banco de dados Tipo no Elasticsearch
Numérico (sem sinal) history_uint uint
Numérico (ponto flutuante) history dbl
Caractere history_str str
Log history_log log
Texto history_text text
Binário history_bin não suportado pelo Zabbix
JSON history_json json

Notas importantes

  • O Elasticsearch requer libcurl. Veja os requisitos para mais detalhes.
  • O housekeeper não exclui dados do Elasticsearch.
  • Se todos os dados de histórico forem armazenados no Elasticsearch, as tendências não serão calculadas ou armazenadas no banco de dados. Considere estender o período de armazenamento do histórico.
  • Quando o Elasticsearch é usado, as consultas de intervalo que recuperam valores do banco de dados são limitadas pelo timestamp do período de armazenamento dos dados.
  • O Elasticsearch não é suportado para o Zabbix proxy; por favor, use o SQLite.

Se o Elasticsearch ainda não estiver instalado, consulte o guia oficial de instalação antes de prosseguir.

Configurando o Elasticsearch

Para armazenar dados históricos no Elasticsearch, você precisa:

  • Criar um índice para cada tipo de valor que deseja armazenar—é aqui que o Elasticsearch armazena os dados, semelhante a uma tabela em um banco de dados relacional.
  • Definir um mapeamento para cada índice—isso define a estrutura dos dados, semelhante ao esquema de uma tabela.
  • Configurar um pipeline de ingestão para processar valores antes do armazenamento (necessário para valores JSON e índices baseados em data).

O Elasticsearch pode armazenar dados em um único índice por tipo de valor ou em vários índices baseados em data. Ambas as abordagens são descritas abaixo.

Armazenando histórico em um único índice

Nesta abordagem, todos os dados de histórico para um determinado tipo de valor são gravados em um único índice (por exemplo, uint ou text).

Para criar um índice para o tipo de valor Numérico (sem sinal), envie a seguinte solicitação (com /uint na URL) para sua instância do 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" }
      }
   }
}'

O Elasticsearch responderá com uma confirmação de que o índice foi criado:

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

Solicitações semelhantes devem ser enviadas para cada tipo de valor adicional que você deseja armazenar no Elasticsearch.

Os mapeamentos para todos os tipos de valor estão disponíveis no repositório de código-fonte do Zabbix.

Por exemplo, para criar um índice para o tipo de valor Texto:

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 de valor JSON

Ao contrário de outros tipos de valor, os valores JSON requerem processamento adicional antes do armazenamento.

O índice abaixo utiliza campos separados para valores analisados e brutos, portanto, um ingest pipeline é necessário para analisar cada valor como JSON e armazená-lo no campo correto.

Para criar um índice para o tipo de valor JSON, envie a seguinte solicitação (com /json na URL) para sua instância do 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 }
    }
  }
}'

Em seguida, crie o 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 }}}"
         }
      }
   ]
}'

O Elasticsearch responderá com uma confirmação de que o ingest pipeline foi criado:

{"acknowledged": true}

Armazenando histórico em índices baseados em data

Em vez de gravar todos os dados históricos em um único índice (por exemplo, uint), o Elasticsearch pode distribuir esses dados em vários índices baseados em data (por exemplo, uint-2026-01-01, uint-2026-01-02). Isso facilita o gerenciamento do volume de dados e da retenção ao longo do tempo.

Para habilitar isso, você precisa:

  • Criar um template de índice para cada tipo de valor que deseja armazenar—isso informa ao Elasticsearch qual mapeamento aplicar quando ele criar automaticamente um novo índice baseado em data.
  • Criar um pipeline de ingestão para cada tipo de valor—ele processa cada valor recebido e o direciona para o índice baseado em data correto.
  • Configurar o parâmetro HistoryStorageDateIndex no arquivo de configuração do Zabbix server—isso permite armazenar valores em vários índices baseados em data.
Indexar templates

Para criar um template para o índice text, envie uma solicitação com os seguintes detalhes:

  • Use _template/text_template na URL da sua instância do Elasticsearch.
  • Use "text*" no campo "index_patterns" para corresponder ao nome do índice.
  • Use um mapeamento para o tipo de valor text (veja os mapeamentos no repositório fonte do 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 para o índice 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 de ingestão

Para criar um pipeline de ingestão para o índice text:

  • Use _ingest/pipeline/text-pipeline na URL da sua instância do Elasticsearch.
  • Inclua um processador date_index_name para direcionar cada valor para o índice baseado em data correto com base em seu 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"
         }
      }
   ]
}'

Para o índice json, o pipeline também precisa analisar o valor JSON antes de direcioná-lo para o índice correto:

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

Configurando o Zabbix server

No arquivo de configuração do Zabbix server (zabbix_server.conf), defina os seguintes parâmetros:

Por exemplo, para armazenar valores dos tipos Character, Log, Text e JSON no Elasticsearch (mantendo os valores Numeric em um banco de dados):

HistoryStorageURL=http://localhost:9200
HistoryStorageTypes=str,log,text,json

Se você estiver usando índices baseados em data para todos os valores armazenados no Elasticsearch, também defina o parâmetro HistoryStorageDateIndex:

HistoryStorageDateIndex=1

Após fazer as alterações, reinicie o Zabbix server:

systemctl restart zabbix-server

Configurando o frontend do Zabbix

No arquivo de configuração do frontend do Zabbix (zabbix.conf.php), declare $HISTORY como uma variável global e defina os valores de url e types para corresponder à configuração do server:

// Arquivo de configuração da interface web do Zabbix.
global $DB, $HISTORY;

$HISTORY['url']   = 'http://localhost:9200';
$HISTORY['types'] = ['str', 'log', 'text', 'json'];

Solução de problemas

As etapas a seguir podem ajudá-lo a solucionar problemas com sua configuração do Elasticsearch:

  1. Verifique se auto_create_index está habilitado:
curl -X GET \
 "http://localhost:9200/_cluster/settings?include_defaults=true&filter_path=**.auto_create_index"

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

Para habilitá-lo, envie a seguinte solicitação:

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. Verifique se os mapeamentos, templates e pipelines de ingestão estão corretos enviando solicitações GET para suas respectivas URLs:
curl -X GET http://localhost:9200/json
curl -X GET http://localhost:9200/_template/json*
curl -X GET http://localhost:9200/_ingest/pipeline/json*

Você pode comparar as respostas recebidas com as respostas esperadas na documentação da API do Elasticsearch.

  1. Verifique se algum shard está em estado de falha; reiniciar o Elasticsearch pode resolver isso.

  2. Verifique se sua configuração do Elasticsearch permite acesso a partir do Zabbix server e do Zabbix frontend.

  3. Use o parâmetro de configuração do Zabbix server LogSlowQueries para identificar consultas lentas.

  4. Verifique os logs do Elasticsearch em busca de erros.

  5. Se você precisar redefinir sua configuração do Elasticsearch e começar do zero, poderá excluir todos os índices, templates e pipelines de ingestão:

curl -X DELETE "http://localhost:9200/_all"
curl -X DELETE "http://localhost:9200/_template/*"
curl -X DELETE "http://localhost:9200/_ingest/pipeline/*"