请参与 Prometheus 用户调研(2026 年 3 月版) ,帮助社区确定未来开发工作的优先级!

介绍 Prometheus Agent 模式:一种高效且云原生的指标转发方式

2021年11月16日作者 Bartlomiej Plotka (@bwplotka)

Bartek Płotka 自 2019 年起担任 Prometheus 维护者,现任红帽(Red Hat)首席软件工程师。他是 CNCF Thanos 项目的合著者,也是 CNCF 大使及 CNCF 可观测性技术咨询组(TAG Observability)的技术负责人。在空闲时间,他正在撰写 O'Reilly 出版的《Efficient Go》一书。文中观点仅代表个人意见!

我个人对 Prometheus 项目情有独钟,这也是我加入该团队的众多原因之一,那就是该项目对自身目标的极致专注。Prometheus 始终致力于在提供务实、可靠、廉价且不可或缺的基于指标的监控方面不断突破界限。Prometheus 超级稳定且健壮的 API、查询语言以及集成协议(例如 Remote Write 和 OpenMetrics )为云原生计算基金会(CNCF)指标生态系统的强劲增长奠定了坚实基础。最终,奇迹由此诞生。

  • 我们现在可以看到社区提供的用于获取几乎所有事物指标的导出器(exporter),例如 容器 eBPF Minecraft 服务器统计信息 ,甚至是园艺中植物的健康状况 
  • 如今,大多数人期望云原生软件具有一个 Prometheus 可以抓取的 HTTP/HTTPS /metrics 端点。这一概念最早在 Google 内部秘密开发,并由 Prometheus 项目在全球范围内推广开来。
  • 可观测性范式发生了转变。我们看到 SRE 和开发人员从第一天起就严重依赖指标,这提高了软件的韧性、可调试性和数据驱动的决策能力!

最终,我们几乎看不到没有运行 Prometheus 的 Kubernetes 集群。

Prometheus 社区的强大专注力也促使其他开源项目成长起来,将 Prometheus 的部署模型从单节点扩展开来(例如 Cortex Thanos  等等)。更不用提云厂商对 Prometheus API 和数据模型的采纳(例如 Amazon Managed Prometheus Google Cloud Managed Prometheus Grafana Cloud  等)。如果你在寻找 Prometheus 项目如此成功的唯一理由,那就是:让监控社区专注于真正重要的事情

在这篇(冗长的)博文中,我很乐意介绍 Prometheus 的一种名为“Agent(代理)”的新运行模式。它直接内置于 Prometheus 二进制文件中。Agent 模式禁用了 Prometheus 的一些常规功能,并对二进制文件进行了优化,使其专注于抓取并将指标远程写入远程位置。引入一种减少功能数量的模式可以实现新的使用模式。在这篇博文中,我将解释为什么这对 CNCF 生态系统中的某些部署方式而言是一个转折点。我对此感到非常兴奋!

转发用例的历史

Prometheus 的核心设计在整个项目生命周期中一直未变。受Google Borgmon 监控系统 的启发,你可以在想要监控的应用程序旁边部署一个 Prometheus 服务器,告知 Prometheus 如何访问它们,并允许其定期抓取指标的当前值。这种收集方法通常被称为“拉取模型(pull model)”,它是使 Prometheus 轻量且可靠的核心原则。此外,它使得应用程序插桩和导出器变得非常简单,因为它们只需要提供一个简单且人类可读的 HTTP 端点,其中包含所有跟踪指标的当前值(采用 OpenMetrics 格式)。所有这些都不需要复杂的推送基础设施和繁琐的客户端库。总的来说,一个简化的典型 Prometheus 监控部署如下所示。

Prometheus high-level view

这效果很好,多年来我们已经看到数以百万计的成功部署,处理着数千万个活动序列。其中一些用于更长时间的数据保留,比如两年左右。所有这些都允许查询、告警和记录对集群管理员和开发人员都有用的指标。

然而,云原生世界在不断成长和演变。随着托管 Kubernetes 解决方案的增长,以及在几秒钟内按需创建集群的能力,我们现在终于能够将集群视为“牲畜(cattle)”而非“宠物(pets)”(换句话说,我们不太关注这些集群的单个实例)。在某些情况下,解决方案甚至不再具备集群的概念,例如 kcp Fargate  以及其他平台。

Yoda

另一个正在出现的有趣用例是边缘(Edge)集群或网络的概念。随着电信、汽车和物联网设备等行业采用云原生技术,我们看到越来越多的资源受限的小型集群。这迫使所有数据(包括可观测性数据)必须传输到远程的、体量更大的对应端,因为这些远程节点几乎无法存储任何东西。

这意味着什么?这意味着监控数据必须以某种方式进行聚合、呈现给用户,有时甚至需要存储在全局层面。这通常被称为全局视图(Global-View)功能。

天真地想,我们可以通过在全局层面部署 Prometheus 并跨远程网络抓取指标,或者让应用程序直接将指标推送到中心位置进行监控来实现这一点。让我解释一下为什么这两种做法通常都非常糟糕。

🔥 如果跨网络边界进行抓取会给监控管道引入新的未知因素,那将是一个挑战。本地拉取模型允许 Prometheus 准确地知道指标目标何时出问题以及原因。也许是目标宕机、配置错误、重启、抓取太慢(例如 CPU 饱和)、服务发现无法发现、没有访问凭据,或者仅仅是 DNS、网络或整个集群宕机。通过将我们的抓取器放在网络之外,我们冒着因引入与单个目标无关的抓取不可靠性而丢失部分此类信息的风险。最糟糕的是,如果网络暂时中断,我们甚至可能彻底丢失重要的可见性。请不要这样做。这不值得。(

🔥 将指标直接从应用程序推送到某个中心位置同样糟糕。特别是当你监控大型集群时,当你无法从远程应用程序看到指标时,你简直一无所知。是应用程序挂了吗?是我的接收管道挂了吗?也许应用程序授权失败了?也许它未能获取远程集群的 IP 地址?也许它太慢了?也许网络断了?更糟糕的是,你可能甚至不知道某些应用程序目标的指标数据丢失了。而且你也没有获得太多收益,因为你需要跟踪所有应该发送数据的对象的状态和状况。这样的设计需要仔细分析,因为它很容易导致失败。

注意无服务器函数(Serverless functions)和短生命周期容器通常是我们考虑从应用程序端进行“推送”以作为补救措施的场景。不过,此时我们讨论的是我们可能希望聚合到更长生命周期时间序列中的事件或指标片段。这个话题在这里 有讨论,欢迎贡献并帮助我们更好地支持这些场景!

Prometheus 引入了三种方式来支持全局视图用例,每种方式都有其优缺点。让我们简要介绍一下它们。它们在下图中以橙色标出。

Prometheus global view

  • 联邦(Federation)是作为第一个用于聚合目的的功能引入的。它允许全局层面的 Prometheus 服务器从叶子 Prometheus 节点抓取一部分指标。这种“联邦”抓取减少了跨网络的一些未知因素,因为联邦端点暴露的指标包含了原始样本的时间戳。然而,它通常受限于无法联邦所有指标,并且在较长时间(几分钟)的网络分区期间会丢失数据。
  • Prometheus Remote Read(远程读取)允许在没有直接 PromQL 查询的情况下,从远程 Prometheus 服务器的数据库中选择原始指标。你可以在全局层面部署 Prometheus 或其他解决方案(例如 Thanos)来对这些数据执行 PromQL 查询,同时从多个远程位置获取所需的指标。这非常强大,因为它允许你在“本地”存储数据,仅在需要时进行访问。不幸的是,也有缺点。如果没有像查询下推(Query Pushdown) 这样的功能,在极端情况下,我们为了回答一个查询可能会拉取数 GB 的压缩指标数据。此外,如果我们遇到网络分区,我们就会暂时失明。最后但同样重要的一点是,某些安全准则不允许入站流量,只允许出站流量。
  • 最后,我们有 Prometheus Remote Write(远程写入),这似乎是当今最受欢迎的选择。由于 Agent 模式专注于远程写入用例,让我们更详细地解释一下它。

远程写入 (Remote Write)

Prometheus Remote Write 协议允许我们将 Prometheus 收集的所有或部分指标转发(流式传输)到远程位置。你可以配置 Prometheus 将某些指标(如果需要,包括所有元数据和样本数据!)转发到一个或多个支持 Remote Write API 的位置。事实上,Prometheus 同时支持接收和发送 Remote Write,因此你可以在全局层面部署 Prometheus 来接收该流并跨集群聚合数据。

虽然官方的 Prometheus Remote Write API 规范尚处于评审阶段 ,但生态系统已经采用了 Remote Write 协议作为默认的指标导出协议。例如,Cortex、Thanos、OpenTelemetry 以及 Amazon、Google、Grafana、Logz.io 等云服务都支持通过 Remote Write 接收数据。

Prometheus 项目还为其 API 提供了官方合规性测试,例如针对提供 Remote Write 客户端能力的解决方案的 remote-write 发送端合规性测试 。这是快速判断你是否正确实现了该协议的绝佳方式。

从这样的抓取器流式传输数据通过允许你在中心位置存储指标数据,实现了全局视图用例。这也实现了关注点分离,当应用程序由不同于可观测性或监控管道的团队管理时,这非常有用。此外,这也是 Remote Write 被那些希望尽可能为客户卸载工作的厂商所选中的原因。

等等,Bartek。你刚才提到从应用程序直接推送指标并不是一个好主意!

确实,但神奇之处在于,即使使用 Remote Write,Prometheus 仍然使用拉取模型从应用程序收集指标,这使我们能够理解那些不同的故障模式。在此之后,我们批量处理样本和序列,并将数据导出、复制(推送)到 Remote Write 端点,从而限制了中心点需要监控的未知因素的数量!

值得注意的是,可靠且高效的远程写入实现是一个非同小可的难题。Prometheus 社区花费了大约三年时间才提出了一个稳定且可扩展的实现。我们多次重写了 WAL(预写日志),增加了内部队列、分片、智能退避策略等。所有这些对用户都是隐藏的,用户可以享受高性能的流式传输,或将大量指标存储在中心位置。

远程写入动手实践:Katacoda 教程

所有这些在 Prometheus 中都不是什么新鲜事。我们许多人已经在使用 Prometheus 抓取所有必需的指标,并将其中全部或部分远程写入到远程位置。

假设你想体验一下远程写入的功能,我们推荐 Thanos Katacoda 关于 Prometheus 指标远程写入的教程 ,它解释了 Prometheus 将所有指标转发到远程位置所需的所有步骤。它是免费的,只需注册一个帐户即可享受教程!🤗

注意,此示例使用 Thanos 的接收模式作为远程存储。如今,你可以使用许多其他与远程写入 API 兼容的项目。

既然远程写入工作良好,为什么我们要给 Prometheus 增加一个特殊的 Agent 模式呢?

Prometheus Agent 模式

从 Prometheus v2.32.0(下一个版本)开始,每个人都能够通过 --enable-feature=agent 实验性标志运行 Prometheus 二进制文件。如果你想在发布前尝试它,欢迎使用 Prometheus v2.32.0-beta.0  或者使用我们的 quay.io/prometheus/prometheus:v2.32.0-beta.0 镜像。

Agent 模式针对远程写入用例优化了 Prometheus。它禁用了查询、告警和本地存储,并用定制的 TSDB WAL 取代了它们。其他一切保持不变:抓取逻辑、服务发现和相关配置。如果你只是想将数据转发到远程 Prometheus 服务器或任何其他兼容 Remote-Write 的项目,它可以作为 Prometheus 的直接替代品使用。本质上它看起来像这样。

Prometheus agent

Prometheus Agent 最好的部分是它内置于 Prometheus 中。相同的抓取 API、相同的语义、相同的配置和发现机制。

如果你不打算在本地查询或对数据进行告警,而是将指标流式传输到外部,那么使用 Agent 模式有什么好处呢?有以下几点:

首先是效率。我们定制的 Agent TSDB WAL 在成功写入后会立即移除数据。如果它无法到达远程端点,它会暂时将数据保留在磁盘上,直到远程端点恢复在线。目前这仅限于 2 小时的缓冲区,与非 Agent 模式的 Prometheus 类似,希望很快能解除此限制 。这意味着我们不需要在内存中构建数据块。我们不需要为查询目的维护完整的索引。本质上,Agent 模式使用的资源只是普通 Prometheus 服务器在类似情况下所需资源的一小部分。

这种效率重要吗?很重要!正如我们所提到的,对于某些部署而言,边缘集群上使用的每一个 GB 内存和每一个 CPU 核心都很关键。另一方面,如今使用指标进行监控的范式已经相当成熟。这意味着在同样的成本下,你能传输的指标越相关、基数(cardinality)越大,效果就越好。

注意随着 Agent 模式的引入,原有的 Prometheus 服务器模式仍然是推荐的、稳定的且受维护的模式。带有远程存储的 Agent 模式引入了额外的复杂性。请谨慎使用。

其次,新的 Agent 模式的好处在于它能够实现更轻松的水平扩展能力以进行摄取。这是我最感到兴奋的一点。让我解释一下原因。

梦想:可自动扩展的指标摄取

一个真正的可自动扩展的抓取解决方案需要基于指标目标的数量以及它们暴露的指标数量。我们要抓取的数据越多,我们自动部署的 Prometheus 实例就越多。如果目标数量或它们的指标数量减少,我们就可以缩减规模并移除几个实例。这将消除手动调整 Prometheus 大小的负担,并停止在集群暂时较小的情况下过度分配 Prometheus 的需求。

仅使用服务器模式的 Prometheus,这是很难实现的。这是因为服务器模式的 Prometheus 是有状态的。无论收集什么,都会原样保留在一个地方。这意味着缩减流程需要在终止前将收集到的数据备份到现有实例。然后我们就会面临重叠抓取、误导性的陈旧标记等问题。

除此之外,我们还需要某种能够聚合所有实例数据的全局视图查询(例如 Thanos Query 或 Promxy)。最后但同样重要的一点是,服务器模式下的 Prometheus 的资源使用情况取决于比单纯摄取更多的因素。还有告警、记录、查询、压缩、远程写入等,这些可能需要更多或更少的资源,而与指标目标的数量无关。

Agent 模式本质上将发现、抓取和远程写入移动到了一个独立的微服务中。这允许在仅摄取方面实现专注的操作模型。结果是,Agent 模式下的 Prometheus 几乎是无状态的。是的,为了避免指标丢失,我们需要部署一对高可用的 Agent 并挂载持久磁盘。但从技术上讲,如果我们有成千上万个指标目标(例如容器),我们可以部署多个 Prometheus Agent 并安全地更改哪个副本在抓取哪些目标。这是因为,归根结底,所有样本都将被推送到同一个中心存储。

总的来说,Agent 模式下的 Prometheus 实现了基于 Prometheus 的抓取功能的轻松水平自动扩展,可以响应指标目标的动态变化。这绝对是我们未来将与 Prometheus Kubernetes Operator  社区共同探索的方向。

现在让我们看一下 Prometheus 中目前实现的 Agent 模式状态。它准备好使用了吗?

Agent 模式已在大规模场景中得到验证

Prometheus 的下一个版本将包含 Agent 模式作为实验性功能。标志、API 和磁盘上的 WAL 格式可能会发生变化。但得益于 Grafana Labs  的开源工作,该实现的性能已经过实战考验。

我们 Agent 自定义 WAL 的初始实现灵感来源于当前的 Prometheus 服务器 TSDB WAL,并由 Robert Fratto  在 2019 年创建,并在 Prometheus 维护者 Tom Wilkie  的指导下完成。它随后被用于开源的 Grafana Agent  项目,该项目自那时起已被许多 Grafana Cloud 客户和社区成员所使用。鉴于该解决方案的成熟度,现在是将其捐赠给 Prometheus 以进行原生集成并获得更大采用规模的时候了。Robert(来自 Grafana Labs),在 Srikrishna(来自红帽)和社区的帮助下,将代码移植到了 Prometheus 代码库中,并于两周前合并到了 main 分支!

捐赠过程相当顺利。由于一些 Prometheus 维护者之前在 Grafana Agent 中就为这段代码做过贡献,而且新的 WAL 灵感来源于 Prometheus 自己的 WAL,因此当前的 Prometheus TSDB 维护者将其纳入完全维护并不困难!Robert 加入 Prometheus 团队担任 TSDB 维护者(恭喜!)也确实很有帮助。

现在,让我们解释一下你如何使用它!(

如何详细使用 Agent 模式

从现在开始,如果你查看 Prometheus 的帮助输出(--help 标志),你应该会看到大致如下内容。

usage: prometheus [<flags>]

The Prometheus monitoring server

Flags:
  -h, --help                     Show context-sensitive help (also try --help-long and --help-man).
      (... other flags)
      --storage.tsdb.path="data/"
                                 Base path for metrics storage. Use with server mode only.
      --storage.agent.path="data-agent/"
                                 Base path for metrics storage. Use with agent mode only.
      (... other flags)
      --enable-feature= ...      Comma separated feature names to enable. Valid options: agent, exemplar-storage, expand-external-labels, memory-snapshot-on-shutdown, promql-at-modifier, promql-negative-offset, remote-write-receiver,
                                 extra-scrape-metrics, new-service-discovery-manager. See https://prometheus.ac.cn/docs/prometheus/latest/feature_flags/ for more details.

由于 Agent 模式位于功能标志之后,如前所述,请使用 --enable-feature=agent 标志以 Agent 模式运行 Prometheus。现在,其余标志要么适用于服务器和 Agent,要么仅适用于特定模式。你可以通过检查标志帮助字符串的最后一句来查看哪个标志对应哪个模式。“Use with server mode only”表示仅用于服务器模式。如果你没有看到这样的提及,则表示该标志是通用的。

Agent 模式接受与服务器模式相同的抓取配置,包含相同的发现选项和远程写入选项。

它还暴露了一个禁用了查询功能的 Web UI,但像普通 Prometheus 服务器一样显示构建信息、配置、目标和服务发现信息。

Prometheus Agent 动手实践:Katacoda 教程

类似于 Prometheus 远程写入教程,如果你想体验 Prometheus Agent 的功能,我们推荐 Thanos Katacoda 关于 Prometheus Agent 的教程 ,它解释了运行 Prometheus Agent 是多么容易。

总结

希望你觉得这篇文章很有趣!在这篇文章中,我们介绍了新出现的用例,例如:

  • 边缘集群
  • 受限访问网络
  • 大量集群
  • 临时且动态的集群

然后我们解释了新的 Prometheus Agent 模式,它允许高效地将抓取的指标转发到远程写入端点。

一如既往,如果你有任何问题或反馈,欢迎在 GitHub 上提交工单或在邮件列表中提问

这篇博文是 CNCF、Grafana 和 Prometheus 协调发布的一部分。也欢迎阅读 CNCF 公告  以及关于 作为 Prometheus Agent 基础的 Grafana Agent 的相关报道