3. 成本可观测性数据采集

成本治理的第一步不是省钱,而是“看得见”。Elastic 集群的成本由多个维度共同决定:节点规格与数量决定基础算力开销,索引与分片数量决定元数据与存储压力,快照仓库决定冷备成本,查询负载决定 CPU 与堆内存的实际消耗。这些维度分散在不同的 API、不同的采集工具中,如果不把它们汇聚成一条统一的数据管道,后续的归因、分摊和优化就无从谈起。本节围绕“采集什么、用什么采、怎么汇成管道”三个问题展开。

一、先明确成本相关指标的四个来源层

Elastic 集群的成本指标可以按采集对象分为四层,每层的采集方式和关注点都不同:

  • 节点层:节点数量、角色(master/data/ingest/coordinating)、JVM 堆使用率、CPU 使用率、磁盘容量与剩余空间。这些指标直接对应硬件成本,是成本分摊的基础。
  • 索引与分片层:索引数量、主分片与副本分片数、单分片大小、段数量、文档数。分片过多会推高集群状态开销,副本过多会成倍放大存储成本。
  • 快照层:快照仓库类型(S3、HDFS、共享文件系统)、快照数量、快照总大小、最近一次快照时间。快照是冷数据的成本主体,需要单独计量。
  • 查询负载层:查询 QPS、慢查询数量、搜索线程池队列、拒绝次数、聚合耗时。查询负载决定了为满足性能而必须保留的算力冗余,是“隐性成本”的来源。

这四层并非孤立:节点层是成本载体,索引与分片层是成本放大器,快照层是成本沉淀,查询负载层是成本驱动。采集时必须保证四层数据带有统一的时间戳和集群标识,否则无法在后续做关联分析。

二、用 Elasticsearch API 采集集群原生指标

Elasticsearch 自身提供了丰富的 REST API,适合做低频、精确的“盘点式”采集。常用的成本相关接口包括:

# 节点层:节点角色、堆内存、磁盘
GET _cat/nodes?v&h=name,node.role,heap.percent,disk.used_percent,cpu

# 索引与分片层:索引大小、分片数、文档数
GET _cat/indices?v&h=index,pri,rep,store.size,docs.count

# 分片层:分片分布与大小
GET _cat/shards?v&h=index,shard,prirep,state,store,node

# 快照层:仓库与快照列表
GET _snapshot/_all
GET _snapshot/my_repo/_all?verbose=false

# 查询负载层:搜索线程池与拒绝
GET _cat/thread_pool/search?v&h=node_name,active,queue,rejected

这些接口返回的是“当前快照”,适合每小时或每天采集一次,写入一个独立的成本指标索引,例如 finops-cluster-metrics-YYYY.MM.dd。采集脚本可以用 curl 配合 jq 解析,也可以用 Python 的 elasticsearch 客户端。关键点是:每次采集都要记录采集时间、集群名称、采集批次 ID,这样后续才能做趋势对比和异常回溯。

需要注意的是,_cat/indices 返回的 store.size 是主分片加副本的总大小,而 pri.store.size 才是主分片大小。做存储成本分摊时,副本占用的空间同样要计入,但应单独标记,便于判断“副本冗余成本”是否合理。

三、用 Metricbeat 建立持续采集管道

API 采集是离散的,而成本治理需要连续的时序数据。Metricbeat 的 elasticsearch 模块可以按固定周期抓取节点、索引、分片等指标,并直接写入监控索引。一个典型的配置片段如下:

metricbeat.modules:
- module: elasticsearch
  metricsets:
    - node
    - node_stats
    - index
    - index_recovery
    - shard
  period: 30s
  hosts: ["http://es-coordinating:9200"]
  username: "metricbeat_writer"
  password: "${ES_PWD}"
  xpack.enabled: false

其中 node_stats 提供 JVM 堆、GC、线程池等运行时指标,index 提供每个索引的文档数、存储大小、查询与索引速率,shard 提供分片级别的状态与大小。采集周期建议 30 秒到 1 分钟:太短会加重集群负担,太长会丢失负载尖峰。采集账号应使用最小权限角色,只授予 monitor 和 read 相关权限,避免成本采集本身成为安全风险。

Metricbeat 写入的索引通常是 metricbeat-*,建议通过 ILM 策略控制其保留周期,例如热数据 7 天、温数据 30 天,避免监控数据自身膨胀成新的成本项。

四、用 Prometheus 汇聚多集群成本指标

当存在多个 Elastic 集群时,Metricbeat 逐集群部署会带来管理负担。此时可以用 Prometheus 的 elasticsearch_exporter 统一抓取,再通过 Prometheus 的标签体系给每个集群打上 cluster、env、team 标签,实现多集群成本数据的统一汇聚。核心指标包括:

指标名含义成本用途
elasticsearch_jvm_memory_used_bytesJVM 堆使用量判断是否需要扩容或优化查询
elasticsearch_indices_store_size_bytes索引存储总大小存储成本分摊
elasticsearch_indices_docs文档总数单位文档成本计算
elasticsearch_cluster_health_number_of_nodes节点数量算力成本基数
elasticsearch_thread_pool_rejected_count线程池拒绝次数性能冗余成本信号

Prometheus 侧建议配置 recording rule,把原始指标预聚合为“每集群每小时存储增量”“每索引每日查询次数”等成本口径,减少查询时的计算开销。Grafana 则用于把这些指标呈现为成本看板,例如“存储成本 Top 10 索引”“查询负载与节点数趋势对比”。

五、成本数据管道的整体结构

把上述采集方式串起来,就形成了一条从集群到成本看板的数据管道。下图展示了四层指标来源、采集工具与汇聚目标之间的关系:

Elastic 成本可观测性数据管道 节点层 节点数 / 角色 / 堆 / CPU / 磁盘 索引与分片层 索引数 / 主副本 / 分片大小 快照层 仓库类型 / 快照数 / 总大小 查询负载层 QPS / 慢查询 / 拒绝 / 队列 Elasticsearch API _cat / _snapshot / _cluster 低频盘点式采集 Metricbeat node / index / shard 30s 周期持续采集 Prometheus Exporter 多集群标签汇聚 recording rule 预聚合 成本指标索引 finops-cluster-metrics-* 统一时间戳 + 集群标识 成本看板与归因 存储成本 Top N 索引 查询负载 vs 节点数趋势 四层指标经三类工具采集后,统一写入成本指标索引,最终支撑成本看板与归因分析

这条管道的设计要点有三个。第一,统一标识:所有采集数据必须携带 cluster_name、env、team 三个标签,否则多集群场景下无法归因。第二,分层采集频率:节点和查询负载用 30 秒级持续采集,索引和分片用 5 分钟级,快照用小时级,避免高频采集拖垮集群。第三,成本数据自身也要控成本:监控索引设置 ILM 滚动删除,原始指标保留 30 天,预聚合指标保留 1 年。

采集账号建议单独创建,只授予 monitor、view_index_metadata 和快照仓库的只读权限。不要复用超级用户,避免采集脚本泄露导致集群被篡改。

六、采集结果的初步校验

管道搭好后,不要急着做成本分析,先做三项校验:一是完整性,确认四层指标都有数据落入成本索引,可以用 _cat/indices/finops-cluster-metrics-* 查看文档数是否随时间增长;二是一致性,把 API 采集的索引总大小与 Metricbeat 采集的 store.size 做对比,偏差超过 5% 就要排查采集口径;三是时效性,检查最新一条数据的时间戳与当前时间差是否在采集周期的 2 倍以内,超时说明采集链路中断。

只有这三项校验通过,采集到的数据才具备进入成本归因环节的资格。否则,后续无论做多精细的分摊模型,都只是在错误的数据上做计算。