索引生命周期管理
1 产品简介
ISM (Index State Management,索引生命周期管理) 是bes提供的一项索引自动化管理功能,它允许用户通过配置策略(Policy),对索引进行全生命周期的自动化运维管理,ISM 旨在替代人工脚本和手动运维,帮助用户根据索引的时间、大小或文档数量等条件,自动执行索引的滚动、迁移、备份和清理等操作,从而实现集群存储成本的优化与数据管理的规范化。
1.1 支持的核心action
ISM 策略允许您在索引的不同生命周期阶段执行以下具体动作:
- Rollover:滚动索引,创建新索引接收写入。
- Force Merge:合并分段,优化存储和查询。
- Replica Count:修改索引的副本数量。
- ReadOnly / ReadWrite:切换索引的读写状态。
- Snapshot:创建索引快照到存储仓库。
- Close / Open:关闭索引(不占用内存但保留在磁盘)或重新打开。
- Delete:永久删除索引。
- Shrink:将现有的索引收缩成一个新的拥有更少主分片的目标索引。
- Allocation:配置索引的分片分配规则,用于将索引自动迁移到具有不同配置的特定节点上,比如冷数据节点。
- Index Priority:设置索引的恢复优先级,数值越高,在节点重启或集群恢复时,该索引就会越早被恢复。
2 核心概念
在使用ISM之前,理解其核心组件及其相互关系至关重要,ISM 的工作机制本质上是一个有限状态机,索引在同一时间只能处于一个状态 (State),在当前状态下执行动作 (Action),并根据满足的条件 (Condition) 通过流转 (Transition) 进入下一个状态。
2.1 策略 (Policy)
policy是ISM的核心配置文件,它定义了索引管理的完整规则集合,参数说明:
| 参数 | 描述 | 必填 |
|---|---|---|
| description | 策略描述 | 是 |
| default_state | 索引应用策略后进入的初始状态 | 是 |
| states | 索引可能经历的所有状态列表 | 是 |
| ism_template | 用于自动将该策略应用到匹配特定模式的新索引上 | 否 |
| ism_template.index_patterns | 索引名称模式列表,当新创建的索引名称匹配该模式时,会自动应用此策略 | 否 |
| ism_template.priority | 模版优先级,当一个索引匹配多个ISM模板时,优先级数值较高的策略将被应用 | 否 |
举例:
1{
2 "description": "Example policy",
3 "default_state": "hot",
4 "states": [
5
6 ],
7 "ism_template": {
8 "index_patterns": [
9 "log-*"
10 ],
11 "priority": 100
12 }
13}
2.2 状态 (State)
state是索引生命周期中的一个独立单元,一个被管理的索引在同一时间只能处于一个状态,每个状态定义主要由两部分组成:要执行的动作(action)和移动到下一个状态的流转(transitions),参数说明:
| 参数 | 描述 | 必填 |
|---|---|---|
| name | 状态的唯一名称 | 是 |
| actions | 进入该状态时需要执行的任务列表(如:Rollover, Snapshot) | 是 |
| transitions | 定义索引何时以及如何离开当前状态,进入下一个状态 | 是 |
当索引进入一个状态时,ISM将按顺序执行定义的所有动作,当所有动作成功完成后,ISM 将开始检查流转条件,如果未定义动作,ISM 将立即开始检查流转条件
举例:
1{
2 "name": "ingest",
3 "actions": [
4 {
5 "rollover": {
6 "min_doc_count": 5
7 }
8 }
9 ],
10 "transitions": [
11 {
12 "state_name": "search"
13 }
14 ]
15 }
2.3 动作 (Action)
action是ISM对索引执行的具体操作,即1.1中描述的核心功能,在同一个状态内定义的动作列表是按顺序串行执行的,如果某个动作执行失败,ISM会自动重试,如果多次重试后仍然失败,索引将进入Failed状态,需要人工干预,action包含的通用配置参数:
| 参数 | 描述 | 必填 |
|---|---|---|
| timeout | 动作执行的超时时间,支持分时天单位,例:1m,1h,1d | 否 |
| retry | 动作失败时的重试策 | 否 |
| retry.count | 最大重试次数 | 如果配置retry则必填 |
| retry.backoff | 重试退避策略,可选值:constant (固定), exponential (指数), linear (线性) | 否 |
| retry.delay | 重试间隔时间,支持分时天单位,例:1m,1h,1d | 否 |
举例:
1{
2 "timeout": "1h",
3 "retry": {
4 "count": 3,
5 "backoff": "exponential",
6 "delay": "10m"
7 }
8}
2.4 流转 (Transition)
transitions定义了索引从当前状态移动到下一个状态的规则,所有action完成后ISM会按顺序评估流转列表中的条件,一旦有一个条件满足,索引就会移动到目标状态,如果未设置条件,则立刻转移到目标状态,transitions包含参数:
| 参数 | 描述 | 必填 |
|---|---|---|
| state_name | 目标状态的名称 | 否 |
| conditions | 触发流转必须满足的条件 | 是 |
| conditions.min_index_age | 最小索引年龄 | 否 |
| conditions.min_rollover_age | 索引完成rollover操作后的最小时长 | 否 |
| conditions.min_doc_count | 文档总数的最小阈值 | 否 |
| conditions.min_size | 主分片总大小的最小阈值 | 否 |
| conditions.cron | 使用cron表达式触发流转 | 否 |
| conditions.cron.cron.expression | cron字符串 | 如果设置corn则必填 |
| conditions.cron.cron.timezone | 时区 | 如果设置corn则必填 |
举例:
1"transitions": [
2 {
3 "state_name": "cold",
4 "conditions": {
5 "min_index_age": "30d",
6 "cron": {
7 "cron": {
8 "expression": "* 17 * * SAT",
9 "timezone": "America/Los_Angeles"
10 }
11 }
12 }
13 }
14]
3 action操作配置
3.1 force_merge
通过合并各个分片的段来减少Lucene段的数量,此操作会在开始合并过程之前尝试将索引设置为只读read_only状态,合并完成后不会自动去掉,需要自己添加read_write的action,建议配合rollover的action使用,旧索引进行force_merge。
示例:
1{
2 "force_merge": {
3 "max_num_segments": 1
4 }
5}
3.2 read_only/read_write
将索引设为只读/可读写状态。
示例:
1#只读
2{
3 "read_only": {}
4}
5#可读写
6{
7 "read_write": {}
8}
3.3 replica_count
设置索引的副本数量。
示例:
1{
2 "replica_count": {
3 "number_of_replicas": 1
4 }
5}
3.4 shrink
将现有索引收缩为一个拥有更少主分片的新索引,参数说明:
| 参数 | 描述 | 示例 | 必填 |
|---|---|---|---|
| num_new_shards | 新索引的主分片数量 | 5 | 是,此参数与max_shard_size、percentage_of_source_shards互斥 |
| max_shard_size | 设定目标分片的最大大小,比如原索引总大小100gb,设为50gb则会生成2个分片 | 50gb | 是,此参数和num_new_shards、percentage_of_source_shards互斥 |
| percentage_of_source_shards | 按原分片数的百分比收缩,值在0.0到1.0之间,例如0.5 表示新索引分片数是原索引的一半 | 0.5 | 是,此参数和num_new_shards、max_shard_size互斥 |
| target_index_name_template | 新索引的命名,{{ctx.index}}代表原索引名 | "source": "{{ctx.index}}-2" | 否 |
| aliases | 给新索引添加别名 | {} | 否 |
| switch_aliases | 默认为 false,如果设为 true,ISM 会尝试将指向原索引的别名自动切换指向新索引 | true | 否 |
| force_unsafe | 强制执行,默认为false,如果设为true,即使当前索引没有副本也允许执行收缩。 | true | 否 |
示例:
1"shrink": {
2 "num_new_shards": 1,
3 "target_index_name_template": {
4 "source": "{{ctx.index}}_shrunken"
5 },
6 "aliases": [
7 {
8 "my-alias": {}
9 }
10 ],
11 "switch_aliases": true,
12 "force_unsafe": false
13}
注:force_unsafe为false时必须有副本
3.5 close/open
关闭/开启索引,关闭的索引不能进行读写操作。
示例:
1#关闭索引
2{
3 "close": {}
4}
5#开启索引
6{
7 "open": {}
8}
3.6 delete
删除索引。
示例:
1{
2 "delete": {}
3}
3.7 rollover
当满足指定条件时,滚动索引,参数说明:
| 参数 | 描述 | 示例 | 必填 |
|---|---|---|---|
| min_size | 主分片总大小的最小阈值 | 20gb or 5mb | 否 |
| min_primary_shard_size | 单个主分片大小的最小阈值 | 20gb or 5mb | 否 |
| min_doc_count | 文档总数的最小阈值 | 2000000 | 否 |
| min_index_age | 最小索引年龄 | 5d or 7h | 否 |
| copy_alias | 是否复制别名,默认为false,如果设为true,除了Rollover别名外,旧索引绑定的其他别名也会被复制到新索引上。 | true | 否 |
示例:
1{
2 "rollover": {
3 "min_size": "50gb"
4 }
5}
6{
7 "rollover": {
8 "min_primary_shard_size": "30gb"
9 }
10}
11{
12 "rollover": {
13 "min_doc_count": 100000000
14 }
15}
16{
17 "rollover": {
18 "min_index_age": "30d"
19 }
20}
rollover的索引命名必须匹配^.*-\d+$ 例如logs-000001,并且需要添加别名
1POST /_aliases
2{
3 "actions": [
4 {
5 "add": {
6 "index": "logs-000001",
7 "alias": "logs",
8 "is_write_index":true
9 }
10 }
11 ]
12}
索引设置完别名后需要在索引的settings中加上别名配置:
1PUT logs-000001/_settings
2{
3 "settings": {
4 "index.plugins.index_state_management.rollover_alias":"logs"
5 }
6}
在后面rollover最佳实践中有完整的例子参考。
3.8 snapshot
创建索引的快照备份,参数说明:
| 参数 | 描述 | 示例 | 必填 |
|---|---|---|---|
| repository | 注册的快照仓库名称 | my_backup | 是 |
| snapshot | 快照名称 | my_snapshot | 是 |
示例:
1{
2 "snapshot": {
3 "repository": "my_backup",
4 "snapshot": "my_snapshot"
5 }
6}
3.9 index_priority
设置索引的优先级,在节点重启或集群恢复时,优先级数值较高的索引将优先恢复,参数说明:
| 参数 | 描述 | 示例 | 必填 |
|---|---|---|---|
| priority | 优先级数值 | 1 | 是 |
示例:
1{
2 "index_priority": {
3 "priority": 50
4 }
5 }
3.10 allocation
通过更新索引的设置,控制索引分片在集群节点上的分配位置,常用于将索引从热节点迁移到冷节点,参数说明:
| 参数 | 描述 | 示例 | 必填 |
|---|---|---|---|
| require | 必须包含的节点属性 | { "data_tier": "warm" } | 是 |
示例:
1{
2 "allocation": {
3 "require": { "data_tier": "warm" }
4 }
5 }
4 ism api
4.1 创建策略
创建一个ism策略
示例:
1PUT _plugins/_ism/policies/policy_1
2{
3 "policy": {
4 "description": "ingesting logs",
5 "default_state": "ingest",
6 "states": [
7 {
8 "name": "ingest",
9 "actions": [
10 {
11 "rollover": {
12 "min_doc_count": 5
13 }
14 }
15 ],
16 "transitions": [
17 {
18 "state_name": "search"
19 }
20 ]
21 },
22 {
23 "name": "search",
24 "actions": [],
25 "transitions": [
26 {
27 "state_name": "delete",
28 "conditions": {
29 "min_index_age": "5m"
30 }
31 }
32 ]
33 },
34 {
35 "name": "delete",
36 "actions": [
37 {
38 "delete": {}
39 }
40 ],
41 "transitions": []
42 }
43 ]
44 }
45}
4.2 添加策略
将一个策略应用到索引上,如果索引已经存在策略,则此操作不会更改策略
示例:
1POST _plugins/_ism/add/index_1
2{
3 "policy_id": "policy_1"
4}
如果使用通配符为所有索引应用策略,ism会将包括系统索引在内的所有索引都加上策略,如果配置的策略中包含delete动作,可能会意外删除集群的系统索引,所以请勿使用宽泛的通配符,而是在使用 _ism/add API时指定前缀,例如 my-logs*。
4.3 更新策略
更新一个策略需要使用seq_no和primary_term参数来更新现有策略,如果这些参数与现有策略不匹配,或者策略不存在,ISM 会报错,seq_no和primary_term可以使用get policy的api获取,更新时为覆盖更新。
示例:
1PUT _plugins/_ism/policies/policy_1?if_seq_no=7&if_primary_term=1
2{
3 "policy": {
4 "description": "ingesting logs",
5 "default_state": "ingest",
6 "states": [
7 {
8 "name": "ingest",
9 "actions": [
10 {
11 "rollover": {
12 "min_doc_count": 5
13 }
14 }
15 ],
16 "transitions": [
17 {
18 "state_name": "search"
19 }
20 ]
21 },
22 {
23 "name": "search",
24 "actions": [],
25 "transitions": [
26 {
27 "state_name": "delete",
28 "conditions": {
29 "min_index_age": "5m"
30 }
31 }
32 ]
33 },
34 {
35 "name": "delete",
36 "actions": [
37 {
38 "delete": {}
39 }
40 ],
41 "transitions": []
42 }
43 ]
44 }
45}
4.4 获取策略信息
通过policy_id获取策略详情。
示例:
1GET _plugins/_ism/policies/policy_1
响应:
1{
2 "_id": "policy_1",
3 "_version": 2,
4 "_seq_no": 10,
5 "_primary_term": 1,
6 "policy": {
7 "policy_id": "policy_1",
8 "description": "ingesting logs",
9 "last_updated_time": 1577990934044,
10 "schema_version": 1,
11 "error_notification": null,
12 "default_state": "ingest",
13 "states": [
14 {
15 "name": "ingest",
16 "actions": [
17 {
18 "rollover": {
19 "min_doc_count": 5
20 }
21 }
22 ],
23 "transitions": [
24 {
25 "state_name": "search"
26 }
27 ]
28 },
29 {
30 "name": "search",
31 "actions": [],
32 "transitions": [
33 {
34 "state_name": "delete",
35 "conditions": {
36 "min_index_age": "5m"
37 }
38 }
39 ]
40 },
41 {
42 "name": "delete",
43 "actions": [
44 {
45 "delete": {}
46 }
47 ],
48 "transitions": []
49 }
50 ]
51 }
52}
4.5 从索引移除策略
从受管索引中移除策略。
示例:
1POST _plugins/_ism/remove/index_1
4.6 更新应用到索引上的策略
该操作将受管索引的策略更新为一个新策略,可以使用索引通配符一次性更新多个索引,当批量更新多个索引时可以包含一个状态过滤器,以便只影响处于指定状态的特定受管索引,此外还可以显式指定受管索引在更改策略生效后要流转到的目标状态,策略更改是一个异步后台过程,这些更改会被放入队列,并不会立即由后台进程执行,这种执行延迟是为了保护当前正在运行的受管索引,防止其因突然变更而陷入损坏或错误状态,如果要切换到的策略仅包含一些微小的配置更改,那么更改会立即生效,例如如果策略将rollover条件中的min_index_age参数从1000d改为100d,这个更改将在下一次执行检查时立即生效。但如果更改修改了索引当前所处状态的结构(例如修改了状态本身、具体的actions或动作的执行顺序),那么更改不会立即发生,而是会等到索引完成当前状态的所有操作后,在流转到下一个状态之前才会应用新的策略。
示例:
1POST _plugins/_ism/change_policy/index_1
2{
3 "policy_id": "policy_1",
4 "state": "delete",
5 "include": [
6 {
7 "state": "searches"
8 }
9 ]
10}
上述命令意思为更新处在searches状态的index_1策略到policy_1,更新后的索引处在delete状态。
4.7 重试失败索引
重试action处于failed状态的受管索引,可以使用通配符重试多个索引。
示例:
1POST _plugins/_ism/retry/index_1
2{
3 "state": "delete"
4}
4.8查看受管索引状态
获取一个或多个索引的当前 ISM 状态,可使用索引通配符,使用此API可以查看索引处于哪个策略(路径加上?show_policy=true)、哪个状态,以及是否有任何操作失败。
示例:
1GET _plugins/_ism/explain/index_1?show_policy=true
响应:
1{
2 "index_1": {
3 "index.plugins.index_state_management.policy_id": "sample-policy",
4 "index.opendistro.index_state_management.policy_id": "sample-policy",
5 "index": "index_1",
6 "index_uuid": "gCFlS_zcTdih8xyxf3jQ-A",
7 "policy_id": "sample-policy",
8 "enabled": true,
9 "policy": {
10 "policy_id": "sample-policy",
11 "description": "ingesting logs",
12 "last_updated_time": 1647284980148,
13 "schema_version": 13,
14 "error_notification": null,
15 "default_state": "ingest",
16 "states": [...],
17 "ism_template": null
18 }
19 },
20 "total_managed_indices": 1
21}
4.9 删除策略
通过policy_id删除策略。
示例:
1DELETE _plugins/_ism/policies/policy_1
4.10 错误预防验证
自动执行action时可能会因各种原因而失败,可以使用错误预防验证API来检查可能导致操作失败的潜在问题,在使用此功能前,需要通过集群设置开启验证功能
1PUT _cluster/settings
2{
3 "persistent":{
4 "plugins.index_state_management.action_validation.enabled": true
5 }
6}
要检查错误预防验证的状态和信息,需要在调用explain接口时传递validate_action=true参数,
1GET _plugins/_ism/explain/test-000001?validate_action=true
响应中会包含一个额外的validate对象,其中显示了验证信息和状态,
1{
2 "test-000001" : {
3 "index.plugins.index_state_management.policy_id" : "test_rollover",
4 "index.opendistro.index_state_management.policy_id" : "test_rollover",
5 "index" : "test-000001",
6 "index_uuid" : "CgKsxFmQSIa8dWqpbSJmyA",
7 "policy_id" : "test_rollover",
8 "policy_seq_no" : -2,
9 "policy_primary_term" : 0,
10 "rolled_over" : false,
11 "index_creation_date" : 1667410460649,
12 "state" : {
13 "name" : "rollover",
14 "start_time" : 1667410766045
15 },
16 "action" : {
17 "name" : "rollover",
18 "start_time" : 1667411127803,
19 "index" : 0,
20 "failed" : false,
21 "consumed_retries" : 0,
22 "last_retry_time" : 0
23 },
24 "step" : {
25 "name" : "attempt_rollover",
26 "start_time" : 1667411127803,
27 "step_status" : "starting"
28 },
29 "retry_info" : {
30 "failed" : true,
31 "consumed_retries" : 0
32 },
33 "info" : {
34 "message" : "Previous action was not able to update IndexMetaData."
35 },
36 "enabled" : false,
37 "validate" : {
38 "validation_message" : "Missing rollover_alias index setting [index=test-000001]",
39 "validation_status" : "re_validating"
40 }
41 },
42 "total_managed_indices" : 1
43}
5 最佳实践
5.1 自动rollover
以下例子展示了如何创建自动rollover的ism流程,如果想让某个索引跳过rollover动作,设置该索引的index.plugins.index_state_management.rollover_skip为true。
- 创建策略的模版ism_template,让索引自动应用策略。
1PUT _plugins/_ism/policies/rollover_policy
2{
3 "policy": {
4 "description": "Example rollover policy.",
5 "default_state": "rollover",
6 "states": [
7 {
8 "name": "rollover",
9 "actions": [
10 {
11 "rollover": {
12 "min_doc_count": 1
13 }
14 }
15 ],
16 "transitions": []
17 }
18 ],
19 "ism_template": {
20 "index_patterns": ["log*"],
21 "priority": 100
22 }
23 }
24}
- 创建索引的模板_index_template,让索引加上自动plugins.index_state_management.rollover_alias配置
1PUT _index_template/ism_rollover
2{
3 "index_patterns": ["log*"],
4 "template": {
5 "settings": {
6 "plugins.index_state_management.rollover_alias": "log"
7 }
8 }
9}
- 创建索引时设置别名
1PUT log-000001
2{
3 "aliases": {
4 "log": {
5 "is_write_index": true
6 }
7 }
8}
如果是已存在的索引,则需使用
1POST /_aliases
2{
3 "actions": [
4 {
5 "add": {
6 "index": "log-000001",
7 "alias": "log",
8 "is_write_index": true
9 }
10 }
11 ]
12}
5.2 添加/移除别名
以下例子展示了如何配置别名,在rollover后去掉旧索引的别名
1PUT /_plugins/_ism/policies/rollover_policy?pretty
2{
3 "policy": {
4 "description": "Example rollover policy.",
5 "default_state": "rollover",
6 "states": [
7 {
8 "name": "rollover",
9 "actions": [
10 {
11 "rollover": {
12 "min_doc_count": 1
13 }
14 }
15 ],
16 "transitions": [{
17 "state_name": "alias",
18 "conditions": {
19 "min_doc_count": "2"
20 }
21 }]
22 },
23 {
24 "name": "alias",
25 "actions": [
26 {
27 "alias": {
28 "actions": [
29 {
30 "remove": {
31 "alias": "log"
32 }
33 }
34 ]
35 }
36 }
37 ]
38 }
39 ],
40 "ism_template": {
41 "index_patterns": ["log*"],
42 "priority": 100
43 }
44 }
45}
添加别名时把remove改成add即可
5.3 索引置冷到冷数据节点
以下例子展示了热数据存在7天或者主分片达到30gb后转移数据到冷数据节点并把本分片降为1,冷数据存在30天后自动删除。
1{
2 "policy": {
3 "description": "hot warm delete workflow",
4 "default_state": "hot",
5 "schema_version": 1,
6 "states": [
7 {
8 "name": "hot",
9 "actions": [
10 {
11 "rollover": {
12 "min_index_age": "7d",
13 "min_primary_shard_size": "30gb"
14 }
15 }
16 ],
17 "transitions": [
18 {
19 "state_name": "warm"
20 }
21 ]
22 },
23 {
24 "name": "warm",
25 "actions": [
26 {
27 "replica_count": {
28 "number_of_replicas": 1
29 }
30 },
31 {
32 "allocation": {
33 "require": {
34 "data_tier": "warm"
35 }
36 }
37 }
38 ],
39 "transitions": [
40 {
41 "state_name": "delete",
42 "conditions": {
43 "min_index_age": "30d"
44 }
45 }
46 ]
47 },
48 {
49 "name": "delete",
50 "actions": [
51 {
52 "delete": {}
53 }
54 ]
55 }
56 ],
57 "ism_template": {
58 "index_patterns": ["log*"],
59 "priority": 100
60 }
61 }
62}
