了解并使用多目标导出器模式
本指南将向您介绍多目标导出器模式。为此,我们将:
- 描述多目标导出器模式及其使用原因,
- 运行 blackbox 导出器作为该模式的示例,
- 为 blackbox 导出器配置自定义查询模块,
- 让 blackbox 导出器针对 Prometheus 网站运行基本指标查询,
- 研究一种常见的 Prometheus 配置模式,即使用重新标记来抓取导出器。
多目标导出器模式是什么?
我们所说的多目标导出器模式是指一种特定的设计,其中:
- 导出器将通过网络协议获取目标的指标。
- 导出器不必运行在采集指标的机器上。
- 导出器将目标和查询配置字符串作为 Prometheus GET 请求的参数。
- 导出器在收到 Prometheus 的 GET 请求后开始抓取,并在抓取完成后返回结果。
- 导出器可以查询多个目标。
此模式仅用于某些导出器,例如 blackbox 和 SNMP 导出器。
原因是,我们要么无法在目标上运行导出器(例如使用 SNMP 的网络设备),要么我们明确关注距离(例如从我们网络外部的特定点访问网站的延迟和可达性),这是 blackbox 导出器的常见用例。
运行多目标导出器
多目标导出器对其环境非常灵活,可以以多种方式运行。可以作为常规程序、在容器中、作为后台服务、在裸机上或在虚拟机上运行。因为它们通过网络进行查询和被查询,所以需要开放适当的端口。除此之外,它们对资源要求不高。
现在,让我们自己动手试试吧!
使用 Docker 启动一个 blackbox 导出器容器,在终端中运行此命令。根据您的系统配置,您可能需要在命令前加上 `sudo`
docker run -p 9115:9115 prom/blackbox-exporter
您应该会看到几行日志,如果一切顺利,最后一行应该报告 `msg="Listening on address"`,如下所示:
level=info ts=2018-10-17T15:41:35.4997596Z caller=main.go:324 msg="Listening on address" address=:9115
多目标导出器的基本查询
有两种查询方式:
- 查询导出器本身。它有自己的指标,通常在 `/metrics` 路径下可用。
- 查询导出器以抓取另一个目标。通常在一个“描述性”端点可用,例如 `/probe`。当您使用多目标导出器时,这很可能是您主要感兴趣的。
您可以在另一个终端中使用 curl 手动尝试第一种查询类型,或者使用此链接
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
go_goroutines 9
[…]
# 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
process_open_fds 7
# 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 格式的指标。它们来自导出器的自身检测,告诉我们导出器运行时的状态。这被称为白盒监控,在日常运维实践中非常有用。如果您好奇,可以尝试我们的指南,了解如何为自己的应用程序添加指标。
对于第二种查询类型,我们需要在 HTTP GET 请求中提供一个目标和一个模块作为参数。目标是一个 URI 或 IP,而模块必须在导出器的配置中定义。blackbox 导出器容器带有一个有意义的默认配置。我们将使用目标 `prometheus.io` 和预定义的模块 `http_2xx`。它告诉导出器像浏览器访问 `prometheus.io` 那样发出一个 GET 请求,并期望得到一个 200 OK 的响应。
现在,您可以在终端中使用 curl 告诉您的 blackbox 导出器查询 `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
probe_http_redirects 0
# HELP probe_http_ssl Indicates if SSL was used for the final redirect
# TYPE probe_http_ssl gauge
probe_http_ssl 0
# HELP probe_http_status_code Response HTTP status code
# TYPE probe_http_status_code gauge
probe_http_status_code 0
# HELP probe_http_version Returns the version of HTTP of the probe response
# TYPE probe_http_version gauge
probe_http_version 0
# HELP probe_ip_protocol Specifies whether probe ip protocol is IP4 or IP6
# TYPE probe_ip_protocol gauge
probe_ip_protocol 6
# HELP probe_success Displays whether or not the probe was a success
# TYPE probe_success gauge
probe_success 0
请注意,几乎所有指标的值都是 `0`。最后一个是 `probe_success 0`。这意味着探测器无法成功访问 `prometheus.io`。原因隐藏在值为 `6` 的 `probe_ip_protocol` 指标中。默认情况下,探测器会使用 IPv6,除非另有说明。但是 Docker 守护进程在默认情况下会阻止 IPv6。因此,我们运行在 Docker 容器中的 blackbox 导出器无法通过 IPv6 连接。
我们现在可以告诉 Docker 允许 IPv6,或者告诉 blackbox 导出器使用 IPv4。在现实世界中,两者都有其道理,对于“该怎么办?”这个问题,答案常常是“视情况而定”。因为这是一个关于导出器的指南,我们将修改导出器,并借此机会配置一个自定义模块。
配置模块
模块预定义在 Docker 容器内一个名为 `config.yml` 的文件中,该文件是 GitHub 仓库中 blackbox.yml 的副本。
我们将复制这个文件,根据自己的需求进行调整,并告诉导出器使用我们的配置文件,而不是容器中包含的那个。
首先使用 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` 的 `modules`,它们都有一个 `http` 探测器,其中一个的 `method` 值被明确设置为 `POST`。你现在将修改 `http_2xx` 模块,通过将 `http` 探测器的 `preferred_ip_protocol` 明确设置为字符串 `ip4`。
modules:
http_2xx:
prober: http
http:
preferred_ip_protocol: "ip4"
http_post_2xx:
prober: http
http:
method: POST
如果您想了解更多关于可用探测器和选项的信息,请查阅文档。
现在我们需要告诉 blackbox 导出器使用我们刚刚修改的文件。你可以使用 `--config.file="blackbox.yml"` 标志来做到这一点。但是因为我们正在使用 Docker,我们首先必须使用 `--mount` 命令使这个文件在容器内部可用。
注意如果您使用的是 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`:
- 使用容器外部的端口 `9115` 映射到容器内部的端口 `9115` 来 `run` 一个容器。
- 将当前目录(`$(pwd)` 表示打印工作目录)下的文件 `blackbox.yml` 以 `readonly` 模式 `mount` 到 `/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
probe_http_redirects 1
# HELP probe_http_ssl Indicates if SSL was used for the final redirect
# TYPE probe_http_ssl gauge
probe_http_ssl 1
# 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
probe_http_version 1.1
# HELP probe_ip_protocol Specifies whether probe ip protocol is IP4 or IP6
# TYPE probe_ip_protocol gauge
probe_ip_protocol 4
# 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
probe_success 1
# 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 导出器还在 localhost:9115 提供了一个小型的 Web 界面,供您查看最近几次的探测、加载的配置和调试信息。它甚至提供了一个直接探测 `prometheus.io` 的链接。如果您想知道为什么某些东西不起作用,这会很方便。
使用 Prometheus 查询多目标导出器
到目前为止,一切顺利。恭喜您。blackbox 导出器已经工作,您可以手动告诉它查询一个远程目标。您几乎成功了。现在您需要告诉 Prometheus 为我们进行查询。
下面是一个最小的 Prometheus 配置。它告诉 Prometheus 抓取导出器本身,就像我们之前使用 `curl 'localhost:9115/metrics'` 所做的那样。
注意如果您使用 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 # To get metrics about the exporter itself
metrics_path: /metrics
static_configs:
- targets:
- localhost:9115
适用于 macOS 和 Windows 的 `prometheus.yml`
global:
scrape_interval: 5s
scrape_configs:
- job_name: blackbox # To get metrics about the exporter itself
metrics_path: /metrics
static_configs:
- targets:
- host.docker.internal:9115
现在运行一个 Prometheus 容器,并告诉它挂载我们上面的配置文件。由于主机上的网络在容器中寻址的方式,您需要在 Linux 上使用与在 MacOS 和 Windows 上略有不同的命令。
在 Linux 上运行 Prometheus(不要在生产环境中使用 `--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 上运行 Prometheus
docker \
run -p 9090:9090 \
--mount type=bind,source="$(pwd)"/prometheus.yml,target=/prometheus.yml,readonly \
prom/prometheus \
--config.file="/prometheus.yml"
此命令的运作方式类似于使用配置文件运行 blackbox 导出器。
如果一切正常,您应该能够访问 localhost:9090/targets,并在 `blackbox` 下看到一个状态为绿色 `UP` 的端点。如果您得到一个红色的 `DOWN`,请确保您上面启动的 blackbox 导出器仍在运行。如果您什么也看不到或者看到一个黄色的 `UNKNOWN`,说明您太快了,需要再等几秒钟再刷新浏览器标签页。
要告诉 Prometheus 查询 `"localhost:9115/probe?target=prometheus.io&module=http_2xx"`,您需要添加另一个抓取作业 `blackbox-http`,在 Prometheus 配置文件 `prometheus.yml` 中将 `metrics_path` 设置为 `/probe`,并将参数放在 `params:` 下。
global:
scrape_interval: 5s
scrape_configs:
- job_name: blackbox # To get metrics about the exporter itself
metrics_path: /metrics
static_configs:
- targets:
- localhost:9115 # For Windows and macOS replace with - host.docker.internal:9115
- job_name: blackbox-http # To get metrics about the exporter’s targets
metrics_path: /probe
params:
module: [http_2xx]
target: [prometheus.io]
static_configs:
- targets:
- localhost:9115 # For Windows and macOS replace with - host.docker.internal:9115
保存配置文件后,切换到运行 Prometheus docker 容器的终端,按 `ctrl+C` 停止它,然后使用现有的命令再次启动它以重新加载配置。
终端应该返回消息 `"Server is ready to receive web requests."`,几秒钟后,您应该开始在您的 Prometheus中看到彩色的图表。
这行得通,但有几个缺点:
- 实际的目标位于参数配置中,这非常不寻常,以后很难理解。
- `instance` 标签的值是 blackbox 导出器的地址,这在技术上是正确的,但不是我们感兴趣的。
- 我们看不到我们探测了哪个 URL。这不实用,而且如果我们探测多个 URL,还会将不同的指标混为一谈。
要解决这个问题,我们将使用重新标记。重新标记在这里很有用,因为在幕后,Prometheus 中的许多东西都是用内部标签配置的。细节很复杂,超出了本指南的范围。因此,我们将自己限制在必要的范围内。但如果您想了解更多,可以看看这个演讲。目前,如果您理解以下内容就足够了:
- 所有以 `__` 开头的标签在抓取后都会被丢弃。大多数内部标签都以 `__` 开头。
- 您可以设置名为 `__param_<name>` 的内部标签。这些标签会为抓取请求设置一个键为
<name>的 URL 参数。 - 有一个内部标签 `__address__`,它由 `static_configs` 下的 `targets` 设置,其值是抓取请求的主机名。默认情况下,它后来被用来设置标签 `instance` 的值,该标签附加到每个指标上,告诉您指标来自何处。
这里是您将用来实现此目的的配置。如果一下子信息量有点大,别担心,我们会一步步讲解:
global:
scrape_interval: 5s
scrape_configs:
- job_name: blackbox # To get metrics about the exporter itself
metrics_path: /metrics
static_configs:
- targets:
- localhost:9115 # For Windows and macOS replace with - host.docker.internal:9115
- job_name: blackbox-http # To get metrics about the exporter’s targets
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets:
- https://prometheus.ac.cn # Target to probe with http
- https://prometheus.ac.cn # Target to probe with https
- http://example.com:8080 # Target to probe with http on port 8080
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: localhost:9115 # The blackbox exporter’s real hostname:port. For Windows and macOS replace with - host.docker.internal:9115
那么与上一个配置相比,有什么新内容呢?
`params` 不再包含 `target`。相反,我们将实际目标添加到 `static configs:` `targets` 下。我们还使用了多个目标,因为我们现在可以这样做了。
params:
module: [http_2xx]
static_configs:
- targets:
- https://prometheus.ac.cn # Target to probe with http
- https://prometheus.ac.cn # Target to probe with https
- http://example.com:8080 # Target to probe with http on port 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 # The blackbox exporter’s real hostname:port. For Windows and macOS replace with - host.docker.internal:9115
在应用重新标记规则之前,Prometheus 将发出的请求的 URI 看起来会是这样:`"https://prometheus.ac.cn/probe?module=http_2xx"`。重新标记之后,它将看起来像这样:`"https://:9115/probe?target=https://prometheus.ac.cn&module=http_2xx"`。
现在让我们来探究每条规则是如何做到这一点的。
首先,我们从标签 `__address__`(其中包含 `targets` 的值)中获取值,并将它们写入一个新的标签 `__param_target`,这会向 Prometheus 抓取请求添加一个 `target` 参数。
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
之后,我们想象中的 Prometheus 请求 URI 现在有了一个目标参数:`"https://prometheus.ac.cn/probe?target=https://prometheus.ac.cn&module=http_2xx"`。
然后我们从标签 `__param_target` 中获取值,并创建一个带有这些值的实例标签。
relabel_configs:
- source_labels: [__param_target]
target_label: instance
我们的请求不会改变,但是从我们的请求返回的指标现在将带有一个 `instance="https://prometheus.ac.cn"` 的标签。
之后,我们将值 `localhost:9115`(我们导出器的 URI)写入标签 `__address__`。这将用作 Prometheus 抓取请求的主机名和端口。这样它就会查询导出器,而不是直接查询目标 URI。
relabel_configs:
- target_label: __address__
replacement: localhost:9115 # The blackbox exporter’s real hostname:port. For Windows and macOS replace with - host.docker.internal:9115
我们的请求现在是 `"localhost:9115/probe?target=https://prometheus.ac.cn&module=http_2xx"`。通过这种方式,我们可以将实际目标放在那里,将它们作为 `instance` 标签值,同时让 Prometheus 对 blackbox 导出器发出请求。
人们经常将这些与特定的服务发现结合起来。有关更多信息,请查看配置文档。使用它们没有问题,因为这些服务发现会像在 `static_configs` 下定义的 `targets` 一样写入 `__address__` 标签。
就是这样。重新启动 Prometheus docker 容器,看看你的指标。注意,你选择的时间段是指标实际收集的时间。
摘要
在本指南中,您学习了多目标导出器模式的工作原理,如何运行带有自定义模块的 blackbox 导出器,以及如何使用重新标记配置 Prometheus 以抓取带有探测器标签的指标。