5月27日 23:49

Elasticsearch 的索引生命周期管理(ILM)如何配置?

Elasticsearch ILM 是什么?

ILM(Index Lifecycle Management)是 Elasticsearch 提供的索引生命周期自动化管理机制,它根据索引的年龄、大小等条件,自动将索引在不同存储层级之间迁移,最终删除过期数据,从而降低存储成本和运维负担。

没有 ILM 时,常见的问题是:索引无限增长导致分片过大(恢复慢)、热节点磁盘告警、过期数据占满存储。ILM 通过定义策略(policy),让索引自动经历 hot → warm → cold → frozen → delete 五个阶段,每阶段执行特定操作(rollover、shrink、force_merge、delete 等)。

ILM 的五个阶段

阶段触发条件典型操作节点角色
hot索引活跃写入rollover(按大小/时间滚动)data_hot
warm不再写入,仍常查询shrink(缩减分片)、force_merge(合并段)data_warm
cold偶尔查询searchable_snapshot(可搜索快照)data_cold
frozen极少查询freeze(7.x)/ searchable_snapshot(8.x)data_frozen
delete超过保留期delete(永久删除)

注意:frozen 阶段从 7.12 版本正式引入,8.x 中推荐用 searchable snapshot 替代 freeze 操作。

如何创建 ILM 策略?

通过 _ilm/policy API 创建策略,指定每个阶段的 min_ageactions

json
PUT _ilm/policy/log_retention_policy { "policy": { "phases": { "hot": { "min_age": "0ms", "actions": { "rollover": { "max_size": "50gb", "max_age": "7d", "max_docs": 100000000 }, "set_priority": { "priority": 100 } } }, "warm": { "min_age": "30d", "actions": { "shrink": { "number_of_shards": 1 }, "force_merge": { "max_num_segments": 1 }, "set_priority": { "priority": 50 } } }, "cold": { "min_age": "90d", "actions": { "searchable_snapshot": { "snapshot_repository": "my_backup" }, "set_priority": { "priority": 0 } } }, "delete": { "min_age": "180d", "actions": { "delete": {} } } } } }

关键参数说明:

  • min_age:索引进入该阶段需等待的最短时间,从索引进入上一阶段算起(不是从索引创建时间算)
  • rollover:在 hot 阶段滚动创建新索引,三个条件满足任一即触发
  • shrink:在 warm 阶段将分片数缩减,降低资源占用
  • force_merge:合并段文件,减少文件句柄和查询开销
  • searchable_snapshot:将索引转为快照挂载,大幅降低存储成本

如何将 ILM 策略绑定到索引?

有两种方式:索引模板(Index Template)和 Data Stream。

方式一:索引模板绑定

json
PUT _index_template/log_template { "index_patterns": ["app-log-*"], "priority": 500, "template": { "settings": { "index.lifecycle.name": "log_retention_policy", "index.lifecycle.rollover_alias": "app-log", "number_of_shards": 3, "number_of_replicas": 1 } } }

创建初始索引时,需以 000001 结尾才能触发 rollover:

json
PUT app-log-000001 { "aliases": { "app-log": { "is_write_index": true } } }

方式二:Data Stream 绑定(推荐 7.9+)

Data Stream 天然支持 ILM,创建时直接关联策略:

json
PUT _data_stream/app-logs { "index_template": "log_template" }

写入 Data Stream 时,自动在背后创建 backing index,ILM 自动管理这些 backing index 的生命周期。Data Stream 的优势在于写入时无需关心底层索引名称,滚动完全自动化。

如何监控和排查 ILM?

查看所有索引的 ILM 状态:

json
GET _ilm/explain?pretty

查看特定索引的 ILM 阶段和下一步操作:

json
GET _ilm/explain/my-index-000001?pretty

常见排查思路:

  • ILM 不生效:检查 indices.lifecycle.poll_interval(默认 10 分钟),策略变更后需等待轮询周期
  • 索引卡在某个阶段:用 _ilm/explain 查看 step_info 中的错误原因,常见原因是目标节点角色未配置
  • rollover 未触发:确认索引名以数字结尾(如 000001)且设置了 is_write_index: true
  • shrink 失败:目标分片数必须是原分片数的因子,且索引必须先设为只读

手动推进 ILM 步骤(排查用):

json
POST _ilm/retry/my-index-000001

ILM 配置有哪些常见坑?

  1. min_age 的理解偏差:min_age 是从索引进入上一阶段开始计时,不是索引创建时间。比如 warm 阶段 min_age: 30d 指的是进入 hot 阶段 30 天后(若 hot 阶段无 min_age 限制),而非索引创建 30 天后

  2. allocate 语法变更:7.x 中用 allocate.include/require 分配节点,8.x 已废弃,改用节点角色自动路由(配置 data_hot/data_warm/data_cold 角色,ILM 自动迁移)

  3. 节点角色互斥data_hot/data_warm/data_cold 不能与旧版 data 角色同时配置,需搭配 data_content 使用

  4. shrink 前必须只读:执行 shrink 前索引必须设为 index.blocks.write: true,否则会失败

  5. Data Stream 不可删除单条数据:Data Stream 是追加模型,不支持按文档 ID 删除,只能通过 ILM 删除整个 backing index

追问:frozen 阶段和 cold 阶段有什么区别?

cold 阶段的数据仍以完整分片存储在节点磁盘上,查询性能较好但存储成本高。frozen 阶段使用 searchable snapshot,数据存储在快照仓库中,查询时按需从快照加载缓存,存储成本极低但查询延迟较高。简单说:cold 是"低频但随时可查",frozen 是"几乎不查但保留可搜索"。

标签:ElasticSearch