Prometheus存储实战 && HTTPS认证 && 黑盒监控

10163 字
51 分钟
Prometheus存储实战 && HTTPS认证 && 黑盒监控
Prometheus存储实战 && HTTPS认证 && 黑盒监控

Prometheus存储实战 && HTTPS认证 && 黑盒监控#

[TOC]


环境规划#

前三篇打通了 Linux 主机 + 中间件 + 中间件 exporter + 自定义监控 + 服务发现 + 联邦模式 本篇收尾六个方向:

  • VictoriaMetrics:单机部署 + Prometheus remote_write 远端存储
  • HTTPS & 认证:自建 CA + Basic Auth
  • 黑白名单:客户端(node-exporter)+ 服务端(Prometheus)
  • 标签管理:relabel_configs / metric_relabel_configs
  • blackbox-exporter:HTTP / ICMP / TCP 黑盒探测
  • Grafana MySQL 存储:SQLite → MySQL 后端切换

Docker (10.0.0.9)

Exporter 层

Prom (10.0.0.10)

pull

pull

pull

remote_write

MySQL存储

Prometheus

:9090 HTTPS

Grafana

:3000

node1 (10.0.0.2)

node-exporter :9100

node2 (10.0.0.11)

node-exporter :9100

node3 (10.0.0.12)

node-exporter :9100

VictoriaMetrics :8428

blackbox-exporter :9115

MySQL 8.0.36

:3306

Docker (10.0.0.9)

Exporter 层

Prom (10.0.0.10)

pull

pull

pull

remote_write

MySQL存储

Prometheus

:9090 HTTPS

Grafana

:3000

node1 (10.0.0.2)

node-exporter :9100

node2 (10.0.0.11)

node-exporter :9100

node3 (10.0.0.12)

node-exporter :9100

VictoriaMetrics :8428

blackbox-exporter :9115

MySQL 8.0.36

:3306

虚拟机IP系统本篇角色
Prom10.0.0.10UbuntuPrometheus server(HTTPS+认证)+ Grafana(MySQL后端)
node110.0.0.2Rockynode-exporter(黑白名单实验)
node210.0.0.11Rockynode-exporter(黑白名单/探测实验)
node310.0.0.12Rockynode-exporter + VictoriaMetrics + blackbox-exporter
Docker10.0.0.9UbuntuMySQL 8.0.36 容器(Grafana存储后端)

VictoriaMetrics单机部署#

VirctoriaMetrics单节点架构图解
VirctoriaMetrics单节点架构图解

为什么要用远端存储?

Prometheus 本地 TSDB 在数据量大时面临磁盘瓶颈和单点风险 VictoriaMetrics 是一个高性能时序数据库,支持 Prometheus remote_write 协议,可以把数据”投递”到远端存储

Tip

📌 VictoriaMetrics 的优势

  • 比 Prometheus 本地存储压缩率更高,节省磁盘
  • 支持 PromQL 兼容查询,Grafana 可直接当数据源
  • 单机版免费开源(Apache 2.0),社区活跃

单节点部署
单节点部署

单点部署参考链接:https://docs.victoriametrics.com/victoriametrics/quick-start/#starting-vm-single-from-a-binary

部署VictoriaMetrics#

VictoriaMetrics 部署在 node3(10.0.0.12)

Terminal window
1)下载软件包
'官方社区版,Apache 2.0 许可'
jiuzhao@Ubuntu 下载$ wget -P /home/jiuzhao/下载 https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.150.0/victoria-metrics-linux-amd64-v1.150.0.tar.gz
jiuzhao@Ubuntu 下载$ scp /home/jiuzhao/下载/victoria-metrics-linux-amd64-v1.150.0.tar.gz node3:/tmp
# 拷贝到 /tmp 目录
2)解压二进制到 /usr/local/bin/
[root@node3 ~]# tar tf /tmp/victoria-metrics-linux-amd64-v1.150.0.tar.gz
victoria-metrics-prod
[root@node3 ~]# tar xf /tmp/victoria-metrics-linux-amd64-v1.150.0.tar.gz -C /usr/local/bin/
[root@node3 ~]# ls /usr/local/bin/victoria-metrics-prod
/usr/local/bin/victoria-metrics-prod
# 直接解压出单个二进制,不需要额外依赖
3)创建数据目录
[root@node3 ~]# mkdir -p /var/lib/victoria-metrics
4)创建 systemd 服务文件
[root@node3 ~]# cat > /etc/systemd/system/victoria-metrics.service <<'EOF'
[Unit]
Description=VictoriaMetrics Server
Documentation=https://docs.victoriametrics.com/
# 等待网络就绪后再启动
After=network-online.target
# 主动声明依赖网络在线目标
Wants=network-online.target
[Service]
# 前台常驻进程:拉起即算成功
Type=simple
# 异常退出时自动重启
Restart=on-failure
# 重启间隔 3 秒
RestartSec=3
# 文件描述符上限
LimitNOFILE=65536
ExecStart=/usr/local/bin/victoria-metrics-prod \
-httpListenAddr=0.0.0.0:8428 \
-storageDataPath=/var/lib/victoria-metrics \
-retentionPeriod=3
# -httpListenAddr: 监听地址和端口
# -storageDataPath: 数据存储路径
# -retentionPeriod=3: 数据保留3个月
[Install]
WantedBy=multi-user.target
EOF
5)启动并设置开机自启
[root@node3 ~]# systemctl daemon-reload
[root@node3 ~]# systemctl enable --now victoria-metrics.service
[root@node3 ~]# systemctl status victoria-metrics.service
● victoria-metrics.service - VictoriaMetrics Server
Loaded: loaded (/etc/systemd/system/victoria-metrics.service; enabled; ...)
Active: active (running) since ...
Main PID: 12345 (victoria-metrics)
✅️ 状态 active (running),启动成功
6)验证端口
[root@node3 ~]# ss -ntl | grep 8428
LISTEN 0 4096 0.0.0.0:8428 0.0.0.0:*
# 8428 端口正常监听 ✅️
7)验证 WebUI
http://10.0.0.12:8428/
# VictoriaMetrics 自带简洁的 Web 界面

VictoriaMetrics 单机部署完成
VictoriaMetrics 单机部署完成

配置Prometheus remote_write#

在 Prom(10.0.0.10)上修改 Prometheus 配置,开启 remote_write 投递数据到 VictoriaMetrics

Terminal window
1)修改 prometheus.yml,添加 remote_write
root@Prom ~# vim /etc/prometheus/prometheus.yml
...
# 在顶级字段中添加 remote_write(与 scrape_configs 同级)
remote_write:
- url: http://10.0.0.12:8428/api/v1/write
# remote_write 使用 VM 的 write 接口
root@Prom ~# egrep -v '^[[:space:]]*$|^[[:space:]]*#' /etc/prometheus/prometheus.yml
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
alerting:
alertmanagers:
- static_configs:
- targets:
rule_files:
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
labels:
app: "prometheus"
- job_name: "kpyun-node-exporter" # job 名称自定义
metrics_path: "/metrics" # 被监控路径
scheme: "http" # 协议
static_configs:
- targets: ["10.0.0.2:9100","10.0.0.11:9100","10.0.0.12:9100"] # 后端地址
remote_write:
- url: http://10.0.0.12:8428/api/v1/write
2)检查配置文件语法
root@Prom ~# promtool check config /etc/prometheus/prometheus.yml
Checking /etc/prometheus/prometheus.yml
SUCCESS: /etc/prometheus/prometheus.yml is valid prometheus config file syntax
3)重启 Prometheus
root@Prom ~# systemctl restart prometheus
# remote_write 是顶级字段,需要重启才能生效
4)验证 Prometheus 日志,确认 remote_write 已连接
root@Prom ~# tail -f /var/log/prometheus/prometheus.log
"msg":"Done replaying WAL","component":"remote","url":"http://10.0.0.12:8428/api/v1/write"
✅ remote_watcher 已完成 WAL 重放(启动完成)
✅ 目标地址:http://10.0.0.12:8428/api/v1/write(VictoriaMetrics)

必须

可选

Prometheus

本地 TSDB

保留60天

VictoriaMetrics

保留3个月

必须

可选

Prometheus

本地 TSDB

保留60天

VictoriaMetrics

保留3个月

Important

📌 数据存储架构:本地 + 远端双写

依据我们当前的配置,Prometheus 数据同时存储在两个位置:

存储位置配置来源用途优势
本地 TSDB--storage.tsdb.path=/var/lib/prometheus快速查询最近数据延迟低,Prometheus 原生格式
VictoriaMetricsremote_write: url: http://10.0.0.12:8428/api/v1/write长期存储 + 备份压缩率高,节省磁盘,支持 PromQL
  • 本地存储是必须的:Prometheus 核心功能依赖本地 TSDB,无法禁用

  • remote_write 是额外的:在本地存储基础上,额外把数据副本发送到远端

  • 本地 + VictoriaMetrics 是最完整的方案:本地保证实时告警和近期低延迟查询,远端负责海量历史数据的高性能分析+备份,保证数据持久化

  • 本地 TSDB在处理海量历史数据扫描时,性能很差且内存占用极高,容易 OOM

  • VictoriaMetrics 拥有更好的压缩算法和面向扫描的索引结构,在长周期、大数据量查询上,VM 的性能和资源消耗远优于原生 Prometheus

验证数据写入#

在 VictoriaMetrics 的 WebUI 中查询数据,确认所有 target 都在写入

8428/vmui
1)在 VictoriaMetrics WebUI 查询
2)测试查询语句
# 查询负载(三个node-exporter)
node_load15
# 查询 target 状态
up
`验证要点`:应该看到 '4 个 target' (Prometheus 自身 + 3 台 node-exporter)都在

target状态
target状态

15分钟负载
15分钟负载


在 Grafana 中添加 VictoriaMetrics 作为数据源,并导入 Node Exporter Full 模板

Terminal window
1)添加 VictoriaMetrics 数据源
# Grafana WebUI → 连接 → 数据源 → 添加数据源
# 选择 Prometheus 类型
# URL 填写: http://10.0.0.12:8428
# Name 自定义: kpyun-victoria-metrics
# 点击 Save & Test
✅️ 绿色 'Successfully queried the Prometheus API.' 表示连接成功
2)导入 Grafana 模板
# Grafana WebUI → Dashboards → Import
# 输入模板 ID: 1860 (Node Exporter Full)
# 选择刚创建的 kpyun-victoria-metrics 数据源
# 点击 Import
✅️ 模板加载成功,可以看到所有节点的详细监控面板

集群架构远端存储#

VirctoriaMetrics集群架构图解
VirctoriaMetrics集群架构图解

Terminal window
1)VirctoriaMetrics集群架构概述
集群部署参考链接:
https://docs.victoriametrics.com/victoriametrics/quick-start/#starting-vm-cluster-from-binaries
https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/#architecture-overview
2)下载软件包
jiuzhao@Ubuntu ~$ wget -P /home/jiuzhao/下载
https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.150.0/victoria-metrics-linux-amd64-v1.150.0-cluster.tar.gz
jiuzhao@Ubuntu ~$ tar tf ~/下载/victoria-metrics-linux-amd64-v1.150.0-cluster.tar.gz
vminsert-prod
vmstorage-prod
vmselect-prod
`软件包会提供3个程序,该程序对应了集群的3个组件`

VictoriaMetrics 集群三大组件总结

组件 (程序)角色定位核心职责关键技术细节默认监听端口 (参考)
vminsert数据写入网关 (无状态)接受数据摄入,根据指标名+标签的一致性哈希,将数据分发到不同的 vmstorage 节点无状态,可水平扩展。支持数据副本机制(-replicationFactor),如果副本数>1,会同时写入多个存储节点8480
vmstorage数据存储节点 (有状态)存储原始时序数据,响应查询时返回指定时间段的数据有状态,需要挂载持久化磁盘。负责数据去重、压缩和保留策略(Retention)8482 (接收写入) 8401 (接收查询)
vmselect数据查询网关 (无状态)接收查询请求,向所有 vmstorage 节点拉取数据,合并、去重后排重后返回结果无状态,可水平扩展。查询性能取决于 vmstorage 的数量,并发拉取时加速明显8481

Prometheus启用HTTPS及认证#

为什么需要HTTPS ?

Prometheus 默认 HTTP 明文传输,生产环境中暴露指标数据存在安全风险

启用 HTTPS + Basic Auth 后,访问 Prometheus WebUI 和 API 都需要证书认证 + 用户名密码

生成 Root CA#

Warning

生产环境使用权威机构颁发的证书,这里用自签名证书做实验

本实验统一使用 4096 位 RSA 私钥,Root CA、Intermediate CA 和 Prometheus Server Certificate 保持相同的密钥强度 生产环境可根据性能、兼容性和证书机构策略选择 2048、3072 或 4096 位

Terminal window
1)创建证书工作区
root@Prom ~# mkdir -p /etc/prometheus/certs
root@Prom ~# cd /etc/prometheus/certs
root@Prom certs# mkdir private certs
# private: 存放 Root CA、Intermediate CA 和服务器私钥
# certs: 存放各种证书和证书链
root@Prom certs# chmod 700 private
# 私钥目录只允许 root 访问
2)生成 Root CA 私钥
root@Prom certs# openssl genrsa -out private/rootCA.key 4096
# 4096 位 RSA 根私钥
3)生成 Root CA 自签名证书
root@Prom certs# openssl req -x509 -new -nodes \
-key private/rootCA.key \
-sha256 \
-days 3650 \
-out certs/rootCA.crt \
-subj "/C=CN/ST=Beijing/L=Beijing/O=kpyun/CN=kpyun-RootCA"
# rootCA.crt 是后续导入客户端信任库的根证书
✅️ Root CA 生成完成

生成 Intermediate CA#

Tip

📌 为什么需要中间证书?

生产环境中 Root CA 通常离线保存(物理锁在保险柜里),不直接签发服务器证书 用 Intermediate CA 代替 Root CA 签发,即使泄露也只影响 Intermediate,吊销即可

Terminal window
1)生成 Intermediate CA 私钥
root@Prom certs# openssl genrsa -out private/intermediate.key 4096
# 4096 位 RSA Intermediate CA 私钥
2)生成 Intermediate CA 的 CSR
root@Prom certs# openssl req -new \
-key private/intermediate.key \
-out intermediate.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=kpyun/CN=kpyun-IntermediateCA"
3)Root CA 签发 Intermediate CA
root@Prom certs# openssl x509 -req \
-in intermediate.csr \
-CA certs/rootCA.crt \
-CAkey private/rootCA.key \
-CAcreateserial \
-out certs/intermediate.crt \
-days 1825 \
-sha256 \
-extfile <(printf "basicConstraints=critical,CA:TRUE,pathlen:0\nkeyUsage=critical,keyCertSign,cRLSign")
# pathlen:0 表示不允许继续签发下一级 Intermediate CA
4)验证 Intermediate CA
root@Prom certs# openssl x509 -in certs/intermediate.crt -noout -subject -issuer
subject=C=CN, ST=Beijing, L=Beijing, O=kpyun, CN=kpyun-IntermediateCA
issuer=C=CN, ST=Beijing, L=Beijing, O=kpyun, CN=kpyun-RootCA
✅️ Intermediate CA 已由 Root CA 签发

生成 Server Certificate#

Terminal window
1)生成 Prometheus 服务器私钥
root@Prom certs# openssl genrsa -out private/prometheus.kpyun.com.key 4096
# 4096 位 RSA 服务器私钥
2)生成 Prometheus 服务器 CSR
root@Prom certs# openssl req -new \
-key private/prometheus.kpyun.com.key \
-out prometheus.kpyun.com.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=kpyun/OU=Prometheus/CN=prometheus.kpyun.com"
# 先生成服务器私钥和 CSR,再准备证书扩展信息
3)创建服务器证书扩展文件
root@Prom certs# cat > prometheus-server.ext <<'EOF'
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage=critical,digitalSignature,keyEncipherment
extendedKeyUsage=serverAuth
subjectAltName=@alt_names
[alt_names]
DNS.1=kpyun.com
DNS.2=prometheus.kpyun.com
DNS.3=localhost
IP.1=10.0.0.10
IP.2=127.0.0.1
EOF
# SAN 中写入所有实际访问 Prometheus 的域名和 IP
4)Intermediate CA 签发 Prometheus 服务器证书
root@Prom certs# openssl x509 -req \
-in prometheus.kpyun.com.csr \
-CA certs/intermediate.crt \
-CAkey private/intermediate.key \
-CAcreateserial \
-out certs/prometheus.kpyun.com.crt \
-days 365 \
-sha256 \
-extfile prometheus-server.ext
# 这里用 Intermediate CA 签发,不是 Root CA 直接签发
5)合并完整证书链
root@Prom certs# cat certs/prometheus.kpyun.com.crt certs/intermediate.crt > certs/fullchain.crt
# fullchain.crt = Prometheus 服务器证书 + Intermediate CA 证书
6)验证完整证书链
root@Prom certs# openssl verify \
-CAfile certs/rootCA.crt \
-untrusted certs/intermediate.crt \
certs/prometheus.kpyun.com.crt
certs/prometheus.kpyun.com.crt: OK
✅️ Root CA → Intermediate CA → Prometheus Server Certificate 验证通过
7)查看最终目录
root@Prom certs# tree .
.
├── certs
│ ├── fullchain.crt
│ ├── intermediate.crt
│ ├── intermediate.srl
│ ├── prometheus.kpyun.com.crt
│ └── rootCA.crt
├── intermediate.csr
├── private
│ ├── intermediate.key
│ ├── prometheus.kpyun.com.key
│ └── rootCA.key
├── prometheus-server.ext
├── prometheus.kpyun.com.csr
└── rootCA.srl

准备认证文件#

Terminal window
1)生成 Basic Auth 用户密码
'使用 htpasswd 工具生成 bcrypt 哈希'
root@Prom ~# apt-get -y install apache2-utils
root@Prom ~# htpasswd -Bbc /tmp/auth kpyun kpyun123
-B # 强制使用 bcrypt 加密算法(当前推荐,安全性高)
-b # 在命令行中直接提供密码(注意:此方式会暴露密码,生产环境慎用)
-c # 创建新文件(若文件已存在则覆盖)
Adding password for user kpyun
root@Prom ~# cat /tmp/auth
kpyun:$2y$05$F99Z4rJKrgrmKaJZt1pVi.NbfEo2KEInl0CCmRjy6RPFfM.kL.dmW
# 用户名: kpyun,密码: kpyun123
===================================
`无需按装,直接生成(系统有 Python 3 和 bcrypt 库)`
root@Prom ~# python3 -c 'import bcrypt; pwd="kpyun123"; print("kpyun: " + bcrypt.hashpw(pwd.encode(), bcrypt.gensalt(rounds=10)).decode())'
kpyun: $2b$10$yLoDjSLYj5oLa64ptcv9JuFfCAGeKjHIyJGUM7G10Ob4glXn1ZiP2
2)创建 Prometheus 认证配置文件
root@Prom ~# cat > /etc/prometheus/auth.yml <<'EOF'
tls_server_config:
cert_file: /etc/prometheus/certs/certs/fullchain.crt
key_file: /etc/prometheus/certs/private/prometheus.kpyun.com.key
basic_auth_users:
kpyun: $2y$05$F99Z4rJKrgrmKaJZt1pVi.NbfEo2KEInl0CCmRjy6RPFfM.kL.dmW
EOF
# cert_file: 使用 fullchain.crt(包含中间证书链)
# key_file: private/ 下的 Prometheus 服务端私钥
# ⚠️ 密码哈希要从 htpasswd 输出中复制完整
Caution

⚠️ 认证文件格式注意

  • basic_auth_users 下的密码是 bcrypt 哈希,不是明文
    • 用户名:🔥空格🔥哈希(中间有个空格)
  • YAML 缩进必须用空格,不能用 Tab
  • 证书路径要写绝对路径

HTTPS访问并抓取自身#

Terminal window
1)修改 Prometheus 的 systemd 服务,添加 --web.config.file 参数
root@Prom ~# vim /etc/systemd/system/prometheus.service
....
--web.config.file=/etc/prometheus/auth.yml \
# --web.config.file: 指定认证配置文件路径
# ✅ 重点就加了这一行
2)重启 Prometheus
root@Prom ~# systemctl daemon-reload
root@Prom ~# systemctl restart prometheus
root@Prom ~# ss -ntl | grep 9090
LISTEN 0 4096 *:9090 *:*
# 端口正常监听
3)浏览器访问
# 打开 https://10.0.0.10:9090
# 浏览器会提示"不安全"(自签名证书),点击"继续访问"
# 弹出认证框,输入用户名: kpyun,密码: kpyun123
✅️ 登录成功,看到 Prometheus WebUI
4)命令行验证
root@Prom ~# curl -k -u kpyun:kpyun123 https://10.0.0.10:9090/-/healthy
Prometheus Server is Healthy.
✅️ HTTPS + Basic Auth 均正常
5)不带认证测试(应被拒绝)
root@Prom ~# curl -k https://10.0.0.10:9090/-/healthy
401 Unauthorized
✅️ 未认证访问被正确拦截
https://10.0.0.10:9090/targets?search=prometheus

Caution

Prometheus 启用 HTTPS 后,需要配置它自己也通过 HTTPS 来抓取自身指标

官方配置说明:https://prometheus.io/docs/prometheus/3.13/configuration/configuration/

Terminal window
1)修改 prometheus.yml 中 prometheus job
root@Prom ~# vim /etc/prometheus/prometheus.yml
...
- job_name: "prometheus"
scheme: 'https'
tls_config:
insecure_skip_verify: true
# 自签名证书,跳过校验
basic_auth:
username: kpyun
password: kpyun123
static_configs:
- targets: ["10.0.0.10:9090"]
# scheme: https → 使用 HTTPS 协议
# insecure_skip_verify: true → 不校验证书(自签名场景)
2)热加载配置
root@Prom ~# curl -k -u kpyun:kpyun123 -X POST https://10.0.0.10:9090/-/reload
# -k: 跳过证书校验
# -u: Basic Auth 认证
3)验证抓取状态
# 浏览器访问 https://10.0.0.10:9090/targets?search=prometheus
# Prometheus job 的 target 状态应为 UP ✅️

Prometheus 成功通过 HTTPS 抓取自身指标
Prometheus 成功通过 HTTPS 抓取自身指标

Note

📌 热加载 vs 重启

方式命令影响
热加载curl -X POST http://localhost:9090/-/reload只更新配置,不中断服务(需要 --web.enable-lifecycle)
重启systemctl restart prometheus重启进程,会短暂中断抓取

关键区别:

  • scrape_configs、alerting、rule_files 等抓取相关字段:热加载即可生效
  • remote_write、remote_read、global 等顶级字段:必须重启才能生效,热加载无效

生产环境优先用热加载,只有修改顶级字段时才走重启

导入CA证书#

Terminal window
1)拷贝到宿主机
jiuzhao@Ubuntu 下载$ scp Prom:/etc/prometheus/certs/certs/rootCA.crt .
2)修改宿主机 hosts表
jiuzhao@Ubuntu ~$ sudo vim /etc/hosts
10.0.0.10 prometheus.kpyun.com kpyun.com
`两个域名都可以进行访问`
3)CA证书导入浏览器
edge://certificate-manager/localcerts/usercerts
# 在“受信任的证书”栏目下,点击 “导入” (刚才拷贝的 rootCA.crt 文件)
4)测试访问
https://prometheus.kpyun.com:9090
# 地址栏应显示安全锁标志,不再提示“您的连接不是私密连接”

用户认证
用户认证

安全连接
安全连接

Terminal window
1)未导入系统证书
root@Prom ~# curl -u kpyun:kpyun123 https://10.0.0.10:9090/-/healthy
curl: (60) SSL certificate problem: unable to get local issuer certificate
`SSL证书问题:无法获取本地颁发者证书`
# 需要 -k 跳过 SSL 校验
2)根证书导入 Linux 系统信任库
# 复制根证书到系统证书目录
root@Prom ~# sudo cp /etc/prometheus/certs/certs/rootCA.crt /usr/local/share/ca-certificates/
# 更新系统证书库
root@Prom ~# sudo update-ca-certificates
3)不再需要 -k(跳过校验)SSL 校验通过
root@Prom ~# curl -u kpyun:kpyun123 https://10.0.0.10:9090/-/healthy
Prometheus Server is Healthy.

node-exporter黑白名单#

Prometheus黑白名单
Prometheus黑白名单

黑白名单用于控制采集哪些指标,可以从客户端(exporter)或服务端(Prometheus)两个维度实现

维度黑名单白名单
客户端--no-collector.xxx--collector.disable-defaults --collector.xxx
服务端params: exclude[]: [xxx]params: collect[]: [xxx]
效果该指标不暴露/不采集只暴露/采集指定指标

客户端黑白名单#

在 node1(10.0.0.2)上操作 node-exporter 进程

Terminal window
1)停止 node-exporter 服务
[root@node1 ~]# systemctl stop node-exporter
2)【黑名单】禁用指定 collector
[root@node1 ~]# node_exporter --version | head -1
node_exporter, version 1.12.1
[root@node1 ~]# node_exporter \
--no-collector.cpu \
--no-collector.meminfo \
--no-collector.loadavg
# --no-collector.cpu: 不采集 CPU 指标
# --no-collector.meminfo: 不采集内存信息
# --no-collector.loadavg: 不采集负载信息
root@Prom ~# curl -s 10.0.0.2:9100/metrics | grep -c node_cpu_*
0
# 访问 http://10.0.0.2:9100/metrics 验证
# node_cpu_* 指标: 🈚 不存在
# node_memory_* 指标: 🈚 不存在
# node_load* 指标: 🈚 不存在
✅️ 黑名单生效,指定指标已隐藏
3)【白名单】只启用指定 collector
[root@node1 ~]# node_exporter \
--collector.disable-defaults \
--collector.cpu \
--collector.uname \
--collector.diskstats
# --collector.disable-defaults: 先禁用所有 collector
# --collector.cpu: 只启用 CPU collector
# --collector.uname: 只启用系统信息 collector
# --collector.diskstats: 只启用磁盘统计 collector
root@Prom ~# curl -s 10.0.0.2:9100/metrics | grep -c node_disk_*
98
# 访问 http://10.0.0.2:9100/metrics 验证
# 指标数量大幅减少,只保留 cpu/uname/diskstats 相关
# node_cpu_seconds_total: ✅️ 存在
# node_uname_info: ✅️ 存在
# node_disk_*: ✅️ 存在
root@Prom ~# curl -s 10.0.0.2:9100/metrics | grep -c node_memory_*
0
# node_memory_*: 🈚 不存在
# node_load*: 🈚 不存在
✅️ 白名单生效,只暴露指定指标
4)恢复默认配置并重启服务
[root@node1 ~]# systemctl start node-exporter
# 测试完毕恢复原状

服务端黑白名单#

在 Prom(10.0.0.10)上通过 Prometheus 配置控制采集

Terminal window
1)【黑名单】排除指定 collector
root@Prom ~# vim /etc/prometheus/prometheus.yml
...
- job_name: "kpyun-blacklist"
params:
exclude[]:
- cpu
- meminfo
static_configs:
- targets: ["10.0.0.2:9100"]
# exclude[]: 排除 cpu 和 meminfo collector
2)检查配置并热加载
root@Prom ~# promtool check config /etc/prometheus/prometheus.yml
Checking /etc/prometheus/prometheus.yml
SUCCESS: /etc/prometheus/prometheus.yml is valid prometheus config file syntax
root@Prom ~# curl -k -u kpyun:kpyun123 -X POST https://10.0.0.10:9090/-/reload
3)验证黑名单
# Prometheus WebUI 查询:
node_cpu_seconds_total{job="kpyun-blacklist",instance="10.0.0.2:9100"}
# 🈚 无数据(被 exclude 排除了)
node_uname_info{job="kpyun-blacklist",instance="10.0.0.2:9100"}
# ✅️ 有数据(uname 未被排除)
✅️ 服务端黑名单生效
4)【白名单】只采集指定 collector
root@Prom ~# vim /etc/prometheus/prometheus.yml
...
- job_name: "kpyun-whitelist"
params:
collect[]:
- uname
- diskstats
static_configs:
- targets: ["10.0.0.2:9100"]
# collect[]: 只采集 uname 和 diskstats
5)检查配置并热加载
root@Prom ~# promtool check config /etc/prometheus/prometheus.yml
root@Prom ~# curl -k -u kpyun:kpyun123 -X POST https://10.0.0.10:9090/-/reload
6)验证白名单
# Prometheus WebUI 查询:
node_uname_info{job="kpyun-whitelist",instance="10.0.0.2:9100"}
# ✅️ 有数据
node_disk_io_now{job="kpyun-whitelist",instance="10.0.0.2:9100"}
# ✅️ 有数据
node_cpu_seconds_total{job="kpyun-whitelist",instance="10.0.0.2:9100"}
# 🈚 无数据(collect 未包含 cpu)
✅️ 服务端白名单生效
Tip

💡 客户端 vs 服务端黑白名单的区别

  • 客户端:直接控制 exporter 暴露哪些指标,减少网络传输量
  • 服务端:Prometheus 侧过滤,exporter 仍然暴露全部指标
  • 生产环境建议客户端优先,减少 exporter 的资源开销 ✅️

标签管理#

Prometheus 的每一条**时间序列(time series)**都由两部分唯一确定:

  • 指标名(如 node_cpu_seconds_total)
  • 一组标签(labels),也就是这条序列的”维度”,例如 job="node"、instance="10.0.0.2:9100"、cpu="0"

同一个指标名 + 不同的标签组合 = 不同的时间序列,换言之,标签就是用来区分、过滤、聚合数据的维度——没有标签,你就没法在 PromQL 里写 up{job="node"} 去按 job 筛选,也没法按 instance 看单台机器的曲线

Note

📌 先认清”指标名”和”series(时间序列)”

  • 指标名(metric name):如 node_cpu_seconds_total,只是一个名字(类别)
  • series(时间序列):指标名 + 全部标签 的唯一组合,才是真正落盘、能被查询的那条数据线
  • 一个指标名下会有成百上千条 series(每个 CPU 核、每台机器各一条,标签不同就另算一条)
  • 后面会看到 metric_relabel_configs 里用 source_labels: [__name__] + drop,是按指标名筛、一次性删掉该指标名下的所有 series——口语说”删掉整个指标”没错,但严谨的底层对象是 series(时间序列)

💡 一句话:指标名是”类别”,series(时间序列)是该类下带具体标签的一条条真实数据;后面所有 relabel 操作,本质都是在搬动、筛选这些 series 及其标签

Prometheus 的标签按来源和生命周期可以分为四类:

标签类型格式/示例生命周期说明
自动注入标签(保留标签)job、instance持久化存储抓取时自动附加到每条时间序列:job=当前 job_name,instance=target 的 __address__(host)
这两个标签永远存在,action: labeldrop 对它们无效
内部标签(临时,双下划线)__address__、__scheme__、__metrics_path__、__param_*、__scrape_interval__、__scrape_timeout__抓取后丢弃抓取前(relabel_configs 阶段)存在,用于定位目标与传递参数,不写入 TSDB,relabel_configs 结束后即被丢弃,只有被它映射到非 __ 标签才会保留
服务发现标签__meta_*抓取后丢弃服务发现(consul/file_sd/k8s 等)产生的元数据标签,仅 relabel_configs 阶段可用,默认抓取后被丢弃,需在 relabel_configs 中用 keep/labelmap 才能保留
自定义标签用户自定义(如 auther、school、class)持久化存储在 static_configs 的 labels: 手动添加,或在 relabel 规则(relabel_configs / metric_relabel_configs)中用 replace/labelmap 生成
Note

📌 job/instance 与 __address__ 的区别(重要)

  • __address__ 是内部临时标签,抓取完成后被丢弃
  • instance 是 Prometheus 从 __address__ 自动固化出来的保留标签,会持久化
  • 同理 job 来自 job_name,也是自动注入并保留
  • 所以”默认存在的标签”不是 __address__,而是 job 和 instance,这也是为什么 labeldrop 删不掉它们——relabel_configs 结束后会由 __address__/job_name 重新派生
Note

📌 __meta_* 服务发现标签的生命周期(重要)

  • 由服务发现(consul/k8s/file_sd 等)在发现 target 时附加,static_configs 静态配置没有 __meta_*
  • 只在 relabel_configs 阶段可用,常用 labelmap 把它映射成正式标签,或用 keep/drop 基于它筛选 target
  • 抓取完成后自动丢弃,不会写入 TSDB——想保留必须先在 relabel_configs 阶段映射/保留出来

流程架构#

一条时间序列从”被发现”到”落盘”,标签会经历下面这条流水线,先记住两个关键停靠点:relabel_configs(抓取前) 和 metric_relabel_configs(抓取后),后面会反复用到

服务发现

找到 targets

生成 __meta_* 服务发现标签

加载内部标签

__scheme__ / __address__ / __metrics_path__

自动注入保留标签

job / instance

relabel_configs

抓取前标签操作

抓取 /metrics

metric_relabel_configs

抓取后指标操作

存储到 TSDB

服务发现

找到 targets

生成 __meta_* 服务发现标签

加载内部标签

__scheme__ / __address__ / __metrics_path__

自动注入保留标签

job / instance

relabel_configs

抓取前标签操作

抓取 /metrics

metric_relabel_configs

抓取后指标操作

存储到 TSDB

两个 relabel 阶段的根本区别

这是整个标签管理最核心、也最容易混的概念,只在这里讲一次,后面实战不再重复

Important

📌 relabel_configs vs metric_relabel_configs

  • relabel_configs:作用于抓取前,操作 target 的标签(如修改 __address__、instance)
  • metric_relabel_configs:作用于抓取后,操作已采集的指标标签(如删除某些指标)
  • ⚠️ relabel_configs 阶段 job/instance 不能用 labeldrop 删除(relabel_configs 结束后会由 __address__/job_name 重新派生),但可用 replace 等动作修改
  • 📌 instance 默认取值 = relabel_configs 后 __address__ 的值,所以改 __address__ 会连带改 instance,黑盒探测正是先改 __address__ 为 blackbox 地址,再显式把 instance 设回真实目标,二者才被解耦

📌 两套 7 种 action 完全通用,但”对象”不同:下面列出的 7 种动作,relabel_configs 和 metric_relabel_configs 都能写,区别只在前者动 target、后者动已采集的样本——同一个 action: drop,在 relabel_configs 丢整条 target,在 metric_relabel_configs 只丢匹配的 series(时间序列)(target 早已抓取完,丢不掉了)。因此 action 只讲一次,实战里直接套用

action 速查#

relabel_configs / metric_relabel_configs 都是基于正则对标签做”整形”,支持 7 种 action(其中 replace 是默认动作,省略 action: 即按 replace 处理),先按作用层级分成两类:target 级(整条保留/丢弃)和标签级(改/删某个 key)

动作作用层级效果典型示例常见用途
replace(默认动作)标签级source_labels+regex 匹配,结果写入 target_label(标签不存在则新建,存在则覆盖)__address__→instance生成/改写标签、黑盒改 __address__
keeptarget 级source_labels 匹配则保留该 target,否则整条丢弃keep __meta_kubernetes_namespace=~"kube-system"只采集特定 target
droptarget 级source_labels 匹配则丢弃该 targetdrop __meta_.* 某条件排除不需要的 target
labelmap标签级把匹配 regex 的标签名映射成新标签名(值复制过去)(job|app) → ${1}_kpyun批量重命名标签
labeldrop标签级按**标签名(key)**匹配,删掉整个 key=value(值随 key 一起消失)labeldrop (job|app)去掉敏感/多余标签
labelkeep标签级只保留匹配 key 的标签(整条 key=value),其余删除labelkeep (job|instance|__name__)精简标签、降基数
hashmod标签级对 source_labels 哈希取模,结果写入 target_label(配 modulus)hashmod modulus: 4多 Prometheus 分片采集
Note

📌 replacement 字段的双向语义

  • 在 replace 里:target_label 决定”写到哪个标签(名)“,replacement 决定”写什么值”(可引用 ${1} 等捕获组重组来源值);不写 source_labels 时,replacement 就是写死的固定值(如 blackbox 地址)
  • 在 labelmap 里:replacement 配合正则捕获组(如 ${1})决定”新标签的名”,值原样复制过去——所以 labelmap 的 replacement 改的是名
  • 一句话:replacement 既能改值(replace 场景)也能改名(labelmap 场景),区别在于 action

⚠️ 上表”target 级 / 标签级”的划分是基于 relabel_configs(抓取前) 的视角:keep/drop 在这里决定整条 target 采不采集;到了 metric_relabel_configs(抓取后),同样的 7 种 action 都能写,但 keep/drop 作用的对象变成了已采集的 series(时间序列)——丢的是匹配的 series(时间序列),不是 target 本身

Important

📌 怎么区分这些 action(重要,一次讲清)

  • target 级 vs 标签级:keep/drop 没带 label,动的是”整条 target 采不采集”(作用于整个抓取目标),labelkeep/labeldrop 带 label,动的是”这条序列上保留/删除哪些 key”(target 照采,只是标签被筛掉),记忆口诀:没 label 动 target,有 label 动标签名
  • 动 key 还是 value:labeldrop/labelkeep 只按标签名(key)匹配,删/留的是整个 key=value,值跟着 key 一起走,不存在”只删 key 留 value”,想改值用 replace(读 source_labels 的值、正则重组后写进 target_label,已存在则覆盖其值=改值,不存在则新建标签);⚠️ replace 只产出一个 target_label,不删标签、不能直接改名(改名用 labelmap),source_labels 仅作输入、自身不会被改动,keep/drop 在 relabel_configs 阶段根本不碰 key/value,直接决定整条 target 采不采集(到了 metric_relabel_configs 阶段则改为决定哪些 series(时间序列) 留存)
  • target / instance / 时间序列 的关系:一个 target(如 10.0.0.2:9100)= 一个 instance 标签的值,一个 instance 被抓取后会产出成百上千条时间序列(node_load5、各 CPU 核的 node_cpu_* 等),它们共享同一个 instance/job,所以 keep/drop 丢掉 target 是丢掉它名下所有序列,labelkeep/labeldrop 只是把每条序列上的某些标签 key 筛掉,序列本身还在

实战演练#

下面从最简单的”加标签”开始,逐步做标签操作实验

1️⃣ 自定义标签(static_configs labels)#

在 static_configs 中为 targets 添加自定义标签:

Terminal window
1)修改 prometheus.yml
root@Prom ~# vim /etc/prometheus/prometheus.yml
...
- job_name: "kpyun-custom-labels"
static_configs:
- targets: ["10.0.0.2:9100","10.0.0.11:9100","10.0.0.12:9100"]
labels:
auther: jiuzhao
school: kpyun-edu
class: C413
# labels 下自定义三个标签: auther、school、class
'给每个 target 打上同样的自定义标签'
2)检查配置并热加载
root@Prom ~# promtool check config /etc/prometheus/prometheus.yml
SUCCESS: /etc/prometheus/prometheus.yml is valid prometheus config file syntax
✅️ 配置语法没问题
root@Prom ~# curl -k -u kpyun:kpyun123 -X POST https://10.0.0.10:9090/-/reload
'热加载,不用重启 Prometheus'
3)验证自定义标签
# Prometheus WebUI 查询:
up{job="kpyun-custom-labels"}
# 每个 target 都带上了 auther="jiuzhao"、school="kpyun-edu"、class="C413"
https://prometheus.kpyun.com:9090/query

自定义标签添加成功
自定义标签添加成功

Note

📌 relabel_configs vs labels 的区别

  • labels:直接在 static_configs 中添加,简单但功能有限(只能写死值)
  • relabel_configs:基于正则进行标签操作,可拼接、映射、删除,功能更强

2️⃣ relabel_configs 实战:replace 改写/合成标签#

用 replace 读取源标签(多个值可先拼接)、经正则重组后写入目标标签(不存在则新建、存在则覆盖):

Tip

💡 replace 是 relabel 的默认动作,“拼接”只是 source_labels 多值、靠 separator 粘起来时的可选手段;它只把结果写到 target_label——能改值、能新建标签,但不能删标签、不能直接改名

Terminal window
1)修改 prometheus.yml
root@Prom ~# vim /etc/prometheus/prometheus.yml
...
- job_name: "kpyun-relabel-replace"
static_configs:
- targets: ["10.0.0.2:9100","10.0.0.11:9100","10.0.0.12:9100"]
labels:
auther: jiuzhao
relabel_configs:
# 指定源标签: 将 __scheme__、__address__、__metrics_path__ 拼接
- source_labels:
- __scheme__
- __address__
- __metrics_path__
# 正则分组匹配,"${1}" 和 "${2}" 引用匹配结果
regex: "(http|https)(.*)"
# 拼接分隔符,不指定默认为分号 ";"
# 空字符串,拼接时源标签的值之间什么都不加
separator: ""
# 替换值: scheme://address+path
replacement: "${1}://${2}"
# 新标签名称
target_label: "kpyun_prometheus_ep"
action: replace
# 假设数据: __scheme__="http", __address__="10.0.0.2:9100", __metrics_path__="/metrics"
# 拼接后: "http10.0.0.2:9100/metrics"
# 正则分组: ${1}="http", ${2}="10.0.0.2:9100/metrics"
# 最终 kpyun_prometheus_ep = "http://10.0.0.2:9100/metrics"
'把三个内部标签拼成了一个访问端点'
2)检查配置并热加载
root@Prom ~# promtool check config /etc/prometheus/prometheus.yml
SUCCESS: /etc/prometheus/prometheus.yml is valid prometheus config file syntax
✅️ 配置语法没问题
root@Prom ~# curl -k -u kpyun:kpyun123 -X POST https://10.0.0.10:9090/-/reload
'热加载'
3)验证替换结果
# Prometheus WebUI 查询:
up{job="kpyun-relabel-replace"}
# 每个 target 多了一个标签 kpyun_prometheus_ep,值为 "http://10.0.0.x:9100/metrics"

relabel_configs 替换标签成功
relabel_configs 替换标签成功

3️⃣ relabel_configs 实战:labelmap + labeldrop#

将已有标签通过正则映射生成新标签,再删除原始标签:

Note

📌 labelmap 的机理

拿标签的”名”(key)去匹配正则,把匹配到的标签改名,值原样复制过去 例如 regex:"__address__" + replacement:"__param_target",会造出 __param_target=原值

💡 它适合”按标签名批量重命名”

Terminal window
1)修改 prometheus.yml
root@Prom ~# vim /etc/prometheus/prometheus.yml
...
- job_name: "kpyun-labelmap"
static_configs:
- targets: ["10.0.0.2:9100","10.0.0.11:9100","10.0.0.12:9100"]
relabel_configs:
# labelmap: 将匹配到的标签名映射为新标签名(值复制过去)
- regex: "(job|app)"
replacement: "${1}_kpyun_labelmap"
action: labelmap
# 把 job 的值复制到 job_kpyun_labelmap
# 如 job="kpyun-labelmap" → job_kpyun_labelmap="kpyun-labelmap"
- regex: "(job|app)"
action: labeldrop
# 删除匹配到的 job 和 app 标签(连同值一起消失)
'先复制一份新标签,再删掉旧的'
2)检查配置并热加载
root@Prom ~# promtool check config /etc/prometheus/prometheus.yml
root@Prom ~# curl -k -u kpyun:kpyun123 -X POST https://10.0.0.10:9090/-/reload
3)验证 labelmap 结果
# Prometheus WebUI 查询:
up{job_kpyun_labelmap="kpyun-labelmap"}
# ✅️ 原始 job 标签已删除,新标签 job_kpyun_labelmap 存在
`标签值(kpyun-labelmap)不变,直接复制过去`
# 🈚 up{job="kpyun-labelmap"} → 查不到(job 已被 drop)

原始 job 标签已删除
原始 job 标签已删除

新标签 job_kpyun_labelmap 存在
新标签 job_kpyun_labelmap 存在

4️⃣ metric_relabel_configs 实战:按 name 删指标#

metric_relabel_configs 运行在”数据已拉回、但还没写进 TSDB 之前”,典型用途是按 __name__ 删除整个指标以省存储

Note

💡 注意这里的 drop 和 relabel_configs 里的 drop 不是一回事:此刻 target 早已抓取完成,drop 不可能再丢整条 target 链条,它只能丢掉匹配到的 series(时间序列)——target 照抓、其它指标照存

Terminal window
1)修改 prometheus.yml
root@Prom ~# vim /etc/prometheus/prometheus.yml
...
- job_name: "kpyun-metric-relabel"
static_configs:
- targets: ["10.0.0.2:9100","10.0.0.11:9100","10.0.0.12:9100"]
relabel_configs:
- regex: "(job|app)"
replacement: "${1}_kpyun_test"
action: labelmap
- regex: "(job|app)"
action: labeldrop
metric_relabel_configs:
# 删除所有 node_cpu_* 开头的指标
- source_labels:
- __name__
regex: "node_cpu_.*"
action: drop
# __name__ 是指标名称的内置标签
# regex 匹配所有 node_cpu_* 指标,执行 drop 动作
'抓取后直接把整类指标扔掉,省存储'
2)检查配置并热加载
root@Prom ~# promtool check config /etc/prometheus/prometheus.yml
SUCCESS: /etc/prometheus/prometheus.yml is valid prometheus config file syntax
✅️ 配置语法没问题
root@Prom ~# curl -k -u kpyun:kpyun123 -X POST https://10.0.0.10:9090/-/reload
'热加载'
3)验证 metric_relabel_configs 结果
# 测试语句 1: 查询 node_cpu 指标
node_cpu_seconds_total{job_kpyun_test="kpyun-metric-relabel"}[10s]
# 🈚 无数据(被 metric_relabel_configs drop 了)
# 测试语句 2: 查询 node_load 指标哈哈
node_load5{job_kpyun_test="kpyun-metric-relabel"}[10s]
# ✅️ 有数据(node_load 不在 drop 列表中)
✅️ metric_relabel_configs 过滤成功

node_cpu_.*
node_cpu_.*

node_load5
node_load5

Tip

💡 怎么选(决策清单)

  • 要修改 target 的标签(如改 __address__、instance)→ 用 relabel_configs
  • 要删除/修改已采集的指标(如按 __name__ 过滤 collector)→ 用 metric_relabel_configs
  • 要控制采集哪些 collector → 用黑白名单(更简单,见上节 node-exporter 黑白名单)
  • 不确定?记住一句话:抓取前动 target 用前者,抓取后动样本用后者

blackbox-exporter黑盒监控#

对比白盒监控黑盒监控
关注点内部指标(CPU、内存、磁盘)外部结果(端口、HTTP状态码、连通性)
时机事件未发生时预测事件已发生后检测
类比看汽车仪表盘的油量,提前加油车开不动了才知道没油了
组件node-exporter、各种 exporterblackbox-exporter
Important

📌 为什么黑盒只能”事后检测”、白盒能”事前预测”

  • 黑盒(blackbox-exporter):从外部探(HTTP 通不通、端口在不在、ping 得通不通)
    • 它探测失败的那一刻,故障对用户已经发生了——网站已经打不开了,你才探测到失败
    • 它是”黑盒”看不到服务内部,根本没有内部指标可用来预测,只能事后发现
  • 白盒(node-exporter 等):看内部指标(CPU、内存、磁盘、错误率、队列长度…)
    • 这些指标往往在”用户可见的大故障”之前就出现异常趋势(内存缓慢上涨、错误率从 0.1% 爬到 1%、TCP 重传变多)

    • 所以能靠前置信号提前预警,当然故障真发生了它也能检测

💡 一句话:白盒 = 能事前预测(看内部趋势)+ 能事后检测;黑盒 = 只能事后检测(看不到内部,无法预测)

Tip

blackbox-exporter 支持基于 HTTP、HTTPS、DNS、TCP、ICMP、gRPC 协议对目标进行探测

📌 blackbox-exporter 的定位

一般用于监控:网站是否存活、端口是否监听、证书是否过期 它不是采集内部指标,而是从外部视角验证服务是否可达

部署blackbox-exporter#

Terminal window
# blackbox-exporter 部署在 `node3`(10.0.0.12)
1)下载软件包
[root@node3 ~]# wget -P /tmp https://github.com/prometheus/blackbox_exporter/releases/download/v0.28.0/blackbox_exporter-0.28.0.linux-amd64.tar.gz
'包先放 /tmp'
2)解压
[root@node3 ~]# tar tf /tmp/blackbox_exporter-0.28.0.linux-amd64.tar.gz
blackbox_exporter-0.28.0.linux-amd64/
blackbox_exporter-0.28.0.linux-amd64/LICENSE # ❌没用
blackbox_exporter-0.28.0.linux-amd64/NOTICE # ❌没用
blackbox_exporter-0.28.0.linux-amd64/blackbox.yml
blackbox_exporter-0.28.0.linux-amd64/blackbox_exporter
[root@node3 ~]# mkdir -p /etc/blackbox/ && tar xf /tmp/blackbox_exporter-0.28.0.linux-amd64.tar.gz -C /etc/blackbox/ --strip-components 1 blackbox_exporter-0.28.0.linux-amd64/blackbox.yml
[root@node3 ~]# tar xf /tmp/blackbox_exporter-0.28.0.linux-amd64.tar.gz -C /usr/local/bin/ --strip-components 1 blackbox_exporter-0.28.0.linux-amd64/blackbox_exporter
'二进制进 /usr/local/bin,配置进 /etc/blackbox'
[root@node3 ~]# blackbox_exporter --version | head -1
blackbox_exporter, version 0.28.0
✅️ 版本正确,二进制与配置就位
3)查看默认配置
[root@node3 ~]# cat /etc/blackbox/blackbox.yml
modules:
http_2xx:
prober: http
http:
preferred_ip_protocol: "ip4"
.......
tcp_connect:
prober: tcp
icmp:
prober: icmp
# 默认支持 http_2xx、tcp_connect、icmp、grpc、ssh、postgresql 等模块
4)启动 blackbox-exporter
[root@node3 ~]# blackbox_exporter --config.file=/etc/blackbox/blackbox.yml
# 默认监听 0.0.0.0:9115
# 后台运行: nohup 或写 systemd 服务
'指定配置文件路径再启动'
5)验证端口
[root@node3 ~]# ss -ntl | grep 9115
LISTEN 0 4096 0.0.0.0:9115 0.0.0.0:*
6)访问 WebUI
# 浏览器访问 http://10.0.0.12:9115/
# 可以在 Web 界面上直接测试探测

HTTP探测#

通过 blackbox 的 http_2xx 模块探测目标网站是否返回 200 状态码

Terminal window
1)在 blackbox WebUI 测试
# 浏览器访问 http://10.0.0.12:9115/
# 选择模块: http_2xx
# Target 填写: www.baidu.com
http://10.0.0.12:9115/probe?target=www.baidu.com&module=http_2xx
2)测试多个 HTTP 目标
# www.baidu.com → ✅️ success(HTTP 200)
# 10.0.0.2:9100(node1 node-exporter)→ ✅️ success
# 10.0.0.11:9100(node2 node-exporter)→ ✅️ success

Terminal window
3)在 Prometheus 中配置 HTTP 探测
root@Prom ~# vim /etc/prometheus/prometheus.yml
...
- job_name: "kpyun-blackbox-http"
# 修改访问路径 /probe → blackbox 的探测接口
metrics_path: /probe
# params.module: http_2xx → 使用 HTTP 2xx 模块(从而判断相应的返回状态码是否为200)
params:
module: [http_2xx]
# 静态配置,需要手动指定监控目标
static_configs:
# 需要监控的目标
- targets:
# 支持 https 协议
- https://www.baidu.com
# 支持 http 协议和自定义端口
- http://10.0.0.2:9100
- http://10.0.0.11:9100
# 对目标节点进行重新打标签配置
relabel_configs:
# ① 读 __address__ 的值,写入 __param_target → URL 里变成 ?target=真实目标
- source_labels: [__address__]
target_label: __param_target
# ② 把真实目标也写进 instance 标签,否则第③步改完 __address__ 后 instance 会被推导成 blackbox 地址,分不清谁是谁
- source_labels: [__param_target]
target_label: instance
# ③ 直接把 __address__ 设成固定值(blackbox 地址),让 Prometheus 真正去问 blackbox 而非直连目标
- target_label: __address__
replacement: 10.0.0.12:9115
# 三条规则都没写 action,因为默认动作就是 replace
# ① 决定探谁(?target=) / ② 保留身份(instance) / ③ 把抓取对象重定向到 blackbox
# 最终 Prometheus 请求 10.0.0.12:9115/probe?target=xxx&module=http_2xx
4)热加载并验证
root@Prom ~# promtool check config /etc/prometheus/prometheus.yml
root@Prom ~# curl -k -u kpyun:kpyun123 -X POST https://10.0.0.10:9090/-/reload
`Prometheus WebUI → Targets: kpyun-blackbox-http 的所有 target 状态应为 UP`
# 查询探测指标: probe_success{job="kpyun-blackbox-http"}
# ✅️ 全部返回 1(成功)

target 状态
target 状态

探测指标
探测指标

Tip

💡 relabel_configs 的核心逻辑

黑盒探测的 relabel_configs 都是同一个套路(三步顺序不能乱): ① 把 __address__(真实目标)复制到 __param_target(URL 参数 ?target=) ② 把 __param_target 复制到 instance(序列标识/查询用,用来区分每条探测结果) ③ 把 __address__ 替换为 blackbox-exporter 的地址(真正去请求的地址) ⚠️ ② 必须在 ③ 之前:否则 instance 会被改写成 blackbox 地址,分不清谁是谁

数据源配置
数据源配置

Note

📌 Grafana 导入 blackbox 模板

常用 blackbox 模板 ID:

  • 7587:Blackbox Exporter
  • 13659:Blackbox Exporter (HTTP prober)

在 Grafana → Dashboards → Import 中输入模板 ID,选择对应数据源即可

Blackbox Exporter
Blackbox Exporter

ICMP探测#

通过 blackbox 的 icmp 模块探测目标主机是否可达(ping)

Terminal window
1)在 blackbox WebUI 测试
# 选择模块: icmp
# Target: 10.0.0.2 → ✅️ success
http://10.0.0.12:9115/probe?target=10.0.0.2&module=icmp
2)在 Prometheus 中配置 ICMP 探测
root@Prom ~# vim /etc/prometheus/prometheus.yml
...
- job_name: "kpyun-blackbox-icmp"
metrics_path: /probe
params:
module: [icmp]
static_configs:
- targets:
- 10.0.0.2
- 10.0.0.11
- 10.0.0.12
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: 10.0.0.12:9115
3)热加载并验证
root@Prom ~# promtool check config /etc/prometheus/prometheus.yml
root@Prom ~# curl -k -u kpyun:kpyun123 -X POST https://10.0.0.10:9090/-/reload
# 查询: probe_success{job="kpyun-blackbox-icmp"}
# ✅️ 全部返回 1(ping 通)

TCP探测#

通过 blackbox 的 tcp_connect 模块探测目标端口是否监听

Terminal window
1)在 blackbox WebUI 测试
# 选择模块: tcp_connect
# Target: 10.0.0.2:22 → ✅️ success(SSH 端口)
# Target: 10.0.0.11:9100 → ✅️ success(node-exporter 端口)
# Target: 10.0.0.10:9090 → ✅️ success(Prometheus 端口)
http://10.0.0.12:9115/probe?target=10.0.0.2:22&module=tcp_connect
2)在 Prometheus 中配置 TCP 探测
root@Prom ~# vim /etc/prometheus/prometheus.yml
...
- job_name: "kpyun-blackbox-tcp"
metrics_path: /probe
params:
module: [tcp_connect]
static_configs:
- targets:
- 10.0.0.2:22
- 10.0.0.11:9100
- 10.0.0.10:9090
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: 10.0.0.12:9115
3)热加载并验证
root@Prom ~# promtool check config /etc/prometheus/prometheus.yml
root@Prom ~# curl -k -u kpyun:kpyun123 -X POST https://10.0.0.10:9090/-/reload
# 查询: probe_success{job="kpyun-blackbox-tcp"}
# ✅️ 全部返回 1(端口可达)

Grafana指定MySQL存储#

Grafana配置MySQL作为存储后端
Grafana配置MySQL作为存储后端

Grafana 默认使用 SQLite 数据库存储元数据(dashboard、用户、数据源配置等)

Terminal window
1)查看配置文件默认数据库类型
root@Prom ~# grep sqlite3 /etc/grafana/grafana.ini | grep -v '^#'
;type = sqlite3
# 分号开头表示被注释,是默认值
2)查看本地 SQLite 数据库文件
root@Prom ~# ll -lh /var/lib/grafana/ | grep 'grafana\.db'
-rw-r----- 1 grafana grafana 8.6M Aug 21 08:29 grafana.db
root@Prom ~# file /var/lib/grafana/grafana.db
/var/lib/grafana/grafana.db: SQLite 3.x database, ...
# 确认当前使用 SQLite
Note

📌 为什么要切换到 MySQL

SQLite 是单文件数据库,适合开发和小规模使用 生产环境中,Grafana 连接数多、数据量大时,SQLite 性能不足 切换到 MySQL 后,元数据存储在远程数据库,Grafana 服务器可以无状态扩展

准备MySQL环境#

Docker VM(10.0.0.9)上有 MySQL 镜像,只需创建对应的容器( Grafana 专用的库和用户)

Terminal window
1)创建数据库
root@Docker ~# docker container run \
-e MYSQL_ALLOW_EMPTY_PASSWORD="yes" \
-d \
-p 3306:3306 \
--name mysql-server \
-e MYSQL_DATABASE="grafana" \
-e MYSQL_USER="grafana" \
-e MYSQL_PASSWORD="oldboy123.com" \
-e TZ=Asia/Shanghai \
mysql:8.0.36 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci \
--default-authentication-plugin=mysql_native_password \
--default-time-zone='+8:00'
2)确认 MySQL 容器运行状态
root@Docker ~# docker ps -l
mysql:8.0.36 "docker-entrypoint.s…" Up 0.0.0.0:3306->3306/tcp, 33060/tcp mysql-server
root@Docker ~# ss -ntl | grep 3306
LISTEN 0 151 *:3306 *:*
✅️ MySQL 容器正常运行
3)登录 MySQL 验证 Grafana 数据库和用户
root@Docker ~# docker exec -it mysql-server mysql
Welcome to the MySQL monitor.
Server version: 8.0.36 MySQL Community Server - GPL
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| grafana |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
mysql> SELECT USER, HOST FROM mysql.user WHERE USER='grafana';
+---------+------+
| USER | HOST |
+---------+------+
| grafana | % |
+---------+------+
✅️ grafana 数据库和用户创建完成
mysql> USE grafana;
Database changed
mysql> SHOW TABLES;
Empty set (0.00 sec)
`grafana 数据库里面一张表都没有`

存储迁移到MySQL#

Terminal window
1)修改 Grafana 配置文件
root@Prom ~# vim /etc/grafana/grafana.ini
...
[database]
# 默认被注释的是 sqlite3
# type = sqlite3
# path = /var/lib/grafana/grafana.db
# 修改为 MySQL
type = mysql
host = 10.0.0.9:3306
name = grafana
user = grafana
password = oldboy123.com
# host: MySQL 容器的 IP 和端口
# name: 刚才创建的数据库名
# user/password: 刚才创建的用户
2)重启 Grafana
root@Prom ~# systemctl restart grafana-server.service
root@Prom ~# ss -ntl | grep 3000
LISTEN 0 4096 *:3000 *:*
# 3000 端口正常监听
3)验证 Grafana WebUI 可访问
# 浏览器访问 http://10.0.0.10:3000
# 使用 admin/admin 登录(首次登录会提示修改密码)
✅️ Grafana 正常启动,存储后端已切换到 MySQL
Note

⚠️ 切到 MySQL 后首次登录 Grafana 仪表盘/数据源全空,是正常的

  • 旧配置(仪表盘、数据源、用户)都还在 SQLite 的 grafana.db 里,Grafana 不会跨数据库自动迁移,所以新 MySQL 里是空的
  • 你的监控指标(metrics)存在 Prometheus / VictoriaMetrics,根本不在 Grafana 的数据库里,指标数据毫发无损,只是“看板”空了
  • 原 grafana.db 文件仍在 /var/lib/grafana/,可备份保留
Terminal window
4)验证MySQL表
# 登录 MySQL 查看 Grafana 自动创建所需的表
root@Docker ~# docker exec -it mysql-server mysql grafana
mysql> SHOW TABLES;
+------------------------------------+
| Tables_in_grafana |
+------------------------------------+
| alert |
| ........... |
| user_role |
| user_stats |
+------------------------------------+
110 rows in set (0.00 sec)
✅️ Grafana 自动创建了 110 张表,MySQL 存储后端切换成功
Important

📌 验证要点

  • Grafana WebUI 能正常登录 → 配置正确
  • MySQL 中有 110 张表 → 自动迁移成功
  • 原来的 SQLite 文件 grafana.db 还在但不再使用 → 可以备份后删除

⚠️ 如果重启后 Grafana 起不来,按下面三处排查:

  • MySQL 容器是否在运行(docker ps / ss -ntl | grep 3306)
  • grafana.ini 里 MySQL 的 host / name / user / password 是否与创建库和用户时一致
  • MySQL 用户 grafana 是否允许远程连接(授权 host 需含 'grafana'@'%')
Note

📌 恢复旧仪表盘:Grafana 数据库里只存元数据(仪表盘、数据源、用户、文件夹、告警规则),不存监控指标——指标一直在 Prometheus / VictoriaMetrics。切到 MySQL 后旧的 grafana.db(SQLite)被弃用,仪表盘/数据源都变空;用 WebUI 迁移最直观:

  • 仪表盘:在旧 SQLite 实例上,打开仪表盘 → 右上角「导出」→「导出为代码」→ 下载 JSON 文件;再到新 MySQL 实例 Dashboard → Import,上传该 JSON 文件即可
  • 数据源:在 MySQL 实例里手动重新加一次,指向已有的 Prometheus 数据源

导入后仪表盘重新指向 Prometheus 就能出图

API导出仪表盘和数据源#

Terminal window
'旧数据在 SQLite 的 grafana.db,需先让 Grafana 临时回到 SQLite 把配置导出来'
1)临时切回 SQLite,导出旧仪表盘与数据源
root@Prom ~# vim /etc/grafana/grafana.ini
# 把 [database] 改回 type = sqlite3(注释掉 mysql),重启让 Grafana 读回 grafana.db
root@Prom ~# systemctl restart grafana-server.service
2)导出旧仪表盘(先拿 uid 列表,再逐个导出)
'列表文件名不用 dash_ 前缀,否则会被下面的 /tmp/dash_*.json 通配符误伤'
root@Prom ~# curl -s -k -u admin:admin "http://10.0.0.10:3000/api/search?type=dash-db" -o /tmp/dashboards_list.json
root@Prom ~# for uid in $(jq -r '.[].uid' /tmp/dashboards_list.json); do curl -s -k -u admin:admin "http://10.0.0.10:3000/api/dashboards/uid/$uid" -o /tmp/dash_$uid.json; done
3)导出数据源
root@Prom ~# curl -s -k -u admin:admin http://10.0.0.10:3000/api/datasources -o /tmp/datasources.json
4)切回 MySQL,准备导入
root@Prom ~# vim /etc/grafana/grafana.ini
# 恢复 type = mysql,重启
root@Prom ~# systemctl restart grafana-server.service
5)导入数据源(/api/datasources 只收单个对象,需逐个取出数组元素 POST)
jq -c '.[]' /tmp/datasources.json | while IFS= read -r ds; do
curl -s -k -u admin:admin -X POST -H "Content-Type: application/json" --data-binary "$ds" http://10.0.0.10:3000/api/datasources; echo
done
✅️ 数据源导入成功
`提前切换语言为中文,才能正常显示!`
6)导入仪表盘(先删掉 dashboard 里的 id,避免内部 ID 冲突)
for f in /tmp/dash_*.json; do
jq -c '{dashboard: (.dashboard | del(.id)), overwrite: true, folderId: 0}' "$f" | curl -s -k -u admin:admin -X POST -H "Content-Type: application/json" --data-binary @- http://10.0.0.10:3000/api/dashboards/db; echo
done
✅️ 旧仪表盘已恢复到 MySQL 后端,重新指向 Prometheus 数据源即可出图
'嫌命令行麻烦,也可用 Grafana WebUI'

恢复仪表盘
恢复仪表盘

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

相关文章智能推荐
1
Prometheus监控 & Grafana可视化
Prometheus监控二进制部署 Prometheus 3.13.2(mv 方案 + systemd 托管),编写 install-prometheus-server.sh / install-node-exporter.sh 一键安装卸载脚本,node-exporter 监控 Linux 主机,PromQL 四大数据类型与函数实战(stress 压测 CPU),Grafana 可视化展示,监控 ZK/Kafka/ES/Docker 主流中间件
2
Prometheus监控中间件 & Grafana进阶
Prometheus监控使用各中间件 exporter(mysqld/mongodb/redis/nginx-vts/tomcat)监控 MySQL、MongoDB、Redis、Nginx、Tomcat,Grafana 导入模板 ID(14057/17320/16504/11835/2949/9785),进阶掌握 Grafana 插件安装、自定义 Dashboard、变量、表格制作、备份与恢复
3
Prometheus自定义监控 && 服务发现 && 联邦模式
Prometheus监控部署 pushgateway 实现短期任务/自定义指标的推送式监控(API 推送删除、honor_labels、TCP 12 状态、丢包率脚本),用 Go + client_golang 开发自定义 exporter(静态编译零依赖),落地 file_sd 与 consul 服务发现(consul 2.0.3 集群 + consul_exporter),最后用 3 台 Prometheus server 搭建联邦模式实现分布式采集汇总
4
Prometheus 告警 && etcd 集群实战
Prometheus监控Alertmanager 告警路由/模板/静默/抑制 + 钉钉插件,etcd 3.7 TLS 高可用集群部署/备份恢复/Prometheus 监控,复用既有 kpyun CA 体系
5
ES 集群安全加固 & ES9 部署 & Zookeeper 集群
ES集群ES7 集群启用 HTTPS 与 api-key 认证,ES7 集群调优,ES9 集群实战(TLS 自动配置 + enrollment token),Zookeeper 单点与集群部署
Profile Image of the Author
久棹
不是先学好了再干,而是先干起来再学习,干中学!
分类
站点统计
文章
115
分类
15
标签
272
总字数
306,562
运行时长
0 天
最后活动
0 天前
文章目录