
# 通过ISM实现自动滚动索引
在日志分析、实时监控等时序数据场景中，数据量随时间呈爆发式增长。如果持续向单一索引写入，会导致索引体积过大、查询性能急剧下降且磁盘空间难以回收。传统的依靠脚本手动切分索引的方式维护成本极高，通过给Elasticsearch集群索引配置索引生命周期管理（ISM）策略，您可以根据索引的大小或存活时间自动触发滚动（Rollover）并最终自动清理过期索引，实现存储成本与查询性能的平衡。
- ISM (Index State Management)：索引状态管理插件，用于自动化执行索引的生命周期任务。
- Rollover (滚动)：当现有索引达到设定的阈值（如大小、时间）时，自动创建一个新索引并将写入流量切过去。
- Alias (别名)：逻辑层面的索引名称。写入数据时别名始终指向"当前活跃索引"，查询时别名同时指向当前索引和历史所有索引。
#### 方案介绍
本案例通过给集群索引配置生命周期管理策略实现自动滚动索引：
- Hot阶段：索引处理高并发写入，当索引的大小达到1TB或索引创建超过1天时，自动生成新索引。
- Warm阶段：当索引创建7天后，关闭数据副本以节省资源。
- Delete阶段：当索引创建30天后，自动删除索引，释放磁盘。
假设某个应用每天产生大量日志数据，平均每天约产生2.4TB的数据，需要通过索引生命周期管理策略来优化存储和查询性能。定义索引别名为"log-alias"，其数据在集群中的组织形态如[图1 log-alias的组织形态]所示**。**查询时，指向所有test开头的索引；写入时，指向最新的索引。
图1log-alias的组织形态   
![](https://support.huaweicloud.com/usermanual-css/figure/zh-cn_image_0000002209172477.png "点击放大")
![](https://support.huaweicloud.com/usermanual-css/public_sys-resources/note_3.0-zh-cn.png)
索引的滚动条件1天是以索引的创建时间来计算的，并不是完整自然日区分的。
#### 约束限制
Elasticsearch集群版本要求不低于7.6.2。
#### 配置索引生命周期管理策略
1. 登录Kibana进入命令执行页面。
   1. 登录[云搜索服务管理控制台](https://console.huaweicloud.com/elasticsearch/)。
   
   2. 在左侧导航栏，选择"集群管理 \> Elasticsearch"。
   
   3. 在集群列表，选择目标集群，单击操作列的"Kibana"，登录Kibana。
   
   4. 在Kibana左侧导航栏选择"Dev Tools"，进入操作页面。 控制台左侧是命令输入框，其右侧的三角形图标为执行按钮，右侧区域则显示执行结果。
      
    
2. 定义生命周期策略，以便自动管理索引的滚动、降级和删除。 例如，创建策略"rollover_workflow"，当索引的大小达到1TB或索引创建超过1天时，自动进行滚动；当索引创建7天后，关闭数据副本；当索引创建30天后，删除索引。
   ```
   PUT _opendistro/_ism/policies/rollover_workflow
   {
     "policy": {
       "description": "rollover test",
       "default_state": "hot",
       "states": [
         {
           "name": "hot",
           "actions": [
             {
               "rollover": {
                 "min_size": "1tb",
                 "min_index_age": "1d"
               }
             }
           ],
           "transitions": [
             {
               "state_name": "warm",
               "conditions": {
                 "min_index_age": "7d"
               }
             }
           ]
         },
         {
           "name": "warm",
           "actions": [
             {
               "replica_count": {
                 "number_of_replicas": 0
               }
             }
           ],
           "transitions": [
             {
               "state_name": "delete",
               "conditions": {
                 "min_index_age": "30d"
               }
             }
           ]
         },
         {
           "name": "delete",
           "actions": [
             {
               "delete": {}
             }
           ]
         }
       ]
     }
   }
   ```
   当生命周期策略创建完成后，执行如下命令可以查询策略详情：
   ```
   GET _opendistro/_ism/policies/rollover_workflow
   ```
   
3. 绑定索引模板，确保所有新生成的满足条件的索引都能自动继承生命周期策略和别名。
   例如，创建索引模板"template_test"，定义所有新生成的"test"开头的索引自动关联上生命周期策略"rollover_workflow"，并且Rollover时使用"log_alias"作为别名。
   ```
   PUT _template/template_test
   {
     "index_patterns": "test*",
     "settings": {
       "number_of_replicas": 1,  // 索引副本数
       "number_of_shards": 1,    // 索引分片数
       "opendistro.index_state_management.policy_id": "rollover_workflow",    // 生命周期策略名称
       "index.opendistro.index_state_management.rollover_alias": "log_alias"  // Rollover的索引别名
     },
     "mappings": {
       "properties": {
         "name": {
           "type": "text"
         }
       }
     }
   }
   ```
   当索引模板创建完成后，可以通过如下命令查询模板详情：
   ```
   GET _template/template_test
   ```
   
4. 初始化首个索引，创建启动滚动的第一个索引，并指定写入入口，以便开始索引滚动流程。
   例如，创建第一个索引并设置日期编码，指定"aliases"，并配置"is_write_index"为"true"。该索引会自动应用索引模板"template_test"，并通过索引模板关联生命周期策略"rollover_workflow"。
   ```
   PUT %3Ctest-%7Bnow%2Fd%7D-000001%3E
   {
     "aliases": {
       "log_alias": {
         "is_write_index": true  // 告诉集群所有发往log_alias的写入请求都落在当前索引上
       }
     }
   }
   ```
   以上索引名称是对\<test-{now/d}-000001\>进行URL编码后的结果，其创建时默认会带上当天日期，如当天日期是"2022.6.02"，则创建出来的索引名称为"test-2022.06.02-000001"。
   
5. 写入数据，使用别名"log_alias"批量写入数据，且写入时"log_alias"始终指向最后一个索引。
   ```
   POST log_alias/_bulk
   {"index":{}}
   {"name":"name1"}
   {"index":{}}
   {"name":"name2"}
   {"index":{}}
   {"name":"name3"}
   {"index":{}}
   {"name":"name4"}
   {"index":{}}
   {"name":"name5"}
   {"index":{}}
   {"name":"name6"}
   ```
   
6. 查询数据，确认数据是否实现滚动索引。
   - 在索引创建一天后查看"test"开头的索引：
     ```
     GET _cat/indices/test*?s=i
     ```
     正常情况下会显示至少有两个索引，如下所示：
     ```
     green open test-<日期>-000001 r8ab5NX6T3Ox_hoGUanogQ 1 1 6 0 416b 208b
     green open test-<日期>-000002 sfwkVgy8RSSEw7W-xYjM2Q 1 1 0 0 209b 209b
     ```
     其中，"test-\<日期\>-000001"为[4]创建的索引，"test-\<日期\>-000002"为滚动生成的索引。
     
   
   - 查询别名"log_alias"关联的索引情况：
     ```
     GET _cat/aliases/log_alias?v
     ```
     正常情况下会显示该别名指向多个索引：
     ```
     alias     index                  filter routing.index routing.search is_write_index
     log_alias test-<日期>-000001      -      -             -              false
     log_alias test-<日期>-000002      -      -             -              true
     ```
     
    
 
#### FAQ：如何跳过索引的rollover步骤？
**使用场景**
- 手动执行过rollover的场景：当用户使用生命周期进行索引的rollover，并在policy中设置了基于时间的rollover条件。在条件未被满足之前，用户进行了手动的rollover操作。随后，当索引生命周期中配置的时间条件被满足时，自动的rollover尝试执行，但由于之前手动rollover的存在，导致自动rollover失败，生命周期任务停止。为解决此问题，用户需要配置跳过索引的rollover，然后重试生命周期任务，以使滚动索引能够继续执行。
- 对已经自动rollover的索引执行过remove或add policy操作的场景：通过生命周期自动rollover过的索引，在修改过policy（如remove policy和add policy）之后，生命周期会从头开始执行，当再次执行到rollover时，任务会失败。为了解决此问题，用户需要配置跳过索引的rollover，然后重试生命周期任务，以使滚动索引能够继续执行。
![](https://support.huaweicloud.com/usermanual-css/public_sys-resources/warning_3.0-zh-cn.png)
索引在设置跳过rollover步骤以后，索引生命周期将不再对索引进行rollover步骤，也不会生成rollover后的索引，因此，对正常执行的索引进行跳过rollover步骤可能会导致数据丢失，请谨慎操作。
**约束限制**
支持跳过索引rollover步骤的Elasticsearch集群要求版本号为7.6.2或7.10.2，并且集群镜像版本号不低于7.x.2_25.1.0_x.x.x。
**操作步骤**
1. 当索引生命周期任务因为rollover失败而停止时，执行如下命令配置跳过索引的rollover。
   ```
   PUT {index_name}/_settings
   {
     "index.plugins.index_state_management.rollover_skip": true
   }
   ```
   返回结果为"true"，表示配置成功。
   
2. 配置跳过索引的rollover之后，执行如下命令，重试生命周期任务。
   ```
   POST _opendistro/_ism/retry/{index_name}
   ```
   返回如下信息，表示重试成功。
   ```
   {
     "updated_indices": 1,
     "failures": false,
     "failed_indices": []
   }
   ```
   
 
