在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