索引生命周期

索引生命周期管理 #

索引生命周期管理(Index Lifecycle Management, ILM)为您提供了一种集成化、自动化的方式来高效管理时序数据。 通过配置 ILM 策略,您可以根据性能、可用性与数据保留需求,自动执行索引的滚动、归档和清理等操作。

从 1.15.2 版本开始,index-management 已经成为 modules 的一部分,不需要单独安装插件。

典型应用场景 #

  • 自动滚动生成新索引:当现有索引达到指定大小或文档数量时,自动创建新索引。
  • 周期性轮换索引:按天、周或月创建新索引,并将历史索引归档。
  • 强制数据保留策略:自动删除过期索引,确保合规与存储成本可控。
  • 分层存储:将热数据分配到高性能节点,冷数据迁移到廉价存储节点。

策略管理 API #

创建策略 #

创建一个新的生命周期策略。

请求 #

PUT _ilm/policy/{policyID}
参数描述类型是否必需
policyID策略 ID。string

查询参数 #

参数描述类型默认值
if_seq_no仅当匹配此序列号时更新。long
if_primary_term仅当匹配此主分片任期时更新。long

请求体 #

策略支持 ES 兼容的 phases 格式。系统内部会自动转换为 states 格式。

PUT _ilm/policy/my_lifecycle
{
  "policy": {
    "phases": {
      "hot": {
        "min_age": "0ms",
        "actions": {
          "rollover": {
            "max_age": "7d",
            "max_size": "50gb",
            "max_docs": 100000000
          },
          "set_priority": {
            "priority": 100
          }
        }
      },
      "warm": {
        "min_age": "30d",
        "actions": {
          "forcemerge": {
            "max_num_segments": 1
          },
          "allocate": {
            "require": {
              "box_type": "warm"
            }
          },
          "set_priority": {
            "priority": 50
          }
        }
      },
      "delete": {
        "min_age": "90d",
        "actions": {
          "wait_for_snapshot": {
            "policy": "daily-backup"
          },
          "delete": {}
        }
      }
    }
  }
}

操作名称映射:策略中使用的 ES 兼容名称会自动映射到内部操作名:

  • set_priorityindex_priority
  • allocateallocation
  • forcemergeforce_merge
  • readonlyread_only

响应示例 #

{
  "acknowledged": true
}

应用策略到索引模板 #

要让策略自动生效,需要在索引模板中指定策略名称和滚动索引的别名。

PUT /_index_template/my_template
{
  "index_patterns": ["log-test-*"],
  "template": {
    "settings": {
      "number_of_shards": 1,
      "number_of_replicas": 1,
      "index.lifecycle.name": "my_lifecycle",
      "index.lifecycle.rollover_alias": "log-test"
    }
  }
}

创建初始写入索引 #

设置策略后,需要手动创建第一个托管索引并将其指定为写入索引。索引名称必须匹配模板模式且以数字结尾(后续 rollover 会自动递增)。

PUT /log-test-000001
{
  "aliases": {
    "log-test": {
      "is_write_index": true
    }
  }
}

获取策略 #

通过 policyID 获取策略详情。

请求 #

GET _ilm/policy/{policyID}

响应示例 #

{
  "_id": "my_lifecycle",
  "_version": 3,
  "_seq_no": 27,
  "_primary_term": 2,
  "policy": {
    "policy_id": "my_lifecycle",
    "description": "",
    "last_updated_time": 1682049301487,
    "schema_version": 17,
    "default_state": "hot",
    "states": [
      {
        "name": "hot",
        "actions": [
          {
            "retry": {
              "count": 3,
              "backoff": "exponential",
              "delay": "1m"
            },
            "rollover": {
              "min_size": "50gb",
              "min_doc_count": 100000000,
              "min_index_age": "7d"
            }
          },
          {
            "retry": {
              "count": 3,
              "backoff": "exponential",
              "delay": "1m"
            },
            "index_priority": {
              "priority": 100
            }
          }
        ],
        "transitions": [
          {
            "state_name": "warm",
            "conditions": {
              "min_index_age": "30d"
            }
          }
        ]
      },
      {
        "name": "warm",
        "actions": [
          {
            "retry": {
              "count": 3,
              "backoff": "exponential",
              "delay": "1m"
            },
            "force_merge": {
              "max_num_segments": 1
            }
          },
          {
            "retry": {
              "count": 3,
              "backoff": "exponential",
              "delay": "1m"
            },
            "allocation": {
              "require": { "box_type": "warm" },
              "include": {},
              "exclude": {},
              "wait_for": false
            }
          },
          {
            "retry": {
              "count": 3,
              "backoff": "exponential",
              "delay": "1m"
            },
            "index_priority": {
              "priority": 50
            }
          }
        ],
        "transitions": [
          {
            "state_name": "delete",
            "conditions": {
              "min_index_age": "90d"
            }
          }
        ]
      },
      {
        "name": "delete",
        "actions": [
          {
            "retry": {
              "count": 3,
              "backoff": "exponential",
              "delay": "1m"
            },
            "wait_for_snapshot": {
              "policy": "daily-backup"
            }
          },
          {
            "retry": {
              "count": 3,
              "backoff": "exponential",
              "delay": "1m"
            },
            "delete": {}
          }
        ],
        "transitions": []
      }
    ],
    "ism_template": [
      {
        "index_patterns": [],
        "priority": 100,
        "last_updated_time": 1682049301487
      }
    ]
  }
}

注意:创建策略时使用的是 ES 兼容的 phases 格式,但获取策略时返回的是内部 states 格式。操作名称也会转换为内部名称(如 set_priority 变为 index_priority)。


获取所有策略 #

不指定 policyID 即可列出所有策略。

请求 #

GET _ilm/policy

查询参数 #

参数描述类型默认值
size每页返回数量。int20
from分页起始偏移量。int0
sortField排序字段。stringpolicy.policy_id.keyword
sortOrder排序方向。stringasc
queryString搜索过滤条件。string*

响应示例 #

{
  "policies": [
    {
      "_id": "my_lifecycle",
      "_seq_no": 27,
      "_primary_term": 2,
      "policy": { "..." : "..." }
    }
  ],
  "total_policies": 1
}

更新策略 #

更新已有策略。必须在请求中指定 if_seq_noif_primary_term 进行乐观并发控制。

请求 #

PUT _ilm/policy/{policyID}?if_seq_no=27&if_primary_term=2

请求体格式与创建策略相同。

请求示例 #

PUT _ilm/policy/my_lifecycle?if_seq_no=27&if_primary_term=2
{
  "policy": {
    "phases": {
      "hot": {
        "min_age": "0ms",
        "actions": {
          "rollover": {
            "max_age": "14d",
            "max_size": "100gb"
          }
        }
      },
      "delete": {
        "min_age": "180d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

删除策略 #

通过 policyID 删除策略。

请求 #

DELETE _ilm/policy/{policyID}

请求示例 #

DELETE _ilm/policy/my_lifecycle

响应示例 #

{
  "_index": ".easysearch-ilm-config",
  "_type": "_doc",
  "_id": "my_lifecycle",
  "_version": 2,
  "result": "deleted",
  "forced_refresh": true,
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 10,
  "_primary_term": 1
}

索引策略管理 API #

将策略应用到索引 #

将指定策略应用到一个或多个索引。

请求 #

POST /_ilm/add/{index}
参数描述类型是否必需
index索引名称,支持逗号分隔的多个索引。string

请求体 #

{
  "policy_id": "my_lifecycle"
}

响应示例 #

{
  "updated_indices": 3,
  "failures": false,
  "failed_indices": []
}

移除索引策略 #

从指定索引上移除生命周期策略。

请求 #

POST /_ilm/remove/{index}

请求示例 #

POST /_ilm/remove/log-test-000001

响应示例 #

{
  "updated_indices": 1,
  "failures": false,
  "failed_indices": []
}

变更索引策略 #

将索引当前的策略替换为新策略。

请求 #

POST /_ilm/change_policy/{index}

请求体 #

{
  "policy_id": "new_lifecycle_policy",
  "state": "warm",
  "include": [
    { "state": "hot" }
  ],
  "is_safe": false
}
参数描述类型是否必需
policy_id要切换到的新策略 ID。string
state切换后索引在新策略中的目标状态。string
include按当前状态过滤要变更的索引。array
is_safe是否为安全切换。boolean

响应示例 #

{
  "updated_indices": 1,
  "failures": false,
  "failed_indices": []
}

查看索引策略状态 #

获取索引的当前生命周期管理状态。支持使用索引模式匹配多个索引。

请求 #

GET /_ilm/explain/{index}

查询参数 #

参数描述类型默认值
show_policy是否在响应中包含完整策略。booleanfalse
validate_action是否包含操作验证结果。booleanfalse
local是否使用本地集群状态。booleanfalse
size每页返回数量。int20
from分页起始偏移量。int0
sortField排序字段。stringmanaged_index.index
sortOrder排序方向。stringasc
queryString搜索过滤条件。string*

请求示例 #

GET /_ilm/explain/log-test*

响应示例 #

{
  "log-test-000003": {
    "index.lifecycle.name": "my_lifecycle",
    "index": "log-test-000003",
    "index_uuid": "58YtMBxaRcGBvOhHcJwQ5w",
    "policy_id": "my_lifecycle",
    "policy_seq_no": -2,
    "policy_primary_term": 0,
    "rolled_over": false,
    "index_creation_date": 1682060631245,
    "state": {
      "name": "hot",
      "start_time": 1682060706227
    },
    "action": {
      "name": "rollover",
      "start_time": 1682060764614,
      "index": 0,
      "failed": false,
      "consumed_retries": 0,
      "last_retry_time": 0
    },
    "step": {
      "name": "attempt_rollover",
      "start_time": 1682060764614,
      "step_status": "condition_not_met"
    },
    "retry_info": {
      "failed": false,
      "consumed_retries": 0
    },
    "info": {
      "message": "Pending rollover of index [index=log-test-000003]",
      "conditions": {
        "min_index_age": {
          "condition": "7d",
          "current": "2.2m",
          "creationDate": 1682060631245
        },
        "min_size": {
          "condition": "50gb",
          "current": "0b"
        },
        "min_doc_count": {
          "condition": 100000000,
          "current": 0
        }
      }
    },
    "enabled": true
  },
  "total_managed_indices": 1
}

重试失败操作 #

当生命周期管理操作执行失败时,使用此 API 重试。

请求 #

POST /_ilm/retry/{index}

请求体(可选) #

{
  "state": "hot"
}

指定 state 可以让索引从特定状态重新开始执行。

响应示例 #

{
  "updated_indices": 1,
  "failures": false,
  "failed_indices": []
}

状态转换条件 #

在策略的 states 格式中,每个状态可以定义转换条件。当条件满足时,索引自动进入下一个状态。

条件描述类型示例
min_index_age索引的最小年龄。string"30d"
min_doc_count索引的最小文档数量(须 >0)。long1000000
min_size索引的最小大小(须 >0)。string"50gb"
min_rollover_age自上次 rollover 以来的最小时间。string"7d"
cron基于 cron 表达式的时间条件。object见下方

操作参考 #

所有操作都支持以下通用可选参数:

参数描述类型默认值
timeout操作超时时间。string
retry.count失败时的最大重试次数。long3
retry.backoff重试退避策略。stringexponential
retry.delay重试间隔时间。string1m

操作名称兼容性:在 phases 格式中,可以使用 ES 兼容名称(左列);在 states 格式中,使用内部名称(右列):

ES 兼容名称内部名称
set_priorityindex_priority
allocateallocation
forcemergeforce_merge
readonlyread_only

rollover #

当现有索引满足指定的滚动条件时,将写入目标切换到新索引。

滚动目标可以是数据流或索引别名。当目标为数据流时,新索引将变为数据流的写索引,并且其代数将递增。

如果要滚动索引别名,别名及其写索引必须满足以下条件:

  • 索引名称必须符合模式 ^.*-\d+$,例如 my-index-000001
  • 必须将 index.lifecycle.rollover_alias 配置为要滚动的别名。
  • 索引必须是别名的写索引。
参数描述类型是否必需
min_size / max_size当索引主分片总大小达到此值时触发滚动(不含副本)。string
min_doc_count / max_docs当索引文档数达到此值时触发滚动(不含副本和未刷新文档)。long
min_index_age / max_age当索引年龄达到此值时触发滚动。string
min_primary_shard_size / max_primary_shard_size当最大主分片大小达到此值时触发滚动。string

每对参数中,左侧是内部名称,右侧是 ES 兼容别名。两种写法均可使用。

PUT _ilm/policy/my_policy
{
  "policy": {
    "phases": {
      "hot": {
        "actions": {
          "rollover": {
            "max_size": "50gb",
            "max_age": "7d",
            "max_docs": 100000000
          }
        }
      }
    }
  }
}

set_priority / index_priority #

设置索引的优先级,用于节点恢复后的索引恢复顺序。优先级高的索引先恢复。

参数描述类型是否必需验证
priority索引优先级,值越大越优先。int必须 ≥ 0
PUT _ilm/policy/my_policy
{
  "policy": {
    "phases": {
      "hot": {
        "actions": {
          "set_priority": {
            "priority": 100
          }
        }
      },
      "warm": {
        "actions": {
          "set_priority": {
            "priority": 50
          }
        }
      }
    }
  }
}

forcemerge / force_merge #

通过合并 Lucene 段(segment)来减少段的数量,优化查询性能。此操作在合并前会自动将索引设置为 read_only 状态。

执行步骤:设置只读 → 执行 force merge → 等待合并完成(共 3 步)。

参数描述类型是否必需验证
max_num_segments每个分片合并后的目标段数量。int必须 > 0
PUT _ilm/policy/my_policy
{
  "policy": {
    "phases": {
      "warm": {
        "actions": {
          "forcemerge": {
            "max_num_segments": 1
          }
        }
      }
    }
  }
}

readonly / read_only #

将托管索引设置为只读,即 index.blocks.write 设为 true

注意:此设置不会阻止索引刷新(refresh)操作。

PUT _ilm/policy/my_policy
{
  "policy": {
    "phases": {
      "warm": {
        "actions": {
          "readonly": {}
        }
      }
    }
  }
}

read_write #

将托管索引设置为可读写状态,撤消 read_only 操作的效果。

PUT _ilm/policy/my_policy
{
  "policy": {
    "phases": {
      "warm": {
        "actions": {
          "read_write": {}
        }
      }
    }
  }
}

replica_count #

设置索引的副本分片数量。

参数描述类型是否必需验证
number_of_replicas要设置的副本分片数量。int必须 ≥ 0
PUT _ilm/policy/my_policy
{
  "policy": {
    "phases": {
      "warm": {
        "actions": {
          "replica_count": {
            "number_of_replicas": 1
          }
        }
      }
    }
  }
}

allocate / allocation #

将索引分配到具有特定属性集的节点上。例如,将 require 设置为 { "box_type": "warm" },可以将索引数据迁移到 warm 类型节点。

参数描述类型是否必需默认值
require索引必须分配到具有所有指定属性的节点。object条件必需 ¹{}
include索引可以分配到具有任一指定属性的节点。object条件必需 ¹{}
exclude索引不会分配到具有任一指定属性的节点。object条件必需 ¹{}
wait_for是否等待分配完成后再进入下一步操作。booleanfalse

¹ requireincludeexclude 中至少有一个必须非空。

PUT _ilm/policy/my_policy
{
  "policy": {
    "phases": {
      "warm": {
        "actions": {
          "allocate": {
            "require": {
              "box_type": "warm"
            }
          }
        }
      },
      "cold": {
        "actions": {
          "allocate": {
            "include": {
              "box_type": "cold,frozen"
            },
            "wait_for": true
          }
        }
      }
    }
  }
}

close #

关闭托管索引。关闭的索引仍然存在于磁盘上,但不消耗 CPU 或内存资源,也不能被读取、写入或搜索。

如果需要长期保留数据但短期内无需搜索,且磁盘空间充足,关闭索引是一个好选择。需要时可以重新打开,比从快照恢复更简便。

PUT _ilm/policy/my_policy
{
  "policy": {
    "phases": {
      "cold": {
        "actions": {
          "close": {}
        }
      }
    }
  }
}

open #

打开一个已关闭的托管索引,恢复其读写和搜索能力。

PUT _ilm/policy/my_policy
{
  "policy": {
    "phases": {
      "warm": {
        "actions": {
          "open": {}
        }
      }
    }
  }
}

delete #

删除托管索引,将其从集群中完全移除。

参数描述类型是否必需验证
timestamp_field用于判断索引数据年龄的时间戳字段。须与 min_data_age 配对使用。string否 ¹
min_data_age索引中最新数据的最小年龄要求。须与 timestamp_field 配对使用。string否 ¹必须以天为单位(d),最小 1d

¹ timestamp_fieldmin_data_age 必须同时指定或同时省略。

当两个参数都指定时,系统会:

  1. 查询索引中按指定时间戳字段排序的最新文档。
  2. 计算最新文档时间与当前时间的差值。
  3. 仅当差值 ≥ min_data_age 时才执行删除。

这种机制可以防止意外删除仍在活跃使用的数据。

基本用法

PUT _ilm/policy/my_policy
{
  "policy": {
    "phases": {
      "delete": {
        "min_age": "30d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

带条件检查的删除

PUT _ilm/policy/conditional_delete_policy
{
  "policy": {
    "phases": {
      "delete": {
        "min_age": "30d",
        "actions": {
          "delete": {
            "timestamp_field": "@timestamp",
            "min_data_age": "90d"
          }
        }
      }
    }
  }
}

上面的示例中,即使索引满足了 30 天的 min_age 条件进入删除阶段,也只有当索引中最新的文档(基于 @timestamp 字段)已经至少 90 天未更新时,才会执行实际的删除操作。


snapshot #

将索引创建为快照备份。

执行步骤:执行快照 → 等待快照完成(共 2 步)。

参数描述类型是否必需
repository已注册的快照仓库名称。string
snapshot快照名称。支持 Mustache 模板变量。string
PUT _ilm/policy/my_policy
{
  "policy": {
    "phases": {
      "cold": {
        "actions": {
          "snapshot": {
            "repository": "my_repository",
            "snapshot": "{{ctx.index}}"
          }
        }
      }
    }
  }
}

shrink #

将索引缩小到更少的主分片数量。

执行步骤:迁移分片 → 等待迁移完成 → 执行缩小 → 等待缩小完成(共 4 步)。

必须指定以下三个参数中的恰好一个来确定目标分片数:

参数描述类型验证
num_new_shards目标主分片数量。int必须 > 0
max_shard_size每个分片的最大大小,系统据此计算分片数。string必须 > 0
percentage_of_source_shards目标分片数为原分片数的百分比。double必须 > 0.0 且 < 1.0
可选参数描述类型默认值
target_index_name_template目标索引名称模板(Mustache 格式,语言须为 mustache)。object
aliases新索引的别名列表。array
force_unsafe是否允许不安全缩小。boolean
PUT _ilm/policy/my_policy
{
  "policy": {
    "phases": {
      "warm": {
        "actions": {
          "shrink": {
            "num_new_shards": 1
          }
        }
      }
    }
  }
}

按最大分片大小缩小

PUT _ilm/policy/my_policy
{
  "policy": {
    "phases": {
      "warm": {
        "actions": {
          "shrink": {
            "max_shard_size": "50gb"
          }
        }
      }
    }
  }
}

alias #

管理索引别名。可以在生命周期操作中添加或移除别名。

参数描述类型是否必需
actions别名操作列表,每个操作为 ADD 或 REMOVE。array

注意:别名操作中不能指定 index/indices 参数,操作自动应用于当前托管索引。

PUT _ilm/policy/my_policy
{
  "policy": {
    "phases": {
      "warm": {
        "actions": {
          "alias": {
            "actions": [
              {
                "add": {
                  "alias": "my-data-archive"
                }
              },
              {
                "remove": {
                  "alias": "my-data-active"
                }
              }
            ]
          }
        }
      }
    }
  }
}

rollup #

在生命周期操作中自动创建 rollup 作业,将细粒度时序数据汇总为粗粒度数据以节省存储空间。

执行步骤:创建 Rollup 作业 → 等待 Rollup 完成(共 2 步)。

参数描述类型是否必需
ism_rollupISM Rollup 配置对象。object

ISM Rollup 配置 #

参数描述类型是否必需验证
descriptionRollup 作业描述。string
target_index存储 rollup 结果的目标索引名称。string不能为空
page_size每批处理的文档数。int1 ~ 10000
dimensions维度定义列表。array第一个必须是 date_histogram
metrics指标聚合定义列表。array
PUT _ilm/policy/my_policy
{
  "policy": {
    "phases": {
      "cold": {
        "actions": {
          "rollup": {
            "ism_rollup": {
              "description": "Hourly rollup",
              "target_index": "rollup-my-index",
              "page_size": 1000,
              "dimensions": [
                {
                  "date_histogram": {
                    "source_field": "@timestamp",
                    "fixed_interval": "1h",
                    "timezone": "UTC"
                  }
                },
                {
                  "terms": {
                    "source_field": "host.name"
                  }
                }
              ],
              "metrics": [
                {
                  "source_field": "cpu.usage",
                  "metrics": [
                    { "avg": {} },
                    { "max": {} },
                    { "min": {} }
                  ]
                }
              ]
            }
          }
        }
      }
    }
  }
}

wait_for_snapshot #

在删除索引之前,等待指定的快照管理策略(SLM)完成执行。确保被删除索引的快照是可用的。

参数描述类型是否必需
policy要等待的快照管理策略(SLM)名称。string
PUT _ilm/policy/my_policy
{
  "policy": {
    "phases": {
      "delete": {
        "actions": {
          "wait_for_snapshot": {
            "policy": "daily-backup"
          },
          "delete": {}
        }
      }
    }
  }
}

完整示例 #

以下示例展示一个典型的多阶段生命周期策略,涵盖从数据摄入到归档删除的完整流程:

PUT _ilm/policy/production_lifecycle
{
  "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": {
          "forcemerge": {
            "max_num_segments": 1
          },
          "shrink": {
            "num_new_shards": 1
          },
          "allocate": {
            "require": {
              "box_type": "warm"
            }
          },
          "set_priority": {
            "priority": 50
          },
          "replica_count": {
            "number_of_replicas": 1
          }
        }
      },
      "cold": {
        "min_age": "90d",
        "actions": {
          "readonly": {},
          "allocate": {
            "require": {
              "box_type": "cold"
            }
          },
          "set_priority": {
            "priority": 0
          }
        }
      },
      "delete": {
        "min_age": "365d",
        "actions": {
          "wait_for_snapshot": {
            "policy": "nightly-backup"
          },
          "delete": {}
        }
      }
    }
  }
}

应用策略 #

PUT /_index_template/production_logs
{
  "index_patterns": ["logs-prod-*"],
  "template": {
    "settings": {
      "number_of_shards": 3,
      "number_of_replicas": 1,
      "index.lifecycle.name": "production_lifecycle",
      "index.lifecycle.rollover_alias": "logs-prod"
    }
  }
}
PUT /logs-prod-000001
{
  "aliases": {
    "logs-prod": {
      "is_write_index": true
    }
  }
}

检查生命周期状态 #

GET /_ilm/explain/logs-prod*?show_policy=true

手动为已有索引添加策略 #

POST /_ilm/add/old-logs-2024
{
  "policy_id": "production_lifecycle"
}