理解和使用 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 gauge
blackbox_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 summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0
go_gc_duration_seconds{quantile="0.5"} 0
go_gc_duration_seconds{quantile="0.75"} 0
go_gc_duration_seconds{quantile="1"} 0
go_gc_duration_seconds_sum 0
go_gc_duration_seconds_count 0
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
process_cpu_seconds_total 0.05
# HELP process_max_fds Maximum number of open file descriptors.
# TYPE process_max_fds gauge
process_max_fds 1.048576e+06
# HELP process_open_fds Number of open file descriptors.
# TYPE process_open_fds gauge
# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
process_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 gauge
process_start_time_seconds 1.54115492874e+09
# HELP process_virtual_memory_bytes Virtual memory size in bytes.
# TYPE process_virtual_memory_bytes gauge
process_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 gauge
probe_dns_lookup_time_seconds 0.061087943
# HELP probe_duration_seconds Returns how long the probe took to complete in seconds
# TYPE probe_duration_seconds gauge
probe_duration_seconds 0.065580871
# HELP probe_failed_due_to_regex Indicates if probe failed due to regex
# TYPE probe_failed_due_to_regex gauge
probe_failed_due_to_regex 0
# HELP probe_http_content_length Length of http content response
# TYPE probe_http_content_length gauge
probe_http_content_length 0
# HELP probe_http_duration_seconds Duration of http request by phase, summed over all redirects
# TYPE probe_http_duration_seconds gauge
probe_http_duration_seconds{phase="connect"} 0
probe_http_duration_seconds{phase="processing"} 0
probe_http_duration_seconds{phase="resolve"} 0.061087943
probe_http_duration_seconds{phase="tls"} 0
probe_http_duration_seconds{phase="transfer"} 0
# HELP probe_http_redirects The number of redirects
# TYPE probe_http_redirects gauge
# HELP probe_http_ssl Indicates if SSL was used for the final redirect
# TYPE probe_http_ssl gauge
# HELP probe_http_status_code Response HTTP status code
# TYPE probe_http_status_code gauge
# HELP probe_http_version Returns the version of HTTP of the probe response
# TYPE probe_http_version gauge
# HELP probe_ip_protocol Specifies whether probe ip protocol is IP4 or IP6
# TYPE probe_ip_protocol gauge
# HELP probe_success Displays whether or not the probe was a success
# TYPE probe_success gauge
注意事项
可以发现,几乎所有的指标值都是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
然后在编辑器中打开它,前几行看起来像这样:
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 gauge
probe_dns_lookup_time_seconds 0.02679421
# HELP probe_duration_seconds Returns how long the probe took to complete in seconds
# TYPE probe_duration_seconds gauge
probe_duration_seconds 0.461619124
# HELP probe_failed_due_to_regex Indicates if probe failed due to regex
# TYPE probe_failed_due_to_regex gauge
probe_failed_due_to_regex 0
# HELP probe_http_content_length Length of http content response
# TYPE probe_http_content_length gauge
probe_http_content_length -1
# HELP probe_http_duration_seconds Duration of http request by phase, summed over all redirects
# TYPE probe_http_duration_seconds gauge
probe_http_duration_seconds{phase="connect"} 0.062076202999999996
probe_http_duration_seconds{phase="processing"} 0.23481845699999998
probe_http_duration_seconds{phase="resolve"} 0.029594103
probe_http_duration_seconds{phase="tls"} 0.163420078
probe_http_duration_seconds{phase="transfer"} 0.002243199
# HELP probe_http_redirects The number of redirects
# TYPE probe_http_redirects gauge
# HELP probe_http_ssl Indicates if SSL was used for the final redirect
# TYPE probe_http_ssl gauge
# HELP probe_http_status_code Response HTTP status code
# TYPE probe_http_status_code gauge
probe_http_status_code 200
# HELP probe_http_uncompressed_body_length Length of uncompressed response body
# TYPE probe_http_uncompressed_body_length gauge
probe_http_uncompressed_body_length 14516
# HELP probe_http_version Returns the version of HTTP of the probe response
# TYPE probe_http_version gauge
# HELP probe_ip_protocol Specifies whether probe ip protocol is IP4 or IP6
# TYPE probe_ip_protocol gauge
# HELP probe_ssl_earliest_cert_expiry Returns earliest SSL cert expiry in unixtime
# TYPE probe_ssl_earliest_cert_expiry gauge
probe_ssl_earliest_cert_expiry 1.581897599e+09
# HELP probe_success Displays whether or not the probe was a success
# TYPE probe_success gauge
# HELP probe_tls_version_info Contains the TLS version used
# TYPE probe_tls_version_info gauge
probe_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
文件:
- job_name : blackbox # 用于获取 Exporter 本身的指标
macOS 和 Windows 的 prometheus.yml
文件:
- job_name : blackbox # 用于获取 Exporter 本身的指标
- 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
- job_name : blackbox # 用于获取 Exporter 本身的指标
- localhost:9115 # 对于 MacOS 和 Windows,请替换为 - host.docker.internal:9115
- job_name : blackbox-http # 用于获取 Exporter Target 的指标
- 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
的值,该标签告诉你指标来自何处。
以下是用于执行此操作的配置。我们将逐步解释:
- job_name : blackbox # 用于获取 Exporter 本身的指标
- localhost:9115 # 对于 MacOS 和 Windows,请替换为 - host.docker.internal:9115
- job_name : blackbox-http # 用于获取 Exporter Target 的指标
- http://prometheus.io # 要探测的 http Target
- https://prometheus.io # 要探测的 https Target
- http://example.com:8080 # 要探测的 http Target(端口 8080)
- source_labels : [ __address__ ]
target_label : __param_target
- source_labels : [ __param_target ]
- target_label : __address__
replacement : localhost:9115 # blackbox exporter 的真实主机名:端口。对于 MacOS 和 Windows,请替换为 - host.docker.internal:9115
与上一配置相比,这里有什么新东西?
params
不再包含target
,而是我们在static_configs
下的targets
添加实际的 Target。我们现在也可以这样做:
- 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 : __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
:
- source_labels : [ __address__ ]
target_label : __param_target
经过这一步,我们想象中的 Prometheus 请求 URI 现在有了 Target 参数:"http://prometheus.io/probe?target=http://prometheus.io&module=http_2xx"
。
然后,我们从标签__param_target
中提取值,并创建一个具有这些值的instance
标签。
- source_labels : [ __param_target ]
请求本身不会被改变,但从我们的请求返回的指标值现在会携带一个标签instance="http://prometheus.io"
。
接下来,我们将值localhost:9115
(我们的 Exporter 的 URI)写入标签__address__
。这将被用于 Prometheus 抓取请求用到的主机名和端口,以使得 Prometheus 查询 Exporter 而不是直接查询指向 Target 的 URI。
- 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 官方文档 翻译而成。