ElasticSearch ILM实践

2022-05-15 09:04:29 浏览数 (1)

在ES没有提供ILM功能以前,我们的索引生命周期管理一般是自己写脚本或者curator工具来管理的。

提供ILM功能后,索引生命周期管理基本上可以在ElasticStack内自治了。

ILM的理论可以参考官方文档,具体不在赘述。

ILM分为四个Phase,分别是Hot、Warm、Cold和Delete。

在Hot阶段支持Rollover Action,在Warm阶段支持Read-Only、Force-Merge、Shrink、Allocate等Action,在Cold阶段支持Frozen、Allocate等Action,在Delete阶段支持Delete的Action。

生产上 2个阶段(hotdelete)或3个阶段(hotwarmdelete) ,通常就够用了。

标准的ILM的实施总结起来就是4步骤:

代码语言:javascript复制
第一步:创建Policy  
第二步:创建索引模版
第三步:创建初始索引
第四步:通过别名写入数据

为啥叫做标准的, 因为官方文档就是这么操作的。

TIPS: 对于日志场景下通常已经是按天切割了,我们有时候直接就简化为:

代码语言:javascript复制
1、创建policy
2、创建索引模板
3、通过外部脚本创建当日索引
4、通过当日索引写入数据(filebeat logstash之类默认这么干的)

ILM标准方案的实操样例如下:

这里直接用命令行方式操作。

0、需要具备一套冷热分离的集群

可以参考这篇一键拉起测试集群 ​​https://blog.51cto.com/lee90/5286094​​

我下面的步骤中,强依赖到了node.attr.temperature 。需要保证实验的ES的这个参数值 为hot 或者warm

1、创建名为nginx-log的ILM Policy

代码语言:javascript复制
- hot:设置rollover条件,超过一天 或 体积达到50gb 或 docs数达到1000w就触发rollover
- warm:写入超过2天,自动迁移到warm节点,做shrink和forcemerge操作,并把副本降低为0
- delete: 写入超过7天的index,自动删除

PUT _ilm/policy/nginx-log-policy
{
  "policy": {
    "phases": {
      "hot" : {
            "min_age" : "0ms",
            "actions" : {
              "rollover" : {
                "max_size" : "50gb",
                "max_age" : "1d",
                "max_docs" : 10000000
              },
              "set_priority" : {
                "priority" : 100
              }
            }
      },      
      "warm": {
        "min_age": "2d",
        "actions": {
          "forcemerge": {
            "max_num_segments": 1
          },
          "set_priority": {
            "priority": 50
          },
          "shrink": {
            "number_of_shards": 1
          },
          "allocate": {
            "require": {
              "temperature": "warm"
            },
            "number_of_replicas": 1
          }
        }
      },
      "delete": {
        "min_age": "7d",
        "actions": {
          "delete": {
            "delete_searchable_snapshot": true
          }
        }
      }
    }
  }
}

2、创建名为nginx-log-template的索引模板,并关联上面创建的ILM策略,匹配nginx-log-*的索引,自动放置在hot节点上

代码语言:javascript复制
PUT _index_template/nginx-log-template
{
  "template": {
    "settings": {
      "index": {
        "lifecycle": {
          "name": "nginx-log-policy",
          "rollover_alias": "nginx-log"
        },
        "routing": {
          "allocation": {
            "require": {
              "temperature": "hot"
            }
          }
        },
        "hidden": "false",
        "number_of_shards": "3",
        "number_of_replicas": "1"
      }
    }
  },
  "index_patterns": [
    "nginx-log-*"
  ]
}

3、创建索引 

代码语言:javascript复制
PUT 
{
"aliases": {
    "nginx-log":{
       "is_write_index": true
        }
      }
}

GET nginx-log/_settings  查看这个alias的index的结果如下:

{
  "nginx-log-2022.05.11-000001" : {
    "settings" : {
      "index" : {
        "lifecycle" : {
          "name" : "nginx-log-policy",
          "rollover_alias" : "nginx-log"
        },
        "routing" : {
          "allocation" : {
            "include" : {
              "_tier_preference" : "data_content"
            },
            "require" : {
              "temperature" : "hot"
            }
          }
        },
        "hidden" : "false",
        "number_of_shards" : "3",
        "provided_name" : "<nginx-log-{now/d}-000001>",
        "creation_date" : "1652250986540",
        "priority" : "100",
        "number_of_replicas" : "1",
        "uuid" : "acesatMWTly2O0O-ZuxrVQ",
        "version" : {
          "created" : "8020099"
        }
      }
    }
  }
}

4、写个脚本,在cronjob里面,写入测试数据

代码语言:javascript复制
ts=$(date -u  "%F"T"%T".000Z)  # 拼接个UTC的@timestamp
echo ${ts}

# 按照个jq 便于格式化json输出
# 通过别名写入
for i in {1..100};do
  curl -s -X POST "http://localhost:9200/nginx-log/_doc/" -H 'Content-Type: application/json' -d "{"service":"app01","location":"Shanghai","traceId":"ssdfsd-4323443-dfvgdfgdfg-efrwewer-213213321","msg":"this is a test msg","@timestamp":"${ts}"}" | jq .
done

下面是配置好或者运行几天后的一些截图

运行几天后,cerebro界面看的索引节点分布情况

为了监控nginx-log这个index是啥时rollover的、啥时候shrink的。我们可以再在cronjob加个每分钟执行一次采集脚本

代码语言:javascript复制
$ cat monit_indices.sh 

curl -s -XPOST http://localhost:9200/nginx-log/_refresh | jq .
echo $(date  "%F %H:%M:%S") >> ./index_list.log
curl -s http://localhost:9200/_cat/indices?v | egrep 'nginx|status'  >>  ./index_list.log
echo "--------------------------------------------- " >>  ./index_list.log

看下kibana上,这个nginx-log索引最早的创建时间,是2022-05-11日14点37分。ILM在该索引创建的第三天后将其做了shrink(并且移动到ES warm节点)

至于为啥是3天? 因为ILM里面配置的wam phases里面min_age=2days,这个2day是从rollover后才开始计数的,加上rollover还需要一天,所以shrink是索引数据写入后的第三天。(也就是:2022.05.11创建的索引,会在2022.05.14做warm phases的操作)

Index Lifecycle Policies界面也有相关说明,如下图:

附:ILM相关API  API说明

代码语言:javascript复制
PUT _ilm/policy/<policy_id> 创建ILM的Policy
GET _ilm/policy<policy_id>  获取ILM的Policy
DELETE _ilm/policy/<policy_id>  删除特定的Policy
GET _ilm/status 获取ILM的状态
POST _ilm/start 启动ILM
POST _ilm/stop  停止ILM的执行
GET <index_name>/_ilm/explain 获取ILM的执行详情
POST <index_name>/_ilm/retry  重试某个索引的ILM执行

补充:

生产上我目前没有采用全套ILM解决方案(暂时只用了index template),还是用的脚本来做索引管理工作: 包括每天晚上定时创建下一天的索引,定时移动索引或删除索引。

原因如下:

我将索引的一些元数据信息,都是存在数据库里面,便于做自动化运维和后台统计

  • 索引的配置项都存在数据库里面(该索引属于那个业务线、索引需要几个shards、几个replicas、是否要定制化的mapping)
  • 数据库里面存储了每个索引的状态(hot、closed、warm_shrink、deleted),便于绘制运维看板
  • 脚本统计每个业务线的索引的大小用来估算费用摊销
  • 通过晚上低峰期创建索引,避免之前遇到的0点大批量创建索引导致集群负载过高(造成集群短时间内变黄或变红)的情况
  • 通过每天晚上23点采集了当天索引的大小,可以根据当天的索引大小,计算出下一天的索引是否需要扩大shard数(确保每个shard不超过50GB)

ILM个人认为用起来也是不错的选择, test、dev 之类的环境,直接ILM配一下一劳永逸。 prod环境,如果没啥太多需求,ILM也是够用的了。

参考:

​​https://cloud.tencent.com/developer/article/1910776​​

​​https://blog.csdn.net/zhangpfly/article/details/109238869​​

0 人点赞