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

Bartek Płotka 自 2019 年以来一直是 Prometheus Maintainer,并且是 Red Hat 的首席软件工程师。CNCF Thanos 项目的共同作者。CNCF 大使和 CNCF TAG 可观测性技术负责人。在空闲时间,他正在与 O'Reilly 合著一本名为《高效 Go》的书籍。观点仅代表个人!

我个人喜欢 Prometheus 项目的一点,也是我加入该团队的众多原因之一,就是该项目对目标的激光般聚焦。Prometheus 始终致力于在提供实用、可靠、廉价但又非常宝贵的基于指标的监控方面突破界限。Prometheus 超稳定且强大的 API、查询语言和集成协议(例如 Remote Write 和 OpenMetrics)使云原生计算基金会 (CNCF) 指标生态系统能够在这些坚实的基础上发展壮大。因此,发生了许多令人惊叹的事情

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

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

Prometheus 社区的强大关注也促使其他开源项目发展壮大,从而将 Prometheus 部署模型扩展到单节点之外(例如 CortexThanos 等)。更不用说云供应商采用 Prometheus 的 API 和数据模型(例如 Amazon Managed PrometheusGoogle Cloud Managed PrometheusGrafana Cloud 等)。如果您正在寻找 Prometheus 项目如此成功的一个原因,那就是:将监控社区的注意力集中在重要的事情上

在这篇(冗长的)博文中,我想介绍一种新的 Prometheus 运行操作模式,称为“Agent”。它直接内置于 Prometheus 二进制文件中。Agent 模式禁用 Prometheus 的一些常用功能,并优化二进制文件以进行抓取和远程写入到远程位置。引入减少功能的模式可以实现新的使用模式。在这篇博文中,我将解释为什么它对 CNCF 生态系统中的某些部署来说是游戏规则改变者。我对此感到非常兴奋!

转发用例的历史

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

Prometheus high-level view

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

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

Yoda

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

这意味着什么?这意味着监控数据必须以某种方式聚合、呈现给用户,有时甚至存储在全局级别。这通常被称为 全局视图 功能。

天真地,我们可以考虑通过将 Prometheus 放在全局级别并跨远程网络抓取指标,或者直接从应用程序将指标推送到中央位置进行监控来实施此功能。让我解释一下为什么这两种方法通常都是非常糟糕的主意

🔥 跨网络边界抓取可能会带来挑战,因为它会在监控管道中增加新的未知因素。本地拉取模型允许 Prometheus 确切地知道指标目标为何出现问题以及何时出现问题。可能是它已关闭、配置错误、重新启动、速度太慢而无法提供指标(例如 CPU 饱和)、无法通过服务发现发现、我们没有访问凭据,或者只是 DNS、网络或整个集群已关闭。通过将我们的抓取器放在网络外部,我们可能会因在抓取中引入与单个目标无关的不可靠性而丢失部分信息。最重要的是,如果网络暂时中断,我们可能会完全失去重要的可见性。请不要这样做。这不值得。(

🔥 直接从应用程序将指标推送到某个中央位置同样糟糕。特别是当您监控大型集群时,当您看不到来自远程应用程序的指标时,您实际上什么都不知道。应用程序是否已关闭?我的接收器管道是否已关闭?也许应用程序未能授权?也许它未能获取我的远程集群的 IP 地址?也许它太慢了?也许网络已关闭?更糟糕的是,您甚至可能不知道来自某些应用程序目标的数据丢失了。而且您甚至没有获得太多收益,因为您需要跟踪应该发送数据的所有内容的状态和状态。这种设计需要仔细分析,因为它很容易成为失败的根源。

注意: 无服务器函数和短生命周期容器通常是我们考虑从应用程序推送作为救援措施的情况。然而,此时我们讨论的是我们可能想要聚合到更长时间序列的事件或指标片段。此主题在 此处 讨论,欢迎随时贡献并帮助我们更好地支持这些情况!

Prometheus 引入了三种方法来支持全局视图用例,每种方法都有其自身的优点和缺点。让我们简要地了解一下这些方法。它们在下图中以橙色显示

Prometheus global view

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

Remote Write

Prometheus Remote Write 协议允许我们将 Prometheus 收集的所有或部分指标转发(流式传输)到远程位置。您可以配置 Prometheus 将某些指标(如果需要,包括所有元数据和 exemplars!)转发到一个或多个支持 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 仍然使用拉取模型从应用程序收集指标,这使我们能够了解这些不同的故障模式。之后,我们批量处理样本和序列并导出,将数据复制(推送)到 Remote Write 端点,从而限制中央点拥有的监控未知数!

重要的是要注意,可靠且高效的远程写入实现是一个不容忽视的问题。Prometheus 社区花费了大约三年的时间才提出了稳定且可扩展的实现方案。我们多次重新实现了 WAL(预写日志),添加了内部排队、分片、智能退避等等。所有这些都对用户隐藏起来,用户可以享受高性能流式传输或存储在中央位置的大量指标。

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 Agent 最好的部分是它内置于 Prometheus 中。相同的抓取 API、相同的语义、相同的配置和发现机制。

如果您计划不在本地查询或告警数据,并将指标流式传输到外部,那么使用 Agent 模式有什么好处呢?有以下几点

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

这种效率重要吗?是的!正如我们所提到的,对于某些部署来说,边缘集群上使用的每 GB 内存和每个 CPU 核心都很重要。另一方面,使用指标执行监控的范式在当今已相当成熟。这意味着,您可以在相同成本下传输更多相关的、具有更高基数的指标 - 效果越好。

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

其次,新 Agent 模式的优势在于它为摄取实现了更轻松的水平可扩展性。这是我最兴奋的事情。让我解释一下原因。

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

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

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

最重要的是,服务器模式下 Prometheus 的资源使用量取决于比仅摄取更多的事情。有告警、记录、查询、压缩、远程写入等,这些可能需要更多或更少的资源,而与指标目标的数量无关。

Agent 模式本质上将发现、抓取和远程写入移动到单独的微服务。这允许专注于仅摄取的运营模式。因此,Agent 模式下的 Prometheus 或多或少是无状态的。是的,为了避免指标丢失,我们需要部署一对 HA 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 maintainer Tom Wilkie 的指导下创建。然后,它被用于开源 Grafana Agent 项目中,此后被许多 Grafana Cloud 客户和社区成员使用。鉴于该解决方案的成熟度,现在是将该实现捐赠给 Prometheus 以进行原生集成和更大规模采用的时候了。Robert (Grafana Labs) 在 Srikrishna (Red Hat) 和社区的帮助下,将代码移植到 Prometheus 代码库中,该代码库已在 2 周前合并到 main 中!

捐赠过程非常顺利。由于一些 Prometheus maintainer 之前在 Grafana Agent 中为该代码做出了贡献,并且由于新的 WAL 受到 Prometheus 自己的 WAL 的启发,因此当前的 Prometheus TSDB maintainer 毫不费力地将其纳入全面维护之下!Robert 加入 Prometheus 团队担任 TSDB maintainer(恭喜!)也确实有所帮助。

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

如何详细使用 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 模式,要么仅用于特定模式。您可以通过检查标志帮助字符串的最后一句话来查看哪个标志用于哪种模式。“仅用于服务器模式”表示它仅用于服务器模式。如果您没有看到任何类似的提及,则表示该标志是共享的。

Agent 模式接受相同的抓取配置,具有相同的发现选项和远程写入选项。

它还公开了一个 Web UI,其中禁用了查询功能,但显示了构建信息、配置、目标和服务发现信息,与正常的 Prometheus 服务器相同。

Prometheus Agent 实践示例:Katacoda 教程

与 Prometheus 远程写入教程类似,如果您想尝试 Prometheus Agent 功能的实践经验,我们推荐 Thanos Katacoda 教程,了解 Prometheus Agent,其中解释了运行 Prometheus Agent 是多么容易。

总结

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

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

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

与往常一样,如果您有任何问题或反馈,请随时 在 GitHub 上提交工单或在邮件列表中提问

这篇博文是 CNCF、Grafana 和 Prometheus 之间协调发布的一部分。欢迎阅读 CNCF 公告 以及关于 Grafana Agent (Prometheus Agent 的基础) 的角度