将任何与 Prometheus 兼容的客户端指向 Elasticsearch,直接对照现有指标运行 PromQL。Elasticsearch 正在以技术预览版形式添加原生 Prometheus 查询、发现及元数据终端,这些终端适用于通过 Prometheus Remote Write、OpenTelemetry 或批量 API 采集的指标。API 运行在 Elasticsearch 的时序数据流 (TSDS) 之上,因此无需额外维护独立的 Prometheus 专用存储层。
本文解释了查询、发现和元数据终端如何基于先前的摄取和查询工作,共同构成该 API 接口表面。多篇配套文章对各个部分进行了更深入的探讨:
- ES|QL 中的原生 PromQL 支持涵盖了如何将 PromQL 查询转换为 ES|QL 执行计划。
- 使用 Remote Write 将 Prometheus 指标发送到 Elasticsearch,涵盖了数据摄取设置。
- How Prometheus Remote Write Ingestion Works in Elasticsearch 一文介绍了 Prometheus 远程写入的摄取内部机制。
这项工作仍在进行中。以下各节列出了目前支持的部分以及仍在发展的部分。
API 接口表面
如今,与 Prometheus 兼容的 API 接口表面分为三类。
查询终端
查询终端允许 Prometheus 兼容客户端评估 PromQL 表达式:
GET /_prometheus/api/v1/query_range在一个时间窗口内(矩阵结果)评估 PromQL 表达式。GET /_prometheus/api/v1/query在单一时间点评估(向量结果)。当前实现为返回最后一个样本的短范围查询。
目前查询终端仅支持 GET 方法。某些客户端默认使用 POST 请求,因此您可能需要将其配置为使用 GET 请求。Prometheus 的 POST 约定使用 application/x-www-form-urlencoded 主体,Elasticsearch 的 HTTP 层会在请求到达处理程序之前将其拒绝,以防止 CSRF 攻击。
有关 PromQL 的完整覆盖状态,请参阅 ES|QL 中有关 PromQL 的配套文章。
元数据终端
元数据终端提供客户端进行自动补全、变量下拉列表和指标浏览所需的发现信息。
系列、标签和标签值终端均接受 match[] 选择器和时间范围(start/end)。参数 match[] 接受一个 Prometheus 系列选择器(如 http_requests_total{job="api"}),并将响应限制为匹配的时间序列。这确保了在具有大量指标的集群上,响应速度快且相关性高。例如:
第一个返回 http_requests_total 中符合 job="api" 条件的所有系列及其完整标签集。第二个仅返回 http_requests_total 系列中存在的标签名称。第三个仅返回匹配序列中出现的 instance 值。
GET /_prometheus/api/v1/metadata 有所不同:它返回每个指标的类型和单位,并可通过 metric 参数按名称筛选。
它不接受 match[] 选择器或时间范围。在 Prometheus 中,元数据是从活动抓取目标(它们公开的 HELP、TYPE 和 UNIT 行)收集的,因此响应不涉及数据扫描。Elasticsearch 没有那样的专用元数据存储,因此当前实现通过访问最近 24 小时的时间序列数据来发现指标元数据。这样可以保持快速查询,而无需进行完整的索引扫描。该 24 小时回看窗口是固定的:Prometheus 元数据 API 不公开 start 或 end 参数,Elasticsearch 无法利用这些参数来实现用户可调。
元数据终端的工作原理,包括支持它们的 TS_INFO 和 METRICS_INFO 命令,已在下方详细说明。
索引预过滤
所有查询和元数据终端都接受 /_prometheus/ 之后的可选 {index} 路径段:
这限制了在任何表达式评估开始之前,查询针对哪些 Elasticsearch 索引运行。在跨团队或环境拥有大量数据流的集群中,这避免了扫描无关索引,并能显著降低查询延迟。您可以为每个索引模式配置单独的数据源,以便团队获得对其自身指标的限定访问权限。
关于远程写入的说明
对于数据摄取,Elasticsearch 还公开了标准的 Prometheus Remote Write 终端:
POST /_prometheus/api/v1/write通过 Prometheus Remote Write v1 协议摄取时间序列。v2 暂不支持。
Remote Write 将数据写入 Elasticsearch 的现有时序数据流 (TSDS),而不是一个单独的 Prometheus 特定存储层。Prometheus 标签变成 TSDS 维度,而度量名称变成索引映射中的字段。远程写入架构文章详细介绍了完整的映射,包括如何推断指标类型以及如何使用 labels. 前缀存储标签。
运作方式
在底层,所有终端的工作方式相同:解析传入的 HTTP 参数,构建 ES|QL 查询计划,针对时序数据流执行,并将列式结果转换回 Prometheus 客户端期望的 JSON 格式。
TS_INFO 和 METRICS_INFO
元数据终端需要回答诸如“存在哪些标签?”或“定义了哪些指标类型?”等问题,要在可能数百万个时间序列中完成,而无需扫描每个数据点。
在内部实现上,Prometheus 元数据终端会通过围绕两个新的处理命令 METRICS_INFO 和 TS_INFO 构建 ES|QL 计划,来回答这些问题。您无需直接使用这些命令即可使用 Prometheus API,但它们是元数据响应背后的核心执行原语。两者都通过每个时间序列仅访问一个文档来提取其元数据,而不是扫描所有样本。这意味着它们的成本与不同时间序列的数量成正比,而不是与数据点的数量成正比。
METRICS_INFO 为每个不同的指标返回一行,包含其名称、类型、单位和关联的维度字段。TS_INFO 更加细粒度:为每个(指标,时间序列)组合返回一行,将实际的维度值作为一个 JSON 对象包含在内。
一篇关于 TS_INFO 和 METRICS_INFO 的专门博客文章即将推出,内容将涵盖两阶段执行模型、它们的扩展方式,以及如何在 ES|QL 查询中直接使用它们,而不仅仅是通过 Prometheus API。
元数据终端如何使用它们
每个元数据终端都会都以这些命令之一为核心构建 ES|QL 计划。
/api/v1/labels /api/v1/series 使用 TS_INFO,因为它们需要按时间序列的详细信息(存在哪些标签,每个系列由哪些维度值标识)。/api/v1/metadata和/api/v1/label/__name__/values使用METRICS_INFO,因为它们只需要每个指标的信息(指标名称、类型、单位)。
/api/v1/label/{name}/values 对于常规标签(除 __name__ 之外的任何标签),则不使用这两个命令。如 job 或 instance)的常规标签是索引中的实际维度字段,因此终端可以直接使用分组聚合来查询它们。当提供 match[] 选择器时,它们将转换为 WHERE 子句,在聚合运行之前对时序进行筛选。
__name__ 标签需要一种不同的策略,因为它并不总是作为维度字段存在。Prometheus Remote Write 确实存储 labels.__name__,但通过其他路径(OpenTelemetry、批量 API)摄取的指标则不会。指标名称被编码在字段名称本身中(例如 metrics.http_requests_total)。您可以通过查看索引映射来枚举字段名称,但仅凭映射无法告诉您哪个指标具有哪些维度,也无法通过 match[] 选择器的标签值进行筛选。METRICS_INFO 可以同时执行两项操作:跨索引枚举指标名称,同时使用上游 WHERE 筛选器。
在所有情况下,API 层都会将转换处理回 Prometheus 约定:去除 labels. 和 metrics. 存储前缀,并为缺少它的非 Prometheus 指标合成 __name__。
结语
结果:任何兼容 Prometheus 的客户端都可以通过其已经理解的终端来查询和探索 Elasticsearch 指标。Remote Write 指标、OpenTelemetry 指标以及通过其他途径索引的指标,都将通过同一 API 呈现,并由相同的 TSDS 索引提供支持。
本文提及的所有 Prometheus API 目前在 Elasticsearch Serverless 中以技术预览版形式提供。对于自管型集群和 Elastic Cloud Hosted 部署,除 GET /_prometheus/api/v1/metadata 外,其他 API 在 Elasticsearch 9.4 中以技术预览版形式提供。要在本地进行实验,请使用 start-local。
常见问题
兼容 Prometheus 的查询和元数据 API 是否仅适用于通过 Remote Write 采集的数据?
不。兼容 Prometheus 的 API 运行在 Elasticsearch 的任何时序数据流 (TSDS) 之上。存储来自 Prometheus Remote Write、OpenTelemetry 或 Bulk API 的指标的同一索引,会直接通过 PromQL 查询,无需操作额外的存储层。
为什么我的 Prometheus 客户端在调用查询终端时使用 POST 会失败?
目前 Prometheus 查询终端上仅支持 GET 方法。某些客户端默认使用带有 application/x-www-form-urlencoded 的 POST 请求,而 Elasticsearch 的 HTTP 层会将其作为 CSRF 防护机制拒绝,请求无法到达处理程序。请将客户端配置为使用 GET 方法。
我能否将 Prometheus 查询限定到 Elasticsearch 中的一部分索引?
可以。每个查询和元数据终端都接受一个可选的 {index} 路径段,例如 /_prometheus/metrics-prod-*/api/v1/query_range。这会在求值之前将查询限定到匹配的索引,从而避免扫描不相关的数据。
原生 Prometheus API 与运行专用 Prometheus 服务器相比如何?
Elasticsearch 将 Prometheus Remote Write、OpenTelemetry 及其他采集路径整合到一个基于 TSDS 的统一存储中,可通过 PromQL 或 ES|QL 进行查询。您可以在保持 Prometheus 客户端兼容性的同时,复用 Elasticsearch 的现有能力,例如长期存储、索引生命周期管理(ILM),以及与存储在同一集群中的日志和追踪数据进行关联分析。




