是时候了解一些 Prometheus 配置了。本章将探索堆栈的核心组件,向您介绍常见的使用模式和虚拟机和容器下的完整设置过程场景。这将使您能够真正验证到目前为止所收集的知识,并为您提供真实示例来测试您的知识。
简而言之,本章将涵盖以下主题:
- Deep dive into the Prometheus configuration
- Managing Prometheus in a standalone server
- Managing Prometheus in Kubernetes
是时候了解一些 Prometheus 配置了。本章将探索堆栈的核心组件,向您介绍常见的使用模式和虚拟机和容器下的完整设置过程场景。这将使您能够真正验证到目前为止所收集的知识,并为您提供真实示例来测试您的知识。
简而言之,本章将涵盖以下主题:
Prometheus 的一个关键特性是,由于非常合理的默认配置,它可以从在本地计算机上运行的快速测试扩展到生产级实例,每秒处理数百万个样本,而无需触及几乎任何它的许多旋钮和刻度盘。说了 ,了解哪些配置选项可用于从 Prometheus 中获得最大价值是非常有用的。
Prometheus 服务器上有两种主要的配置类型——命令行标志和通过配置文件提供的操作逻辑。命令行标志控制在运行时无法更改的参数,例如存储路径或要绑定到的 TCP 端口,并且需要完全重新启动服务器才能应用在此级别完成的任何更改。配置文件控制运行时配置,例如抓取作业定义、规则文件位置或远程存储设置。在以下部分中,我们将深入探讨这两种类型的配置。
虽然在没有启动配置的情况下运行 Prometheus 服务器对于本地实例来说已经足够了,但建议为任何严重的部署配置几个基本的命令行标志。
在撰写本文时,Prometheus 有近 30 个命令行标志用于调整其操作配置的多个方面,按以下命名空间分组:config、web、存储、rules、alertmanager、query和log。 --help 标志很好地描述了大多数选项,但它在某些地方可能有点简洁,因此我们将突出显示对任何部署都很重要或其功能并不明显。
通常首先需要设置的是 Prometheus 配置文件路径,通过 --config.file 标志。默认情况下,Prometheus 会在当前工作目录中查找名为 prometheus.yml 的文件。虽然这对本地测试非常有用,但生产部署通常将服务器二进制文件和配置文件放在自己的路径中,因此通常需要此标志。附带说明一下,这个和存储目录是启动 Prometheus 服务器的唯一硬性要求;没有配置文件,Prometheus 拒绝启动。
按照上一节的相同逻辑,应设置 --storage.tsdb.path 标志以配置数据存储位置的基本路径。这默认为当前工作目录上的 data/,因此建议将其指向更合适的路径 - 可能指向不同的驱动器/卷,其中可以安全地保存数据和 I/O可以减轻争用。请注意,不支持 NFS(包括 AWS EFS),因为它不支持安全数据库文件管理所需的 POSIX 锁定原语。将 Prometheus 数据存储目录放在网络共享中也是不明智的,因为短暂的网络故障会影响监控系统继续运行的能力——就在你最需要它的时候。
Prometheus 本地存储一次只能由单个 Prometheus 实例写入。 为了确保是这种情况,它在数据目录中使用了一个锁定文件。在启动时,它会尝试使用特定于操作系统的系统调用来锁定这个文件,如果文件已经被另一个进程锁定,它将拒绝启动。
这种行为可能存在极端情况;当使用持久卷来存储数据目录时,有可能在重新启动 Prometheus 作为另一个使用相同卷的容器实例时,前一个实例可能没有解锁数据库。这个问题会使这种设置容易受到竞争条件的影响。幸运的是,有 --storage.tsdb.no-lockfile 标志,可以在这种情况下使用。但请注意,一般情况下(即在大多数 Prometheus 部署中),禁用锁定文件是一个坏主意,因为这样做会使意外的数据损坏更容易。
下一步是配置用户将使用什么地址来访问 Prometheus 服务器。 --web.external-url 标志设置此基本 URL,以便在 Web 用户界面和传出警报中生成的 Web 链接正确链接回 Prometheus 服务器或服务器。这可能是负载均衡器/反向代理、Kubernetes 服务的 DNS 名称,或者在最简单的部署中,是运行服务器的主机的可公开访问的完全限定域名。为完整起见,正如官方文档中所述,当 Prometheus 位于具有内容切换(也称为基于位置的切换或 URL 前缀路由)的某些第七层反向代理后面时,也可以在此处提供 URL 路径。
Prometheus 服务器通过在接收到 SIGHUP 时重新加载其配置文件(连同规则文件)来充当传统的 *nix 守护进程。但是,在某些情况下发送此信号并不方便(例如,在 Kubernetes 等容器编排系统中运行或使用自定义构建的自动化时)甚至是不可能的(在 Windows 上运行 Prometheus 时)。在这些情况下,--web.enable-lifecycle 标志可用于启用 /-/reload 和 /-/quit HTTP端点,可分别用于控制、重新加载和关闭。为了防止意外触发这些端点,并且由于 GET 在语义上不正确,因此需要 POST 请求。默认情况下,此标志处于关闭状态,因为对这些端点的不受限制的访问会带来安全问题。
同样,出于同样的原因,--web.enable-admin-api 标志也默认关闭。此标志启用提供一些高级管理操作的 HTTP 端点,例如创建数据快照、删除时间序列和清理墓碑。
您可能已经在 第 3 章中注意到,设置在测试环境中,官方的 Prometheus 压缩包还带来了两个额外的目录,consoles 和 console_libraries。这些是启用 Prometheus 的本机仪表板功能所必需的,这些功能经常被忽视。这些目录包含一些预配置的仪表板(称为控制台)和支持模板库,用 Go 模板语言编写。 Prometheus 可以配置为通过使用 --web.console.templates 和 --web.console.libraries 标志来加载这些。之后,这些仪表板将在 /consoles 端点上可用(如果存在 index.html 文件,则主 Web UI 中将提供一个链接)。
本节是关于调整查询引擎的内部工作的。有些很容易理解,例如给定查询在中止之前可以运行多长时间(--query.timeout),或者可以同时运行多少个查询(--query.max -并发)。
但是,其中两个设置了可能产生不明显后果的限制。第一个是--query.max-samples,它是在Prometheus 2.5.0 中引入的,它设置了可以加载到内存中的最大样本数。这样做是为了限制查询子系统可以使用的最大内存(通过将它与 --query.max-concurrency 一起使用)来尝试防止可怕的 query-of-死亡——一个将大量数据加载到内存中的查询,它使 Prometheus 达到了内存限制,然后终止了进程。 2.5.0 后的行为是,如果任何查询达到此标志设置的限制(默认为 50,000,000 个样本),则查询将失败。
第二个是--query.lookback-delta。在不详细介绍 PromQL 内部如何工作的情况下,此标志设置了 Prometheus 在考虑时间序列数据点过时之前查找时间序列数据点的时间限制。这隐含地意味着,如果您以大于此处设置的间隔(默认为五分钟)收集数据,您将在警报和图表中得到不一致的结果,因此,两分钟是允许失败的最大理智值。
我们在上一节中提到的配置文件声明了 Prometheus 实例的运行时配置。正如我们将看到的,与抓取作业、规则评估和远程读/写配置相关的所有内容都在这里定义。正如我们之前提到的,这些配置可以在不关闭 Prometheus 服务器的情况下重新加载,方法是向进程发送 SIGHUP,或者向 /-/reload 发送 HTTP POST 请求。 kbd> 端点(当 --web.enable-lifecycle 在启动时使用)。
在高层次上,我们可以将配置文件拆分为以下部分:
再一次,Prometheus 官方文档包含了这个文件的架构,它是用 YAML 格式编写的。在本章中,我们将介绍一个示例配置供我们分析,但仅详细介绍 global 和 scrape_configs 部分。 第 9 章中介绍了警报和 rule_files /a>,定义警报和记录规则,而 remote_read 和 remote_write 在 第 14 章,将长期存储与 Prometheus 集成。
可以在 Prometheus 项目 GitHub 存储库中找到包含最全面可用选项列表的配置文件,该存储库位于以下地址:https://github.com/prometheus/prometheus/blob/v2.9.2/config/testdata/conf.good.yml。
我们的示例配置如下所示:
乍一看,它可能看起来有点密集,但为了清楚起见,我们正在制作一些默认值通常不需要触及的配置显式。
让我们详细检查每个部分。
global 配置定义了每个其他配置部分的默认参数,并概述了应该向外部系统的指标添加哪些标签,如以下代码块所示:
scrape_interval 设置应该被抓取的默认频率目标。这通常在 10 秒到 1 分钟之间,默认的 1m 是一个很好的保守值开始。较长的间隔是不可取的,因为丢失的粒度(特别是在仪表中)开始影响正确警告问题的能力并使查询变得挑剔,因为您需要知道一些较短的间隔可能不会返回数据。此外,考虑到五分钟的默认环回增量(在命令行标志中提到),任何超过 150 秒(2 分 30 秒)的 scrape_interval 将意味着给定目标的每个时间序列将是如果单个刮擦失败,则认为是陈旧的。
scrape_timeout 定义了 Prometheus 在关闭连接并将抓取标记为失败之前默认等待目标响应的时间(如果未声明则为 10 秒)。请记住,尽管预计目标对抓取的响应速度相当快,但指标展示指南要求收集应该在抓取时进行而不是缓存,这意味着可能有一些出口商需要更长的时间来响应。
与 scrape_interval 类似,evaluation_interval 设置默认频率记录并评估警报规则。为了理智,两者都应该有相同的。这将在 Chapter 9 中更详细地讨论, 定义警报和记录规则:
最后,external_labels 允许您设置添加到时间序列的标签名称/值对或发送到外部系统的警报,例如 Alertmanager、远程读写基础设施,甚至通过联合的其他 Prometheis。此功能通常用于唯一标识给定警报或时间序列的来源;因此,识别区域、数据中心、分片甚至是 Prometheus 服务器的实例标识符是很常见的。
尽管 Prometheus 接受一个空文件作为有效的配置文件,但绝对最小的有用配置需要一个 scrape_configs 部分。这是我们定义指标收集目标的地方,以及在实际摄取之前是否需要一些后抓取处理。
在我们之前介绍的配置示例中,我们定义了两个抓取作业:prometheus 和 blackbox。在 Prometheus 术语中,scrape 是通过来自目标实例的 HTTP 请求收集指标、解析响应并将收集到的样本提取到存储中的操作。 Prometheus 生态系统中用于度量收集的默认 HTTP 端点被恰当地命名为 /metrics。
此类实例的集合称为job。作业中的实例通常都是同一服务的所有运行副本,因此每种受监控软件通常都有一个作业定义,尽管在使用服务发现时可能会有所不同,正如我们将在 第 12 章,选择正确的服务发现 .实例和作业的组合标识了收集样本的来源,因此这些样本会自动作为标签添加到摄取的数据中,如以下代码块所示:
一个抓取作业定义至少需要一个 job_name 和一组目标。在此示例中,static_configs 用于声明两个抓取作业的目标列表。虽然 Prometheus 支持很多方法来动态定义这个列表,但 static_configs 是最简单和最直接的方法:
详细分析 prometheus 抓取作业,我们可以看到 scrape_interval 和 scrape_timeout 都可以在作业级别重新声明,从而覆盖全局值.如前所述,不鼓励使用不同的间隔,因此仅在绝对必要时使用。
通过设置 sample_limit,Prometheus 将确保无论设置什么值,都会在每次抓取时收集这些样本,方法是在样本数量超过限制时不摄取这些样本并将抓取标记为失败。这是一个很好的安全网,可以防止来自您无法控制的目标的基数爆炸影响监控系统。
这里最后一个相关配置是metric_relabel_configs。这是一个强大的重写引擎,允许在保存到存储之前转换甚至删除收集的指标的身份。此功能最常见的用例是将一组行为不端的指标列入黑名单,在不损害指标身份的情况下删除标签,或更改标签以更好地匹配 Prometheus 语义。理想情况下,metric_relabel_configs 应该用作权宜之计,而问题并没有从源头上解决,因此经常使用它可能是一个危险信号。前面的示例使用 metric_relabel_configs 删除以 expensive_metric_ 开头的每个指标:
虽然我们将在下一章深入探讨 blackbox exporter,但这里使用它的配置来帮助解释以下重要配置:
然而,最重要和最有用的配置是 relabel_configs。它提供了与 metric_relabel_configs 相同的强大语义,但功能却大不相同; relabel_configs 用于操作抓取作业的目标列表。重新标记操作按顺序执行,因此可以创建或修改标签,然后在下一个操作中使用它们。默认情况下,目标将有几个自动生成的标签,可用于重新标记:job 标签将设置为 job_name 配置,< kbd>__address__ 标签将使用目标的主机和端口创建,__scheme__ 和 __metrics_path__ 标签将设置为各自的配置(scheme 和 metrics_path),并且将为 params 配置中定义的每个参数创建一个 __param_<name> 标签。此外,__meta_ 标签将在使用服务发现机制时可用,正如我们将在 第 12 章,选择正确的服务发现。如果在重新标记阶段结束时未设置 instance 标签,则将使用 __address__ 来设置它。以两个下划线 (__) 开头的标签将在重新标记阶段结束时被删除。最后一点,如果您在重新标记过程中需要临时标签,请始终使用 __tmp 前缀,因为它保证不会与 Prometheus 内部标签重叠。
对于黑盒导出器,此功能非常有用,因为我们需要将探测请求发送到导出器,然后导出器将使用 target GET 参数执行其工作。因此,通过示例,对于 static_configs 中指定的每个目标,此配置执行以下操作:
必须引入的一个非常有用的指标是 up 指标。该指标公开了抓取作业的状态。它至少包括一个带有对应作业名称的标签和另一个带有目标实例的标签。在它的示例中,我们可以将值 1 用于成功的抓取,或将 0 用于失败的抓取。
接下来,我们将开始在不同的部署环境中管理 Prometheus。
正如我们之前经历过的几个配置定义一样,我们现在准备通过管理一个独立的 Prometheus 实例来将它们付诸实践。在这些示例中,我们将公开几个配置,同时提供一个验证它们的环境。
要创建 Prometheus 的新实例,请移至正确的存储库路径,如下所示:
确保没有其他测试环境正在运行并启动本章的环境,如下所示:
片刻之后,新实例将可供检查,并且可以通过 http://192.168.42.10:9090 访问 Prometheus Web 界面。
随着新创建的实例运行,是时候使用以下命令登录了:
我们可以通过使用以下命令查看其systemd单元文件来验证正在使用的启动配置:
以下摘录显示了当前存在的标志:
由 --config.file 标志定义的 Prometheus 本身的配置文件可以查看如下:
正如我们所见,使用的配置与之前在 Prometheus 配置文件演练中介绍的配置相似。我们现在可以验证我们之前提到的几个概念。
由于 prometheus 作业中的 metric_relabel_configs,我们可以使用 Prometheus 的两个 per-scrape 指标来确定我们的配置丢弃的样本数,如下所示:
如果我们减去这两个指标,我们会得到丢弃样本的数量(在我们的示例中,这是所有以 go_ 开头的指标名称):
我们可以确认配置重新标记的结果,在我们的示例中,它在 blackbox 作业下生成实例标签:
您可以使用提供的名为 promtool 的实用程序来验证 Prometheus 配置,该实用程序将在 第 8 章,故障排除和验证。使用新配置重新加载 Prometheus 时,您还可以选择查看 prometheus_config_last_reload_successful 指标来评估配置是否已成功解析和应用。
完成测试后,只需确保您位于 chapter05/ 路径内并执行以下命令:
不要太担心——如果需要,您可以轻松地再次启动环境。
Kubernetes 是第一个从 CNCF 毕业的项目,目前是容器编排的事实标准。早期,Heapster 被广泛用作 Kubernetes 开箱即用的监控解决方案。它最初是一个将监控数据发送到外部系统的工具,但后来发展成为一个监控系统本身。不过没过多久,Prometheus 就成为了 Kubernetes 集群事实上的标准监控系统。如今,构成 Kubernetes 集群的大多数组件都具有原生 Prometheus 工具。
在接下来的部分中,我们将通过使用基于 Kubernetes 项目和 Prometheus Operator 项目的示例来介绍如何将 Prometheus 集成到 Kubernetes 环境中。
确保您满足第 3 章,设置测试环境,在其特定版本中可用,尤其是以下版本:
尽管这种方法远未得到建议,但它为更好地理解和排除在 Kubernetes 中运行的 Prometheus 服务器提供了基础。在此示例中,我们将使用 ConfigMap 创建 Prometheus 部署来定义服务器配置。
确保没有运行以下命令的 minikube 实例:
使用以下规范启动一个新的 minikube 实例:
上一条命令完成后,应该可以使用新的 Kubernetes 环境。您可以使用以下命令访问其仪表板,该命令将在您的默认浏览器中打开 Kubernetes 仪表板地址:
要继续我们的示例,请确保您进入正确的存储库路径,如下所示:
为了组织起见,我们将在 kubectl 的帮助下使用以下清单创建一个名为 monitoring 的新命名空间:
使用以下命令应用之前的清单:
我们可以在 Kubernetes 仪表板上验证命名空间创建是否成功:
有了我们的新命名空间,是时候创建一个非常简单的 Prometheus 配置并使用以下清单将其保存在 ConfigMap 中:
使用以下命令应用之前的清单:
现在,是时候开始新的 Prometheus 部署了,确保我们将之前配置的 ConfigMap 挂载到我们正在部署的 pod 中。 Deployment 对象配置有以下元数据:
Prometheus 容器将以其配置文件和来自卷挂载的数据目录启动,如下所示:
config-volume 卷是从 ConfigMap 创建的,而 prometheus-data 卷是使用空目录创建的。这可以在以下代码段中看到:
使用以下命令应用之前的清单:
我们可以使用以下代码片段跟踪部署状态:
我们应该使用以下命令查看 Prometheus 实例的日志:
成功部署后,我们准备为我们的实例分配一个新服务,选择 NodePort 这样我们就可以在不需要端口转发的情况下访问它,如下所示:
使用以下内容应用之前的清单:
您已准备好使用以下代码片段检查您的新 Prometheus 服务:
这将在 Prometheus 服务端点上打开您的浏览器。 您现在可以使用 Prometheus Web 界面检查运行配置和目标:
现在我们已经在 Kubernetes 中运行了 Prometheus,我们可以开始为它添加要抓取的目标。在下一节中,我们将看看如何实现这一目标。
为了这个示例,我们将部署另一个服务并将其添加到我们的 Prometheus 服务器,逐步说明如何执行此操作。我们将使用名为 Hey 的小型 Hello World 类型的应用程序进行设置。
这些步骤与 Prometheus 服务器的部署非常相似。首先使用以下清单为 Hey 创建一个新部署:
使用以下命令应用之前的清单:
我们可以使用以下代码片段跟踪部署状态:
我们可以使用以下命令验证 Hey 实例的日志:
成功部署后,我们准备为我们的实例分配一个新服务,选择 NodePort 以便我们可以在不需要端口转发的情况下访问它,如下所示:
使用以下命令应用之前的清单:
现在,您已准备好检查您的新 Hey 服务,如下所示:
由于在我们的示例中 Prometheus 是静态管理的,因此我们需要添加新的 Hey 目标以进行度量收集。这意味着我们需要更改 Prometheus ConfigMap 以反映新添加的服务,如下所示:
使用以下命令应用之前的清单:
如果您检查正在运行的 Prometheus 配置,则没有任何变化;这是因为没有触发新的部署。为此,需要对部署定义进行更改,因此我们只需更改版本注释并应用新清单,如下所示:
我们可以使用以下命令跟踪部署状态:
片刻之后,将进行新的部署,更改 Prometheus 配置,并出现一个新目标,您可以在 Prometheus Web 用户界面中对其进行验证:
CoreOS 是构建称为 Operator 的模式的先驱,该模式抽象了 Kubernetes 应用程序的打包、部署和管理的复杂性。 Operator 将应用运行所需的知识(例如配置和部署逻辑)综合到 Kubernetes 自定义资源和自定义控制器中。
将 Kubernetes 自定义资源和自定义控制器组合成一个模式是使 Operator 定义栩栩如生的原因。
在实现这种类型的模式时,用户宁愿只请求该应用程序的一个实例,而不是定义例如应用程序的持久存储以及其环境的特定配置,而操作员将抽象所有需要的依赖关系并自动提供最终结果。
在我们的案例中,除了管理部署,包括 Prometheus 服务器的 Pod 数量和持久卷,Prometheus Operator 还将使用 ServiceMonitor 的概念动态更新配置,该概念针对正在运行的容器标签匹配规则的服务:
借助这些知识,我们将提供一个示例,说明如何使用 Prometheus Operator 部署和配置 Prometheus,包括从应用程序收集指标,这次在不同的命名空间上运行。
确保没有运行 minikube 的实例,如下所示:
使用以下规范启动一个新的 minikube 实例:
上一条命令完成后,应该可以使用新的 Kubernetes 环境。您可以使用以下命令访问其仪表板,该命令将在您的默认浏览器中打开 Kubernetes 仪表板地址:
要继续部署我们的示例,请确保您进入正确的存储库路径,如下所示:
与前面的示例一样,我们将在 kubectl 的帮助下创建一个名为 monitoring 的新命名空间,如下所示:
有了可用的新命名空间,是时候确保 Prometheus Operator 的所有访问权限都到位了,如下面的几个配置片段所示。第一个定义了 ClusterRole:
然后,我们将 ClusterRole 应用到 ClusterRoleBinding:
最后,我们为 ClusterRoleBinding 创建一个 ServiceAccount:
使用以下命令应用包含先前代码片段的清单:
配置了新的服务帐户,我们就可以部署 Operator 本身了,如下所示:
使用以下命令应用之前的清单:
我们可以使用以下代码片段跟踪部署状态:
部署了 Operator,我们现在可以使用它来部署和管理 Prometheus 实例。
在继续设置 Prometheus 之前,我们需要为其实例授予正确的访问控制权限。 Prometheus RBAC 清单中的以下片段就是这样做的。首先我们需要创建一个 ClusterRole 允许 Prometheus 通过 GET 请求访问 /metrics:
接下来,我们创建一个 ClusterRoleBinding 来将上述 ClusterRole 的权限授予用户,在我们的例子中是一个 ServiceAccount:
最后,我们为 Prometheus 创建一个 ServiceAccount:
使用以下命令应用包含先前代码片段的清单:
准备好服务帐户后,我们现在可以使用 Prometheus Operator 使用以下清单部署我们的 Prometheus 服务器:
使用以下命令应用之前的清单:
我们可以使用以下命令跟踪部署进度:
部署完成后,我们将准备好为 Prometheus 服务器创建新服务并启动 Web 界面以验证当前设置,如下所示:
以下是Prometheus Operator创建的Prometheus 默认配置:
到目前为止,我们已经部署了 Operator,并使用它来部署 Prometheus 本身。现在,我们已准备好添加目标并了解如何生成它们的逻辑。
在继续之前,我们还将部署一个应用程序以增加可用目标的数量。为此,我们将再次使用 Hey 应用程序,这次使用默认命名空间:
注意标签和端口名称, 如下代码块所示;它们将被服务监视器使用:
使用以下命令应用包含先前代码片段的清单:
我们可以使用以下命令跟踪部署状态:
部署完成后,我们将创建一个新服务,如以下代码块所示。密切注意服务监视器将用于定位此服务的标签:
使用以下命令应用之前的清单:
最后,我们将为 Prometheus 实例和 Hey 应用程序创建服务监视器,这将指示 Operator 配置 Prometheus,添加所需的目标。密切注意选择器配置——它将用于匹配我们之前创建的服务。
以下是 Prometheus 的服务监视器:
Hey 应用程序的服务监视器如下:
使用以下命令应用以前的清单:
您可以使用以下命令验证服务监视器的成功部署:
在 Operator 重新配置 Prometheus 后(这可能需要几秒钟),添加的目标应该可以在您的 Prometheus Web 界面上使用:
ServiceMonitors 是使用 Prometheus Operator 时的主要构建块。您可以配置进入抓取作业的任何内容,例如抓取和超时间隔、要抓取的指标端点、HTTP 查询参数等。您可以在 https:// 找到这些配置的文档github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint。
在本章中,我们介绍了设置 Prometheus 服务器的一些最重要的配置概念。这些知识是为您的特定场景定制 Prometheus 的基础。从启动标志到配置文件,我们还启动了一个实例来试验和验证我们获得的知识。
随着越来越多的工作负载过渡到容器,特别是 Kubernetes,我们深入研究了如何在这样的环境中设置和管理 Prometheus。我们开始尝试使用静态配置作为垫脚石,以了解更强大的方法,即 Prometheus Operator。
在下一章中,我们将介绍最常见的导出器,并在我们所学的基础上再接再厉,以便我们能够成功地从 Prometheus 上的各种不同来源收集数据。