Configuração do Elasticsearch
O Zabbix pode armazenar dados históricos no Elasticsearch como alternativa a um banco de dados relacional.
Este guia aborda a configuração das versões compatíveis do Elasticsearch.
O Zabbix server não é iniciado se a sua versão do Elasticsearch for anterior à versão mínima compatível.
Se for posterior à versão máxima compatível, o Zabbix server será iniciado somente se o parâmetro AllowUnsupportedDBVersions estiver definido como 1.
O Elasticsearch pode armazenar os seguintes tipos de valor:
| Tipo de valor do item | Tabela do banco de dados | Tipo do 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 compatível com o Zabbix |
| JSON | history_json | json |
Observações importantes
- O Elasticsearch requer libcurl. Consulte requisitos para obter detalhes.
- O housekeeper não exclui dados do Elasticsearch. Para controlar por quanto tempo os dados são mantidos, consulte Index Lifecycle Management.
- O Zabbix não calcula nem armazena tendências no Elasticsearch. Considere estender o período de armazenamento do histórico para preservar dados mais antigos.
- 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 é compatível com proxies do Zabbix.
- A partir do Elasticsearch 8.0, os recursos de segurança são habilitados por padrão: o Elasticsearch requer autenticação e usa HTTPS para sua API HTTP, com certificados assinados por uma CA gerada automaticamente.
Os exemplos nesta página usam
http://localhost:9200sem autenticação. Se a segurança estiver habilitada, use uma URLhttps://e passe o certificado da CA e as credenciais nas suas solicitações (por exemplo,sudo curl --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic https://localhost:9200; o arquivo de certificado da CA pode ser lido somente porroote pelo grupoelasticsearch). Para conectar o server e o frontend do Zabbix a esse cluster, consulte Conectando-se a um cluster seguro.
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.
Armazenamento do histórico em um único índice
Nesta abordagem, todos os dados de histórico de 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 solicitação a seguir (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 que você deseja armazenar no Elasticsearch, ou seja, para cada tipo listado na opção value_types da configuração do Zabbix server.
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 exigem processamento adicional antes do armazenamento. O índice do tipo de valor JSON armazena cada valor em um de dois campos:
value_parsed—objetos JSON, armazenados como um campo flattened, para que possam ser pesquisados por chave e valor;value_raw—todos os outros valores JSON (arrays, strings, números, booleanos enull), armazenados como uma string.
Um pipeline de ingestão analisa cada valor como JSON e o armazena no campo correto. Valores que não são JSON válido não são enviados ao Elasticsearch, pois os itens que os recebem se tornam incompatíveis.
Primeiro, crie o pipeline de ingestão:
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\"); }"
}
}
]
}'
O Elasticsearch responderá com uma confirmação de que o pipeline de ingestão foi criado:
{"acknowledged": true}
Em seguida, crie um índice para o tipo de valor JSON enviando a solicitação a seguir (com /json na URL) à sua instância do Elasticsearch.
A configuração default_pipeline faz com que o Elasticsearch processe cada valor gravado nesse índice com o pipeline de ingestão json.
Essa configuração é necessária porque o Zabbix server não especifica um pipeline de ingestão ao armazenar o histórico em um único índice.
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 }
}
}
}'
O Elasticsearch não pode indexar valores keyword e flattened com mais de 32766 bytes.
Com "ignore_above": 8191, strings com mais de 8191 caracteres não são indexadas (e não podem ser pesquisadas), mas continuam armazenadas e são retornadas integralmente ao Zabbix.
Sem esse limite, o Elasticsearch rejeita esses valores, e eles são perdidos.
Armazenando o histórico em índices baseados em data
Em vez de gravar todos os dados de histórico em um único índice (por exemplo, uint), o Elasticsearch pode distribuir esses dados entre 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 index template 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 ingest pipeline para cada tipo de valor — ele processa cada valor recebido e o encaminha para o índice baseado em data correto.
Templates de índice
Para criar um template para o índice text, envie uma solicitação com os seguintes detalhes:
- Use
_index_template/text_templatena URL da sua instância do Elasticsearch. - Use
"text-*"no campo"index_patterns"para corresponder aos nomes dos índices baseados em data. - No campo
"template", especifique as configurações do índice e um mapeamento para o tipo de valortext(consulte os mapeamentos no repositório de código-fonte do 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"
}
}
}
}
}'
Crie um template para cada tipo de valor que deseja armazenar, alterando o nome do template, o padrão do índice e o mapeamento conforme necessário.
Por exemplo, um template para o índice json (para obter detalhes sobre os campos value_parsed e value_raw, consulte Tipo de valor 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 }
}
}
}
}'
Use templates de índice compostos (_index_template), conforme mostrado acima.
Os templates de índice legados (_template) estão obsoletos, e o Elasticsearch rejeita templates legados cujos padrões de índice se sobrepõem aos templates integrados, por exemplo, um template legado com o padrão log* para o índice log.
Pipelines de ingestão
Para criar um pipeline de ingestão para o índice text:
- Use
_ingest/pipeline/text-pipelinena URL da sua instância do Elasticsearch. - Inclua um processador
date_index_namepara encaminhar cada valor ao índice correto baseado em data, de acordo com o 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"
}
}
]
}'
Crie um pipeline para cada tipo de valor que deseja armazenar, alterando o nome do pipeline, a descrição e o valor de "index_name_prefix" conforme necessário.
O nome do pipeline deve consistir no nome do índice e no sufixo -pipeline (por exemplo, uint-pipeline), pois o Zabbix server usa esse nome ao enviar valores para o Elasticsearch.
Para o índice json, o pipeline também precisa analisar o valor JSON antes de encaminhá-lo ao í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 o parâmetro HistoryProvider.
Por exemplo, para armazenar valores dos tipos Character, Log, Text e JSON no Elasticsearch (mantendo os valores Numeric em um banco de dados):
HistoryProvider=elasticsearch;value_types="str,log,text,json",url=http://localhost:9200
Se você estiver usando índices baseados em data, adicione date_index=1 ao parâmetro:
HistoryProvider=elasticsearch;value_types="str,log,text,json",url=http://localhost:9200,date_index=1
Se os recursos de segurança do Elasticsearch estiverem habilitados, especifique uma URL https:// com credenciais (consulte Conectando-se a um cluster protegido).
Após fazer as alterações, reinicie o Zabbix server:
systemctl restart zabbix-server
Configurando o frontend do Zabbix
No seu arquivo de configuração do frontend do Zabbix (zabbix.conf.php), defina a variável $HISTORY_PROVIDERS para corresponder à configuração do server:
$HISTORY_PROVIDERS[] = [
'types' => ['str','log','text','json'],
'provider' => 'elasticsearch',
'url' => 'http://localhost:9200'
];
Se os recursos de segurança do Elasticsearch estiverem habilitados, especifique a mesma URL https:// com as credenciais usadas na configuração do server (consulte Conectando-se a um cluster protegido).
Conectando-se a um cluster protegido
Se os recursos de segurança do Elasticsearch estiverem habilitados (padrão desde o Elasticsearch 8.0), o Zabbix server e o Zabbix frontend deverão confiar no certificado da CA da camada HTTP do Elasticsearch e autenticar-se com um nome de usuário e uma senha.
- Crie uma role e um usuário para o Zabbix.
A role a seguir permite que o Zabbix recupere a versão do Elasticsearch (o privilégio de cluster
monitor), crie índices, grave e leia dados de histórico e exclua dados de histórico quando o histórico do item for limpo:
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" ]
}'
- Adicione o certificado da CA do Elasticsearch aos certificados confiáveis do sistema operacional nos hosts do Zabbix server e do Zabbix frontend.
Se o Zabbix for executado em um host diferente do Elasticsearch, copie primeiro o certificado da CA (
/etc/elasticsearch/certs/http_ca.crt) para esse host. Por exemplo, no Debian/Ubuntu:
sudo cp /etc/elasticsearch/certs/http_ca.crt /usr/local/share/ca-certificates/elasticsearch-http-ca.crt
sudo update-ca-certificates
O nome do host na URL deve corresponder ao certificado HTTP do Elasticsearch.
O certificado gerado automaticamente é válido para localhost, para o nome do host e para os endereços IP do host do Elasticsearch.
- Especifique as credenciais na URL, tanto no arquivo de configuração do Zabbix server quanto no arquivo de configuração do frontend.
Se a senha contiver caracteres especiais, codifique-os usando percent-encoding (por exemplo,
@como%40,:como%3Ae,como%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'
];
- Reinicie o Zabbix server e o PHP-FPM (ou o web server, se o PHP for executado como um módulo do web server).
Solução de problemas
As etapas a seguir podem ajudar você a solucionar problemas na configuração do Elasticsearch:
- Verifique os logs do Elasticsearch ou do Zabbix server em busca de erros. Por exemplo, as mensagens a seguir no log do Zabbix server indicam problemas de conexão com um cluster protegido (consulte Conectando-se a um cluster protegido):
cannot query Elasticsearch: SSL certificate problem: self-signed certificate in certificate chain—o certificado CA do Elasticsearch não é confiável;cannot query Elasticsearch, HTTP error message: The requested URL returned error: 401—as credenciais estão ausentes ou incorretas;cannot query Elasticsearch, HTTP error message: The requested URL returned error: 403—o usuário não tem os privilégios necessários.
O frontend do Zabbix exibe erros semelhantes (por exemplo, Elasticsearch error: missing authentication credentials for REST request).
-
Para identificar consultas lentas, defina o parâmetro de configuração do Zabbix server
LogSlowQueries. Se a leitura do histórico do Elasticsearch demorar mais do que o tempo especificado, o Zabbix server registraráslow query: <N> sec, "<query>". Enquanto aguarda uma resposta do Elasticsearch, o Zabbix server também registrawaiting for Elasticsearch response <N>seccada vez que o tempo especificado passa ou a cada 10 segundos seLogSlowQueriesestiver definido como 0. -
Verifique se o Elasticsearch permite acesso a partir do Zabbix server e do frontend do Zabbix.
-
Verifique se
auto_create_indexestá habilitado (ele está habilitado por padrão):
curl -X GET \
"http://localhost:9200/_cluster/settings?include_defaults=true&filter_path=**.auto_create_index"
# {"persistent": {"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": {} }
- Verifique se os mapeamentos, templates e pipelines de ingestão estão corretos enviando solicitações
GETpara os respectivos URLs:
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*"
Você pode comparar as respostas recebidas com as respostas esperadas na documentação da API do Elasticsearch.
-
Verifique se algum shard está em estado de falha; reiniciar o Elasticsearch pode resolver o problema. Em um cluster de nó único, os índices com réplicas (
"number_of_replicas": 1) têm status amarelo, pois as réplicas não podem ser alocadas no mesmo nó que os shards primários; isso não afeta o Zabbix. Para evitar isso, defina"number_of_replicas"como0. -
Consulte o Elasticsearch para verificar se os dados coletados pelo Zabbix estão armazenados, por exemplo:
curl "http://localhost:9200/json*/_search" \
-H 'Content-Type: application/json' \
-d '{
"query": {
"term": {
"itemid": 42269
}
}
}'
- Se precisar redefinir a configuração do Elasticsearch e começar novamente, exclua os índices, os templates de índice e os pipelines de ingestão criados para o Zabbix (isso exclui todos os dados históricos armazenados no Elasticsearch).
Por padrão, o Elasticsearch não permite excluir índices usando expressões curinga; portanto, para excluir índices baseados em data, altere temporariamente a configuração
action.destructive_requires_name. Os templates de índice e os pipelines de ingestão devem ser excluídos um por um; as solicitações para templates ou pipelines inexistentes retornam um erro, que pode ser ignorado.
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"