如果你要处理时间序列数据,则不想将所有内容连续转储到单个索引中。 取而代之的是,你可以定期将数据滚动到新索引,以防止数据过大而又缓慢又昂贵。 随着索引的老化和查询频率的降低,你可能会将其转移到价格较低的硬件上,并减少分片和副本的数量。
要在索引的生命周期内自动移动索引,可以创建策略来定义随着索引的老化对索引执行的操作。 索引生命周期策略在与 Beats 数据发件人一起使用时特别有用,Beats 数据发件人不断将运营数据(例如指标和日志)发送到 Elasticsearch。 当现有索引达到指定的大小或期限时,你可以自动滚动到新索引。 这样可以确保所有索引具有相似的大小,而不是每日索引,其大小可以根 beats 数和发送的事件数而有所不同。
让我们通过动手操作场景跳入索引生命周期管理(Index cycle management: ILM)。 本文章将利用你可能不熟悉的ILM独有的许多新概念。 我们先用一个示例来展示。本示例的目标是建立一组索引,这些索引将封装来自时间序列数据源的数据。 我们可以想象有一个像Filebeat这样的系统,可以将文档连续索引到我们的书写索引中。 我们希望在索引达到50 GB,或文档的数量超过10000,或已在30天前创建索引后对其进行 rollover,然后在90天后删除该索引。
不要分配一个太大的索引或者多个的太小的索引。
可以把一个大的索引分配到多个节点大小适中的索引当中去存储
上图显示一个 Log 文档在 Elasticsearch 中生命周期。
针对一个超大规模的集群:
ILM 由一些策略(policies)组成,而这些策略可以触发一些 actions。这些 actions 可以为:
Action | Description |
Set Priority | 这设置了执行步骤的优先级。 |
Unfollow | 这为跨集群索引设置为标准索引。follower 索引将不再跟随 leader 索引而变化 |
Rollover | 这设置了一个翻转索引。创建一个新的索引,基于数据的时间跨度,大小及文档的多少 |
Read-Only | 这会将索引设置为只读模式。 它跟随一个翻转命令。 |
Shrink | 这减少了当前索引的分片数量。减少 primary shards 的数目 |
Force Merge | 这优化了索引中的段数。合并 shard 的 segments |
Allocate | 这会更改可以托管索引的节点。 |
Migrate | 这会改变索引的层级(并且可以减少请求的分片数量)。 |
Freeze | 这会冻结索引(将其从内存中删除)。 |
Searchable Snapshot | 这会将快照挂载为可搜索的索引。 |
Wait for Snapshot | 这会等待索引的完整快照,以确保在删除之前存在索引的备份副本。 |
Delete | 永久地删除一个索引 |
并非所有操作都可用于不同阶段; 下表总结了各个阶段的操作:
索引生命周期由五个阶段(phases)组成:hot,warm,cold,frozen 及 delete。每个阶段有一组可用的 actions。这些 actions 由上面的 actions 中的一些组成。把这些阶段和相应的 actions 一起组合起来就形成了一个策略(policy)。我们可以通过 API 的形式或者直接在 Kibana 中使用 UI 的形式来创建这些 policies。
ILM 策略实例:
- 在 hot 阶段,你可能 rollover 一个 alias 从而每两个星期就生成一个新的索引,避免太大的索引数据。在这个阶段你可以做导入数据,并允许繁重的搜索。
- 在 warm 阶段,你可能把索引变成 read-only,并把索引保留于这个阶段一个星期。在这个阶段,不可以导入数据,但是可以进行适度的搜索。
- 在 cold 阶段,你可能 freeze 索引,并减少 replica 的数量,并保留于这个阶段三个星期。在这个阶段,不可以导入数据,但是可以进行极其少量的搜索,
- 在 delete 阶段,只有一个动作可以选择。比如你可以删除超过6个星期的索引数据以节省成本。
自 Beats 7.0 一来,Beats 在默认的情况下,采用 ILM 策略。通过 Beats 的 index template 自动地配置到每个 Beats 的索引中。默认的策略是:当索引的大小超过 50G,或者 age 超过 30 天,就会自动创建一个新的索引。但是它不移动索引,不提供更为高级的功能。开发者可以通过 Kibana 中的 Management 界面进行修改或者使用 Elasticsearch API 接口来进行修改。
运行两个 node 的 Elasticsearch 集群
我们可以参考文章 “Elasticsearch:运用shard filtering来控制索引分配给哪个节点” 运行起来两个 node 的 cluster。其实非常简单,当我们安装好 Elasticsearch 后,打开一个 terminal,并运行如下的命令:
./bin/elasticsearch -E node.name=node1 -E node.attr.data=hot -Enode.max_local_storage_nodes=2
它将运行起来一个叫做 node1 的节点。同时在另外 terminal 中运行如下的命令:
./bin/elasticsearch -E node.name=node2 -E node.attr.data=warm -Enode.max_local_storage_nodes=2
它运行另外一个叫做 node2 的节点。我们可以通过如下的命令来进行查看:
GET _cat/nodes?v
显示两个节点:
我们可以用如下的命令来检查这两个 node 的属性:
GET _cat/nodeattrs?v&s=name
显然其中的一个 node 是 hot,另外一个是 warm。
准备数据
运行起来我们的 Kibana:
我们分别点击上面的1和2处:
点击上面的 “Add data”。这样我们就可以把我们的 kibana_sample_data_logs 索引加载到 Elasticsearch 中。我们可以通过如下的命令进行查看:
GET _cat/indices/kibana_sample_data_logs
命令显示结果为:
它显示 kibana_sample_data_logs 具有11.1M的数据,并且它有 14074 个文档。
建立 ILM policy
我们可以通过如下的方法来建立一个 ILM 的 policy.
PUT _ilm/policy/logs_policy
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_size": "50gb",
"max_age": "30d",
"max_docs": 10000
},
"set_priority": {
"priority": 100
}
}
},
"delete": {
"min_age": "90d",
"actions": {
"delete": {}
}
}
}
}
}
这里定义的一个 policy 意思是:
- 如果一个 index 的大小超过 50GB,那么自动 rollover
- 如果一个 index 日期已在30天前创建索引后,那么自动 rollover
- 如果一个 index 的文档数超过10000,那么也会自动 rollover
- 当一个 index 创建的时间超过90天,那么也自动删除
其实这个我们也可以通过 Kibana 帮我们来实现。请按照如下的步骤:
紧接着点击“Index Lifecycle Policies”:
再点击“Create Policy”:
最后点“Save as new Policy”及可以在我们的Kibana中同过如下的命令可以查看到:
GET _ilm/policy/logs_policy
显示结果:
设置 Index template
我们可以通过如下的方法来建立 template:
PUT _template/datastream_template
{
"index_patterns": ["logs*"],
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1,
"index.lifecycle.name": "logs_policy",
"index.routing.allocation.require.data": "hot",
"index.lifecycle.rollover_alias": "logs"
}
}
这里的意思是所有以 logs 开头的 index 都需要遵循这个规律。这里定义了 rollover 的 alias 为 “logs”。这在我们下面来定义。同时也需要注意的是 "index.routing.allocation.require.data": "hot"。这个定义了我们需要 indexing 的 node 的属性是 hot。请看一下我们上面的 policy 里定义的有一个叫做 phases 里的,它定义的是 "hot"。在这里我们把所有的 logs* 索引都置于 hot 属性的 node 里。在实际的使用中,hot 属性的 index 一般用作 indexing。我们其实还可以定义一些其它 phase,比如 warm,这样可以把我们的用作搜索的 index 置于 warm 的节点中。这里就不一一描述了。
定义 Index alias
我们可以通过如下的方法来定义:
PUT logs-000001
{
"aliases": {
"logs": {
"is_write_index": true
}
}
}
在这里定义了一个叫做 logs 的 alias,它指向 logs-00001 索引。注意这里的 is_write_index 为 true。如果有 rollover 发生时,这个alias会自动指向最新 rollover 的 index。
生成数据
在这里,我们使用之前我们已经导入的测试数据 kibana_sample_data_logs,我们可以通过如下的方法来写入数据:
POST _reindex?requests_per_second=500
{
"source": {
"index": "kibana_sample_data_logs"
},
"dest": {
"index": "logs"
}
}
上面的意思是每秒按照500个文档从 kibana_sample_data_logs 索引 reindex 文档到 logs 别名所指向的 index。我们运行后,通过如下的命令来查看最后的结果:
GET logs*/_count
显示如下:
我们可以看到有14074个文档被 reindex 到 logs* 索引中。
我们稍等一段时间让 rollover 发生。这个时间是由如下的参数来决定的:
indices.lifecycle.poll_interval
我们可以在地址找到这个参数的设置。在默认的情况下,这个参数是10分钟的时间。我们需要等一段时间。我们也可以通过如下的命令来进行修改这个时间:
PUT _cluster/settings
{
"transient": {
"indices.lifecycle.poll_interval": "10s"
}
}
上面表明 Elasticsearch 每隔10秒钟进行查询。
通过如下的命令来查看:
GET _cat/shards/logs*
我们可以看到 logs-000002 已经生成,并且所有的索引都在 node1 上面。我们可以通过如下的命令进行查看:
GET _cat/indices/logs?v
我们可以看到 logs-000001 索引中有10000个文档,而 logs-000002 中含有4074个文档。
由于我们已经设定了policy,那么所有的这些logs*索引的生命周期只有90天。90天过后(从索引被创建时算起),索引会自动被删除掉。