Elasticsearch配置ILM策略自动清理索引数据指南
约 1030 字大约 3 分钟
2026-02-24
适用场景:通过 Logstash 接收应用日志,写入 Elasticsearch,并自动删除 60 天前的日志 Elasticsearch 版本:8.x(如 8.19.0) 核心机制:Index Lifecycle Management (ILM) + 索引模板(Index Template) + 按日志日期自动解析
✅ 一、整体架构说明
- 日志流向:应用 → Logstash(TCP input) → Elasticsearch
- 索引命名规则:
elk-logs-<platform>-YYYY.MM.dd(例如elk-logs-mall-2026.02.24) - 生命周期策略:日志所属日期 + 60 天后自动删除
- 关键特性:
- 使用
parse_origination_date: true,按索引名中的日期计算生命周期(非写入时间) - 避免使用
logs-前缀,防止触发 Data Stream 限制 - 通过索引模板统一管理 mapping 和 ILM 策略
- 使用
✅ 二、完整操作步骤
步骤 1:创建 ILM 策略(保留 60 天后删除)
PUT _ilm/policy/delete_logs_after_60d
{
"policy": {
"phases": {
"delete": {
"min_age": "60d",
"actions": {
"delete": {}
}
}
}
}
}✅ 说明:
min_age: "60d"表示从日志日期起 60 天后进入 delete 阶段。
步骤 2:创建索引模板(绑定 ILM + 定义字段)
PUT _index_template/elk_logs_ilm_template
{
"index_patterns": ["elk-logs-*-*"],
"template": {
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1,
"index.lifecycle.name": "delete_logs_after_60d",
"index.lifecycle.parse_origination_date": true
},
"mappings": {
"dynamic": true,
"properties": {
"@timestamp": { "type": "date" },
"@version": { "type": "keyword" },
"platform": { "type": "keyword" },
"app_name": { "type": "keyword" },
"logger_name": { "type": "keyword" },
"thread_name": { "type": "keyword" },
"level": { "type": "keyword" },
"tags": { "type": "keyword" },
"message": {
"type": "text",
"fields": { "keyword": { "type": "keyword", "ignore_above": 256 } }
},
"level_value": { "type": "long" }
}
}
},
"priority": 300
}🔑 关键点:
index_patterns: 使用elk-logs-*-*匹配elk-logs-mall-2026.02.24- 避免
logs-前缀,防止 ES 误判为 Data Streamparse_origination_date: true:自动从索引名末尾提取日期(支持YYYY.MM.DD)- 字符串字段设为
keyword(除message外),提升性能
步骤 3:配置 Logstash output(生成合规索引名)
output {
stdout { codec => rubydebug }
elasticsearch {
hosts => ["http://elasticsearch:9200"]
index => "elk-logs-%{[platform]}-%{+YYYY.MM.dd}"
}
}✅ 示例输出索引名:
elk-logs-mall-2026.02.24⚠️ 必须使用-分隔 +YYYY.MM.dd格式,这是 ES 8.x 的强制要求
步骤 4:增强 Logstash filter(防错处理)
filter {
# 确保 platform 字段存在
if ![platform] {
mutate { add_field => { "platform" => "unknown" } }
}
# 清理非法字符(只保留字母、数字、下划线、连字符)
mutate {
gsub => [ "platform", "[^a-zA-Z0-9_-]", "_" ]
lowercase => [ "platform" ]
}
}防止生成非法索引名(如含空格、斜杠等)
✅ 三、验证是否生效
1. 发送测试日志
确保 JSON 中包含 platform 字段:
{"platform":"mall","message":"test ILM"}2. 检查索引是否创建成功
GET /elk-logs-mall-2026.02.24/_search3. 验证 ILM 管理状态
GET /elk-logs-mall-2026.02.24/_ilm/explain✅ 预期返回关键字段:
{
"indices": {
"elk-logs-mall-2026.02.24": {
"managed": true,
"policy": "delete_logs_after_60d",
"lifecycle_date_millis": 1771891200000, // = 2026-02-24 00:00:00 UTC
"age": "Xh", // 距离日志日期的时间
"phase": "new"
}
}
}📌
lifecycle_date_millis必须等于日志所属日期(证明parse_origination_date生效)
✅ 四、常见问题与解决
❌ 问题1:index name does not match pattern '^.*-(\\d{4}.\\d{2}.\\d{2})'
- 原因:索引名格式不合规(如用
_或YYYYMMdd) - 解决:Logstash 中使用
%{+YYYY.MM.dd},索引名形如xxx-2026.02.24
❌ 问题2:only write ops with op_type of create are allowed in data streams
- 原因:索引名以
logs-、metrics-开头,触发 Data Stream 机制 - 解决:改用
elk-logs-、app-等前缀
❌ 问题3:managed: false
- 原因:索引创建时未匹配模板(模板 pattern 错误或优先级低)
- 解决:
- 模板
index_patterns必须能匹配新索引 - 设置高
priority(如 300) - 模板只对新建索引生效
- 模板
⚠️ 问题4:历史索引未自动删除
原因:ILM 不 retroactively 生效
解决(可选):
PUT /old-index-name/_settings { "index.lifecycle.name": "delete_logs_after_60d" }
✅ 五、维护命令速查
| 操作 | 命令 |
|---|---|
| 查看 ILM 策略 | GET _ilm/policy/delete_logs_after_60d |
| 查看索引模板 | GET _index_template/elk_logs_ilm_template |
| 删除模板 | DELETE _index_template/elk_logs_ilm_template |
| 手动触发 ILM 检查 | POST _ilm/run |
| 查看 ILM 全局状态 | GET _ilm/status |
| 为现有索引绑定策略 | PUT /index_name/_settings { "index.lifecycle.name": "xxx" } |
✅ 六、注意事项
- 索引模板只影响新建索引,已有索引需手动处理
- 不要使用
?或[0-9]在index_patterns中(ES 8.x 只支持*) - 日期格式必须为
YYYY.MM.dd(带点分隔),这是 ES 8.x 的硬性要求 - 避免
logs-前缀,除非你明确要使用 Data Stream - ILM 默认每 10 分钟检查一次,删除不会“准时”发生,但误差在可接受范围
📌 最终效果: 每天生成的索引
elk-logs-xxx-YYYY.MM.dd将在 日志所属日期的 60 天后自动被 Elasticsearch 删除,无需人工干预。
