索引管理:给HSM日志安个家
说实话,很多人在Kibana里折腾可视化,第一步就卡在索引管理上。数据倒进去了,查不到,或者查得慢,十有八九是索引没管好。HSM审计日志这个场景尤其典型——数据量大、写入频率高、还得长期保存。我今天就把索引管理的四个核心动作掰开讲清楚。
创建索引:不只是PUT一下
创建索引最简单的方式,确实就是发个PUT请求。但我建议你养成一个习惯:创建时就把配置写清楚。
PUT /hsm-audit-logs-2025-01
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}
这里面有两个关键参数:shards和replicas。我遇到过有人把分片数设成20,觉得越大越快。其实分片越多,管理开销越大。HSM日志这种场景,每天一个索引,3个主分片完全够用。副本数设1,保证高可用就行。
索引映射:字段类型决定一切
映射(mapping)定义了字段的类型和属性。映射设错了,查询结果就全歪了。
我曾经踩过一个坑:审计日志里有个event_time字段,没指定类型,Elasticsearch自动识别成了text。结果Kibana时间筛选器死活不认,查个时间段的数据都得手动写范围查询。后来我强制指定为date类型,问题秒解。
PUT /hsm-audit-logs-2025-01/_mapping
{
"properties": {
"event_time": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
},
"user_id": {
"type": "keyword"
},
"operation": {
"type": "keyword"
},
"key_id": {
"type": "keyword"
},
"status": {
"type": "keyword"
},
"message": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
注意看上面的映射:user_id、operation这些字段我全用keyword。为什么?因为这些字段用于聚合查询、分组统计,text会先分词再聚合,结果完全不对。说白了,精确匹配用keyword,全文搜索用text。
| 字段 | 推荐类型 | 原因 |
|---|---|---|
| event_time | date | 时间序列分析、范围筛选 |
| user_id, operation, key_id | keyword | 精确匹配、聚合统计 |
| message, details | text + keyword子字段 | 既支持全文搜索,也支持精确聚合 |
| ip_address, hostname | ip, keyword | IP范围查询用ip,分组统计用keyword |
索引生命周期管理:让数据自己动起来
HSM审计日志不能一直堆在一个索引里。时间一长,查询慢、存储贵。索引生命周期管理(ILM)就是用来解决这个问题的。
ILM把数据分为四个阶段:
- Hot阶段:频繁写入和查询的数据。用SSD盘,分片分配优化写入性能。
- Warm阶段:不再写入,偶尔查询。可以降低副本数,挪到HDD。
- Cold阶段:很少查询。可以合并分片,甚至只保留一份数据。
- Delete阶段:超过保存期限,直接删掉。
PUT _ilm/policy/hsm_audit_log_policy
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_size": "50GB",
"max_age": "7d"
},
"set_priority": {
"priority": 100
}
}
},
"warm": {
"min_age": "30d",
"actions": {
"shrink": {
"number_of_shards": 1
},
"set_priority": {
"priority": 50
},
"allocate": {
"require": {
"data_type": "warm"
}
}
}
},
"cold": {
"min_age": "90d",
"actions": {
"freeze": {},
"set_priority": {
"priority": 0
},
"allocate": {
"require": {
"data_type": "cold"
}
}
}
},
"delete": {
"min_age": "365d",
"actions": {
"delete": {}
}
}
}
}
}
这里有个关键点:rollover。它会在索引达到50GB或7天时自动创建一个新索引。我有个项目就是没配这个,一个索引写了200GB,查询直接超时。
你想想看,有了ILM,你只需要操心业务逻辑。数据什么时候挪、什么时候删,交给策略去执行。这才是工程化的做法。
数据流:日志写入的标准化姿势
数据流(Data Stream)是ELK 7.x之后推荐的方式。它的背后是一组按时间滚动的隐藏索引,你用数据流名就能读取到所有数据。
为什么要用数据流?
- 自动滚动:不需要手动创建索引,达到容量或时间阈值自动新建。
- 统一别名:对用户透明,写入和查询都指向同一个名字。
- 和ILM无缝集成:一个策略挂上去,全自动管理。
PUT _index_template/hsm_audit_log_template
{
"index_patterns": ["hsm-audit-logs-*"],
"data_stream": {},
"template": {
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"index.lifecycle.name": "hsm_audit_log_policy",
"index.lifecycle.rollover_alias": "hsm-audit-logs"
},
"mappings": {
"properties": {
"@timestamp": {
"type": "date"
},
"event_time": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
},
"user_id": {
"type": "keyword"
},
"operation": {
"type": "keyword"
},
"key_id": {
"type": "keyword"
},
"status": {
"type": "keyword"
},
"message": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
},
"priority": 200
}
看到没?我把映射、ILM策略、滚动别名全写在一个模板里。以后写入数据,只需要往 hsm-audit-logs 这个数据流名写,它自动创建索引、自动滚动、自动迁移。
嗯,这里要注意:索引模板中的priority越高,匹配优先级越高。我建议你给HSM日志专门的模板设一个高优先级,避免被其他通用模板覆盖掉。
@timestamp字段,否则会报错。我以前调试时没注意这个,日志全写丢了,排查了好久才发现是少了这个字段。
一张图看懂索引管理全流程
我把上面四个步骤串成了一张流程图。你看看数据从写入到删除,是怎么流转的。
这张图的核心逻辑就是:一次定义,全自动运转。数据源头进来,模板负责定义结构,ILM负责管理生命周期,数据流负责对外统一接口。你只需要关心业务,不用再操心索引翻来覆去的手动操作。
以上就是索引管理的核心内容。从创建索引到定义映射,从ILM策略到数据流,每一步都直接影响Kibana的查询性能和存储成本。我个人建议,新项目直接上数据流+ILM,老项目逐步迁移。这是最稳妥的路径。