8 Elasticsearch 设置
Zabbix 可以将历史数据存储在 Elasticsearch 中,作为关系型数据库的替代方案。
当前对 Elasticsearch 的支持仍处于实验阶段。
本指南介绍 Elasticsearch 7.X 的设置。 如果您使用的是其他版本,某些功能可能无法按预期工作。
该设置包括为每种值类型创建 Elasticsearch 存储位置、设置预处理(如有需要),以及将 Zabbix 连接到您的 Elasticsearch 实例。
Elasticsearch 可以存储以下值类型:
| 监控项值类型 | 数据库表 | Elasticsearch 类型 |
|---|---|---|
| 数值(无符号) | history_uint | uint |
| 数值(浮点) | history | dbl |
| 字符 | history_str | str |
| 日志 | history_log | log |
| 文本 | history_text | text |
| 二进制 | history_bin | Zabbix 不支持 |
| JSON | history_json | json |
重要说明
- Elasticsearch 需要 libcurl。详情请参见要求。
- housekeeper 不会从 Elasticsearch 中删除数据。
- 如果所有历史数据都存储在 Elasticsearch 中,则不会在数据库中计算或存储趋势数据。请考虑延长历史数据存储期。
- 使用 Elasticsearch 时,从数据库中检索值的范围查询会受到数据存储期时间戳的限制。
- Zabbix proxy 不支持 Elasticsearch;请改用 SQLite。
如果尚未安装 Elasticsearch,请先参阅官方安装指南后再继续。
配置 Elasticsearch
要将历史数据存储到 Elasticsearch 中,您需要:
- 为要存储的每种值类型创建一个 索引——这是 Elasticsearch 存储数据的位置,类似于关系型数据库中的表。
- 为每个索引定义一个 映射——它定义了数据的结构,类似于表结构。
- 设置一个 ingest pipeline,以便在存储前处理值(JSON 值和基于日期的索引必须使用)。
Elasticsearch 可以将数据存储在每种值类型对应的单个索引中,也可以分布在多个基于日期的索引中。
下面将介绍这两种方法。
将历史数据存储在单个索引中
在这种方法中,给定值类型的所有历史数据都会写入单个索引(例如 uint 或 text)。
要为 Numeric (unsigned) 值类型创建索引,请向您的 Elasticsearch 实例发送以下请求(URL 中使用 /uint):
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 将返回确认信息,表明索引已创建:
{"acknowledged": true, "shards_acknowledged": true, "index": "uint"}
对于您希望存储在 Elasticsearch 中的每种其他值类型,都必须发送类似的请求。
所有值类型的映射均可在 Zabbix 源代码仓库 中找到。
例如,要为 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"
}
}
}
}'
JSON 值类型
与其他值类型不同,JSON 值在存储前需要额外处理。
下面的索引对已解析值和原始值使用了单独的字段,因此需要使用 ingest pipeline 将每个值解析为 JSON 并存储到正确的字段中。
要为 JSON 值类型创建索引,请向您的 Elasticsearch 实例发送以下请求(URL 中包含 /json)。
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 }
}
}
}'
然后,创建 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 将返回一条确认信息,表明 ingest pipeline 已创建:
{"acknowledged": true}
在基于日期的索引中存储历史数据
Elasticsearch 不必将所有历史数据写入单个索引中(例如 uint),而是可以将这些数据分布到多个基于日期的索引中(例如 uint-2026-01-01、uint-2026-01-02)。
这样可以更轻松地管理随时间增长的数据量和数据保留。
要启用此功能,您需要:
- 为要存储的每种值类型创建一个索引模板——这会告知 Elasticsearch 在其自动创建新的基于日期的索引时应应用什么映射。
- 为每种值类型创建一个摄取管道——它会处理每个传入的值,并将其路由到正确的基于日期的索引。
- 在 Zabbix 服务器配置文件中配置
HistoryStorageDateIndex参数——这将启用在多个基于日期的索引中存储值。
索引模板
要为 text 索引创建模板,请发送包含以下详细信息的请求:
- 在 Elasticsearch 实例的 URL 中使用
_template/text_template。 - 在
"index_patterns"字段中使用"text*"以匹配索引名称。 - 为
text值类型使用映射(请参见 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"
}
}
}
}'
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 }
}
}
}'
Ingest pipeline
要为 text 索引创建 ingest pipeline:
- 在 Elasticsearch 实例的 URL 中使用
_ingest/pipeline/text-pipeline。 - 包含一个
date_index_name处理器,根据时间戳将每个值路由到正确的基于日期的索引。
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"
}
}
]
}'
对于 json 索引,该 pipeline 还需要先解析 JSON 值,然后再将其路由到正确的索引:
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"
}
}
]
}'
配置 Zabbix 服务器
在您的 Zabbix 服务器配置文件(zabbix_server.conf)中,设置以下参数:
HistoryStorageURL- 您的 Elasticsearch 实例的 URL。HistoryStorageTypes- 以逗号分隔的值类型列表,这些值类型将存储在 Elasticsearch 中。
例如,要将 Character、Log、Text 和 JSON 类型的值存储到 Elasticsearch 中(同时将 Numeric 值保留在数据库中):
HistoryStorageURL=http://localhost:9200
HistoryStorageTypes=str,log,text,json
如果您对存储在 Elasticsearch 中的 所有 值都使用基于日期的索引,还需设置 HistoryStorageDateIndex 参数:
HistoryStorageDateIndex=1
完成更改后,重启 Zabbix 服务器:
systemctl restart zabbix-server
配置 Zabbix 前端
在您的 Zabbix 前端配置文件(zabbix.conf.php)中,将 $HISTORY 声明为全局变量,并设置其 url 和 types 值,使其与服务器配置匹配:
// Zabbix GUI configuration file.
global $DB, $HISTORY;
$HISTORY['url'] = 'http://localhost:9200';
$HISTORY['types'] = ['str', 'log', 'text', 'json'];
故障排查
以下步骤可帮助您排查 Elasticsearch 设置中的问题:
- 验证是否已启用
auto_create_index:
curl -X GET \
"http://localhost:9200/_cluster/settings?include_defaults=true&filter_path=**.auto_create_index"
# {"defaults": {"action": {"auto_create_index": "false"} } }
要启用它,请发送以下请求:
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": {} }
- 通过向各自的 URL 发送
GET请求,验证映射、模板和摄取管道是否正确:
curl -X GET http://localhost:9200/json
curl -X GET http://localhost:9200/_template/json*
curl -X GET http://localhost:9200/_ingest/pipeline/json*
您可以将收到的响应与 Elasticsearch API 文档中的预期响应进行比较。
-
检查是否有任何 分片处于失败状态;重启 Elasticsearch 可能会解决此问题。
-
验证您的 Elasticsearch 配置是否允许来自 Zabbix 服务器和 Zabbix 前端的访问。
-
使用
LogSlowQueriesZabbix 服务器配置参数来识别慢查询。 -
检查 Elasticsearch 日志中是否有错误。
-
如果您需要重置 Elasticsearch 设置并重新开始,可以删除所有索引、模板和摄取管道:
curl -X DELETE "http://localhost:9200/_all"
curl -X DELETE "http://localhost:9200/_template/*"
curl -X DELETE "http://localhost:9200/_ingest/pipeline/*"