4. Elasticsearch 索引生命周期管理:ILM 策略设计
在 Golden Signals 日志检索工程中,日志数据具有时间序列强、冷热访问差异大、保留周期明确三大特征。Elasticsearch 索引生命周期管理(ILM)正是应对这些特征的核心工具。通过 ILM,我们可以按时间与信号类型自动分索引,在查询性能与存储成本之间取得最优平衡。
核心目标:将 Golden Signals 日志(延迟、流量、错误、饱和度)按信号类型拆分至独立索引模板,再按时间窗口滚动索引,最终实现热节点高性能写入、温节点低成本存储、冷节点归档或删除。
4.1 ILM 四阶段模型与 Golden Signals 映射
ILM 标准阶段包括 Hot → Warm → Cold → Delete。针对 Golden Signals 日志,每个阶段的存储介质、副本数、分段合并策略均不同:
| ILM 阶段 | 存储介质 | 副本数 | 分段合并 | 适用信号类型 | 典型保留时长 |
|---|---|---|---|---|---|
| Hot | SSD / 高性能云盘 | 1 | 不合并,保持写入性能 | 所有信号(实时写入) | 最近 6 小时 |
| Warm | HDD / 标准云盘 | 1 | forcemerge 到 1 段 | 延迟、错误、饱和度 | 6 小时 ~ 7 天 |
| Cold | 对象存储 / 归档盘 | 0 | 已合并,只读 | 流量、饱和度(低频查询) | 7 天 ~ 30 天 |
| Delete | — | — | — | 所有信号 | 超过 30 天 |
设计要点:错误信号(Error)在 Warm 阶段保留完整原始日志用于根因分析;流量信号(Traffic)在 Cold 阶段可降采样为聚合指标,原始明细直接进入 Delete 阶段以节省成本。
4.2 按信号类型拆分索引模板
每个 Golden Signals 维度对应一个独立的索引模板,确保字段映射、分片数、滚动策略互不干扰:
# 延迟信号索引模板
PUT _index_template/gs-latency-template
{
"index_patterns": ["gs-latency-*"],
"template": {
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"index.lifecycle.name": "gs-latency-policy",
"index.lifecycle.rollover_alias": "gs-latency-write"
},
"mappings": {
"properties": {
"@timestamp": { "type": "date" },
"service": { "type": "keyword" },
"latency_ms": { "type": "long" },
"percentile_99": { "type": "float" },
"host": { "type": "keyword" }
}
}
}
}
# 错误信号索引模板
PUT _index_template/gs-error-template
{
"index_patterns": ["gs-error-*"],
"template": {
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1,
"index.lifecycle.name": "gs-error-policy",
"index.lifecycle.rollover_alias": "gs-error-write"
},
"mappings": {
"properties": {
"@timestamp": { "type": "date" },
"service": { "type": "keyword" },
"error_code": { "type": "keyword" },
"stack_trace": { "type": "text", "index": false },
"severity": { "type": "keyword" }
}
}
}
}
避坑提示:不要将所有信号类型放入同一个索引模板。混合写入会导致分片大小不均、查询过滤效率下降。按信号类型拆分后,每个索引的文档结构高度一致,压缩比和查询性能均可提升 30% 以上。
4.3 ILM 策略完整配置示例
以下策略针对延迟信号设计,展示 Hot → Warm → Cold → Delete 的完整参数:
PUT _ilm/policy/gs-latency-policy
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_size": "50GB",
"max_age": "6h"
},
"set_priority": {
"priority": 100
}
}
},
"warm": {
"min_age": "6h",
"actions": {
"forcemerge": {
"max_num_segments": 1
},
"shrink": {
"number_of_shards": 1
},
"allocate": {
"number_of_replicas": 1,
"require": {
"data_type": "warm"
}
},
"set_priority": {
"priority": 50
}
}
},
"cold": {
"min_age": "7d",
"actions": {
"allocate": {
"number_of_replicas": 0,
"require": {
"data_type": "cold"
}
},
"set_priority": {
"priority": 0
}
}
},
"delete": {
"min_age": "30d",
"actions": {
"delete": {}
}
}
}
}
}
4.4 按时间与信号类型分索引的架构流程
下图展示从日志采集到 ILM 自动流转的完整链路:
4.5 查询与存储成本优化策略
通过 ILM 分索引后,还需配合以下手段进一步优化:
- 按时间范围路由查询:在 Kibana 或 API 查询中强制指定
@timestamp范围,ES 自动跳过不相关的索引,减少分片扫描。 - 使用索引别名分离读写:写别名指向 Hot 索引,读别名指向 Hot+Warm+Cold 所有索引,避免业务侧感知索引名变化。
- Warm 阶段 forcemerge 到 1 段:减少分段数量可降低内存开销,同时提升只读查询性能。
- Cold 阶段副本数设为 0:归档数据不再需要高可用,节省 50% 存储成本。
- 信号类型差异化保留周期:
| 信号类型 | Hot 保留 | Warm 保留 | Cold 保留 | 总保留 | 优化说明 |
|---|---|---|---|---|---|
| 延迟 | 6h | 7d | 23d | 30d | 保留原始百分位数据用于 SLA 审计 |
| 流量 | 6h | 1d | 6d | 7d | 仅保留聚合指标,原始明细提前删除 |
| 错误 | 6h | 7d | 23d | 30d | 保留完整 stack_trace 用于根因分析 |
| 饱和度 | 6h | 3d | 4d | 7d | 高频指标降采样后存储 |
最佳实践:在 ILM 策略中为每个阶段设置
index.routing.allocation.require.data_type,配合节点属性标签(如 node.attr.data_type: hot/warm/cold),确保数据物理隔离。同时开启 indices.lifecycle.poll_interval(默认 10 分钟)为 1 分钟,加速索引滚动。
4.6 监控 ILM 执行状态
部署完成后,通过以下 API 和指标持续观察 ILM 健康度:
# 查看所有索引的 ILM 阶段
GET _ilm/status
# 查看具体索引的 ILM 执行详情
GET gs-latency-2025-04-01-000001/_ilm/explain
# 关键监控指标(Grafana / Kibana 看板)
- ilm.time-since-index-rollover # 距离上次滚动的时间
- ilm.number-of-errors # ILM 执行错误数
- indices.lifecycle.completed # 已完成生命周期管理的索引数
- node.data_type # 各存储层节点的磁盘使用率
常见问题:如果 ILM 策略更新后未生效,检查索引是否已脱离策略管理(如手动修改过 settings)。使用
POST /_ilm/move/<index>?phase=hot 可手动触发阶段迁移,用于测试或故障恢复。