理解和使用 Multi-target Exporter 模式
本指南将为你介绍 Multi-target Exporter(多 Target Exporter)模式。为了实现这一目标,我们将:
- 描述 Multi-target Exporter 模式及其用途,
- 以 blackbox exporter 为例,说明该模式的用法,
- 配置自定义查询模块用于 blackbox exporter,
- 让 blackbox exporter 对 Prometheus 网站执行基本指标查询,
- 探索配置 Prometheus 抓取 Exporter 时使用的主流模式。
Multi-target Exporter 模式?
我们所说的 Multi-target Exporter 模式是指一种特定设计,其中:
- Exporter 通过网络协议获取 Target 的指标。
- Exporter 不必在从其收集指标的机器上运行。
- Exporter 通过 Prometheus 的 GET 请求接收 Target 和查询配置字符串作为参数。
- Exporter 在接收到 Prometheus 的 GET 请求后开始抓取,并在抓取完成后完成响应。
- Exporter 可以查询多个 Target。
这种模式仅适用于某些 Exporter,例如 blackbox 和 SNMP exporter。这是因为我们要么无法在采集 Target 上运行 Exporter(例如使用 SNMP 的网络设备),要么我们明确感兴趣的是访问的距离(例如网站从特定点外网的延迟和可达性,这是 blackbox exporter 的一个常见用例)。
运行 Multi-target Exporter
Multi-target Exporter 在运行环境方面具有灵活性,可以以多种方式运行。在容器中作为常规程序,在裸金属上和虚拟机上作为后台服务均可。因为它们通过网络被查询,所以使用时需要开放适当的端口。否则的话,它们的资源消耗量将会更少。
现在让我们来试一试,使用 Docker 启动一个 blackbox exporter 容器。在终端中运行以下命令:
docker run -p 9115:9115 prom/blackbox-exporter
你应该看到几条日志,如果一切顺利的话,最后一条应提示 “Listening on address”,如下所示:
level=info ts=2018-10-17T15:41:35.4997596Z caller=main.go:324 msg="Listening on address" address=:9115
Multi-target Exporter 的基本查询
有二种方式查询:
- 查询 Exporter 本身。它有自己的指标,通常可从
/metrics
端点访问。 - 查询 Exporter 以抓取另一个 Target。这通常可以在例如
/probe
的描述性端点(descriptive endpoint)上访问。当使用 Multi-target Exporter 时,这可能是你主要感兴趣的数据查询方式。
你可以手动使用 curl 在另一个终端中尝试第一种类型的查询,或者使用此链接访问:http://localhost:9115/metrics
:
curl 'localhost:9115/metrics'
得到响应应该是这样的:
# HELP blackbox_exporter_build_info A metric with a constant '1' value labeled by version, revision, branch, and goversion from which blackbox_exporter was built.# TYPE blackbox_exporter_build_info gaugeblackbox_exporter_build_info{branch="HEAD",goversion="go1.10",revision="4a22506cf0cf139d9b2f9cde099f0012d9fcabde",version="0.12.0"} 1# HELP go_gc_duration_seconds A summary of the GC invocation durations.# TYPE go_gc_duration_seconds summarygo_gc_duration_seconds{quantile="0"} 0go_gc_duration_seconds{quantile="0.25"} 0go_gc_duration_seconds{quantile="0.5"} 0go_gc_duration_seconds{quantile="0.75"} 0go_gc_duration_seconds{quantile="1"} 0go_gc_duration_seconds_sum 0go_gc_duration_seconds_count 0# HELP go_goroutines Number of goroutines that currently exist.# TYPE go_goroutines gaugego_goroutines 9
[…]
# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.# TYPE process_cpu_seconds_total counterprocess_cpu_seconds_total 0.05# HELP process_max_fds Maximum number of open file descriptors.# TYPE process_max_fds gaugeprocess_max_fds 1.048576e+06# HELP process_open_fds Number of open file descriptors.# TYPE process_open_fds gaugeprocess_open_fds 7# HELP process_resident_memory_bytes Resident memory size in bytes.# TYPE process_resident_memory_bytes gaugeprocess_resident_memory_bytes 7.8848e+06# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.# TYPE process_start_time_seconds gaugeprocess_start_time_seconds 1.54115492874e+09# HELP process_virtual_memory_bytes Virtual memory size in bytes.# TYPE process_virtual_memory_bytes gaugeprocess_virtual_memory_bytes 1.5609856e+07
这些是 Prometheus 格式的指标。它们来自 Exporter 的仪表化过程,并且告诉我们 Exporter 运行时的状态。这个过程被称为白箱监控,对于日常操作实践非常有用。如果你对此感兴趣,请查阅我们的如何自定义应用程序的指南,了解如何监控自己的应用。
对于第二种类型的查询,我们需要在 HTTP GET 请求中提供 Target 和模块作为参数。Target 是一个 URI 或 IP 地址,而模块必须在 Exporter 的配置中定义。blackbox exporter 容器带有一个有用的默认配置。我们将使用 Target prometheus.io
和预定义的模块http_2xx
。它告诉 Exporter 像浏览器访问prometheus.io
时一样发起GET请求,并期望收到一个200 OK 响应。
现在,你可以在终端中使用 curl 告诉你的 blackbox exporter 查询prometheus.io
:
curl 'localhost:9115/probe?target=prometheus.io&module=http_2xx'
这将返回大量指标:
# HELP probe_dns_lookup_time_seconds Returns the time taken for probe dns lookup in seconds# TYPE probe_dns_lookup_time_seconds gaugeprobe_dns_lookup_time_seconds 0.061087943# HELP probe_duration_seconds Returns how long the probe took to complete in seconds# TYPE probe_duration_seconds gaugeprobe_duration_seconds 0.065580871# HELP probe_failed_due_to_regex Indicates if probe failed due to regex# TYPE probe_failed_due_to_regex gaugeprobe_failed_due_to_regex 0# HELP probe_http_content_length Length of http content response# TYPE probe_http_content_length gaugeprobe_http_content_length 0# HELP probe_http_duration_seconds Duration of http request by phase, summed over all redirects# TYPE probe_http_duration_seconds gaugeprobe_http_duration_seconds{phase="connect"} 0probe_http_duration_seconds{phase="processing"} 0probe_http_duration_seconds{phase="resolve"} 0.061087943probe_http_duration_seconds{phase="tls"} 0probe_http_duration_seconds{phase="transfer"} 0# HELP probe_http_redirects The number of redirects# TYPE probe_http_redirects gaugeprobe_http_redirects 0# HELP probe_http_ssl Indicates if SSL was used for the final redirect# TYPE probe_http_ssl gaugeprobe_http_ssl 0# HELP probe_http_status_code Response HTTP status code# TYPE probe_http_status_code gaugeprobe_http_status_code 0# HELP probe_http_version Returns the version of HTTP of the probe response# TYPE probe_http_version gaugeprobe_http_version 0# HELP probe_ip_protocol Specifies whether probe ip protocol is IP4 or IP6# TYPE probe_ip_protocol gaugeprobe_ip_protocol 6# HELP probe_success Displays whether or not the probe was a success# TYPE probe_success gaugeprobe_success 0
注意事项
可以发现,几乎所有的指标值都是0
。最后一个读取到的是probe_success 0
。这意味着探针无法成功访问prometheus.io
。原因在名为probe_ip_protocol
的指标中,其值为6
。默认情况下,探针默认使用 IPv6。但是,Docker 守护进程默认阻止了 IPv6 流量。因此,运行在 Docker 容器中的 blackbox exporter 无法通过 IPv6 进行连接。
我们现在可以要么告诉 Docker 允许使用 IPv6,要么让 blackbox exporter 使用 IPv4。在实际情况中,这两者都有可能适用,并且正如我们经常遇到的那样,“该怎么做?”的答案往往是“这取决于具体情况”。因为这是一个有关 Exporter 的指南,我们将更改 Exporter 的配置并利用这个机会配置自定义模块。
模块配置
模块可以在名为config.yml
的文件中预定义,此文件位于 Docker 容器内部,是 GitHub 仓库中blackbox.yml
文件的一个副本。
我们将复制这个文件,并根据我们的需求进行调整,然后告诉 Exporter 使用我们的配置文件而不是容器内自带的文件。首先,使用 curl 或浏览器下载文件:
curl -o blackbox.yml https://raw.githubusercontent.com/prometheus/blackbox_exporter/master/blackbox.yml
然后在编辑器中打开它,前几行看起来像这样:
modules: http_2xx: prober: http http_post_2xx: prober: http http: method: POST
YAML 使用空格缩进来表示层次结构,你可以从中识别出两个名为http_2xx
和http_post_2xx
的模块,它们都具有http
探针。对于其中一个,method
被特别设置为POST
。如果你想了解更多可用的探针和选项,请查看文档。
接下来,我们需要告诉 blackbox exporter 使用我们刚刚修改过的文件。这可以通过--config.file="blackbox.yml"
标志来实现。但由于我们正在使用 Docker,首先必须通过--mount
命令使文件blackbox.yml
在容器内部可用。注意:如果你使用的是 macOS,首先需要允许 Docker 守护程序访问存放blackbox.yml
的目录。你可以通过点击菜单栏上的 Docker 小鲸鱼图标,然后选择Preferences
->File Sharing
->+
来完成配置。之后按Apply & Restart
。
首先停止旧的容器:可以切换到它的终端并按ctrl+c
。之后,确保你位于包含blackbox.yml
的目录中,运行下面这个命令。它有点长,我们将会详细解释:
docker run -p 9115:9115 --mount type=bind,source="$(pwd)"/blackbox.yml,target=/blackbox.yml,readonly prom/blackbox-exporter --config.file="/blackbox.yml"
这个命令告诉docker
:
run
一个容器,将外部端口9115
映射到容器内的端口9115
。mount
从当前目录($(pwd)
表示打印工作目录)将文件blackbox.yml
以只读模式挂载到/blackbox.yml
。- 使用 Docker hub 中的
prom/blackbox-exporter
镜像。 - 运行 blackbox exporter,并通过
--config.file
标志告诉它使用/blackbox.yml
作为配置文件。
如果都输入正确,你应该看到类似这样的输出:
level=info ts=2018-10-19T12:40:51.650462756Z caller=main.go:213 msg="Starting blackbox_exporter" version="(version=0.12.0, branch=HEAD, revision=4a22506cf0cf139d9b2f9cde099f0012d9fcabde)"level=info ts=2018-10-19T12:40:51.653357722Z caller=main.go:220 msg="Loaded config file"level=info ts=2018-10-19T12:40:51.65349635Z caller=main.go:324 msg="Listening on address" address=:9115
现在,你可以在终端中尝试使用新的 IPv4 的模块http_2xx
:
curl 'localhost:9115/probe?target=prometheus.io&module=http_2xx'
这应该返回 Prometheus 指标,如下所示:
# HELP probe_dns_lookup_time_seconds Returns the time taken for probe dns lookup in seconds# TYPE probe_dns_lookup_time_seconds gaugeprobe_dns_lookup_time_seconds 0.02679421# HELP probe_duration_seconds Returns how long the probe took to complete in seconds# TYPE probe_duration_seconds gaugeprobe_duration_seconds 0.461619124# HELP probe_failed_due_to_regex Indicates if probe failed due to regex# TYPE probe_failed_due_to_regex gaugeprobe_failed_due_to_regex 0# HELP probe_http_content_length Length of http content response# TYPE probe_http_content_length gaugeprobe_http_content_length -1# HELP probe_http_duration_seconds Duration of http request by phase, summed over all redirects# TYPE probe_http_duration_seconds gaugeprobe_http_duration_seconds{phase="connect"} 0.062076202999999996probe_http_duration_seconds{phase="processing"} 0.23481845699999998probe_http_duration_seconds{phase="resolve"} 0.029594103probe_http_duration_seconds{phase="tls"} 0.163420078probe_http_duration_seconds{phase="transfer"} 0.002243199# HELP probe_http_redirects The number of redirects# TYPE probe_http_redirects gaugeprobe_http_redirects 1# HELP probe_http_ssl Indicates if SSL was used for the final redirect# TYPE probe_http_ssl gaugeprobe_http_ssl 1# HELP probe_http_status_code Response HTTP status code# TYPE probe_http_status_code gaugeprobe_http_status_code 200# HELP probe_http_uncompressed_body_length Length of uncompressed response body# TYPE probe_http_uncompressed_body_length gaugeprobe_http_uncompressed_body_length 14516# HELP probe_http_version Returns the version of HTTP of the probe response# TYPE probe_http_version gaugeprobe_http_version 1.1# HELP probe_ip_protocol Specifies whether probe ip protocol is IP4 or IP6# TYPE probe_ip_protocol gaugeprobe_ip_protocol 4# HELP probe_ssl_earliest_cert_expiry Returns earliest SSL cert expiry in unixtime# TYPE probe_ssl_earliest_cert_expiry gaugeprobe_ssl_earliest_cert_expiry 1.581897599e+09# HELP probe_success Displays whether or not the probe was a success# TYPE probe_success gaugeprobe_success 1# HELP probe_tls_version_info Contains the TLS version used# TYPE probe_tls_version_info gaugeprobe_tls_version_info{version="TLS 1.3"} 1
你可以看到探针运行成功并且获得了许多有用的指标,如各阶段的延迟、状态码、SSL 状态或证书到期时间的 Unix 时间戳。blackbox exporter 还提供了一个小型的 Web 界面,地址为http://localhost:9115
,可以供你检查最近的几次探针信息、加载的配置和调试信息。它甚至提供了探测prometheus.io
的探针,这在当你想知道为什么某些配置不起作用时非常方便。
使用 Prometheus 查询 Multi-target Exporter
如果到目前为止,如果一切顺利,那么恭喜自己吧。blackbox exporter 已经可以正常工作,并且可以让它去查询远程 Target。目前你已经接近完成整个流程,现在你需要告诉 Prometheus 为我们自动执行查询。
以下是 Prometheus 配置的最小示例,它使用curl 'localhost:9115/metrics'
的方式,告诉 Prometheus 自己抓取 Exporter 本身:
注意: 如果你使用的是 Docker for Mac 或 Docker for Windows,则在最后的行中不能使用localhost:9115
,而必须使用host.docker.internal:9115
。这与在这些操作系统上实现 Docker 所使用的虚拟机有关。在生产环境中不要使用此配置。
Linux 的prometheus.yml
文件:
global: scrape_interval: 5s
scrape_configs:- job_name: blackbox # 用于获取 Exporter 本身的指标 metrics_path: /metrics static_configs: - targets: - localhost:9115
macOS 和 Windows 的 prometheus.yml
文件:
global: scrape_interval: 5s
scrape_configs:- job_name: blackbox # 用于获取 Exporter 本身的指标 metrics_path: /metrics static_configs: - targets: - host.docker.internal:9115
现在运行 Prometheus 容器,并告诉它从指定的目录加载我们的配置文件。由于宿主机的网络地址在不同的环境中稍有差异,因此 Linux 上的命令与 MacOS 和 Windows 上的命令略有不同:
运行 Prometheus
Linux(不要在生产环境中使用--network="host"
):
docker run --network="host" --mount type=bind,source="$(pwd)"/prometheus.yml,target=/prometheus.yml,readonly prom/prometheus --config.file="/prometheus.yml"
MacOS 和 Windows:
docker run -p 9090:9090 --mount type=bind,source="$(pwd)"/prometheus.yml,target=/prometheus.yml,readonly prom/prometheus --config.file="/prometheus.yml"
这个命令类似于使用配置文件运行 blackbox exporter 的过程。
如果一切正常,你应该能够通过访问 localhost:9090/targets,看到blackbox
下端点的状态为绿色的UP
。如果你看到的是红色的DOWN
,请确保你之前启动的 blackbox exporter 仍在运行。如果没有显示任何内容或黄色的UNKNOWN
,你可能需要给浏览器重新加载一下试试。
要告诉 Prometheus 查询 "localhost:9115/probe?target=prometheus.io&module=http_2xx"
,你需要在 Prometheus 配置文件prometheus.yml
中添加另一个采集任务blackbox-http
,设置metrics_path
为/probe
,并设置params:
部分的参数:
配置 Prometheus
global: scrape_interval: 5s
scrape_configs:- job_name: blackbox # 用于获取 Exporter 本身的指标 metrics_path: /metrics static_configs: - targets: - localhost:9115 # 对于 MacOS 和 Windows,请替换为 - host.docker.internal:9115
- job_name: blackbox-http # 用于获取 Exporter Target 的指标 metrics_path: /probe params: module: [http_2xx] target: [prometheus.io] static_configs: - targets: - localhost:9115 # 对于 MacOS 和 Windows,请替换为 - host.docker.internal:9115
保存配置文件后,切换到 Prometheus 容器的终端并停止容器(按 ctrl+C
),然后重新启动容器以加载配置。
终端应返回消息"Server is ready to receive web requests."
,几秒钟后你将开始看到丰富的图表出现在你的 Prometheus 上。
这种方法可以正常工作,但有几个缺点:
- 实际的 Target 出现在参数配置中,这非常不寻常且难以理解。
instance
标签包含 blackbox exporter 地址的值,从技术上来说这是正确的,但我们对此不感兴趣。- 我们无法看到我们探测的 URL。如果我们要探测多个 URL,这将导致不同指标混在一起。
为了解决这些问题,我们将使用 relabel_config(relabel 即重标签)。relabel_config 在这里很有用,因为 Prometheus 在后台的许多东西都使用内部标签进行配置。详细的信息比较复杂,超出了本指南的讨论范畴。因此我们在这里只讨论必要的部分。但如果你想了解更多,请参阅这个演讲。目前只需理解以下这些信息就足够了:
- 所有以
__
开头的标签在抓取后都会被丢弃。大多数内部标签都以__
开始。 - 你可以配置称为
__param_<name>
的内部标签,用于在抓取请求中设置键为<name>
的 URL 参数。 - 有一个内部标签
__address__
,由static_configs
下的targets
设置,并用于抓取请求的值。默认情况下,稍后用于设置附加到每个指标的标签instance
的值,该标签告诉你指标来自何处。
以下是用于执行此操作的配置。我们将逐步解释:
global: scrape_interval: 5s
scrape_configs:- job_name: blackbox # 用于获取 Exporter 本身的指标 metrics_path: /metrics static_configs: - targets: - localhost:9115 # 对于 MacOS 和 Windows,请替换为 - host.docker.internal:9115
- job_name: blackbox-http # 用于获取 Exporter Target 的指标 metrics_path: /probe params: module: [http_2xx] static_configs: - targets: - http://prometheus.io # 要探测的 http Target - https://prometheus.io # 要探测的 https Target - http://example.com:8080 # 要探测的 http Target(端口 8080) relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: localhost:9115 # blackbox exporter 的真实主机名:端口。对于 MacOS 和 Windows,请替换为 - host.docker.internal:9115
与上一配置相比,这里有什么新东西?
params
不再包含target
,而是我们在static_configs
下的targets
添加实际的 Target。我们现在也可以这样做:
params: module: [http_2xx] static_configs: - targets: - http://prometheus.io # 要探测的 http Target - https://prometheus.io # 要探测的 https Target - http://example.com:8080 # 要探测的 http Target(端口 8080)
relabel_configs
包含新的重标签规则:
relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: localhost:9115 # blackbox exporter的真实主机名:端口。对于 MacOS 和 Windows,请替换为 - host.docker.internal:9115
在应用重标签规则之前,Prometheus 发出请求的 URI 看起来是这样的:"http://prometheus.io/probe?module=http_2xx"
. 应用重标签规则之后,它看起来会变成这样:“http://localhost:9115/probe?target=http://prometheus.io&module=http_2xx"
。
让我们来看看每个规则是如何实现这一转换的:
首先,我们从标签__address__
(包含targets
的值)中提取值,并将其写入新的标签__param_target
,这会在 Prometheus 抓取请求中添加参数target
:
relabel_configs: - source_labels: [__address__] target_label: __param_target
经过这一步,我们想象中的 Prometheus 请求 URI 现在有了 Target 参数:"http://prometheus.io/probe?target=http://prometheus.io&module=http_2xx"
。
然后,我们从标签__param_target
中提取值,并创建一个具有这些值的instance
标签。
relabel_configs: - source_labels: [__param_target] target_label: instance
请求本身不会被改变,但从我们的请求返回的指标值现在会携带一个标签instance="http://prometheus.io"
。
接下来,我们将值localhost:9115
(我们的 Exporter 的 URI)写入标签__address__
。这将被用于 Prometheus 抓取请求用到的主机名和端口,以使得 Prometheus 查询 Exporter 而不是直接查询指向 Target 的 URI。
relabel_configs: - target_label: __address__ replacement: localhost:9115 # blackbox exporter的真实主机名:端口。对于Windows和macOS,请替换为 - host.docker.internal:9115
此时,我们的请求变为:"localhost:9115/probe?target=http://prometheus.io&module=http_2xx"
。通过这种方式,我们可以在知道实际的 Target,使用它们作为instance
的标签值,同时让 Prometheus 向 blackbox exporter 发起请求。
通常人们会结合特定的服务发现策略。欲了解更多信息,请参阅配置文档。使用服务发现也没有任何问题,因为这些与static_configs
下的targets
一样,都会写入到__address__
标签中。
以上就是本指南的全部内容。重启 Prometheus Docker 容器,查看你的指标。注意你选择的时间段应该是实际收集到数据的时期。
概述
在这篇指南中,你学习了 Multi-target Exporter 模式的原理,如何运行带有自定义模块的 blackbox exporter,以及如何通过使用重标签来配置 Prometheus 以使用探针标签抓取指标值。
该文档基于 Prometheus 官方文档翻译而成。