本指南将向你介绍多目标 Exporter 模式。为此我们将:
- 描述多目标 Exporter 模式及其使用原因,
- 以 blackbox exporter 作为该模式的示例运行,
- 为 blackbox exporter 配置自定义查询模块,
- 让 blackbox exporter 对 Prometheus 网站运行基本指标查询,
- 研究一种使用重新标记配置 Prometheus 抓取 exporter 的常见模式。
什么是多目标 Exporter 模式?
多目标 exporter 模式是指一种特定的设计,其中:
- exporter 通过网络协议获取目标的指标。
- exporter 不需要运行在获取指标的机器上。
- exporter 通过 Prometheus 的 GET 请求参数获取目标和查询配置字符串。
- exporter 在收到 Prometheus 的 GET 请求后开始抓取,并在抓取完成后返回结果。
- exporter 可以查询多个目标。
此模式仅用于某些 exporter,如 blackbox 和 SNMP exporter。
原因是我们要么无法在目标上运行 exporter(例如使用 SNMP 的网络设备),要么我们明确关注距离(例如从网络外部特定点测量网站的延迟和可达性),这是 blackbox exporter 的常见用例。
运行多目标 Exporter
多目标 exporter 对运行环境非常灵活,可以以多种方式运行:作为常规程序、在容器中、作为后台服务、在裸机上或虚拟机上。因为它们通过网络进行查询和被查询,所以需要适当地开放端口。除此之外,它们占用资源很少。
现在让我们亲自尝试一下!
使用 Docker 在终端中运行以下命令来启动一个 blackbox exporter 容器。根据你的系统配置,可能需要在命令前加上 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
多目标 Exporter 的基本查询
有两种查询方式:
- 查询 exporter 本身。它有自己的指标,通常可在
/metrics上获取。 - 查询 exporter 以抓取另一个目标。通常可在一个"描述性"端点上获取,例如
/probe。当使用多目标 exporter 时,这可能是你主要感兴趣的方式。
你可以在另一个终端中使用 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 格式的指标。它们来自 exporter 的插桩,告诉我们 exporter 在运行时自身的状态。这被称为白盒监控,在日常运维实践中非常有用。如果你感兴趣,可以参考我们关于如何对自己的应用程序进行插桩的指南。
对于第二种查询类型,我们需要在 HTTP GET 请求中提供 target 和 module 作为参数。target 是 URI 或 IP,module 必须在 exporter 的配置中定义。blackbox exporter 容器自带了一个有意义的默认配置。
我们将使用目标 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
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 exporter 无法通过 IPv6 连接。
我们现在可以告诉 Docker 允许 IPv6,或者告诉 blackbox exporter 使用 IPv4。在实际环境中两者都有意义,正如很多时候"该怎么做?"的答案是"视情况而定"。因为这是一个 exporter 指南,我们将修改 exporter 并借此机会配置一个自定义模块。
配置模块
模块预定义在 docker 容器内一个名为 config.yml 的文件中,它是 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 使用空白缩进来表示层级关系,所以你可以看到定义了两个 modules,分别名为 http_2xx 和 http_post_2xx,它们都有一个 http prober,其中一个的 method 值特别设置为 POST。
你现在要修改 http_2xx 模块,将 http prober 的 preferred_ip_protocol 明确设置为字符串 ip4。
modules:
http_2xx:
prober: http
http:
preferred_ip_protocol: "ip4"
http_post_2xx:
prober: http
http:
method: POST
如果你想了解更多关于可用 prober 和选项的信息,请查看文档。
现在我们需要告诉 blackbox exporter 使用我们刚刚修改的文件。你可以使用 --config.file="blackbox.yml" 标志来做到这一点。但因为我们使用的是 Docker,所以需要先使用 --mount 命令将此文件挂载到容器内。
NOTE: 如果你使用的是 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。- 从你的当前目录(
$(pwd)代表打印工作目录)mount文件blackbox.yml到容器内的/blackbox.yml,以readonly模式。 - 使用来自 Docker hub 的
prom/blackbox-exporter镜像。 - 使用
--config.file标志运行 blackbox-exporter,告诉它使用/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 exporter 还在 localhost:9115 提供了一个小型 Web 界面,供你查看最近几次探测、已加载的配置和调试信息。它甚至提供了直接探测 prometheus.io 的链接。如果你想知道为什么某些东西不工作,这非常方便。
使用 Prometheus 查询多目标 Exporter
到目前为止一切顺利。恭喜你自己。blackbox exporter 工作了,你可以手动告诉它查询远程目标。你几乎要完成了。现在你需要告诉 Prometheus 为我们执行查询。
下面是一个最小的 Prometheus 配置。它告诉 Prometheus 像我们之前使用 curl 'localhost:9115/metrics' 那样抓取 exporter 本身:
NOTE: 如果你使用 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 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 的抓取 job,将 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 中看到彩色图表。
这可以工作,但有一些缺点:
- 实际目标位于 param 配置中,这非常不寻常,之后很难理解。
instance标签的值是 blackbox exporter 的地址,从技术上讲这是正确的,但不是我们感兴趣的。- 我们看不到探测了哪个 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:
- http://prometheus.io # Target to probe with http
- https://prometheus.io # 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:
- http://prometheus.io # Target to probe with http
- https://prometheus.io # 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 看起来像这样:"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 抓取请求的主机名和端口,使其查询 exporter 而不是直接查询目标 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=http://prometheus.io&module=http_2xx"。这样我们可以将实际目标放在那里,将它们作为 instance 标签值获取,同时让 Prometheus 向 blackbox exporter 发起请求。
人们通常将这些与特定的服务发现结合使用。查看配置文档了解更多信息。使用它们没有问题,因为它们像 static_configs 下定义的 targets 一样写入 __address__ 标签。
就是这样。重启 Prometheus Docker 容器并查看你的指标。注意选择实际收集指标的时间段。
示例配置:在一个 Prometheus job 中使用多个目标和多个模块
在上面的示例中,我们只使用了一个 blackbox exporter 探测模块。module 被指定为 blackbox-http job 的 job 级别参数。由于它是一个列表,可以包含多个元素,但 blackbox exporter 只使用第一个。
然而,如果我们需要用适当的模块分别探测不同组的目标,我们可以在单个 job 中使用多个 blackbox exporter 模块。
不需要在 job 的 module 参数中指定,我们可以在每个 static_config 中指定一个 module 标签。
此外,relabel_configs 序列需要用一个新条目扩展,因为我们此时需要在请求中注入 module(作为 __param_module)。
global:
scrape_interval: 5s
scrape_configs:
- job_name: blackbox # To get metrics about the exporter itself
metrics_path: /metrics
static_configs:
- targets:
- localhost:9115 # The blackbox exporter's real hostname:port
- job_name: blackbox-probes # To get metrics about the exporter's targets with different modules
metrics_path: /probe
static_configs:
- targets: # static_config: targets and http_2xx module
- http://prometheus.io
- https://prometheus.io
- http://example.com:8080
labels:
module: http_2xx
- targets: # static_config: targets and icmp module
- prometheus.io
- example.com
labels:
module: icmp
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- source_labels: [module]
target_label: __param_module
- target_label: __address__
replacement: localhost:9115 # The blackbox exporter's real hostname:port
总结
在本指南中,你学习了多目标 Exporter 模式的工作原理、如何使用自定义模块运行 blackbox exporter,以及如何使用重新标记配置 Prometheus 来抓取带有探针标签的指标。