4. Elasticsearch 索引生命周期管理:ILM 策略设计

在 Golden Signals 日志检索工程中,日志数据具有时间序列强、冷热访问差异大、保留周期明确三大特征。Elasticsearch 索引生命周期管理(ILM)正是应对这些特征的核心工具。通过 ILM,我们可以按时间与信号类型自动分索引,在查询性能与存储成本之间取得最优平衡。

核心目标:将 Golden Signals 日志(延迟、流量、错误、饱和度)按信号类型拆分至独立索引模板,再按时间窗口滚动索引,最终实现热节点高性能写入、温节点低成本存储、冷节点归档或删除。

4.1 ILM 四阶段模型与 Golden Signals 映射

ILM 标准阶段包括 Hot → Warm → Cold → Delete。针对 Golden Signals 日志,每个阶段的存储介质、副本数、分段合并策略均不同:

ILM 阶段 存储介质 副本数 分段合并 适用信号类型 典型保留时长
Hot SSD / 高性能云盘 1 不合并,保持写入性能 所有信号(实时写入) 最近 6 小时
Warm HDD / 标准云盘 1 forcemerge 到 1 段 延迟、错误、饱和度 6 小时 ~ 7 天
Cold 对象存储 / 归档盘 0 已合并,只读 流量、饱和度(低频查询) 7 天 ~ 30 天
Delete — — — 所有信号 超过 30 天
设计要点:错误信号(Error)在 Warm 阶段保留完整原始日志用于根因分析;流量信号(Traffic)在 Cold 阶段可降采样为聚合指标,原始明细直接进入 Delete 阶段以节省成本。

4.2 按信号类型拆分索引模板

每个 Golden Signals 维度对应一个独立的索引模板,确保字段映射、分片数、滚动策略互不干扰:

# 延迟信号索引模板
PUT _index_template/gs-latency-template
{
  "index_patterns": ["gs-latency-*"],
  "template": {
    "settings": {
      "number_of_shards": 3,
      "number_of_replicas": 1,
      "index.lifecycle.name": "gs-latency-policy",
      "index.lifecycle.rollover_alias": "gs-latency-write"
    },
    "mappings": {
      "properties": {
        "@timestamp":    { "type": "date" },
        "service":       { "type": "keyword" },
        "latency_ms":    { "type": "long" },
        "percentile_99": { "type": "float" },
        "host":          { "type": "keyword" }
      }
    }
  }
}

# 错误信号索引模板
PUT _index_template/gs-error-template
{
  "index_patterns": ["gs-error-*"],
  "template": {
    "settings": {
      "number_of_shards": 5,
      "number_of_replicas": 1,
      "index.lifecycle.name": "gs-error-policy",
      "index.lifecycle.rollover_alias": "gs-error-write"
    },
    "mappings": {
      "properties": {
        "@timestamp":    { "type": "date" },
        "service":       { "type": "keyword" },
        "error_code":    { "type": "keyword" },
        "stack_trace":   { "type": "text", "index": false },
        "severity":      { "type": "keyword" }
      }
    }
  }
}
避坑提示:不要将所有信号类型放入同一个索引模板。混合写入会导致分片大小不均、查询过滤效率下降。按信号类型拆分后,每个索引的文档结构高度一致,压缩比和查询性能均可提升 30% 以上。

4.3 ILM 策略完整配置示例

以下策略针对延迟信号设计,展示 Hot → Warm → Cold → Delete 的完整参数:

PUT _ilm/policy/gs-latency-policy
{
  "policy": {
    "phases": {
      "hot": {
        "min_age": "0ms",
        "actions": {
          "rollover": {
            "max_size": "50GB",
            "max_age": "6h"
          },
          "set_priority": {
            "priority": 100
          }
        }
      },
      "warm": {
        "min_age": "6h",
        "actions": {
          "forcemerge": {
            "max_num_segments": 1
          },
          "shrink": {
            "number_of_shards": 1
          },
          "allocate": {
            "number_of_replicas": 1,
            "require": {
              "data_type": "warm"
            }
          },
          "set_priority": {
            "priority": 50
          }
        }
      },
      "cold": {
        "min_age": "7d",
        "actions": {
          "allocate": {
            "number_of_replicas": 0,
            "require": {
              "data_type": "cold"
            }
          },
          "set_priority": {
            "priority": 0
          }
        }
      },
      "delete": {
        "min_age": "30d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

4.4 按时间与信号类型分索引的架构流程

下图展示从日志采集到 ILM 自动流转的完整链路:

按时间与信号类型分索引 — ILM 自动流转架构 日志采集(Filebeat) 信号分类(Logstash) gs-latency-* gs-traffic-* gs-error-* gs-saturation-* ILM 自动流转:Hot(SSD) → Warm(HDD) → Cold(对象存储) → Delete Kibana / API 查询 说明:每个信号类型独立索引 → 独立 ILM 策略 → 按时间滚动 → 自动迁移至不同存储层 查询时通过别名(gs-latency-write / gs-latency-search)透明访问热索引或全量索引

4.5 查询与存储成本优化策略

通过 ILM 分索引后,还需配合以下手段进一步优化:

  • 按时间范围路由查询:在 Kibana 或 API 查询中强制指定 @timestamp 范围,ES 自动跳过不相关的索引,减少分片扫描。
  • 使用索引别名分离读写:写别名指向 Hot 索引,读别名指向 Hot+Warm+Cold 所有索引,避免业务侧感知索引名变化。
  • Warm 阶段 forcemerge 到 1 段:减少分段数量可降低内存开销,同时提升只读查询性能。
  • Cold 阶段副本数设为 0:归档数据不再需要高可用,节省 50% 存储成本。
  • 信号类型差异化保留周期:
信号类型 Hot 保留 Warm 保留 Cold 保留 总保留 优化说明
延迟 6h 7d 23d 30d 保留原始百分位数据用于 SLA 审计
流量 6h 1d 6d 7d 仅保留聚合指标,原始明细提前删除
错误 6h 7d 23d 30d 保留完整 stack_trace 用于根因分析
饱和度 6h 3d 4d 7d 高频指标降采样后存储
最佳实践:在 ILM 策略中为每个阶段设置 index.routing.allocation.require.data_type,配合节点属性标签(如 node.attr.data_type: hot/warm/cold),确保数据物理隔离。同时开启 indices.lifecycle.poll_interval(默认 10 分钟)为 1 分钟,加速索引滚动。

4.6 监控 ILM 执行状态

部署完成后,通过以下 API 和指标持续观察 ILM 健康度:

# 查看所有索引的 ILM 阶段
GET _ilm/status

# 查看具体索引的 ILM 执行详情
GET gs-latency-2025-04-01-000001/_ilm/explain

# 关键监控指标(Grafana / Kibana 看板)
- ilm.time-since-index-rollover    # 距离上次滚动的时间
- ilm.number-of-errors             # ILM 执行错误数
- indices.lifecycle.completed      # 已完成生命周期管理的索引数
- node.data_type                   # 各存储层节点的磁盘使用率
常见问题:如果 ILM 策略更新后未生效,检查索引是否已脱离策略管理(如手动修改过 settings)。使用 POST /_ilm/move/<index>?phase=hot 可手动触发阶段迁移,用于测试或故障恢复。