Bartłomiej Płotka 自 2019 年以来一直是 Prometheus 维护者,也是 Red Hat 的首席软件工程师。CNCF Thanos 项目的合著者。CNCF 大使和 CNCF TAG Observability 的技术负责人。业余时间,他与 O'Reilly 合作撰写了一本名为《Efficient Go》的书。观点为我个人所有!
我个人喜欢 Prometheus 项目的一点,也是我加入团队的众多原因之一,就是它对项目目标的专注。Prometheus 始终致力于在提供实用、可靠、廉价但极具价值的基于指标的监控方面突破界限。Prometheus 超级稳定且强大的 API、查询语言和集成协议(例如 Remote Write 和 OpenMetrics)使得云原生计算基金会 (CNCF) 指标生态系统能够在这些坚实的基础上发展。结果发生了许多令人惊叹的事情:
- 我们可以看到社区导出器几乎可以获取所有指标,例如容器、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 模型”,是使 Prometheus 轻量且可靠的核心原则。此外,它使得应用程序的 instrument 和导出器变得异常简单,因为它们只需要提供一个简单的人类可读的 HTTP 端点,其中包含所有跟踪指标的当前值(以 OpenMetrics 格式)。所有这些都无需复杂的 push 基础设施和非简单的客户端库。总体而言,典型的 Prometheus 监控简化部署如下所示:

这种方式效果很好,多年来我们看到了数百万次成功的此类部署,它们处理着数千万个活跃时间序列。其中一些用于更长时间的数据保留,例如两年左右。所有这些都允许查询、告警和记录对集群管理员和开发者都有用的指标。
然而,云原生世界正在不断增长和演变。随着托管 Kubernetes 解决方案的增长以及在几秒钟内按需创建的集群,我们现在终于能够将集群视为“牛群”,而不是“宠物”(换句话说,我们不太关心这些集群的单个实例)。在某些情况下,解决方案甚至不再具有集群的概念,例如kcp、Fargate和其他平台。

出现的另一个有趣的用例是边缘集群或网络的想法。随着电信、汽车和 IoT 设备等行业采用云原生技术,我们看到越来越多资源受限的小型集群。这迫使所有数据(包括可观测性数据)都必须传输到远程、更大的对应方,因为这些远程节点上几乎无法存储任何东西。
这意味着什么?这意味着监控数据必须以某种方式进行聚合、呈现给用户,有时甚至存储在全局级别。这通常被称为全局视图功能。
天真地想,我们可以通过将 Prometheus 放在全局级别并跨远程网络抓取指标,或者直接从应用程序将指标推送到中心位置进行监控来实现这一点。让我解释一下为什么这两种做法通常都非常糟糕:
🔥 跨网络边界抓取指标可能带来挑战,因为它在监控流水线中增加了新的未知因素。本地 pull 模型允许 Prometheus 知道指标目标出现问题的确切原因和时间。也许它已宕机、配置错误、重启、太慢无法提供指标(例如 CPU 饱和)、无法通过服务发现发现、我们没有访问凭据,或者只是 DNS、网络或整个集群已宕机。通过将抓取器放在网络外部,我们可能会因为引入与单个目标无关的抓取不可靠性而丢失部分信息。最重要的是,如果网络暂时中断,我们可能会完全失去重要的可见性。请不要这样做。这不值得。(
🔥 直接从应用程序将指标推送到某个中心位置同样糟糕。特别是当您监控大量实例时,如果看不到来自远程应用程序的指标,您几乎一无所知。应用程序宕机了吗?我的接收端流水线宕机了吗?也许应用程序授权失败了?也许它未能获取到我的远程集群的 IP 地址?也许它太慢了?也许网络中断了?更糟的是,您甚至可能不知道某些应用程序目标的数据丢失了。而且您也没有获得太多收益,因为您需要跟踪所有应该发送数据的目标的状态。这种设计需要仔细分析,因为它太容易导致失败了。
注意:无服务器函数和短生命周期容器通常是我们需要考虑从应用程序推送指标作为解决方案的情况。然而,在这一点上,我们讨论的是事件或指标片段,我们可能希望将其聚合到更长时间的序列中。这个问题在
此处进行了讨论,欢迎您贡献并帮助我们更好地支持这些情况!
Prometheus 引入了三种支持全局视图的方式,每种方式都有其优缺点。让我们简要介绍一下。它们在下图中使用橙色表示:

-
Federation 作为第一个用于聚合的功能被引入。它允许全局级别的 Prometheus 服务器从叶节点 Prometheus 抓取一部分指标。这种“联合”抓取减少了跨网络的一些未知因素,因为联合端点暴露的指标包含原始样本的时间戳。然而,它通常存在无法联合所有指标以及在较长时间网络分区(分钟)期间丢失数据的缺点。
-
Prometheus Remote Read 允许从远程 Prometheus 服务器的数据库中选择原始指标,而无需直接的 PromQL 查询。您可以在全局级别部署 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 sender compliance。这是一种快速判断您是否正确实现此协议的绝佳方式。
从这样的抓取器流式传输数据,通过将指标数据存储在中心位置,实现了全局视图的用例。这还实现了关注点的分离,当应用程序由不同于可观测性或监控流水线的团队管理时,这非常有用。此外,这也是供应商选择 Remote Write 的原因,他们希望尽可能地减轻客户的工作负担。
等一下,Bartek。你刚才提到直接从应用程序推送指标不是最好的主意!
当然,但令人惊叹的部分在于,即使使用 Remote Write,Prometheus 仍然使用 pull 模型从应用程序收集指标,这使我们能够理解那些不同的故障模式。之后,我们将样本和时间序列批量处理并导出,复制(推送)数据到 Remote Write 端点,从而限制了中心点需要处理的监控未知因素的数量!
重要的是要注意,可靠且高效的远程写入实现是一个非易于解决的问题。Prometheus 社区花费了大约三年时间才拿出了稳定且可扩展的实现。我们多次重新实现了 WAL (write-ahead-log),添加了内部队列、分片、智能退避等等。所有这些都对用户隐藏,用户可以享受高性能的流式传输或将大量指标存储在中心位置。
Remote Write 实操示例: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 中。具有相同的抓取 API、相同的语义、相同的配置和发现机制。
如果您不打算在本地查询或告警数据,而是将指标流式传输到外部,使用 Agent 模式有什么好处?有以下几点:
首先是效率。我们定制的 Agent TSDB WAL 在成功写入后立即删除数据。如果无法到达远程端点,它会将数据临时保存在磁盘上,直到远程端点恢复在线。目前,这仅限于两小时的缓冲,与非 Agent 模式的 Prometheus 类似,希望很快解除此限制。这意味着我们不需要在内存中构建数据块。我们不需要为查询目的维护一个完整的索引。本质上,Agent 模式使用的资源只是正常 Prometheus 服务器在类似情况下使用的资源的一小部分。
这种效率重要吗?是的!正如我们所提到的,对于某些部署来说,边缘集群上使用的每 GB 内存和每个 CPU 核心都很重要。另一方面,使用指标进行监控的范式如今已相当成熟。这意味着您能够以相同的成本发送更多相关且基数更高的指标,效果就越好。
注意:随着 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 在 Prometheus 维护者 Tom Wilkie 的指导下于 2019 年创建。随后它被用于开源项目 Grafana Agent,该项目自此被许多 Grafana Cloud 客户和社区成员使用。考虑到解决方案的成熟度,是时候将实现捐赠给 Prometheus,以实现原生集成和更广泛的应用。Robert (Grafana Labs) 在 Srikrishna (Red Hat) 和社区的帮助下,将代码移植到 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 的不同视角。