隆重推出 Prometheus 代理模式,一种高效的云原生指标转发方式
2021年11月16日作者 Bartlomiej Plotka (@bwplotka)
Bartek Płotka 自2019年起担任 Prometheus 维护者,并任职于 Red Hat 的首席软件工程师。CNCF Thanos 项目的合著者。CNCF 大使及 CNCF TAG 可观测性技术负责人。业余时间,他正在与 O'Reilly 合作撰写一本名为《高效 Go》的书。观点仅代表个人!
我个人热爱 Prometheus 项目的原因之一(也是我加入团队的众多原因之一)是其对项目目标的专注。Prometheus 始终致力于在提供实用、可靠、廉价但却无价的基于指标的监控方面突破界限。Prometheus 极其稳定和健壮的 API、查询语言以及集成协议(例如远程写入和 OpenMetrics)使得云原生计算基金会(CNCF)的指标生态系统得以在这些坚实的基础之上发展壮大。结果令人惊叹
- 我们可以看到社区中涌现出各种导出器,用于获取几乎所有事物的指标,例如 容器、eBPF、Minecraft 服务器统计数据,甚至园艺中 植物的健康状况。
- 如今,大多数人期望云原生软件具有一个 HTTP/HTTPS
/metrics
端点,Prometheus 可以从中抓取数据。这个概念在 Google 内部秘密开发,并由 Prometheus 项目在全球范围内推广。 - 可观测性范式发生了转变。我们看到 SREs 和开发人员从第一天起就严重依赖指标,这提高了软件的弹性、可调试性以及数据驱动的决策能力!
最终,我们几乎看不到没有运行 Prometheus 的 Kubernetes 集群。
Prometheus 社区的强大专注力也促使其他开源项目发展壮大,将 Prometheus 的部署模型扩展到单个节点之外(例如 Cortex、Thanos 等)。更不用说云供应商也采用了 Prometheus 的 API 和数据模型(例如 Amazon Managed Prometheus、Google Cloud Managed Prometheus、Grafana Cloud 等)。如果你要寻找 Prometheus 项目如此成功的一个原因,那就是:将监控社区的注意力集中在重要的事情上。
在这篇(冗长的)博文中,我将介绍一种新的 Prometheus 运行模式,名为“Agent”(代理)。它直接内置于 Prometheus 二进制文件中。代理模式禁用了 Prometheus 的一些常规功能,并优化了二进制文件,使其适用于抓取和远程写入到远端位置。引入一种减少功能数量的模式,从而实现新的使用模式。在这篇博文中,我将解释为什么它对 CNCF 生态系统中的某些部署来说是一个颠覆性的改变。我对此感到非常兴奋!
转发用例的历史
Prometheus 的核心设计在项目整个生命周期中未曾改变。受 Google Borgmon 监控系统的启发,您可以将 Prometheus 服务器与您希望监控的应用程序一同部署,告诉 Prometheus 如何访问它们,并允许它定期抓取这些应用程序的当前指标值。这种收集方法,通常被称为“拉取模型”,是使 Prometheus 轻量级且可靠的核心原则。此外,它使应用程序检测和导出器变得极其简单,因为它们只需提供一个简单的、人类可读的 HTTP 端点,其中包含所有跟踪指标的当前值(采用 OpenMetrics 格式)。所有这些都无需复杂的推送基础设施和非简单的客户端库。总而言之,一个简化的典型 Prometheus 监控部署如下图所示
这种方式效果很好,多年来我们已经看到数百万次成功的部署,它们处理着数千万个活跃时间序列。其中一些用于更长时间的数据保留,例如两年左右。所有这些都允许查询、告警和记录对集群管理员和开发人员都有用的指标。
然而,云原生世界正在不断发展和演变。随着托管 Kubernetes 解决方案的增长以及秒级按需创建集群的能力,我们现在终于能够将集群视为“牲畜”,而非“宠物”(换句话说,我们不太关心它们的单个实例)。在某些情况下,解决方案甚至不再有集群的概念,例如 kcp、Fargate 和其他平台。
另一个有趣的用例是**边缘**集群或网络的出现。随着电信、汽车和物联网设备等行业采用云原生技术,我们看到越来越多资源受限的、更小的集群。这迫使所有数据(包括可观测性数据)被传输到远程的、更大的对应端,因为这些远程节点上几乎无法存储任何东西。
这意味着什么?这意味着监控数据必须以某种方式聚合、呈现给用户,有时甚至存储在*全局*层面。这通常被称为**全局视图**功能。
天真地讲,我们可能会考虑通过两种方式来实现这一点:要么将 Prometheus 放在全局层面,跨远程网络抓取指标;要么直接将指标从应用程序推送到中心位置进行监控。让我解释一下为什么这两种做法通常都是*非常*糟糕的主意
🔥 跨网络边界抓取可能会带来挑战,因为它在监控管道中增加了新的不确定性。本地拉取模型允许 Prometheus 准确知道指标目标何时以及为何出现问题。也许它已宕机、配置错误、重启过、提供指标速度太慢(例如 CPU 饱和)、服务发现无法发现、我们没有访问凭据,或者只是 DNS、网络或整个集群都已宕机。将我们的抓取器放在网络外部,我们可能会因为引入与单个目标无关的抓取不可靠性而丢失部分信息。最重要的是,如果网络暂时中断,我们甚至可能完全失去重要的可见性。请不要这样做。这不值得。(
🔥 直接将指标从应用程序推送到某个中心位置同样糟糕。特别是当你监控一个大型集群时,如果看不到来自远程应用程序的指标,你将一无所知。应用程序是否已宕机?我的接收器管道是否已宕机?也许应用程序授权失败了?也许它未能获取我的远程集群的 IP 地址?也许它太慢了?也许网络已中断?更糟糕的是,你甚至可能不知道某些应用程序目标的数据丢失了。而且你并没有获得太多好处,因为你需要跟踪所有应该发送数据的事物的状态和情况。这种设计需要仔细分析,因为它很容易导致失败。
注意无服务器函数和短生命周期容器通常是我们考虑将应用程序推送作为解决方案的情况。然而,在这一点上,我们讨论的是事件或我们可能希望聚合到更长生命周期时间序列的指标片段。这个问题在此处进行了讨论,欢迎贡献并帮助我们更好地支持这些用例!
Prometheus 引入了三种支持全局视图用例的方式,每种方式都有其优缺点。让我们简要介绍一下。它们在下图中以橙色显示
- 联邦(Federation)是为聚合目的而引入的第一个功能。它允许全局级别的 Prometheus 服务器从叶节点 Prometheus 抓取一部分指标。这种“联邦”抓取减少了跨网络的一些不确定性,因为联邦端点暴露的指标包含原始样本的时间戳。然而,它通常存在无法联邦所有指标的问题,并且在较长时间的网络分区(数分钟)期间会丢失数据。
- Prometheus 远程读取(Remote Read)允许从远程 Prometheus 服务器的数据库中选择原始指标,而无需直接进行 PromQL 查询。您可以在全局层面部署 Prometheus 或其他解决方案(例如 Thanos),对这些数据执行 PromQL 查询,同时从多个远程位置获取所需的指标。这非常强大,因为它允许您“本地”存储数据并在需要时才访问它。不幸的是,它也有缺点。如果没有像 查询下推(Query Pushdown) 这样的功能,在极端情况下,我们可能需要拉取数 GB 的压缩指标数据来回答一个简单的查询。此外,如果发生网络分区,我们也会暂时失明。最后但同样重要的是,某些安全准则不允许入口流量,只允许出口流量。
- 最后,我们有Prometheus 远程写入(Remote Write),这似乎是目前最受欢迎的选择。由于代理模式侧重于远程写入用例,让我们更详细地解释一下。
远程写入
Prometheus 远程写入协议允许我们将 Prometheus 收集的所有或部分指标转发(流式传输)到远程位置。您可以配置 Prometheus 将一些指标(如果您愿意,可以包含所有元数据和示例!)转发到一个或多个支持远程写入 API 的位置。事实上,Prometheus 同时支持摄取和发送远程写入,因此您可以在全局层面部署 Prometheus 来接收该流并聚合跨集群数据。
尽管官方的 Prometheus 远程写入 API 规范处于审查阶段,但生态系统已将远程写入协议作为默认的指标导出协议。例如,Cortex、Thanos、OpenTelemetry 以及 Amazon、Google、Grafana、Logz.io 等云服务都支持通过远程写入摄取数据。
Prometheus 项目还为其 API 提供了官方合规性测试,例如针对提供远程写入客户端功能的解决方案的 远程写入发送者合规性测试。这是一个很好的方法,可以快速判断您是否正确实现了该协议。
从这种抓取器流式传输数据,通过允许您将指标数据存储在集中位置,从而实现了全局视图用例。这也实现了关注点分离,当应用程序由与可观测性或监控管道不同的团队管理时,这非常有用。此外,这也是为什么希望尽可能减轻客户工作负担的供应商选择远程写入的原因。
等一下,Bartlomiej。你刚才不是说直接从应用程序推送指标不是最好的主意吗!
当然,但令人惊喜的是,即使使用远程写入,Prometheus 仍然使用拉取模型从应用程序中收集指标,这使我们能够理解这些不同的故障模式。之后,我们对样本和时间序列进行批量处理,并导出、复制(推送)数据到远程写入端点,从而限制了中心点需要处理的监控不确定性!
值得注意的是,实现可靠高效的远程写入并非易事。Prometheus 社区花费了大约三年时间才提出了一个稳定且可扩展的实现方案。我们多次重新实现了 WAL(预写日志),添加了内部队列、分片、智能退避等功能。所有这些都对用户隐藏,用户可以享受高性能的流式传输或将大量指标存储在集中位置。
远程写入实操示例:Katacoda 教程
所有这些在 Prometheus 中都不是新鲜事。我们中的许多人已经使用 Prometheus 抓取所有必需的指标,并将它们中的全部或部分远程写入到远程位置。
如果您想亲身体验远程写入功能,我们推荐 Thanos Katacoda 的 Prometheus 指标远程写入教程,该教程解释了 Prometheus 将所有指标转发到远程位置所需的所有步骤。它是**免费**的,只需注册一个账户即可享受教程! 🤗
请注意,此示例使用 Thanos 的接收模式作为远程存储。如今,您可以使用许多其他与远程写入 API 兼容的项目。
既然远程写入工作得很好,为什么我们还要在 Prometheus 中添加一个特殊的代理模式呢?
Prometheus 代理模式
从 Prometheus v2.32.0
(下一个版本)开始,每个人都将能够使用实验性的 --enable-feature=agent
标志运行 Prometheus 二进制文件。如果您想在发布前尝试,请随意使用 Prometheus v2.32.0-beta.0 或使用我们的 quay.io/prometheus/prometheus:v2.32.0-beta.0
镜像。
代理模式优化了 Prometheus,以适应远程写入用例。它禁用了查询、告警和本地存储,并将其替换为定制的 TSDB WAL。其他一切保持不变:抓取逻辑、服务发现和相关配置。如果您只想将数据转发到远程 Prometheus 服务器或任何其他兼容远程写入的项目,它可以用作 Prometheus 的直接替代品。本质上它看起来是这样的
Prometheus 代理最棒的地方在于它内置于 Prometheus 中。相同的抓取 API,相同的语义,相同的配置和发现机制。
如果您不打算在本地查询或告警数据,并计划将指标流出,那么使用代理模式有什么好处呢?有以下几点:
首先,效率。我们定制的代理 TSDB WAL 在成功写入后立即删除数据。如果无法连接到远程端点,它会将数据临时持久化到磁盘上,直到远程端点恢复在线。目前,这仅限于两小时的缓冲区,类似于非代理模式的 Prometheus,希望很快能解除限制。这意味着我们不需要在内存中构建数据块。我们不需要为了查询目的而维护完整的索引。本质上,在类似情况下,代理模式使用的资源仅为普通 Prometheus 服务器的一小部分。
这种效率重要吗?是的!如我们所提,在某些部署中,边缘集群上使用的每一 GB 内存和每一个 CPU 核心都至关重要。另一方面,如今使用指标执行监控的范式已经相当成熟。这意味着,在相同成本下,您能传输的基数越多的相关指标——效果越好。
注意随着代理模式的引入,原始的 Prometheus 服务器模式仍然是推荐的、稳定且受维护的模式。带有远程存储的代理模式会带来额外的复杂性。请谨慎使用。
其次,新代理模式的优势在于它能够更轻松地实现摄取数据的横向扩展。这让我感到最兴奋。让我解释一下原因。
梦想:指标摄取自动扩展
一个真正的、可自动扩展的抓取解决方案需要基于指标目标的数量以及它们暴露的指标数量。我们抓取的数据越多,我们自动部署的 Prometheus 实例就越多。如果目标的数量或其指标的数量减少,我们就可以缩减并移除几个实例。这将消除手动调整 Prometheus 大小的负担,并避免在集群临时较小时过度分配 Prometheus 资源的需要。
仅凭服务器模式下的 Prometheus,这很难实现。这是因为服务器模式下的 Prometheus 是有状态的。无论收集到什么数据,都保持原样存储在单个位置。这意味着缩容过程需要在终止前将已收集的数据备份到现有实例。然后我们就会遇到抓取重叠、误导性陈旧标记等问题。
除此之外,我们还需要一个能够聚合所有实例中所有样本的全局视图查询(例如 Thanos Query 或 Promxy)。最后但同样重要的是,服务器模式下 Prometheus 的资源使用量不仅取决于摄取,还取决于其他更多因素。还有告警、记录、查询、压缩、远程写入等,这些可能需要更多或更少的资源,而与指标目标的数量无关。
代理模式本质上将发现、抓取和远程写入功能移至一个独立的微服务。这使得操作模型可以只专注于数据摄取。因此,代理模式下的 Prometheus 或多或少是无状态的。是的,为了避免指标丢失,我们需要部署一对高可用代理并为其附加持久化磁盘。但从技术上讲,如果我们在成千上万的指标目标(例如容器)中,我们可以部署多个 Prometheus 代理,并安全地更改哪个副本抓取哪个目标。这是因为,最终所有样本都将被推送到同一个中心存储。
总而言之,代理模式下的 Prometheus 使得基于 Prometheus 的抓取能够轻松实现横向自动扩展,从而能够响应指标目标中的动态变化。这无疑是我们将来会与 Prometheus Kubernetes Operator 社区一同关注的重点。
现在我们来看看 Prometheus 中代理模式的当前实现状态。它可以使用了吗?
代理模式已在大规模环境中得到验证
Prometheus 的下一个版本将包含代理模式作为实验性功能。磁盘上的标志、API 和 WAL 格式可能会发生变化。但由于 Grafana Labs 的开源工作,该实现的性能已久经考验。
我们代理自定义 WAL 的最初实现灵感来自当前 Prometheus 服务器的 TSDB WAL,并由 Robert Fratto 于 2019 年在 Prometheus 维护者 Tom Wilkie 的指导下创建。随后,它被用于开源的 Grafana Agent 项目,此后被许多 Grafana Cloud 客户和社区成员使用。鉴于该解决方案的成熟度,是时候将该实现捐赠给 Prometheus,以实现原生集成和更广泛的采用。Robert(Grafana Labs)在 Srikrishna(Red Hat)和社区的帮助下,将代码移植到 Prometheus 代码库,并于两周前合并到 main
分支!
捐赠过程相当顺利。由于一些 Prometheus 维护者此前在 Grafana Agent 项目中也为这段代码做出了贡献,并且新的 WAL 受 Prometheus 自身 WAL 的启发,因此 Prometheus 当前的 TSDB 维护者接手其全面维护并非难事!罗伯特(Robert)加入 Prometheus 团队担任 TSDB 维护者也确实很有帮助(恭喜!)。
现在,让我们解释一下如何使用它!(
如何详细使用代理模式
从现在开始,如果您显示 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.
由于代理模式处于功能标志之后,如前所述,请使用 --enable-feature=agent
标志在代理模式下运行 Prometheus。现在,其余的标志要么同时适用于服务器和代理模式,要么仅适用于特定模式。您可以通过查看标志帮助字符串的最后一句话来判断哪个标志适用于哪种模式。“仅用于服务器模式”表示它仅用于服务器模式。如果您没有看到类似这样的说明,则表示该标志是共享的。
代理模式接受相同的抓取配置、相同的发现选项和远程写入选项。
它还暴露了一个 Web UI,该 UI 禁用了查询功能,但会像普通的 Prometheus 服务器一样显示构建信息、配置、目标和服务发现信息。
Prometheus 代理实操示例:Katacoda 教程
类似于 Prometheus 远程写入教程,如果您想亲身体验 Prometheus 代理的功能,我们推荐 Thanos Katacoda 的 Prometheus 代理教程,它解释了运行 Prometheus 代理是多么容易。
总结
我希望您觉得这很有趣!在这篇博文中,我们探讨了新出现的用例,例如
- 边缘集群
- 受限访问网络
- 大量集群
- 短暂且动态的集群
接着,我们解释了新的 Prometheus 代理模式,该模式允许高效地将抓取的指标转发到远程写入端点。
一如既往,如果您有任何问题或反馈,请随时在 GitHub 上提交工单或在邮件列表中提问。
这篇博文是 CNCF、Grafana 和 Prometheus 之间协同发布的一部分。也欢迎阅读 CNCF 的公告 以及作为 Prometheus 代理基础的 Grafana Agent 的相关内容。