为 Elasticsearch 注入活力:添加对原生 Prometheus API 的支持

通过原生 PromQL、发现及元数据终端,从兼容 Prometheus 的客户端直接查询 Elasticsearch。使用 Prometheus Remote Write 将数据发送到 Elasticsearch。

将任何与 Prometheus 兼容的客户端指向 Elasticsearch,直接对照现有指标运行 PromQL。Elasticsearch 正在以技术预览版形式添加原生 Prometheus 查询、发现及元数据终端,这些终端适用于通过 Prometheus Remote Write、OpenTelemetry 或批量 API 采集的指标。API 运行在 Elasticsearch 的时序数据流 (TSDS) 之上,因此无需额外维护独立的 Prometheus 专用存储层。

本文解释了查询、发现和元数据终端如何基于先前的摄取和查询工作,共同构成该 API 接口表面。多篇配套文章对各个部分进行了更深入的探讨:

这项工作仍在进行中。以下各节列出了目前支持的部分以及仍在发展的部分。

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 中,元数据是从活动抓取目标(它们公开的 HELPTYPEUNIT 行)收集的,因此响应不涉及数据扫描。Elasticsearch 没有那样的专用元数据存储,因此当前实现通过访问最近 24 小时的时间序列数据来发现指标元数据。这样可以保持快速查询,而无需进行完整的索引扫描。该 24 小时回看窗口是固定的:Prometheus 元数据 API 不公开 startend 参数,Elasticsearch 无法利用这些参数来实现用户可调。

元数据终端的工作原理,包括支持它们的 TS_INFOMETRICS_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_INFOTS_INFO 构建 ES|QL 计划,来回答这些问题。您无需直接使用这些命令即可使用 Prometheus API,但它们是元数据响应背后的核心执行原语。两者都通过每个时间序列仅访问一个文档来提取其元数据,而不是扫描所有样本。这意味着它们的成本与不同时间序列的数量成正比,而不是与数据点的数量成正比。

METRICS_INFO 为每个不同的指标返回一行,包含其名称、类型、单位和关联的维度字段。TS_INFO 更加细粒度:为每个(指标,时间序列)组合返回一行,将实际的维度值作为一个 JSON 对象包含在内。

一篇关于 TS_INFOMETRICS_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__ 之外的任何标签),则不使用这两个命令。如 jobinstance)的常规标签是索引中的实际维度字段,因此终端可以直接使用分组聚合来查询它们。当提供 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),以及与存储在同一集群中的日志和追踪数据进行关联分析。

这些内容对您有多大帮助?

没有帮助

有点帮助

非常有帮助

相关内容

准备好打造最先进的搜索体验了吗?

足够先进的搜索不是一个人的努力就能实现的。Elasticsearch 由数据科学家、ML 操作员、工程师以及更多和您一样对搜索充满热情的人提供支持。让我们联系起来,共同打造神奇的搜索体验,让您获得想要的结果。

亲自试用