blackbox-exporter 黑盒监控

什么是白盒与黑盒监控?

在监控系统中会经常提到白盒监控与黑盒监控两个关键词,对这俩关键词进行一下简单解释:

  • 黑盒监控:黑盒监控指的是以用户的身份测试服务的运行状态。常见的黑盒监控手段包括 HTTP探针、TCP探针、DNS探测、ICMP等。黑盒监控常用于检测站点与服务可用性、连通性,以及访问效率等。

  • 白盒监控:白盒监控一般指的是日常对服务器状态的监控,如服务器资源使用量、容器的运行状态、中间件的稳定情况等一系列比较直观的监控数据,这些都是支撑业务应用稳定运行的基础设施。通过白盒能监控,可以使我们能够了解系统内部的实际运行状况,而且还可以通过对监控指标数据的观察与分析,可以让我们提前预判服务器可能出现的问题,针对可能出现的问题进行及时修正,避免造成不可预估的损失。

白盒与黑盒监控的区别:

黑盒监控相较于白盒监控最大的不同在于黑盒监控是以故障为导向当故障发生时,黑盒监控能快速发现故障,而白盒监控则侧重于主动发现或者预测潜在的问题。

一个完善的监控目标是要能够从白盒的角度发现潜在问题,能够在黑盒的角度快速发现已经发生的问题。

blackbox_exporter 是 Prometheus 社区提供的官方黑盒监控解决方案,其允许用户通过:HTTP、 HTTPS、 DNS、 TCP 以及 ICMP 的方式对网络进行探测。

K8S 部署 blackbox_exporter

configmap.yaml

首先需要在 Kubernetes 集群中运行 blackbox-exporter 服务,同样通过一个 ConfigMap 资源对象来为其提供配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
apiVersion: v1
kind: ConfigMap
metadata:
name: blackbox-exporter
namespace: kube-mon
labels:
app: blackbox-exporter
data:
blackbox.yml: |-
modules:
http_2xx: # http 检测模块 Blockbox-Exporter 中所有的探针均是以 Module 的信息进行配置
prober: http
timeout: 10s
http:
valid_http_versions: ["HTTP/1.1", "HTTP/2"]
valid_status_codes: [200] # 这里最好作一个返回状态码,在grafana作图时,有明示
method: GET
preferred_ip_protocol: "ip4"
http_post_2xx: # http post 监测模块
prober: http
timeout: 10s
http:
valid_http_versions: ["HTTP/1.1", "HTTP/2"]
method: POST
preferred_ip_protocol: "ip4"
tcp_connect: # TCP 检测模块
prober: tcp
timeout: 10s
dns: # DNS 检测模块
prober: dns
dns:
transport_protocol: "tcp" # 默认是 udp
preferred_ip_protocol: "ip4" # 默认是 ip6
query_name: "kubernetes.default.svc.cluster.local"

blackbox.yml 配置文件说明参考 Blackbox exporter configuration

deploy.yaml

docker 镜像版本参考 DockerHub for blackbox-exporter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
apiVersion: apps/v1
kind: Deployment
metadata:
name: blackbox-exporter
namespace: kube-mon
labels:
k8s-app: blackbox-exporter
spec:
replicas: 1
selector:
matchLabels:
k8s-app: blackbox-exporter
template:
metadata:
labels:
k8s-app: blackbox-exporter
spec:
containers:
- name: blackbox-exporter
image: prom/blackbox-exporter:v0.24.0
imagePullPolicy: IfNotPresent
args:
- --config.file=/etc/blackbox_exporter/blackbox.yml
- --web.listen-address=:9115
- --log.level=error
ports:
- name: http
containerPort: 9115
resources:
limits:
cpu: 200m
memory: 256Mi
requests:
cpu: 100m
memory: 50Mi
livenessProbe:
tcpSocket:
port: 9115
initialDelaySeconds: 5
timeoutSeconds: 5
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
readinessProbe:
tcpSocket:
port: 9115
initialDelaySeconds: 5
timeoutSeconds: 5
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
volumeMounts:
- name: config
mountPath: /etc/blackbox_exporter
volumes:
- name: config
configMap:
name: blackbox-exporter
defaultMode: 420

---
apiVersion: v1
kind: Service
metadata:
name: blackbox-exporter
namespace: kube-mon
labels:
k8s-app: blackbox-exporter
spec:
type: ClusterIP
ports:
- name: http
port: 9115
targetPort: 9115
selector:
k8s-app: blackbox-exporter

创建上面的资源清单后,查看资源部署状态:

1
2
3
4
5
6
$ kubectl -n kube-mon get all |grep  blackbox-exporter
pod/blackbox-exporter-6c58cf8f7f-dwtg6 1/1 Running 0 79s
service/blackbox-exporter ClusterIP 172.16.8.211 <none> 9115/TCP 6h16m
deployment.apps/blackbox-exporter 1/1 1 1 6h16m
replicaset.apps/blackbox-exporter-67b5888b85 0 0 0 6h17m
replicaset.apps/blackbox-exporter-6c58cf8f7f 1 1 1 80s

手动获取 blackbox-exporter 白盒/黑盒的监控指标

查看 blackbox-exporter 自身的 /metrics

1
2
3
4
5
6
7
8
9
10
11
12
$ curl 172.16.8.211:9115/metrics

# HELP blackbox_exporter_build_info A metric with a constant '1' value labeled by version, revision, branch, goversion from which blackbox_exporter was built, and the goos and goarch for the build.
# TYPE blackbox_exporter_build_info gauge
blackbox_exporter_build_info{branch="HEAD",goarch="amd64",goos="linux",goversion="go1.20.4",revision="0b0467473916fd9e8526e2635c2a0b1c56011dff",tags="netgo",version="0.24.0"} 1
# HELP blackbox_exporter_config_last_reload_success_timestamp_seconds Timestamp of the last successful configuration reload.
# TYPE blackbox_exporter_config_last_reload_success_timestamp_seconds gauge
blackbox_exporter_config_last_reload_success_timestamp_seconds 1.6999258154980638e+09
# HELP blackbox_exporter_config_last_reload_successful Blackbox exporter config loaded successfully.
# TYPE blackbox_exporter_config_last_reload_successful gauge
blackbox_exporter_config_last_reload_successful 1
.....

以上都是标准的 prmetheus 标准的 metrics 度量值,是 blackbox-exporter 自身运行状态,称之为白盒监控。

对于黑盒监控的查询,我们需要在HTTP GET请求中提供目标和模块作为参数。目标是一个 URI 或 IP,模块必须在导出器的配置中定义。黑盒导出器容器附带了一个有意义的默认配置。我们将使用目标普罗米修斯。IO和预定义模块 http_get_2xx。它告诉导出器发出一个GET请求,就像浏览器访问普罗米修斯时所做的那样。并期望得到200ok响应。

使用 curl 来获取 prometheus 官网站点的监控状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ curl '172.16.8.211: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.014221177
# HELP probe_duration_seconds Returns how long the probe took to complete in seconds
# TYPE probe_duration_seconds gauge
probe_duration_seconds 0.894175288
# 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
....

Prometheus 抓取 blackbox-exporter 监控指标

Prometheus 配置参考:

blackbox-exporter DNS 监控(可选)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
################################## Kubernetes BlackBox DNS ###################################
- job_name: "dns"
metrics_path: /probe # 不是 metrics,是 probe
params:
module: [dns] # 使用 DNS 模块
static_configs:
- targets:
- kube-dns.kube-system:53 # 不要省略端口号
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox:9115 # 服务地址,和上面的 Service 定义保持一致

blackbox-exporter Service 监控(可选)

除了 DNS 的配置外,上面我们还配置了一个 http_2xx 的模块,也就是 HTTP 探针,HTTP 探针是进行黑盒监控时最常用的探针之一,通过 HTTP 探针能够对网站或者 HTTP 服务建立有效的监控,包括其本身的可用性,以及用户体验相关的如响应时间等等。除了能够在服务出现异常的时候及时报警,还能帮助系统管理员分析和优化网站体验。这里我们可以使用他来对 http 服务进行检测。

因为前面已经给 blackbox-exporter 配置了 http_2xx 模块,所以这里只需要在 Prometheus 中加入抓取任务,这里我们可以结合前面的 Prometheus 的服务发现功能来做黑盒监控,对于 ServiceIngress 类型的服务发现,用来进行黑盒监控是非常合适的,配置如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
################################## Kubernetes BlackBox Services ###################################
- job_name: "services"
metrics_path: /probe
params:
module:
- "http_2xx"
## 使用Kubernetes动态服务发现,且使用Service类型的发现
kubernetes_sd_configs:
- role: service
relabel_configs:
## 设置只监测Kubernetes Service中Annotation里配置了注解prometheus.io/http_probe: true的service
- action: keep
source_labels: [__meta_kubernetes_service_annotation_prometheus_io_http_probe]
regex: "true"
- action: replace
source_labels:
- "__meta_kubernetes_service_name"
- "__meta_kubernetes_namespace"
- "__meta_kubernetes_service_annotation_prometheus_io_http_probe_port"
- "__meta_kubernetes_service_annotation_prometheus_io_http_probe_path"
target_label: __param_target
regex: (.+);(.+);(.+);(.+)
replacement: $1.$2:$3$4
## BlackBox Exporter 的 Service 地址
- target_label: __address__
replacement: blackbox-exporter:9115
- source_labels: [__param_target]
target_label: instance
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_service_name]
target_label: kubernetes_name

blackbox-exporter ingress 监控(推荐)

blackbox-exporter + ingress 服务发现是非常推荐的,因为我们的业务接口,基本上都是以 ingress 的形式部署在 K8S 集群内,通过对指定 ingress 添加注释,就可以自动加入对域名及业务接口的监控:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
################################## Kubernetes BlackBox Ingresses ###################################
- job_name: 'ingresses'
metrics_path: /probe
params:
module: [http_2xx] # 使用定义的http模块
kubernetes_sd_configs:
- role: ingress # ingress 类型的服务发现
relabel_configs:
# 只有ingress的annotation中配置了 prometheus.io/http_probe=true的才进行发现
- source_labels: [__meta_kubernetes_ingress_annotation_prometheus_io_http_probe]
action: keep
regex: true
- source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_path]
regex: (.+);(.+);(.+)
replacement: ${1}://${2}${3}
target_label: __param_target
- target_label: __address__
replacement: blackbox-exporter:9115
- source_labels: [__param_target]
target_label: instance
- action: labelmap
regex: __meta_kubernetes_ingress_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_ingress_name]
target_label: kubernetes_name

我们结合前面的服务发现功能,通过过滤 prometheus.io/http-probe: 'true' 的 Service 和 Ingress 才进行 HTTP 探针类型的黑盒监控。查看抓取任务 target:

如果对监控的路径、端口这些做定制化,可以自己在 relabel_configs 中去做相应的配置,比如自定义 URI:

1
2
3
4
- source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_annotation_prometheus_io_http_probe_path]
regex: (.+);(.+);(.+)
replacement: ${1}://${2}${3}
target_label: __param_target

这样再在 ingress 资源对象配置注解,定制 URI 或端口号:

1
2
3
4
5
# service or ingress
annotations:
prometheus.io/http-probe: "true" ### 设置该服务执行HTTP探测
prometheus.io/http-probe-port: "80" ### 设置HTTP探测的接口
prometheus.io/http-probe-path: "/monior" ### 设置HTTP探测的地址

blackbox-exporter SSL 监控(可选)

这是一种静态添加的方式,可以用于监控 K8S 集群以外的资源,来弥补自动发现监控的不足。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
scrape_configs:
- job_name: 'ssl'
metrics_path: /probe
params:
module:
- "http_2xx"
static_configs:
- targets:
- https://api-test.aibiw.com
- https://api-test.bbqnr.cn
- https://api-test.uxsy.com
- https://api-test.haileyou.com
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-exporter:9115 # 与 prometheus 在相同名称空间下,这里直接写 blackbox-exporter 的 Service Name

查看抓取 target:

最后热加载 prometheus 配置:

1
curl -XPOST http://10.19.xxx.xxx:29090/-/reload

注意上述 blackbox-exporter 和 prometheus 部署在相同的 kube-mon 名称空间下根据,直接写 blackbox-exporter:9115 即可,反正要根据实际的名称空间来更改,比如:blackbox-exporter.kube-mon:9115

现在我们可以使用 probe_duration_seconds 来检查监控结果:

Grafana 数据可视化

Dashboard ID(HTTP 状态监控):13659

Dashboard ID(SSL TCP HTTP 监控):9965(推荐)

Dashboard ID(SSL 证书监控):13230

告警规则

Prometheus 告警规则参考 awesome-prometheus-alerts#blackbox

异常处理

异常1:Failed to watch *v1.Ingress: failed to list *v1.Ingress: ingresses.networking.k8s.io is forbidden: User "system:serviceaccount:kube-mon:prometheus" cannot list resource "ingresses" in API group "networking.k8s.io" at the cluster scope”

异常背景:在添加了 ingress 黑盒监控后,prometheus 控制台无法获取 target,去查看 Pod 日志发现如下报错:

1
ts=2023-11-14T07:43:49.313Z caller=klog.go:116 level=error component=k8s_client_runtime func=ErrorDepth msg="pkg/mod/k8s.io/client-go@v0.22.2/tools/cache/reflector.go:167: Failed to watch *v1.Ingress: failed to list *v1.Ingress: ingresses.networking.k8s.io is forbidden: User \"system:serviceaccount:kube-mon:prometheus\" cannot list resource \"ingresses\" in API group \"networking.k8s.io\" at the cluster scope"

原因分析:prometheus RBAC 用户权限不足,缺少 apiGroupsnetworking.k8s.iolist 权限。

解决措施:按照以下配置对 ClusterRole 区块授权:

1
2
3
4
5
6
7
8
9
- apiGroups:
- "extensions"
- "networking.k8s.io"
resources:
- ingresses
verbs:
- get
- list
- watch

参考文档