HOOOS

日志太多成本hold不住?Elasticsearch ILM来帮你自动管理时序数据,省钱提效!

0 78 ES老司机阿强 ElasticsearchILM日志管理时序数据数据生命周期
Apple

你是不是也遇到了这样的烦恼:系统运行时间越长,产生的日志、指标等时序数据就越多,像滚雪球一样,把你的存储空间吃得一干二净?更头疼的是,这些海量数据不仅存储成本蹭蹭上涨,时间久了,查询分析也变得越来越慢,甚至卡顿,严重影响了问题排查和系统监控的效率。

别担心,如果你正在使用 Elasticsearch (ES) 来存储和分析这些时序数据,那么它内置的索引生命周期管理 (Index Lifecycle Management, ILM) 功能就是你的得力助手!它就像一个智能管家,能帮你自动、高效地管理这些数据的“生老病死”,在保证数据可用性的前提下,大幅优化存储成本和查询性能。

什么是 ILM?它凭啥能管理时序数据?

想象一下数据的生命周期,就像人的生命一样,有“年轻力壮”的活跃期,也有“退休养老”的归档期,最后可能还需要“寿终正寝”。对于时序数据(比如日志、监控指标)来说,这个特点尤其明显:

  • 近期数据(Hot):刚产生的数据,访问最频繁,需要快速写入和查询,通常存储在性能最好的硬件上(比如SSD)。
  • 中期数据(Warm):数据变旧了一些,访问频率降低,但偶尔还需要查询,可以接受稍慢的查询速度,可以考虑迁移到成本稍低的存储上(比如大容量HDD)。
  • 长期数据(Cold/Frozen):数据非常陈旧,几乎不再访问,但可能因为合规性要求或其他原因需要长期保留。查询需求极低,甚至可以接受非常慢的查询或只读访问,目标是最低的存储成本(比如对象存储)。
  • 过期数据(Delete):数据完全失去价值,可以直接删除以释放空间。

ILM 就是 Elasticsearch 提供的一套自动化管理机制,让你能够根据数据的“年龄”和“状态”,预先定义好一套规则(称为策略 Policy),然后将这个策略应用到你的索引上。ES 就会像个不知疲倦的管理员,定期检查索引,并根据策略自动执行相应的操作,推动索引在不同的生命周期阶段 (Phase) 之间流转。

一个典型的 ILM 策略包含以下几个核心部分:

  1. 策略 (Policy):定义了一整套管理规则,包含多个阶段。
  2. 阶段 (Phase):代表数据生命周期的不同时期,常见的有 hotwarmcoldfrozendelete
  3. 动作 (Action):在每个阶段可以执行的具体操作,比如 rollover(滚动索引)、shrink(收缩分片)、forcemerge(强制合并段)、allocate(分配到不同节点)、searchable_snapshot(创建可搜索快照)、delete(删除索引)等。

ILM 如何为你的日志数据“续命”和“瘦身”?

让我们通过一个典型的日志管理场景,看看 ILM 是如何大显身手的。

假设你的应用日志索引模式是 applogs-%{+yyyy.MM.dd}-000001,并且你希望实现以下管理目标:

  • Hot 阶段:日志 активно 写入,需要高性能查询。当索引达到 50GB 或 7 天时,自动创建一个新索引继续写入(Rollover)。
  • Warm 阶段:7 天后的数据进入 Warm 阶段。访问频率降低,为了节省资源和提高查询效率(针对旧数据),将索引分片数减少到 1,并强制合并段。同时,将数据迁移到成本较低的“暖节点”上。
  • Cold 阶段:90 天后的数据进入 Cold 阶段。访问极少,但需要保留。将其迁移到更便宜的“冷节点”存储上,并设置为只读。
  • Delete 阶段:365 天后的数据不再需要,自动删除。

下面我们来分解一下 ILM 在这个过程中扮演的角色:

阶段一:Hot - 性能优先,写入高峰

这是数据的“黄金时期”。新日志源源不断地写入,你也需要能够快速地搜索最近的日志来排查线上问题。

  • 关键动作:rollover
    • 为什么需要 Rollover? 如果你一直往一个索引里写数据,这个索引会变得越来越大。巨大的索引不仅写入性能会下降,查询性能也会变差,而且一旦出问题恢复起来也更困难。想象一下,一个房间无限堆积货物,找东西和放东西都会越来越难。
    • ILM 怎么做? 你可以设置 rollover 条件,比如 max_size: 50gbmax_age: 7dmax_docs: 100000000。当索引满足任一条件时,ILM 会自动:
      1. 创建一个新的索引(例如,applogs-2023.10.27-000002)。
      2. 将索引别名(比如 applogs-write)指向这个新索引。
      3. 后续的写入请求就会自动路由到新索引。
    • 效果: 保持写入索引的大小可控,确保了写入和查询的性能。这就像是仓库满了自动开一个新仓库,并告诉所有人新货往新仓库放。

阶段二:Warm - 优化资源,降低成本

数据不再频繁写入,访问频率也下降了。这时候的主要目标是优化资源占用和存储成本,同时保持数据可查询。

  • 关键动作:allocateshrinkforcemerge
    • allocate 你可以配置 ILM 将索引迁移到具有不同硬件配置的节点上。比如,将 Warm 阶段的索引分配到使用大容量 HDD 而不是 SSD 的“暖节点” (Warm Nodes) 上。ES 通过节点属性 (Node Attributes) 来实现这一点(例如,node.attr.data: warm)。这就像把不常用的东西从市中心的昂贵仓库搬到郊区的廉价仓库。
    • shrink Hot 阶段为了写入吞吐量,你可能设置了较多的主分片。进入 Warm 阶段后,写入停止,可以将主分片数量收缩到一个较小的值(通常是 1)。比如从 5 个分片收缩到 1 个。这会减少集群的元数据开销和资源消耗。注意:收缩前索引必须是只读,并且每个节点上必须有索引所有主分片的副本。
    • forcemerge Lucene(ES 底层搜索引擎)会将数据写入称为“段 (Segment)”的小文件。随着数据写入和更新,段的数量会增多。太多的段会消耗更多的内存和文件句柄,并可能拖慢查询速度。forcemerge 操作会将这些小段合并成更少、更大的段,并可以永久删除已标记为删除的文档。这能释放磁盘空间,并显著提高查询性能(特别是对于不再写入的索引)。这个过程比较消耗 I/O 和 CPU,适合在 Warm 或 Cold 阶段执行。
    • 效果: 通过迁移到更便宜的存储、减少分片开销、优化段文件,有效降低了资源占用和成本,同时还可能提升了对旧数据的查询速度。

阶段三:Cold - 长期归档,最低成本

数据已经很老了,几乎没人会查,但可能因为法规或特殊需求需要保留很长时间。此时,极致的成本优化是首要目标。

  • 关键动作:allocatefreeze (旧版) / searchable_snapshot (推荐)
    • allocate 类似于 Warm 阶段,可以将索引分配到成本最低的“冷节点” (Cold Nodes) 上。
    • freeze (旧版,逐渐被替代): freeze 操作会关闭索引,然后重新打开它,但将其加载到内存中的数据结构最小化。这会显著减少内存占用,但查询速度会变得非常慢,因为它需要在查询时才加载必要的数据结构。冻结的索引是只读的。
    • searchable_snapshot (推荐): 这是更现代、更强大的方式。ILM 可以自动为索引创建可搜索快照 (Searchable Snapshots),并将这些快照存储在低成本的对象存储(如 AWS S3, Azure Blob Storage, Google Cloud Storage, MinIO 等)中。原始索引可以随后删除。当需要查询这些数据时,ES 可以直接在对象存储上“挂载”快照进行查询,而无需将所有数据恢复到 ES 集群的磁盘上。这极大地降低了存储成本,同时仍然保留了查询能力(尽管查询速度会比 Hot/Warm 慢)。你甚至可以创建一个 frozen 阶段专门用于管理这些可搜索快照。
    • 效果: 将长期数据归档到最便宜的存储介质(如对象存储)中,最大限度地降低存储成本,同时通过可搜索快照等技术保留了按需查询的能力。

(可选) 阶段四:Frozen - 极寒冰封,按需解冻

这是 Cold 阶段的延伸,通常完全依赖于可搜索快照。数据完全存储在对象存储中,集群本身几乎不占用存储资源。查询时需要先“挂载”快照,性能最低,但成本也最低。

阶段五:Delete - 清理空间,功成身退

当数据保存期限已到,不再有任何价值时,ILM 可以自动执行 delete 操作,彻底删除索引,释放存储空间。

  • 关键动作:delete
    • ILM 怎么做? 在策略的 delete 阶段设置一个最小年龄(min_age),例如 365d。一旦索引从上一个阶段(比如 Cold)进入 Delete 阶段,并且其年龄达到了 365 天,ILM 就会自动删除该索引。
    • 效果: 自动化数据清理,避免无用数据无限期占用宝贵的存储资源。

实战演练:创建一个简单的日志 ILM 策略

虽然在 Kibana 界面上点几下就能创建 ILM 策略,但了解其背后的 JSON 结构也很有帮助。下面是一个简化的示例策略 my_log_policy

PUT _ilm/policy/my_log_policy
{
  "policy": {
    "phases": {
      "hot": {
        "min_age": "0ms",
        "actions": {
          "rollover": {
            "max_size": "50gb",
            "max_age": "7d"
          },
          "set_priority": { // 热阶段索引优先级最高,优先恢复
            "priority": 100
          }
        }
      },
      "warm": {
        "min_age": "7d", // 进入 warm 阶段的最小时间
        "actions": {
          "allocate": { // 分配到 warm 节点
            "require": {
              "data": "warm"
            }
          },
          "shrink": { // 收缩到 1 个主分片
            "number_of_shards": 1
          },
          "forcemerge": { // 合并段到 1 个,提升查询性能
            "max_num_segments": 1
          },
          "set_priority": { 
            "priority": 50
          }
        }
      },
      "cold": {
        "min_age": "90d",
        "actions": {
          "allocate": { // 分配到 cold 节点
            "require": {
              "data": "cold"
            }
          },
          "set_priority": {
            "priority": 0
          }
          // 这里可以添加 searchable_snapshot 动作
          // "searchable_snapshot": {
          //   "snapshot_repository": "my_s3_repository" 
          // }
        }
      },
      "delete": {
        "min_age": "365d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

创建好策略后,你还需要创建一个索引模板 (Index Template),将这个策略应用到所有匹配 applogs-* 模式的新索引上,并指定用于 rollover 的别名。

PUT _index_template/applogs_template
{
  "index_patterns": ["applogs-*"],
  "template": {
    "settings": {
      "number_of_shards": 3,
      "number_of_replicas": 1,
      "index.lifecycle.name": "my_log_policy", // 应用 ILM 策略
      "index.lifecycle.rollover_alias": "applogs-write" // 指定 rollover 别名
    }
  }
}

最后,你需要手动创建第一个索引并让别名指向它,启动整个流程:

PUT applogs-000001
{
  "aliases": {
    "applogs-write": {
      "is_write_index": true // 标记这是写入别名
    }
  }
}

之后,ILM 就会接管 applogs-* 索引的生命周期管理了!

拥抱 ILM 的核心优势

总结一下,使用 Elasticsearch ILM 管理时序数据(尤其是日志和监控数据)能带来实实在在的好处:

  1. 成本优化显著:通过数据分层(Hot/Warm/Cold/Frozen),将旧数据自动迁移到成本更低的存储介质,特别是结合可搜索快照使用对象存储,能大幅降低存储开销。
  2. 性能保持稳定rollover 机制确保活跃索引大小可控,维持写入和查询性能。forcemerge 优化旧索引的查询速度。
  3. 自动化管理:设定好策略后,ILM 自动执行,无需人工干预索引的迁移、优化和删除,大大减少运维负担和出错风险。
  4. 灵活性高:可以根据不同的数据类型和业务需求,定制不同的生命周期策略。

注意事项和最佳实践

  • 仔细规划:在实施 ILM 前,充分了解你的数据访问模式、保留策略和成本/性能需求,设计合理的阶段和动作。
  • 监控 ILM:使用 GET /<index>/_ilm/explain API 或 Kibana 的 ILM UI 监控策略执行状态,确保一切按预期进行。
  • 资源预留:像 shrinkforcemerge 这样的操作会消耗资源,确保集群有足够的 CPU 和 I/O 能力来处理这些后台任务,尤其是在高峰时段之外执行。
  • 测试先行:在非生产环境充分测试你的 ILM 策略,确认其行为符合预期,再应用到生产环境。
  • 节点角色和属性:合理规划和配置 Hot、Warm、Cold 节点的角色和属性,这是实现数据分层的基础。

结语

面对海量的时序数据,特别是日志和监控指标,Elasticsearch 的 ILM 功能提供了一个强大而灵活的自动化解决方案。它不仅仅是简单地删除旧数据,更是一种精细化的管理哲学,通过在数据的整个生命周期中应用不同的策略和动作,实现了成本、性能和可用性之间的最佳平衡。如果你还在为不断增长的日志数据头疼,那么深入了解并用好 ILM,绝对能让你的 ES 集群管理工作事半功倍,既省钱又省心!

点评评价

captcha
健康