当你用 ELK 作为日志收集系统的时候,你会发现随着时间的增长,索引的数据量也会增多,但是这些数据里只有最近一段时间内的数据可能会被访问到,应该不会真的有人去查询两年前的日志吧? 所以你会不会有这样的疑问:那些很旧的日志没啥用了,我是不是要自己手动删除呢?系统可以帮我自动删除吗?

为了方便用户管理索引,Elastic Stack 在 6.6 版本推出了 ILM(Index Lifecycle Management) 功能,提供了索引全生命周期的托管。我们可以利用 ILM 对历史数据按某种策略定时进行管理、清除来达到释放资源的目的。

简单了解了 ILM 后,我们今天的内容主要有:

  1. ILM 中相关概念介绍与其基本原理
  2. ILM 使用实践
  3. ILM 管理 API 简介

一、ILM 中相关概念的介绍与其原理

ILM 里有三个最基本的概念:Phase、Action、PolicyILM 里将索引的生命周期分为多个 Phase (阶段),Action 是指索引在不同阶段下可以执行的操作。而 Policy 可以将不同阶段的 Action 串联起来,是所有要执行的操作的蓝图。

Phase(阶段)

ILM概念.png

如上图,在 ILM 里 Phase 有 5 个,他们的含义分别如下:

  • Hot,处理时序数据的写入和热点数据的查询。
  • Warm,不再写入和更新数据,索引被设置为只读,主要承担查询操作。
  • Cold,不能执行写操作,这个阶段的数据很少会被查询,而且查询速度很慢。
  • Frozen,不能执行写操作,这个阶段的数据几乎不会再进行查询,其查询速度极慢。
  • Delete,这个阶段的数据不再被系统业务需要了,可以安全地被删除了。

这些阶段都是见名识意,比较好理解。从图中可以得知,在每个阶段里都有支持的 Actions,那 ES 里可用的 Actions 有那些呢?请继续往下看!

Actions

ES 里可用的 Action 有多个:

  • Set Priority,设置 Index 的处理优先级。在节点重启时,优先级越高的索引 recover 时优先被处理。
  • Unfollow,在 CCR 架构中,将一个 CCR 跟随索引转换为普通索引,即取消 follow。
  • Rollover,提供根据文档数量、索引大小、创建时间自动切换到新的索引。
  • Read-Only,设置索引只读。
  • Force Merge,强制合并索引,最大限度地使得索引占用更少的 Segment 文件。
  • Searchable Snapshot,为索引生成快照,并且存储在指定的仓库和挂载这个快照。
  • Shrink,这个我们之前介绍过了,用来缩小索引主分片 (Shard)的数量的。
  • Allocate,提供更新索引设置的功能,可以重新分配索引分片的存储节点和更改分片的副本数量。
  • Migrate,将索引迁移到对应阶段的数据层级节点上。
  • Freeze,冻结索引以最大限度地减少其占用的存储空间。
  • Wait For Snapshot,在删除索引前,等待指定的 SLM(快照生命周期管理) 协议执行完成,这样可以保证被删除索引的快照可用。
  • Delete,永久地删除索引。

从上图中我们知道,ILM 的每个阶段(Phase)都可以对应多个 Action,下面是各个 Phase 和 Action 的关系:

ILM Phase 对应阶段可执行的 Actions
Hot Set Priority、Unfollow、Rollover、Read-Only、Shrink、Force Merge、Searchable Snapshot
Warm Set Priority、Unfollow、Read-Only、Allocate、Migrate、Shrink、Force Merge
Cold Set Priority、Unfollow、Read-Only、Searchable Snapshot、Allocate、Migrate、Freeze
Frozen Searchable Snapshot
Delete Wait For Snapshot、Delete

ES 支持的 Action 比较多,下面对几个重要的进行详细介绍。更多的 Action 信息和使用示例可以参考官方文档

1. Rollover 假如我们想实现一个功能:当一个索引的 size 大于 20G 的时候自动创建一个新的索引来保存数据,这个时候 Rollover 就可以帮到我们了。

从字面上来理解,Rollover 就是滚动的意思。当 Rollover 因满足某些条件被触发的时候,系统会创建新的索引来存储新的数据,并且将索引别名指向新的索引来使得客户端写入无感知,所以 Rollover 需要和 Alias 结合使用。

Rollover.png

如上图,客户端向 app_log 的索引别名中写入业务数据,当没有触发 Rollover 条件的时候,app_log 别名将指向 app-log-000001,并且 app-log-000001 是一个 write index。而一旦触发 Rollover 条件的时候系统会自动创建 app-log-00002 索引,并且将 app_log 别名指向 app-log-00002,此时会设置 app-log-00001 只读(is_write_index = false)。

可以触发 Rollover 的条件有以下几个:

  • 最大的创建时间。意思是经过多长时间后再次创建新的索引来存储数据。其 API 参数为 max_age。
  • 最大文档数。当文档总数(主分片上的文档数量)达到指定值后触发 Rollover。其 API 选项为 max_docs。
  • 索引大小。当索引所有主分片的 size 之和超过指定值后触发 Rollover。其 API 选项为 max_size。
  • 主分片大小。当某个主分片的 size 超过指定值后触发 Rollover。其 API 选项为 max_primary_shard_size。

要设置 Rollover 条件可以使用如下示例:

  1. # 创建一个索引,并且指定其别名为 app_log
  2. PUT app-log-000001
  3. {
  4. "aliases": {
  5. "app_log": { "is_write_index": true }
  6. }
  7. }
  8. # 指定 app_log 的 rollover 条件
  9. POST /app_log/_rollover
  10. {
  11. "conditions": {
  12. "max_age": "2d",
  13. "max_docs": 1001,
  14. "max_size": "20gb",
  15. "max_primary_shard_size": "5gb"
  16. }
  17. }

可以看到 Rollover 可以帮助我们根据条件管理索引,但不合理的配置可能会导致集群中产生过多的小索引,从而导致集群的总分片过多,增加集群的压力影、响查询性能。

更多关于 Rollover 的信息可以参考官方文档

2. Shrink

Shrink 提供了收缩索引主分片的功能,其使用的 API 我们在 《管理你的索引:索引管理 API 的使用》中已经详细介绍过了,此处我们不再介绍其 API 的使用,如果你已经忘记了的话请再次查阅。下面将介绍 Shrink 的原理。

Shrink 在底层的实现上是通过硬链接来实现的,但如果操作系统不支持硬链接或者使用了多路径的方式挂载了多个磁盘就会通过复制 Lucene 的分段来实现。

那为啥要用硬链接来实现呢?其实 Linux 文件系统用两部分组成:Inode 和 Block。其中 Inode 用来存储元数据,如文件的字节数、文件拥有者、文件的读写、执行权限、链接数(名指向这个 Inode 的文件数)等,而 Block 是实际存储的文件数据。所以系统可以通过 Inode 定位一个文件的数据。

linux链接.png

如上图,在 Linux 系统中链接分为软连接和硬链接。它们的特点是:

  • 软连接:文件的 Inode 和 Block 都是独立的,但是 Block 的内容为目标文件的路径。
  • 硬链接:文件拥有相同的 Inode 和 Block。

所以当源文件被删除的时候,软连接索引的数据会被删除,但是硬链接不会,在删除的时候硬链接只会减少 Inode 的链接数。使用硬链接的另外一个好处是可以不用复制文件,加快 Shrink 操作的速度。

下面看看 Shrink 操作时,硬链接建立的过程。我们将一个拥有 4 个主分片的源索引收缩为只有一个主分片的目标索引,其流程如下:

Shrink硬链接1.png

如上图,源索引有 4 个主分片,当进行 Shrink 操作前,需要将这些分片都汇聚到同一个节点,这些分片各占一个文件,它们都有对应的 Inode Number。

Shrink硬链接2.png 如上图,链接过程会遍历所有的 shard,将所有的 Segment 文件(Segment 有多个类型文件,这里只列出 .cfe 类型)链接到目标索引,目标索引的 Segment 从 0 开始命名。

Shrink硬链接3.png

当硬链接创建好后,就可以把原来的索引删除了,在源索引删除后其最终的形式如上图。

其实你会发现,上图的表达并不完整,因为每个 shard 都是一个 Lucene 的索引,而每个 Lucene 索引包含了多个文件,如:.cef、.cfs、.si 等。所以最终 source-index/shard0/1.cef 和 source-index/shard1/1.cef 将映射到 target_index/shard0/0.cef 和 target_index/shard0/1.cef 。

更多更新 Shrink Action 的信息请参考官方文档

3. Allocate

Allocate action 可以应用在 warm 和 cold 阶段。通过 Allocate 可以更新索引的设置,从而更改索引分片可分配的宿主节点和更改副本数量。

Allocate 的可设置选项有以下四个:

  • number_of_replicas,设置副本的数量。
  • include,分配索引分片到至少拥有一个指定属性的节点上。
  • exclude,分配索引分片到不包含任何一个指定属性的节点上。
  • require,分配索引分片到拥有所有属性的节点上。

使用 Allocate 时,这四个选项必须最少指定一个,否则会报错。

对于 number_of_replicas 其实很好理解,但是 include、exclude、require 并不好理解,下面举个例子来帮助你理解。假如要为一个节点 A 设置 box_type 属性,我们可以在 elasticsearch.yml 配置文件中设置 node.attr.box_type: hot,这个时候 节点 A 的属性中就有了 box_type,并且其值为 hot。我们可以设置一个 ILM 策略使得应用这个策略的索引在 warm 阶段可以把其分片分配到节点 A。

  1. PUT _ilm/policy/my_policy
  2. {
  3. "policy": {
  4. "phases": {
  5. "warm": { # 在 warm 阶段 执行
  6. "actions": { # 定义要执行的 action
  7. "allocate" : { # 重新分配索引分片
  8. "include" : {
  9. # 将索引分片分配到带有 box_type 属性,且其值为 hot 或者 warm 的节点上。
  10. "box_type": "hot,warm" # 指定属性列表
  11. }
  12. }
  13. }
  14. }
  15. }
  16. }
  17. }

如上示例,allocate 使用了 include 选项,其效果是:将索引分片分配到带有 box_type 属性,且其值为 hot 或者 warm 的节点上。所以应用这个 ILM 策略的索引可以在 warn 阶段重新分配索引分片到节点 A 上。

同理,exclude、require 就很好理解了。exclude 就是节点属性 box_type 带有 hot 或者 warm 的节点都不分配,require 就是同时带有 hot 和 warm 才分配。

更多关于 Allocate 的信息请参考官方文档

4. Migrate

Migrate Action 只能用于 warm 和 cold 阶段。使用 Migrate 可以移动索引到与现在 phase 对应的数据层级节点上。

额,啥是数据层级呢?不知道你还记不记得,我们在介绍节点角色类型的时候介绍过,数据节点分为很多类型:data_hot、data_content、data_warm、data_cold、data_frozen。数据层级(data tiers)就是具有相同数据节点角色的节点集合,它们通常有着相同的硬件配置

所以数据层级(data tiers)官方分为以下几种:

  • Content tier, 一般用于保存产品数据的节点,可以索引和检索数据。例如在线书店中书本信息这类数据。
  • Hot tier,主要索引最新的时序数据为主,例如日志。
  • Warm tier,存储不怎么频繁访问、通常不会更新的时序数据。
  • Cold tier,存储很少访问的时序数据,这些数据几乎不会更新。
  • Frozen tier,存储几乎不会被访问、不会更新的时序数据。

通过设置 index.routing.allocation.include._tier_preference 索引设置项来指定数据层级,假如 index.routing.allocation.include._tier_preference 设置为 data_warm,data_hot,那么索引在分配的时候会先分配到 warm 层级的节点上,如果不存在 warm 层级节点,就会分配到 hot 层级的节点上。

下面是 Migrate 的使用示例:

  1. # 迁移索引到 warm 节点上
  2. PUT _ilm/policy/my_policy
  3. {
  4. "policy": {
  5. "phases": {
  6. "warm": {
  7. "actions": {
  8. "migrate" : {
  9. },
  10. "allocate": {
  11. "number_of_replicas": 1
  12. }
  13. }
  14. }
  15. }
  16. }
  17. }

如上示例定义的 ILM 策略,其将会减少索引的副本分片到 1,然后迁移索引到 warm 节点上。需要注意的是,上述示例中 migrate 并没有指定任何操作,所以可以得出 ILM 中会自动执行索引迁移操作,除非你指定具体的分片分配操作或者禁用迁移操作。

禁用 migrate 的示例:

  1. # 不进行 migrate action 的 ILM 策略
  2. PUT _ilm/policy/my_policy
  3. {
  4. "policy": {
  5. "phases": {
  6. "warm": {
  7. "actions": {
  8. "migrate" : {
  9. "enabled": false
  10. },
  11. "allocate": {
  12. "include" : {
  13. "rack_id": "one,two"
  14. }
  15. }
  16. }
  17. }
  18. }
  19. }
  20. }

如上示例,因为 migrate 被明确禁用了,所以这个 migrate action 不会执行。并且你会发现,allocate 指定了选项,其将会把索引分配到带有 rack_id 为 “one” 或者 “tow” 的节点上。需要注意的是,只要指定了 allocate 进行分配选项,migrate 操作就会被禁止,所以使用 allocate 分配索引分片的优先级是比 migrate 要高的

5. Freeze

使用 Freeze Action 可以冻结一个索引从而可以最大限度地减少其占用的内存资源。

其实从占用资源的层面来看,索引有 3 中状态:

  • Open,索引可读写,倒排索引等数据会加载到内存中缓存,所以状态下搜索性能高。
  • Frozen,索引可读不可写,数据不缓存到内存,此时只占用磁盘空间,搜索性能低。
  • Close,索引不可读写,不占用内存,只占用磁盘。

Frozen 状态非常适合存储时序数据的场景和在冷热分离的架构应用。因为 Frozen 的索引不占用内存空间,可以将不怎么访问的历史数据索引设置为 Frozen 来节省资源和保障集群稳定性。

冻结、解冻结、查询冻结的索引的使用示例如下:

  1. # 冻结索引 test
  2. POST /test/_freeze
  3. # 解冻结索引 test
  4. POST /test/_unfreeze
  5. # 查询已经冻结的索引数据
  6. POST /test/_search?ignore_throttled=false
  7. {
  8. "query": {"match_all": {}}
  9. }

需要注意的是,冻结的索引默认是无法检索到数据的,需要查询时加上 ignore_throttled=false 参数

ok,看完了 Action 后,我们来看看上面提到过的 ILM Policy(策略)。

Policy(策略)

Policy 是 ILM 中的引擎,是所有要执行的操作的蓝图Policy 会将不同阶段的 Action 串联起来,而索引只有绑定了 Policy 后才会按照 Policy 定义的 Action 执行

Policy.png

定义或者更新一个 Policy 的示例如下:

  1. # 定义一个策略
  2. # 索引以每 5 个文档做一次 Rollover
  3. # 在 warm 阶段迁移索引到 warm 节点上,
  4. PUT _ilm/policy/my_policy
  5. {
  6. "policy": {
  7. "phases": {
  8. "hot": {
  9. "actions": {
  10. "rollover": {
  11. "max_docs": "5"
  12. }
  13. }
  14. },
  15. "warm": {
  16. "actions": {
  17. "migrate" : {
  18. },
  19. "allocate": {
  20. "number_of_replicas": 1
  21. }
  22. }
  23. }
  24. }
  25. }
  26. }

如上示例,我们定义了一个策略,在 hot 阶段索引会以每 5 个文档做一次 Rollover,在 warm 阶段会先将索引副本数量设置为 1,然后将索引分片分配到 warm 节点上。

查看和删除 Policy 的示例如下:

  1. # 删除 Policy
  2. DELETE _ilm/policy/my_policy
  3. # 获取 Policy 的信息
  4. GET _ilm/policy/my_policy

索引绑定 Policy 的方式有两种:

  • 在 setting 中指定 Policy
  • 在索引模板中指定 Policy,只要新的索引应用了这个索引模板就可以绑定对应的 Policy。

在 setting 中指定 Policy

  1. # 创建索引的时候指定
  2. PUT test1
  3. {
  4. "mappings": {
  5. "properties": { "test_name": { "type": "keyword"} }
  6. },
  7. "settings": {
  8. "index.lifecycle.name":"my_policy"
  9. }
  10. }
  11. # 如果索引 test1 已经存在,直接在 setting 中指定
  12. PUT test1/_settings
  13. {
  14. "settings": {
  15. "index.lifecycle.name":"my_policy"
  16. }
  17. }

如上示例,我们在创建 test1 的时候指定了 Policy 为 my_policy。而当 test1 索引已经存在的情况下,我们可以使用第二个示例进行设置索引的 Policy。

在索引模板中指定 Policy

  1. # 定义一个索引模板
  2. PUT _template/test_template
  3. {
  4. "order": 50,
  5. "index_patterns": [ "test-*" ],
  6. "settings": {
  7. "index": {
  8. "lifecycle": {
  9. "name": "my_policy",
  10. "rollover_alias": "test-log"
  11. }
  12. },
  13. "number_of_shards": "3",
  14. "number_of_replicas": "1"
  15. }
  16. }
  17. # 创建 test-11 索引
  18. PUT test-11
  19. {
  20. "mappings": {
  21. "properties": { "test_name": { "type": "keyword"} }
  22. }
  23. }
  24. # 查看 test-11 的设置
  25. GET test-11/_settings

如上示例,我们定义了一个索引模板:test_template,新创建的以 “test-“ 开头的索引将应用这个索引模板。test_template 指定了在 ILM 中使用 my_policy 策略,并且 rollover 时使用 “test-log” 为索引别名。最后创建 test-11 时将会应用 test_template 模板,通过查看 test-11 的 setting 可以发现,其已经应用了 my_policy 策略。

需要注意的是,Policy 的名称确定后就无法修改,但是 Policy 中的 Phase 和 Actions 是可以修改的,一旦 Policy 修改成功,后续新创建的索引会应用最新的 Policy。而那些正在执行旧 Policy 的索引,会在当前 Phase 的 Actions 执行完成后进入下一个阶段的时才会使用更新后的 Policy。

二、ILM 使用实践

OK,经过前面学习,我们已经对 ILM 中 Phase、Action、Policy 的概念非常清晰了,下面来实践一下,加深对这些概念的认识。

制定需求

在进行实践前,我们先制定我们的需求如下:

  1. 业务的日志数据写入到 hot 节点上,当索引的文档达到 10 条后执行 Rollover Action,新数据写入到新的索引中。
  2. 在 Rollover Action 完成 20 秒后,索引进入 warm 阶段,并且索引被分配到了 warm 节点上。
  3. 在 Rollover Action 完成 30 秒后,索引进入 cold 阶段,并且索引分配到 cold 节点上。
  4. 在 Rollover Action 完成 60 秒后,索引进入 delete 阶段,并且执行索引删除操作。

修改集群设置

1、设置节点的属性 在 elasticsearch.yml 配置文件中设置节点的属性,我们设置 node.attr.box_type 为 hot、warm、cold,分别代表 hot、warm、cold 节点。在我的环境中其配置如下:

  1. # my_node1 配置为 hot 节点
  2. node.attr.box_type: hot
  3. # my_node2 配置为 warm 节点
  4. node.attr.box_type: warm
  5. # my_node3 配置为 cold 节点
  6. node.attr.box_type: cold

如果你使用的是 docker-compose 启动的集群,可以这样配置:

  1. # my_node1 配置为 hot 节点
  2. environment:
  3. - node.name=my_node1
  4. - node.attr.box_type=hot
  5. # my_node2 配置为 warm 节点
  6. environment:
  7. - node.name=my_node2
  8. - node.attr.box_type=warm
  9. # my_node3 配置为 cold 节点
  10. environment:
  11. - node.name=my_node3
  12. - node.attr.box_type=cold

完成重启后,集群节点如下:

hwc集群.png

2、修改策略轮询的时间

默认的情况下 ILM Service 会在后台每 10 分钟轮询执行 Policy,因为我们只是测试,所以设置为 1 秒轮询一次,使用下面指令进行修改:

  1. PUT _cluster/settings
  2. {
  3. "persistent": { "indices.lifecycle.poll_interval":"1s" }
  4. }

需要注意的是,在生产环境中不能把这个值设置得过小,避免过短的时间间隔给集群造成负载过大的情况。每个阶段是按顺序执行的,假如一个阶段的 Action 还没有执行完成,但又触发了到达某个阶段的 Condition 的时候,只会等待当前阶段的 Action 执行完成才会执行下一个阶段的 Action。

操作步骤

通过前面的内容我们可以知道,进行 ILM 实践的操作步骤主要有以下几个:

  1. 创建 Policy,Policy 是蓝图,我们第一步必须定义这个蓝图。
  2. 创建索引模板,将创建的索引模板与上面创建的 Policy 进行绑定。
  3. 使用模板创建初始的索引,并且指定别名,这样索引就绑定了上述的 Policy。
  4. 通过别名写入日志数据

创建 Policy

  1. # 设置 Policy: log_policy
  2. PUT /_ilm/policy/log_policy
  3. {
  4. "policy": {
  5. "phases": {
  6. "hot": {
  7. "actions": {
  8. "rollover": {
  9. "max_docs": 10 # 最大的文档数量为10
  10. }
  11. }
  12. },
  13. "warm": {
  14. "min_age": "20s", # rollover 执行完成 20 秒后,进入 warm 阶段
  15. "actions": {
  16. "allocate": {
  17. "include": {
  18. "box_type": "warm"
  19. }
  20. }
  21. }
  22. },
  23. "cold": {
  24. "min_age": "30s", # rollover 执行完成 30 秒后,进入 cold 阶段
  25. "actions": {
  26. "allocate": {
  27. "include": {
  28. "box_type": "cold"
  29. }
  30. }
  31. }
  32. },
  33. "delete": {
  34. "min_age": "60s", # rollover 执行完成 60 秒后,进入 delete 阶段
  35. "actions": {
  36. "delete": {}
  37. }
  38. }
  39. }
  40. }
  41. }

如上示例定义了一个 Policy:log_policy,这个 Policy 有 hot、warm、cold、delete 阶段。在 hot 阶段指定了 rollover 在超过 10 个文档后执行,产生新的索引来存储新写入的数据。在 rollover 执行完成 20 秒后,进入 warm 阶段,索引数据将分配到 box_type 属性为 warm 的节点上。在 rollover 执行完成 30 秒后,进入 cold 阶段,索引分片将分配在 box_type 属性为 cold 的节点上。最后在 rollover 执行完成 60 秒后,进入 delete 阶段,并且执行索引删除操作。

这里需要对 min_age 字段进行解析,min_age 是指数据从 Rollover 完成后开始计算的时间。如果 Policy 没有设置 rollover,则在索引创建后开始计算。

创建索引模板

  1. # 创建索引模版: log_index_template
  2. PUT /_template/log_index_template
  3. {
  4. "index_patterns" : [ "log_index-*" ],
  5. "settings" : {
  6. "index" : {
  7. "lifecycle" : {
  8. "name" : "log_policy",
  9. "rollover_alias": "app_log"
  10. },
  11. "routing": {
  12. "allocation" : {
  13. "include" : {
  14. "box_type" : "hot"
  15. }
  16. }
  17. }
  18. },
  19. "number_of_shards" : "1",
  20. "number_of_replicas" : "0",
  21. "refresh_interval" : "1s"
  22. }
  23. }

如上示例,我们创建了 log_index_template 索引模板,其中指定了 lifecycle 策略为上面定义的 log_policy,并且指定了 rollover 时的索引别名为 app_log。在 routing 中,指定了新创建的索引它们的分片将分配在 box_type 属性为 hot 的节点上。

在模板中一定要定义 routing 和 rollover_alias 的设置,不然 ILM 在 rollover 时自动创建的新索引将找不到这些设置而导致 ILM 失败,产生莫名奇妙的结果。如果你感兴趣的话可以试一下(可以调整各个阶段的 min_age 值方便观察),这些现象我就不在这里展开了,自己去尝试和思考可以加深理解。

使用模板创建初始的索引

  1. #创建索引:log_index-000001
  2. PUT log_index-000001
  3. {
  4. "aliases": {
  5. "app_log": {
  6. "is_write_index": true
  7. }
  8. },
  9. "mappings": {
  10. "properties": { "log_msg": { "type": "text"} }
  11. }
  12. }

如上示例使用了 log_index_template 模板创建了初始的索引:log_index-000001。需要注意的是,Rollover 阶段对索引的名字是有要求的,其形式为: ^.-\d+$。*

通过别名写入日志数据

  1. POST app_log/_doc
  2. {
  3. "log_msg": "service up ...."
  4. }

如上示例,我们通过 app_log 向索引写入数据(这个 API 会自动分配文档 ID,执行多次可以写入多个文档),这个时候可以在 cerebro 中观察 log_policy 策略的执行过程了。

在我的测试环境中,我简单对执行流程截了几个图:

执行Pocily1.png

如上图,可以看到在 log_index-000001 的文档超过10 的时候,Rollover 自动执行了,并且创建了 log_index-000002 索引。

执行Policy2.png

如上图,此时 log_index-000002 已经进入到 warm 阶段,并且分配到 warm 节点了,而 log_index-000001 已经被执行删除。

执行Policy3.png

如上图,此时 log_index-000003 已经进入到 cold 阶段,并且索引分配到了 cold 节点,而此时 log_index-000002 已经被执行删除了。

执行Policy4.png

如上图,最终这些索引只剩下了 log_index-000004 在 hot 阶段,随着日志的写入,这个索引最终都会进入到 delete 阶段然后被删除。

更多关于 IML API 的使用示例可以参考官方文档

使用 Kibana 中管理 Policy

除了使用 API 的形式管理 Policy 外,我们还可以在 Kibana 中对其进行管理。在 Kiabna 中进入 Stack Management => Index Lifecycle Management 即可打开 Policy 管理界面:

Kibana管理Policy.png

在管理界面中可以看到我们上面创建的 log_policy,点击绿色箭头处的 Actions 可以绑定 Policy 到索引,而点击右上角的 Create Policy 即可创建新的 Policy。直接点击策略名称如 log_policy 即可管理此 Policy 的各个阶段和对应的 Actions:

kibana管理Phase.png

如上图,其中 Hot phase 是必须的,点击 Advanced setting 可以设置其对应的 Actions,下图是我们设置 Hot Rollover Action 的界面:

Kibana管理Rollover.png

三、ILM 管理 API 简介

下面来看看几个 ILM 管理的 API 使用示例,更多关于 ILM 管理 API 的使用示例请查看官方文档

获取 ILM 运行状态

  1. # 获取 ILM 状态
  2. GET _ilm/status
  3. # 结果
  4. {
  5. "operation_mode" : "RUNNING"
  6. }

ILM 默认的情况下是启动了的,使用如上示例可以查看 IML 的状态。返回的 operation_mode 值有以下 3 个:

  • RUNNING,正在运行。
  • STOPPING,正在停止,还有部分 Action 还在处理,处理完成后将转到 STOPPED 状态。
  • STOPPED,已经停止。

停止和启动 ILM

  1. # 停止 ILM 服务
  2. POST _ilm/stop
  3. # 启动 ILM 服务
  4. POST _ilm/start

如上示例,你可以在 Kibana 中执行后使用状态查看的 API 查看 ILM 的状态。

使用 explain 查看 Policy 执行状态

  1. # 查看索引 app_log 的生命周期状态
  2. GET app_log/_ilm/explain

如上示例,使用 explain 可以查看一个或者多少索引的生命周期状态。

重新执行索引的 Policy

  1. # 重新执行 your_index 索引的 Policy
  2. POST your_index/_ilm/retry

如上示例,使用 retry API 可以重新索引的 Policy。需要注意的是,your_index 是你的索引名称,不能为索引的别名。

四、总结

今天为你介绍了 ILM 中相关的概念包括 Phase、Actions、Policy,我们还完成了一个需求来加深对这些概念的理解。最后还介绍了几个ILM 管理相关的 API。

IML 中有5个阶段(Phase)分别为 Hot、Warm、Cold、Frozen、Delete,每个阶段有其对应的 Actions。使用这些 Actions 我们可以在每个阶段执行不同的操作来满足索引管理的需求。Policy 是所有要执行的操作的蓝图,Policy 将不同阶段的 Actrion 串联起来,而索引只有绑定了 Policy 后才会按照 Policy 定义的 Action 执行。

ES 提供的 Actions 有多个,我们主要介绍了以下几个:

  • Rollover,是滚动的意思,可以根据文档数量、索引大小、创建时间自动切换到新的索引。
  • Shrink ,其可以提供索引收缩的功能,在 Linux 下可以通过硬链接来实现。
  • Allocate,可以更新索引的设置,从而更改索引分片可分配的宿主节点和更改副本数量。
  • Migrate,使用 Migrate 可以移动索引到与现在 phase 对应的数据层级节点上。
  • Freeze,可以冻结一个索引从而可以最大限度地减少其占用的内存资源。

在我们要进行 ILM 的时候,一般需要通过以下步骤进行:

  1. 创建 Policy,Policy 是蓝图,我们第一步必须定义这个蓝图。
  2. 创建索引模板,将创建的索引模板与上面创建的 Policy 进行绑定。
  3. 使用模板创建初始的索引,并且指定别名,这样索引就绑定了上述的 Policy。
  4. 通过别名写入日志数据

当然我们也可以通过 Kibana 提供的图形化界面进行操作。