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

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

  • 描述多目标导出器模式及其用途,
  • blackbox  导出器为例演示该模式,
  • 为 blackbox 导出器配置自定义查询模块,
  • 让 blackbox 导出器针对 Prometheus 网站运行基本指标查询,
  • 研究一种使用重写(relabeling)将 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

多目标导出器的基本查询

有两种查询方式:

  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。它告诉导出器像浏览器访问 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。原因隐藏在指标 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 探测器,其中一个方法的 value 被明确设置为 POST。现在您将通过将 http 探测器的 preferred_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 文件以 readonly 模式挂载到容器内的 /blackbox.yml
  3. 使用来自 Docker hub prom/blackbox-exporter 镜像。
  4. 运行 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 的虚拟机有关。您不应该在生产环境中使用它。

prometheus.yml (Linux)

global:
  scrape_interval: 5s

scrape_configs:
- job_name: blackbox # To get metrics about the exporter itself
  metrics_path: /metrics
  static_configs:
    - targets:
      - localhost:9115

prometheus.yml (macOS 和 Windows)

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

这可行,但有几个缺点:

  1. 实际目标在 param 配置中,这非常不寻常且难以理解。
  2. instance 标签的值是 blackbox 导出器的地址,虽然技术上正确,但不是我们感兴趣的。
  3. 我们看不到我们探测了哪个 URL。这不实用,如果我们探测多个 URL,还会将不同的指标混淆。

为了解决这个问题,我们将使用 重写(relabeling)。重写在这里很有用,因为在幕后,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 现在有一个 target 参数:"https://prometheus.ac.cn/probe?target=https://prometheus.ac.cn&module=http_2xx"

然后,我们从 __param_target 标签中提取值,并使用这些值创建 instance 标签。

  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 来抓取带有探测器标签的指标。

本页内容