必须先让集群具备冷热节点属性,否则ILM的warm、cold阶段不会触发;需启用node.attr.box_type(阿里云)或node.attr.data(自建),验证命令GET _cat/nodeattrs?v&h=host,attr,value输出中须同时含hot和warm行。

必须先让集群具备冷热节点属性,否则 ILM 的 warm、cold 阶段根本不会触发流转 —— 这是 90% 配置失败的根源。
确认集群已启用 node.attr.box_type(阿里云)或 node.attr.data(自建)
阿里云 Elasticsearch 实例开启「冷数据节点」后,节点会自动带上 -Enode.attr.box_type=warm 启动参数;自建集群则需在 elasticsearch.yml 中显式配置:
-
node.attr.box_type: hot(热节点) -
node.attr.box_type: warm(温/冷节点,注意:ES 原生不叫cold,warm 就是冷数据承载层)
验证命令必须跑通:
GET _cat/nodeattrs?v&h=host,attr,value
输出中必须同时出现 box_type 值为 hot 和 warm 的行。如果只看到 hot,说明冷热分离未生效,后续所有 ILM 策略中的 warm 阶段都会卡住不动。
ILM 策略中 warm/cold 阶段的关键动作必须显式声明
仅定义 warm 阶段不等于数据就会自动迁走 —— ES 要求你明确告诉它「怎么迁」和「迁到哪」:
- 必须设置
allocation动作,指定include或require属性,例如:"require": { "box_type": "warm" } - 必须设置
shrink动作(可选但强烈推荐),否则 warm 阶段分片仍占用热节点内存资源 - 若想进一步降本,cold 阶段可加
"number_of_replicas": 0,但前提是业务能接受单副本风险
错误写法(策略存在但不生效):
"phase": {
"warm": {
"min_age": "7d",
"actions": {}
}
}
正确写法(带分配与收缩):
"phase": {
"warm": {
"min_age": "7d",
"actions": {
"allocate": {
"require": { "box_type": "warm" }
},
"shrink": { "number_of_shards": 1 }
}
}
}
索引模板必须绑定 ILM 策略且启用 rollover
ILM 不会主动找索引,而是靠索引创建时自动关联策略。这意味着:
- 模板中必须包含
"index.lifecycle.name"字段,值为已存在的策略名 - 模板必须用于 time-based 索引(如
heartbeat-*),且索引名要带日期后缀(如heartbeat-8.12.0-2026.09.28) - 必须启用
"index.lifecycle.rollover_alias"别名,否则无法滚动,hot 阶段永远卡在第一个索引
常见陷阱:
- 直接对已有索引 PUT
_ilm/policy并不生效,必须通过模板或别名绑定 - Heartbeat 默认生成的模板已含 ILM 配置,但如果你手动删过模板,需重新启动 Heartbeat 或手动 PUT 模板
- 使用
PUT /_index_template/heartbeat(不是旧版PUT /_template/...)
为什么 warm 阶段一直不执行?检查这三点
策略已创建、模板已绑定、节点属性也对,但 GET /_ilm/explain?human 显示 warm 阶段始终 action_status: "not_attempted":
- 索引是否处于
read_only状态?warm 阶段要求索引先被rollover,而 rollover 前 ES 会自动设为read_only;若你手动解除了该状态,ILM 将跳过 warm - 是否有未完成的
shrink或forcemerge?这些动作失败会导致阶段阻塞,查_cluster/allocation/explain可定位分片卡点 - 策略中
min_age是从索引创建时间算起,不是文档时间;若索引是手动创建而非 rollover 产生,时间可能远小于预期
真正容易被忽略的是:warm 阶段的执行依赖于协调节点定期扫描(默认每 10 分钟一次),且整个过程是异步的 —— 即便所有配置正确,也要等至少 10 分钟才可能看到分片迁移日志。











