理解和使用多目标导出器模式

本指南将向您介绍多目标导出器模式。为了实现这一点,我们将

  • 描述多目标导出器模式以及为何使用它,
  • 运行 blackbox 导出器作为该模式的示例,
  • 为 blackbox 导出器配置自定义查询模块,
  • 让 blackbox 导出器对 Prometheus 网站 运行基本指标查询,
  • 检查配置 Prometheus 以使用重新标记抓取导出器的流行模式。

多目标导出器模式是什么?

通过多目标 导出器 模式,我们指的是一种特定的设计,其中

  • 导出器将通过网络协议获取目标的指标。
  • 导出器不必在获取指标的机器上运行。
  • 导出器将目标和一个查询配置字符串作为 Prometheus 的 GET 请求的参数获取。
  • 导出器随后在获取 Prometheus 的 GET 请求后开始抓取,并在完成抓取后结束。
  • 导出器可以查询多个目标。

此模式仅用于某些导出器,例如 blackboxSNMP 导出器

原因是我们要么无法在目标上运行导出器(例如,使用 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

多目标导出器的基本查询

有两种查询方式

  1. 查询导出器本身。 它有自己的指标,通常在 /metrics 处可用。
  2. 查询导出器以抓取另一个目标。 通常在“描述性”端点处可用,例如 /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。 它告诉导出器发出像浏览器一样的 GET 请求,如果您访问 prometheus.io,并期望得到 200 OK 响应。

您现在可以告诉您的 blackbox 导出器在终端中使用 curl 查询 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。 原因隐藏在指标 probe_ip_protocol 中,值为 6。 默认情况下,探测器使用 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_2xxhttp_post_2xxmodules,并且它们都具有探测器 http,其中一个的方法值专门设置为 POST
您现在将通过将探测器 httppreferred_ip_protocol 显式设置为字符串 ip4 来更改模块 http_2xx

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

  1. run 一个容器,其中容器外部的端口 9115 映射到容器内部的端口 9115
  2. mount 从您的当前目录($(pwd) 代表打印工作目录)将文件 blackbox.yml 装载到 /blackbox.yml 中,处于 readonly 模式。
  3. 使用来自 Docker hub 的镜像 prom/blackbox-exporter
  4. 运行带有标志 --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 导出器还在 localhost:9115 上提供了一个小型 Web 界面,供您查看最近的几次探测、加载的配置和调试信息。 它甚至提供了直接链接来探测 prometheus.io。 如果您想知道为什么某些东西不起作用,这将非常方便。

使用 Prometheus 查询多目标导出器

到目前为止,一切顺利。 恭喜自己。 blackbox 导出器工作正常,您可以手动告诉它查询远程目标。 您几乎完成了。 现在您需要告诉 Prometheus 为我们执行查询。

下面您将找到一个最小的 prometheus 配置。 它告诉 Prometheus 抓取导出器本身,就像我们 之前 使用 curl 'localhost:9115/metrics' 所做的那样

注意: 如果您为 Mac 或 Windows 使用 Docker,则不能在最后一行使用 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 中的 params: 下将 metrics_path 设置为 /probe 并设置参数。

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 中看到彩色图表。

这可行,但有一些缺点

  1. 实际目标位于 param 配置中,这非常不寻常,并且以后很难理解。
  2. instance 标签的值是 blackbox 导出器的地址,这在技术上是正确的,但不是我们感兴趣的。
  3. 我们看不到我们探测的 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"。 重新标记后,它将如下所示 "http://localhost: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 以使用重新标记抓取带有探测器标签的指标。

本文档是 开源的。 请通过提交问题或拉取请求来帮助改进它。