Prometheus监控 & Grafana可视化

Prometheus监控 && Grafana可视化
[TOC]
环境规划
我们完成了 ElasticStack 全链路 + Kafka 集群的部署 本篇落地 Prometheus 监控体系,覆盖 Linux 主机与主流中间件
| 虚拟机 | IP | 配置 | 角色 |
|---|---|---|---|
| Prom | 10.0.0.10 | 2C/2G | Prometheus server + Grafana |
| node1 | 10.0.0.2 | 2C/2G | node-exporter 被监控机 |
| node2 | 10.0.0.11 | 2C/2G | node-exporter 被监控机 + stress 压测机 |
| node3 | 10.0.0.12 | 2C/2G | node-exporter 被监控机 |
| Elk01 | 10.0.0.6 | 2C/2G | ZK + Kafka + ES 监控目标 |
| Elk02 | 10.0.0.7 | 2C/2G | ZK + Kafka + ES 监控目标 + ES exporter |
| Elk03 | 10.0.0.8 | 2C/2G | ZK + Kafka + ES 监控目标 |
| Docker | 10.0.0.9 | 2C/3G | cadvisor 容器监控 |
📌 主机说明
- Prom / node1 / node2 / node3 为本篇新建:Prom 走 Ubuntu 云镜像,node 系列走 Rocky.img 传统镜像路线
- Elk01/02/03 与 Docker VM 复用之前章节的机器,本篇只往上面装 exporter
Prometheus 架构图解


Prometheus 是一款开源的监控系统,可以监控主流的中间件、操作系统、硬件设备、网络设备等 相比 zabbix,Prometheus 的强项是对容器和微服务的监控更加方便
- 2012 年产品问世,2016 年加入 CNCF,是 CNCF 第二个毕业项目
- 采用 Go 语言编写
相关组件的作用
| 组件 | 作用 |
|---|---|
| Prometheus Server | ① 采集目标数据 ② 存储到本地或远端数据库 ③ 提供 WebUI 查询接口 |
| Grafana | 将 Prometheus 作为数据源,提供 Dashboard 数据展示 |
| Pushgateway | 自定义监控,支持无法被主动抓取的任务 |
| Alertmanager | 告警功能,支持钉钉、企业微信、邮箱等 |
| exporters | 被监控端,负责暴露各类指标 |
二进制部署 Prometheus

1)下载软件包(官方源)root@Prom ~# vim ~/.bashrc# 代理开关函数proxy_on() { export http_proxy=http://43.108.48.171:8888 export https_proxy=http://43.108.48.171:8888 export no_proxy=localhost,127.0.0.1,::1,.local echo "代理已开启"}
proxy_off() { unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY echo "代理已关闭"}root@Prom ~# source ~/.bashrcroot@Prom ~# proxy_on代理已开启root@Prom ~# mkdir -p /server/pkgs/ && cd /server/pkgs/root@Prom /server/pkgs# wget https://github.com/prometheus/prometheus/releases/download/v3.13.2/prometheus-3.13.2.linux-amd64.tar.gz
2)解压到 /usr/local/root@Prom ~# tar xf /server/pkgs/prometheus-3.13.2.linux-amd64.tar.gz -C /usr/local/root@Prom ~# mv /usr/local/prometheus-3.13.2.linux-amd64/ /usr/local/prometheus# 改名root@Prom ~# ls /usr/local/prometheusLICENSE NOTICE prometheus prometheus.yml promtoolroot@Prom ~# mv /usr/local/prometheus/prometheus /usr/local/bin/# 二进制直接 mv 到 /usr/local/bin/(全局命令)root@Prom ~# mv /usr/local/prometheus/promtool /usr/local/bin/
3)创建配置目录root@Prom ~# mkdir -p /etc/prometheusroot@Prom ~# mv /usr/local/prometheus/prometheus.yml /etc/prometheus/# 配置文件 mv 到 /etc/prometheus/'数据目录和日志目录等 systemd 里一起建'
4)删除源数据目录root@Prom ~# ls /usr/local/prometheus/LICENSE NOTICE# 源目录没用了,整个删掉root@Prom ~# rm -rf /usr/local/prometheus/
5)验证版本和全局命令root@Prom ~# which prometheus/usr/local/bin/prometheusroot@Prom ~# prometheus --versionprometheus, version 3.13.2 build user: root@56a9973e8bdd build date: 20260730-11:31:39 go version: go1.26.5 platform: linux/amd64 tags: netgo,builtinassets✅️ 二进制可执行,版本 3.13.2systemd 托管
① 编写 systemd 服务文件
1)编写 systemd 服务文件root@Prom ~# cat > /etc/systemd/system/prometheus.service <<"EOF"[Unit]# 服务描述Description=Prometheus Server# 官方文档地址Documentation=https://prometheus.io/docs/introduction/overview/# 等待网络就绪后再启动After=network-online.target# 主动声明依赖网络在线目标Wants=network-online.target
[Service]# 前台常驻进程:ExecStart 拉起即算成功(不 fork 不后台化)Type=simple# 异常退出时自动重启Restart=on-failure# 重启间隔 3 秒RestartSec=3# 文件描述符上限,防止高并发连接数超出LimitNOFILE=65535# 启动命令(bash -c 包裹,日志重定向到文件)# 必须包 /bin/bash -c:systemd 直接 exec 二进制不经 shell,&>> 会被当参数报错ExecStart=/bin/bash -c "/usr/local/bin/prometheus \ --config.file=/etc/prometheus/prometheus.yml \ --web.enable-lifecycle \ --storage.tsdb.path=/var/lib/prometheus \ --storage.tsdb.retention.time=60d \ --storage.tsdb.retention.size=512MB \ --web.listen-address=0.0.0.0:9090 \ --web.max-connections=65535 \ --web.read-timeout=5m \ --query.timeout=10s \ --query.max-concurrency=20 \ --log.level=info \ --log.format=json \ &>> /var/log/prometheus/prometheus.log"# 不配 ExecReload!热加载只能走 HTTP API: curl -X POST http://localhost:9090/-/reload
[Install]# 开机自启WantedBy=multi-user.targetEOF② 服务文件参数详解
| 参数 | 含义 | 默认值 |
|---|---|---|
--config.file | 指定 Prometheus 主配置文件 | ~ |
--web.config.file | 指定 Web 配置文件(如 HTTPS 证书、认证信息等) | 无 |
--web.enable-lifecycle | 开启热加载(curl -X POST /-/reload) | 关闭 |
--storage.tsdb.retention.time=60d | 数据保留时长 60 天 | 15d |
--storage.tsdb.retention.size=512MB | 数据体积上限 512MB | 0(不限制) |
--web.max-connections=65535 | 最大并发连接数 | 512 |
--web.read-timeout=5m | HTTP 读超时 | 5m |
--query.timeout=10s | 查询超时 | 2m |
--query.max-concurrency=20 | 最大并发查询 | 20 |
--log.level=info | 日志级别 | info |
--log.format=json | 日志格式 | logfmt |
Prometheus 二进制自己就是前台常驻进程,敲下去就一直占住终端
所以用 Type=simple——systemd 拉起即成功,不用猜、不用等
⚠️ 若误配 forking,systemd 会傻等一个不存在的 fork 子进程 → 启动超时
⚠️ 热加载只能用 curl -X POST /-/reload,不能用 systemctl reload!
- 因为 ExecStart 是
/bin/bash -c "prometheus ...",主进程是 bash systemctl reload发 SIGHUP 给 bash → 导致 bash 进程树全灭 → prometheus 也死,服务停- 只有 HTTP 热加载(
curl -X POST /-/reload)由 prometheus 自己处理,才安全
正确姿势:改完 prometheus.yml主配置文件 → curl -X POST http://localhost:9090/-/reload 重载一下
前提是启动参数带了 --web.enable-lifecycle
③ 启动并验证
1)创建数据与日志目录(systemd 参数里指定的路径)root@Prom ~# mkdir -p /var/lib/prometheus /var/log/prometheus'数据目录: --storage.tsdb.path 指定; 日志目录: &>> 重定向目标, 不存在会导致启动失败'
2)重载 + 启动 + 开机自启root@Prom ~# systemctl daemon-reloadroot@Prom ~# systemctl enable --now prometheusroot@Prom ~# systemctl is-active prometheusactive
3)验证端口root@Prom ~# ss -lnt | grep 9090LISTEN 0 4096 *:9090 *:*✅️ 9090 端口已监听
4)查看日志(文件方案)root@Prom ~# tail -f /var/log/prometheus/prometheus.logStarting rule manager...数据目录
1)验证默认数据目录(不带参数启动会建在哪)root@Prom ~# prometheus --help | grep -i 'storage\.tsdb\.path'--storage.tsdb.path="data/"# 官方默认:当前目录下的 data/ 子目录📌 结论:数据目录是 systemd 的 ExecStart 参数规定的,不是 prometheus.yml 规定的
- prometheus.yml 里没有任何数据目录配置,它只管抓取目标、规则、告警
- 数据存哪由启动参数
--storage.tsdb.path决定 - 直接
prometheus启动会在当前目录下建data/→ 运行后自动生成 data 目录
部署后最终布局(mv 方案,无软链接):
| 路径 | 内容 |
|---|---|
/usr/local/bin/prometheus | 主程序(mv) |
/usr/local/bin/promtool | 运维工具(mv) |
/etc/prometheus/prometheus.yml | 配置文件 |
/var/lib/prometheus/ | 数据目录 |
/var/log/prometheus/prometheus.log | 日志文件 |
| 已删除 |
访问 Prometheus WebUI
📌 WebUI 地址:http://10.0.0.10:9090/

1)健康检查root@Prom ~# curl -s http://localhost:9090/-/healthyPrometheus Server is Healthy.
2)自带指标root@Prom ~# curl -s http://localhost:9090/metrics | grep -c "^prometheus_http_requests_total"51✅️ Prometheus 自身也暴露 metrics,可被自己监控✨脚本部署 Prometheus
手动部署流程较繁琐,编写 install-prometheus-server.sh 脚本实现一键安装 / 卸载
# 目录结构(脚本 + 软件包 + 下载目录)autoinstall-prometheus/├── install-prometheus-server.sh # 安装脚本(可执行)└── download/ └── prometheus-3.13.2.linux-amd64.tar.gz # 软件包(安装后保留,卸载不清)脚本用法(支持全称和简写):
| 命令 | 动作 | 说明 |
|---|---|---|
bash install-prometheus-server.sh install 或 i | 一键安装 | 自动完成解压/mv/systemd/启动 |
bash install-prometheus-server.sh remove 或 r | 一键卸载 | 只清部署痕迹,保留脚本和软件包 |
1)给脚本加执行权限(可选,用 bash 跑则不需要)jiuzhao@Ubuntu ~$ chmod +x install-prometheus-server.sh
2)一键安装root@Prom ~# unzip /tmp/autoinstall-prometheus.zip -d /server/scripts/root@Prom ~# cd /server/scripts/autoinstall-prometheus/root@Prom autoinstall-prometheus# lsdownload install-prometheus-server.shroot@Prom ~# bash install-prometheus-server.sh install========================================= 开始安装 Prometheus v3.13.2=========================================软件包已存在,跳过下载: ./download/prometheus-3.13.2.linux-amd64.tar.gz正在解压 Prometheus ...解压完成,目录已改名: /usr/local/prometheus正在移动二进制到 /usr/local/bin/ ...二进制已安装: /usr/local/bin/prometheus /usr/local/bin/promtool正在配置目录与配置文件 ...配置文件已安装: /etc/prometheus/prometheus.yml正在删除源目录 ...正在创建数据与日志目录 ...数据目录: /var/lib/prometheus日志目录: /var/log/prometheus正在生成 systemd 服务文件 ...systemd 服务文件已生成: /etc/systemd/system/prometheus.service服务已启动并设置为开机自启
========================================= 安装成功!Prometheus v3.13.2 已运行=========================================
服务状态: active监听端口:LISTEN 0 4096 *:9090 *:*WebUI 地址: http://0.0.0.0:9090/日志文件: /var/log/prometheus/prometheus.log服务命令: 查看状态: systemctl status prometheus 重启服务: systemctl restart prometheus 热加载配置: curl -X POST http://localhost:9090/-/reload
3)一键卸载(只清部署痕迹,脚本和软件包保留)root@Prom ~# bash install-prometheus-server.sh remove========================================= 开始卸载 Prometheus=========================================正在停止服务并取消开机自启 ...正在删除 systemd 服务文件 ...正在删除二进制文件 ...正在删除配置、数据、日志目录 ...
卸载完成!以下内容已清除: - /etc/systemd/system/prometheus.service - /usr/local/bin/prometheus /usr/local/bin/promtool - /etc/prometheus /var/lib/prometheus /var/log/prometheus软件包保留: ./download/prometheus-3.13.2.linux-amd64.tar.gz💡 卸载保留设计:remove 只清理”部署产物”(服务/二进制/配置/数据/日志)
保留”安装材料”(脚本 + download 里的软件包)→ 下次 install 直接复用,免下载
脚本完整内容
#!/bin/bash#================================# 作者: 久棹# 用途: 在 Linux 上自动安装/卸载 Prometheus Server(二进制方式)# 适用系统: CentOS 7/8/9, Rocky, Ubuntu 18.04+, Debian 10+ 等 systemd 系统#================================
#================================# 第一部分: 定义变量# 把常用的路径、版本号、下载地址定义为变量,方便后续修改和维护#================================
# --- Prometheus 相关配置 ---# Prometheus 的版本号(要与 download 目录下的 tar.gz 文件名匹配)# 注意: 变量名用 PROM_VERSION,避免与 /etc/os-release 里的 VERSION 冲突PROM_VERSION=3.13.2# 系统架构ARCH=amd64# Prometheus 压缩包的文件名SOFTWARE=prometheus-${PROM_VERSION}.linux-${ARCH}.tar.gz# Prometheus 在 GitHub 上的下载地址URL=https://github.com/prometheus/prometheus/releases/download/v${PROM_VERSION}/${SOFTWARE}
# --- 本地目录 ---# 预下载文件的存放目录(脚本所在目录下的 download/)DOWNLOAD=./download# 解压后的临时目录名(解压后先改名 prometheus)# 复用 ARCH 变量,避免硬编码 amd64TMPDIR=prometheus-${PROM_VERSION}.linux-${ARCH}# systemd 服务文件的存放路径SYSTEMD_DIR=/etc/systemd/system# systemd 服务名(与笔记一致)SERVICE=prometheus
# --- 安装路径配置(mv 方案,无软链接) ---# 二进制文件 mv 到 /usr/local/bin/(全局命令)BIN_DIR=/usr/local/bin# 配置文件目录CONFIG_DIR=/etc/prometheus# 数据目录(systemd 里 --storage.tsdb.path 指定)DATA_DIR=/var/lib/prometheus# 日志目录(systemd 里 &>> 重定向目标)LOG_DIR=/var/log/prometheus
# --- 服务监听配置 ---HOSTIP=0.0.0.0PORT=9090# 主机名(安装完成提示用)HOSTNAME=`hostname`
# 加载操作系统的 ID 变量(如 centos、ubuntu),用于判断系统类型. /etc/os-releaseOS_VERSION=$ID
#================================# 第二部分: 工具函数#================================
#----------------------------------------------------# 颜色变量#----------------------------------------------------RED='\e[31m'GREEN='\e[32m'YELLOW='\e[33m'BLUE='\e[34m'RESET='\e[0m'
#----------------------------------------------------# 函数名: color# 作用: 按编号输出彩色文本,调用简洁(color 1 "文本")# 参数:# $1 - 颜色编号(1红 2绿 3黄 4蓝)# $* - 要输出的文本#----------------------------------------------------function color(){ local c=$RESET case $1 in 1) c=$RED ;; 2) c=$GREEN ;; 3) c=$YELLOW ;; 4) c=$BLUE ;; esac shift echo -e "${c}$@${RESET}"}
#----------------------------------------------------# 函数名: check_root# 作用: 检查是否以 root 用户运行,非 root 直接退出#----------------------------------------------------function check_root(){ if [ "$(id -u)" -ne 0 ]; then color 1 "错误: 请使用 root 用户或 sudo 运行此脚本!" color 1 "用法: sudo bash $0 install" exit 1 fi}
#----------------------------------------------------# 函数名: prepare# 作用: 下载 Prometheus 软件包(如果本地已经有就跳过下载,节省时间)#----------------------------------------------------function prepare(){ # download 目录不存在则创建 [ -d ${DOWNLOAD} ] || mkdir -p ${DOWNLOAD}
# 判断系统是否安装 wget if [ "$OS_VERSION" == "centos" ] || [ "$OS_VERSION" == "rhel" ] || [ "$OS_VERSION" == "rocky" ]; then rpm -qa | grep -q wget || yum -y install wget elif [ "$OS_VERSION" == "ubuntu" ] || [ "$OS_VERSION" == "debian" ]; then dpkg -l | grep -q wget || apt -y install wget fi
# 判断文件是否存在且非空,不存在才下载 if [ -s ${DOWNLOAD}/${SOFTWARE} ]; then echo "软件包已存在,跳过下载: ${DOWNLOAD}/${SOFTWARE}" else echo "正在下载 Prometheus v${PROM_VERSION} ..." wget -T 20 -t 3 ${URL} -O ${DOWNLOAD}/${SOFTWARE} if [ $? -ne 0 ]; then rm -f ${DOWNLOAD}/${SOFTWARE} color 1 "错误: 无法下载 ${SOFTWARE} ,请检查网络连接!" color 1 "下载地址: ${URL}" color 1 "提示: 若网络不佳,可先手动下载放到 ${DOWNLOAD}/ 目录" exit 100 fi echo "下载完成: ${SOFTWARE}" fi}
#================================# 第三部分: 安装函数#================================
function InstallPrometheus(){ echo "=========================================" echo " 开始安装 Prometheus v${PROM_VERSION}" echo "========================================="
# --- 第 1 步: 检查 root 权限 --- check_root
# --- 第 2 步: 准备环境 + 下载软件包 --- prepare
# --- 第 3 步: 解压到 /usr/local/ 并改名 --- echo "正在解压 Prometheus ..." tar xf ${DOWNLOAD}/${SOFTWARE} -C /usr/local/ mv /usr/local/${TMPDIR} /usr/local/prometheus echo "解压完成,目录已改名: /usr/local/prometheus"
# --- 第 4 步: 二进制 mv 到 /usr/local/bin/(全局命令) --- echo "正在移动二进制到 /usr/local/bin/ ..." mv /usr/local/prometheus/prometheus ${BIN_DIR}/ mv /usr/local/prometheus/promtool ${BIN_DIR}/ echo "二进制已安装: ${BIN_DIR}/prometheus ${BIN_DIR}/promtool"
# --- 第 5 步: 创建配置目录并移动配置文件 --- echo "正在配置目录与配置文件 ..." mkdir -p ${CONFIG_DIR} mv /usr/local/prometheus/prometheus.yml ${CONFIG_DIR}/ echo "配置文件已安装: ${CONFIG_DIR}/prometheus.yml"
# --- 第 6 步: 删除源目录(二进制和配置都已 mv 走,目录没用了) --- echo "正在删除源目录 ..." rm -rf /usr/local/prometheus
# --- 第 7 步: 创建数据与日志目录 --- # 数据目录: systemd 里 --storage.tsdb.path 指定 # 日志目录: systemd 里 &>> 重定向目标,不存在会导致启动失败 echo "正在创建数据与日志目录 ..." mkdir -p ${DATA_DIR} ${LOG_DIR} echo "数据目录: ${DATA_DIR}" echo "日志目录: ${LOG_DIR}"
# --- 第 8 步: 生成 systemd 服务文件 --- echo "正在生成 systemd 服务文件 ..." cat > ${SYSTEMD_DIR}/${SERVICE}.service <<EOF[Unit]# 服务描述Description=Prometheus Server# 官方文档地址Documentation=https://prometheus.io/docs/introduction/overview/# 等待网络就绪后再启动After=network-online.target# 主动声明依赖网络在线目标Wants=network-online.target
[Service]# 前台常驻进程:ExecStart 拉起即算成功(不 fork 不后台化)Type=simple# 异常退出时自动重启Restart=on-failure# 重启间隔 3 秒RestartSec=3# 文件描述符上限,防止高并发连接数超出LimitNOFILE=65535# 启动命令(bash -c 包裹,日志重定向到文件)# ⚠️ 必须包 /bin/bash -c:systemd 直接 exec 二进制不经 shell,&>> 会被当参数报错ExecStart=/bin/bash -c "${BIN_DIR}/prometheus \ --config.file=${CONFIG_DIR}/prometheus.yml \ --web.enable-lifecycle \ --storage.tsdb.path=${DATA_DIR} \ --storage.tsdb.retention.time=60d \ --storage.tsdb.retention.size=512MB \ --web.listen-address=${HOSTIP}:${PORT} \ --web.max-connections=65535 \ --web.read-timeout=5m \ --query.timeout=10s \ --query.max-concurrency=20 \ --log.level=info \ --log.format=json \ &>> ${LOG_DIR}/prometheus.log"# ⚠️ 不用 ExecReload!ExecStart 是 bash -c,SIGHUP 会杀掉 bash 导致进程树全灭# 热加载只能走 HTTP API: curl -X POST http://localhost:9090/-/reload
[Install]# 开机自启WantedBy=multi-user.targetEOF echo "systemd 服务文件已生成: ${SYSTEMD_DIR}/${SERVICE}.service"
# --- 第 9 步: 启动服务并设置开机自启 --- systemctl daemon-reload systemctl enable --now ${SERVICE} &> /dev/null echo "服务已启动并设置为开机自启"
# --- 第 10 步: 验证安装结果 --- sleep 2 if [ "$(systemctl is-active ${SERVICE})" == "active" ]; then color 2 "" color 2 "=========================================" color 2 " 安装成功!Prometheus v${PROM_VERSION} 已运行" color 2 "=========================================" color 2 "" echo "服务状态: $(systemctl is-active ${SERVICE})" echo "监听端口:" ss -lnt | grep ${PORT} || netstat -lnt | grep ${PORT} echo "" echo "WebUI 地址: http://${HOSTIP}:${PORT}/" echo "日志文件: ${LOG_DIR}/prometheus.log" echo "" echo "服务命令:" echo " 查看状态: systemctl status ${SERVICE}" echo " 重启服务: systemctl restart ${SERVICE}" echo " 热加载配置: curl -X POST http://localhost:${PORT}/-/reload" else color 1 "错误: 服务启动失败,请查看日志: ${LOG_DIR}/prometheus.log" exit 1 fi}
#==================# 第四部分: 卸载函数#==================
function RemovePrometheus(){ echo "=========================================" echo " 开始卸载 Prometheus" echo "========================================="
# --- 第 1 步: 检查 root 权限 --- check_root
# --- 第 2 步: 停止服务并禁用开机自启 --- echo "正在停止服务并取消开机自启 ..." systemctl disable --now ${SERVICE} &> /dev/null
# --- 第 3 步: 删除 systemd 服务文件 --- echo "正在删除 systemd 服务文件 ..." rm -f ${SYSTEMD_DIR}/${SERVICE}.service
# --- 第 4 步: 删除二进制文件 --- echo "正在删除二进制文件 ..." rm -f ${BIN_DIR}/prometheus ${BIN_DIR}/promtool
# --- 第 5 步: 删除配置/数据/日志目录 --- echo "正在删除配置、数据、日志目录 ..." rm -rf ${CONFIG_DIR} ${DATA_DIR} ${LOG_DIR}
# --- 第 6 步: 重新加载 systemd 配置 --- systemctl daemon-reload
# --- 第 7 步: 验证卸载结果 --- echo "" color 4 "卸载完成!以下内容已清除:" echo " - ${SYSTEMD_DIR}/${SERVICE}.service" echo " - ${BIN_DIR}/prometheus ${BIN_DIR}/promtool" echo " - ${CONFIG_DIR} ${DATA_DIR} ${LOG_DIR}" echo "软件包保留: ${DOWNLOAD}/${SOFTWARE}" echo ""}
#=============================# 第五部分: 主函数 —— 脚本的入口#=============================
function main(){ case $1 in install|i) InstallPrometheus ;; remove|r) RemovePrometheus ;; *) echo "用法: $0 {install|i|remove|r}" echo "" echo " 示例:" echo " 安装: $0 install" echo " 卸载: $0 remove" echo " 简写: $0 i (安装)" echo " 简写: $0 r (卸载)" ;; esac}
# 调用 main 函数,把命令行的第一个参数传进去main $1Prometheus 监控 Linux 主机

node-exporter 是 Prometheus 官方开源的一款用来暴露 Linux 系统指标的组件 包括但不限于 CPU、内存、磁盘、网络、文件系统、负载情况等
部署 node-exporter(node1/2/3 三台)
1)下载软件包(官方源)jiuzhao@Ubuntu ~$ wget -P /home/jiuzhao/下载 https://github.com/prometheus/node_exporter/releases/download/v1.12.1/node_exporter-1.12.1.linux-amd64.tar.gzjiuzhao@Ubuntu ~$ scp /home/jiuzhao/下载/node_exporter-1.12.1.linux-amd64.tar.gz node1:/tmp# 三台节点都进行拷贝
2)解压并复制二进制到 /usr/local/bin/[root@node1 ~]# tar xf /tmp/node_exporter-1.12.1.linux-amd64.tar.gz -C /usr/local/[root@node1 ~]# ls /usr/local/node_exporter-1.12.1.linux-amd64/LICENSE node_exporter NOTICE[root@node1 ~]# mv /usr/local/node_exporter-1.12.1.linux-amd64/node_exporter /usr/local/bin/'node2 / node3 执行相同操作'[root@node1 ~]# rm -rf /usr/local/node_exporter-1.12.1.linux-amd64/# 源文件什么都没有了
3)编写 systemd 服务文件(三台一样)[root@node1 ~]# cat > /etc/systemd/system/node-exporter.service <<"EOF"[Unit]# 服务描述Description=Kpyun Linux Node Exporter# 官方文档地址Documentation=https://prometheus.io/docs/introduction/overview/# 等待网络就绪后再启动After=network-online.target# 主动声明依赖网络在线目标Wants=network-online.target
[Service]# 前台常驻进程:ExecStart 拉起即算成功(不 fork 不后台化)Type=simple# 异常退出时自动重启Restart=on-failure# 重启间隔 3 秒RestartSec=3# 文件描述符上限,防止高并发连接数超出LimitNOFILE=65535# 启动命令(metrics 路径显式指定 + 监听地址端口)ExecStart=/usr/local/bin/node_exporter \ --web.telemetry-path="/metrics" \ --web.listen-address=0.0.0.0:9100
[Install]# 开机自启WantedBy=multi-user.targetEOF
4)启动并验证[root@node1 ~]# systemctl daemon-reload && systemctl enable --now node-exporter[root@node1 ~]# systemctl is-active node-exporteractive[root@node1 ~]# journalctl -u node-exporter | tail -1msg="TLS is disabled." http2=false address=[::]:9100`这个日志只是陈述状态:告知你"我监听在 9100,用的是 HTTP 明文,没开 TLS 加密"`# node-exporter 默认不启用 TLS——它是内网采集指标用的,用 HTTP 明文就够了[root@node1 ~]# node_exporter --versionnode_exporter, version 1.12.1 build user: root@3a6b59999579 build date: 20260714-12:05:11 go version: go1.26.5 platform: linux/amd64 tags: unknown✅️ node1/2/3 三台 node-exporter 全部 active💡 node-exporter 不需要单独的数据目录和重定向日志文件
- node-exporter 是无状态的纯采集器,它只是读取系统指标并暴露在 /metrics,自己不存储任何数据
- 数据被 Prometheus server 拉走,存到 Prometheus 的
/var/lib/prometheus
- 数据被 Prometheus server 拉走,存到 Prometheus 的
- 只输出几行启动日志,量极小,走 journald(
journalctl -u node-exporter)足够 --web.telemetry-path="/metrics"显式指定
🌰 什么是”无状态”? 无状态 = 程序自己不保存任何持久化数据,每次都是”现读现报”,干完活什么都不留下
- node-exporter 读的是内核
/proc、/sys暴露的实时系统信息(CPU 用了多少、内存剩多少) - 每次请求
/metrics都是”现读现报” - 进程一关,什么都不留下;重启后从零开始,不记得以前
- 所以它不需要
/var/lib/node_exporter数据目录
类比:node-exporter 像体温测量仪(只报数不记录),Prometheus 像病历本(把每次拉的指标存进 /var/lib/prometheus)
✨脚本部署 node-exporter
三台 node 重复手动部署太繁琐,对标 prometheus 的一键脚本,编写 install-node-exporter.sh 实现一键安装 / 卸载
# 目录结构(脚本 + 软件包 + 下载目录)autoinstall-node-exporter/├── install-node-exporter.sh # 安装脚本(可执行)└── download/ └── node_exporter-1.12.1.linux-amd64.tar.gz # 软件包(安装后保留,卸载不清)
1)一键安装(node1/2/3 各跑一次)[root@node1 ~]# bash install-node-exporter.sh install========================================= 开始安装 Node Exporter v1.12.1=========================================软件包已存在,跳过下载: ./download/node_exporter-1.12.1.linux-amd64.tar.gz正在解压 Node Exporter ...解压完成,目录已改名: /usr/local/node_exporter正在移动二进制到 /usr/local/bin/ ...二进制已安装: /usr/local/bin/node_exporter正在删除源目录 ...正在生成 systemd 服务文件 ...systemd 服务文件已生成: /etc/systemd/system/node-exporter.service服务已启动并设置为开机自启
========================================= 安装成功!Node Exporter v1.12.1 已运行=========================================
服务状态: active监听端口:LISTEN 0 4096 *:9100 *:*Metrics 地址: http://0.0.0.0:9100/metrics
服务命令: 查看状态: systemctl status node-exporter 查看日志: journalctl -u node-exporter -f 重启服务: systemctl restart node-exporter
2)验证三台全部 active[root@node1 ~]# systemctl is-active node-exporteractive✅️ node1/2/3 三台全部 active
3)一键卸载(只清部署痕迹,脚本和软件包保留)[root@node1 ~]# bash install-node-exporter.sh remove========================================= 开始卸载 Node Exporter=========================================正在停止服务并取消开机自启 ...正在删除 systemd 服务文件 ...正在删除二进制文件 ...
卸载完成!以下内容已清除: - /etc/systemd/system/node-exporter.service - /usr/local/bin/node_exporter软件包保留: ./download/node_exporter-1.12.1.linux-amd64.tar.gz脚本完整内容
#!/bin/bash#================================# 作者: 久棹# 用途: 在 Linux 上自动安装/卸载 Node Exporter(二进制方式)# 适用系统: CentOS 7/8/9, Rocky, Ubuntu 18.04+, Debian 10+ 等 systemd 系统#================================
#================================# 第一部分: 定义变量#================================
# --- Node Exporter 相关配置 ---# 注意: 变量名用 NODE_EXPORTER_VERSION,避免与 /etc/os-release 里的 VERSION 冲突NODE_EXPORTER_VERSION=1.12.1# 系统架构ARCH=amd64# 压缩包文件名SOFTWARE=node_exporter-${NODE_EXPORTER_VERSION}.linux-${ARCH}.tar.gz# GitHub 下载地址URL=https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/${SOFTWARE}
# --- 本地目录 ---DOWNLOAD=./download# 解压后的临时目录名(复用 ARCH 变量)TMPDIR=node_exporter-${NODE_EXPORTER_VERSION}.linux-${ARCH}# systemd 服务文件存放路径SYSTEMD_DIR=/etc/systemd/system# systemd 服务名SERVICE=node-exporter
# --- 安装路径配置(mv 方案,无软链接) ---BIN_DIR=/usr/local/bin
# --- 服务监听配置 ---HOSTIP=0.0.0.0PORT=9100HOSTNAME=`hostname`
# 加载操作系统 ID 变量,用于判断系统类型. /etc/os-releaseOS_VERSION=$ID
#================================# 第二部分: 工具函数#================================
# 颜色变量RED='\e[31m'GREEN='\e[32m'YELLOW='\e[33m'BLUE='\e[34m'RESET='\e[0m'
# 彩色输出(color 1 "文本",1红 2绿 3黄 4蓝)function color(){ local c=$RESET case $1 in 1) c=$RED ;; 2) c=$GREEN ;; 3) c=$YELLOW ;; 4) c=$BLUE ;; esac shift echo -e "${c}$@${RESET}"}
# 检查 root 权限function check_root(){ if [ "$(id -u)" -ne 0 ]; then color 1 "错误: 请使用 root 用户或 sudo 运行此脚本!" color 1 "用法: sudo bash $0 install" exit 1 fi}
# 下载软件包(已有跳过)function prepare(){ [ -d ${DOWNLOAD} ] || mkdir -p ${DOWNLOAD} if [ "$OS_VERSION" == "centos" ] || [ "$OS_VERSION" == "rhel" ] || [ "$OS_VERSION" == "rocky" ]; then rpm -qa | grep -q wget || yum -y install wget elif [ "$OS_VERSION" == "ubuntu" ] || [ "$OS_VERSION" == "debian" ]; then dpkg -l | grep -q wget || apt -y install wget fi if [ -s ${DOWNLOAD}/${SOFTWARE} ]; then echo "软件包已存在,跳过下载: ${DOWNLOAD}/${SOFTWARE}" else echo "正在下载 Node Exporter v${NODE_EXPORTER_VERSION} ..." wget -T 20 -t 3 ${URL} -O ${DOWNLOAD}/${SOFTWARE} if [ $? -ne 0 ]; then rm -f ${DOWNLOAD}/${SOFTWARE} color 1 "错误: 无法下载 ${SOFTWARE} ,请检查网络连接!" color 1 "提示: 若网络不佳,可先手动下载放到 ${DOWNLOAD}/ 目录" exit 100 fi echo "下载完成: ${SOFTWARE}" fi}
#================================# 第三部分: 安装函数#================================
function InstallNodeExporter(){ echo "=========================================" echo " 开始安装 Node Exporter v${NODE_EXPORTER_VERSION}" echo "========================================="
# 1. 检查 root 权限 check_root # 2. 准备环境 + 下载软件包 prepare # 3. 解压并改名 echo "正在解压 Node Exporter ..." tar xf ${DOWNLOAD}/${SOFTWARE} -C /usr/local/ mv /usr/local/${TMPDIR} /usr/local/node_exporter # 4. 二进制 mv 到 /usr/local/bin/ echo "正在移动二进制到 /usr/local/bin/ ..." mv /usr/local/node_exporter/node_exporter ${BIN_DIR}/ # 5. 删除源目录 echo "正在删除源目录 ..." rm -rf /usr/local/node_exporter # 6. 生成 systemd 服务文件 echo "正在生成 systemd 服务文件 ..." cat > ${SYSTEMD_DIR}/${SERVICE}.service <<EOF[Unit]Description=Kpyun Linux Node ExporterDocumentation=https://prometheus.io/docs/introduction/overview/After=network-online.targetWants=network-online.target
[Service]Type=simpleRestart=on-failureRestartSec=3LimitNOFILE=65535ExecStart=${BIN_DIR}/node_exporter \ --web.telemetry-path="/metrics" \ --web.listen-address=${HOSTIP}:${PORT}
[Install]WantedBy=multi-user.targetEOF # 7. 启动服务并设置开机自启 systemctl daemon-reload systemctl enable --now ${SERVICE} &> /dev/null echo "服务已启动并设置为开机自启" # 8. 验证安装结果 sleep 2 if [ "$(systemctl is-active ${SERVICE})" == "active" ]; then color 2 "=========================================" color 2 " 安装成功!Node Exporter v${NODE_EXPORTER_VERSION} 已运行" color 2 "=========================================" echo "服务状态: $(systemctl is-active ${SERVICE})" echo "监听端口:" ss -lnt | grep ${PORT} || netstat -lnt | grep ${PORT} echo "" echo "Metrics 地址: http://${HOSTIP}:${PORT}/metrics" echo "服务命令:" echo " 查看状态: systemctl status ${SERVICE}" echo " 查看日志: journalctl -u ${SERVICE} -f" echo " 重启服务: systemctl restart ${SERVICE}" else color 1 "错误: 服务启动失败,请查看日志: journalctl -u ${SERVICE}" exit 1 fi}
#==================# 第四部分: 卸载函数#==================
function RemoveNodeExporter(){ echo "=========================================" echo " 开始卸载 Node Exporter" echo "=========================================" # 1. 检查 root 权限 check_root # 2. 停止服务并禁用开机自启 systemctl disable --now ${SERVICE} &> /dev/null # 3. 删除 systemd 服务文件 rm -f ${SYSTEMD_DIR}/${SERVICE}.service # 4. 删除二进制文件 rm -f ${BIN_DIR}/node_exporter # 5. 重新加载 systemd systemctl daemon-reload # 6. 验证卸载结果 echo "" color 4 "卸载完成!以下内容已清除:" echo " - ${SYSTEMD_DIR}/${SERVICE}.service" echo " - ${BIN_DIR}/node_exporter" echo "软件包保留: ${DOWNLOAD}/${SOFTWARE}" echo ""}
#=============================# 第五部分: 主函数#=============================
function main(){ case $1 in install|i) InstallNodeExporter ;; remove|r) RemoveNodeExporter ;; *) echo "用法: $0 {install|i|remove|r}" echo "" echo " 示例:" echo " 安装: $0 install" echo " 卸载: $0 remove" echo " 简写: $0 i (安装)" echo " 简写: $0 r (卸载)" ;; esac}
main $1访问 node-exporter 的 metrics
1)从 Prom 服务器拉取被监控机的指标root@Prom ~# cat >> /etc/hosts << 'EOF'10.0.0.2 node110.0.0.11 node210.0.0.12 node3EOF
root@Prom ~# for h in node{1..3}; do echo "=== $h ===" curl -s http://$h:9100/metrics | wc -l curl -s http://$h:9100/metrics | grep -m1 "^node_boot_time_seconds" done# -m 是 --max-count 的缩写,它的作用是限制匹配的输出行数# -m1,它的含义是:只要 grep 找到第一个匹配的行,就立即停止读取该文件,并输出这一行=== node1 ===1274node_boot_time_seconds 1.786327974e+09=== node2 ===1274node_boot_time_seconds 1.786327975e+09=== node3 ===1274node_boot_time_seconds 1.786327977e+09✅️ 每台暴露 1274 行系统指标Prometheus 配置监控 Linux 主机
1)修改 prometheus.yml,追加 node-exporter 的 jobroot@Prom ~# vim /etc/prometheus/prometheus.ymlscrape_configs: ... - 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"] # 后端地址 # 注意缩进
2)热加载配置文件root@Prom ~# curl -X POST http://10.0.0.10:9090/-/reload# systemd 里加了 --web.enable-lifecycle 才能热加载
3)查询 targets 状态root@Prom ~# curl -s "http://localhost:9090/api/v1/query" --data-urlencode "query=up" | jq -r ".data.result[] | \"\(.metric.job) | \(.metric.instance) | \(.value[1])\""prometheus | localhost:9090 | 1kpyun-node-exporter | 10.0.0.2:9100 | 1kpyun-node-exporter | 10.0.0.11:9100 | 1kpyun-node-exporter | 10.0.0.12:9100 | 1# value=1 表示该 target 采集正常 ✅️WebUI 查看:http://10.0.0.10:9090/targets kpyun-node-exporter 全部 UP

PromQL 语句初体验
PromQL(Prometheus Query Language)是 Prometheus 自带的查询语言
[root@node1 ~]# curl -sS localhost:9100/metrics | grep -A3 node_boot_time'node-exporter 暴露的 metrics 是 Prometheus 文本格式,每个指标由三部分组成:'# HELP node_boot_time_seconds || Node boot time, in unixtime.(节点启动时间,Unix 时间戳)`HELP:帮助信息,描述这个指标是干什么的`# TYPE node_boot_time_seconds || gauge(当前值,所见即所得)`TYPE:数据类型(gauge/counter/histogram/summary)`node_boot_time_seconds 1.786327974e+09`指标名 + 当前值`带标签的指标示例:
node_cpu_seconds_total{cpu="0",mode="idle"} 597.72# └─ 标签{key="value"} ─┘- 指标名:
node_boot_time_seconds,命名规范命名空间_子系统_指标名 - 标签:
{cpu="0",mode="idle"},用于区分不同维度(哪颗 CPU、哪种模式) - 值:数值,具体含义由 TYPE 决定(gauge 是当前值,counter 是累加计数)
Prometheus 的四大数据类型
| 类型 | 含义 | 典型指标/场景 |
|---|---|---|
| gauge | 当前值,所见即所得 | node_boot_time_seconds 节点启动时间 |
| counter | 单调递增计数器 | prometheus_http_requests_total 请求总数,配 rate() 看 QPS |
| histogram | 直方图样本观测 | 请求持续时间、响应时间,配 histogram_quantile() 算分位值 |
| summary | 分位数直接计算结果 | 类似 histogram,但分位值在客户端算好 |
💡 重点掌握 gauge 和 counter(最常用),histogram/summary 了解概念即可
1)gauge 类型:当前值,所见即所得# 查询:直接输指标名,回车即返回当前值node_boot_time_seconds# 结果:每个节点一行,gauge 就是当前这一刻的值,启动时间不会自己增加10.0.0.2:9100 = 178624639510.0.0.11:9100 = 178624647710.0.0.12:9100 = 1786246477- 使用自带的
WebUI进行查询
2)counter 类型:单调递增计数器,只涨不降# ① 请求总数(累计值):/metrics 接口被访问了多少次prometheus_http_requests_total{handler="/metrics"}# 结果:1501
# ② 所有接口请求总数(sum 聚合)sum(prometheus_http_requests_total)# 结果:1622
# ③ QPS:rate(指标[1m]) = 最近 60 秒平均每秒请求数(counter 最常用)# [1m] 是时间窗口,表示"最近一分钟"rate(prometheus_http_requests_total[1m])# 结果:每个接口各一行(带 handler 标签),有请求的才会显示/metrics = 0.067 req/s# 想看单个接口的 QPS:标签选择器要放在指标名后、[1m] 前!rate(prometheus_http_requests_total{handler="/metrics"}[1m])# 想看所有接口总 QPS:sum(rate(...))
# ④ 增量:increase(指标[1m]) = 最近 60 秒一共涨了多少次# 类似 rate 但结果是"次数"不是"速率"increase(prometheus_http_requests_total[1m])# 结果:每个接口各一行,如 /metrics = 4(最近 1 分钟涨了 4 次)rate(prometheus_http_requests_total{handler="/metrics"}[1m])📌 counter 为什么配 rate(),而不是直接看值?
直接查 counter 得到的是累计总数(一个跑了 3 个月的进程可能有几百万),看不出”现在忙不忙”
rate(counter[1m]) 把最近 1 分钟平均一下 → 才知道当前每秒多少请求(QPS),这才是运维关心的
3)histogram 类型:平均访问时间(了解即可)# histogram 自带 _sum(总耗时)和 _count(总次数),相除 = 平均耗时prometheus_http_request_duration_seconds_sum / prometheus_http_request_duration_seconds_count# 结果:每个接口各一行(带 handler 标签),如 /metrics = 0.0033s# 想只看单个接口:加 {handler="/metrics"} 过滤prometheus_http_request_duration_seconds_sum{handler="/metrics"} / prometheus_http_request_duration_seconds_count{handler="/metrics"}
4)histogram 分位值:95 分位延迟(了解即可)# histogram_quantile(0.95, ...):算出 95% 的请求延迟在多少秒以内histogram_quantile(0.95, sum(rate(prometheus_http_request_duration_seconds_bucket[5m])) by (le))# 结果:0.095💡 为什么要用分位值,而不是平均值?
假设 12<30>30>~12<35>35> 大面积服务无法响应,其余时间正常
用平均值算,5 分钟延迟被 24 小时平均后可以忽略不计,运维发现不了故障
histogram_quantile() 只采样短时间范围,能及时暴露毛刺 → 分位值比平均值更能发现问题
PromQL 常见操作符
1)精确匹配(指定 instance + cpu)node_cpu_seconds_total{instance="10.0.0.11:9100",cpu="0"}
2)正则匹配(mode=~"i.*" 匹配 idle/iowait/irq...)node_cpu_seconds_total{instance="10.0.0.11:9100",cpu="0",mode=~"i.*"}# 结果:命中 idle / iowait / irq
3)精确取反(cpu!="0" 排除 cpu0)node_cpu_seconds_total{instance="10.0.0.11:9100",cpu!="0",mode=~"i.*"}# 结果:只剩 cpu1
4)正则取反(mode!~"i.*" 排除 i 开头的模式)node_cpu_seconds_total{instance="10.0.0.11:9100",cpu="0",mode!~"i.*"}# 结果:剩 nice / softirq / steal / system / user(idle/iowait/irq 被排除)
5)算术运算(Prometheus 自带计算器)100/510+20💡 操作符 5 种,WebUI 查询框直接粘贴即可
| 操作符 | 含义 | 例子 |
|---|---|---|
= | 精确匹配 | cpu="0" |
=~ | 正则匹配 | mode=~"i.*" |
!= | 精确排除 | cpu!="0" |
!~ | 正则排除 | mode!~"i.*" |
+ - * / | 算术运算 | 100/5 |
PromQL 常见函数(stress 压测实战)
💡 压力测试 node2
1)node2 安装 stress[root@node2 ~]# dnf install -y epel-release[root@node2 ~]# dnf install -y stress[root@node2 ~]# stress --versionstress 1.0.7
2)启动压测(并发 CPU + IO + 内存,跑 20 分钟)[root@node2 ~]# stress --cpu 4 --io 2 --vm 1 --vm-bytes 128M --timeout 20m--cpu 4 # 启动 4 个进程疯狂计算(超配也无妨)--io 2 # 启动 2 个进程疯狂读写--vm 1 # 启动 1 个进程分配内存--vm-bytes 128M # 每个 vm 进程分配 128M 内存--timeout 20m # 压测持续 20 分钟后自动停止# 压测期间观察 node2 CPU 飙高
3)压测时 node2 系统负载[root@node2 ~]# top -bn1 | head -4-b # 不进入交互界面-n1 # 输出一次快照后立即退出%Cpu(s): 59.3 us, 40.7 sy, 0.0 ni, 0.0 id, 0.0 wa, ...✅️ idle 归零,CPU 被打满💡 计算 CPU 使用率
1)等待 Prometheus 采集 1 分钟后,计算各节点 CPU 使用率(1 - sum(increase(node_cpu_seconds_total{mode="idle"}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)) * 100# 结果:node2(10.0.0.11) 被 stress 打满,CPU 使用率 100%10.0.0.2:9100 = 0.307584146234285410.0.0.11:9100 = 10010.0.0.12:9100 = 0.21954860806182586✅️ PromQL 函数正确反映真实压测状态!📌 公式拆解
CPU 时间被拆成多种 mode(idle 空闲 / user 用户态 / system 内核态 / iowait 等待 IO…) CPU 每一秒要么在干活、要么在发呆,所以”1 − 发呆占比 = 干活占比 = 使用率”
| 片段 | 含义 |
|---|---|
increase(metric[1m]) | 1 分钟内该指标的增量 |
sum(...) by (instance) | 按节点(by)聚合所有 CPU 核(sum) |
mode="idle" | CPU 的空闲时间片 |
1 - idle/总量 | 非空闲占比 = CPU 使用率 |
× 100 | 小数转百分比(0.8 → 80%) |
💡 每个节点的运行时长
1)运行时长(分钟)# node_boot_time_seconds 是"启动时间戳"(节点开机那一刻的 Unix 时间,gauge 不随时间变)# time() 是"当前时间戳",两者相减 = 该节点已运行了多久(uptime)(time() - node_boot_time_seconds) / 60# /60:秒 → 分钟(运行了多少分钟)# 结果:每个节点已运行多少分钟10.0.0.2:9100 = 665.710.0.0.11:9100 = 665.610.0.0.12:9100 = 665.6
2)想显示为小时:/3600(秒 → 小时)(time() - node_boot_time_seconds) / 3600# 结果:每个节点已运行多少小时10.0.0.2:9100 = 11.1💡 Prometheus WebUI 的两个痛点
- 临时性:查询数据是临时的,关闭页面重新打开后并不会保存,该页面主要用来临时调试
- 学习成本:需要学习 PromQL 语法,新手比较痛苦
综上所述,Prometheus 的 WebUI 对新手学习并不友好 → 因此需要 Grafana 图形化展示
图形化展示 Prometheus 数据
Grafana 是一款开源的图形化展示工具,支持从多个数据源读取数据 包括但不限于 Prometheus、MySQL、ElasticSearch、PostgreSQL 等主流数据库
- 官方链接:https://grafana.com/get/
- OSS —> Grafana(download)

Grafana 环境安装(Prom 服务器,Ubuntu 系统)
1)安装依赖包root@Prom ~# apt-get install -y adduser libfontconfig1 musl# Grafana .deb 包的依赖
2)下载 grafana enterpriseroot@Prom ~# cd /server/pkgs/root@Prom /server/pkgs]# wget https://dl.grafana.com/grafana-enterprise/release/13.1.3/grafana-enterprise_13.1.3_31135815010_linux_amd64.deb
3)安装root@Prom ~# dpkg -i grafana-enterprise_13.1.3_31135815010_linux_amd64.deb
4)启动 grafana-serverroot@Prom ~# systemctl enable --now grafana-serverroot@Prom ~# ss -lnt | grep 3000LISTEN 0 4096 *:3000 *:*✅️ 3000 端口已监听访问 Grafana WebUI
📌 WebUI 地址:http://10.0.0.10:3000/
默认用户名密码均为 admin,首次登录会提示修改密码

1)通过 API 修改密码(也可 WebUI 手动改)root@Prom ~# curl -s -u admin:admin -X PUT http://localhost:3000/api/user/password \ -H "Content-Type: application/json" \ -d '{"oldPassword":"admin","newPassword":"kpyun123"}'{"message":"User password changed"}
2)重置密码# 停止 Grafana(CLI 需要独占数据库)root@Prom ~# systemctl stop grafana-server
# 清空登录失败记录root@Prom ~# sqlite3 /var/lib/grafana/grafana.db "DELETE FROM login_attempt;"
# 重置 admin 密码root@Prom ~# grafana-cli --homepath /usr/share/grafana admin reset-admin-password kpyun123# 输出类似: Admin password updated successfully ✔
# 启动 Grafanaroot@Prom ~# systemctl start grafana-server
# 验证root@Prom ~# curl -s -u admin:kpyun123 "http://localhost:3000/api/org" | jq -r ".name"Main Org. `稍微等一会才行~`
3)删除 admin 用户让 Grafana 重建root@Prom ~# systemctl stop grafana-server
# 清空登录失败记录root@Prom ~# sqlite3 /var/lib/grafana/grafana.db "DELETE FROM login_attempt;"
# 删除 admin 用户root@Prom ~# sqlite3 /var/lib/grafana/grafana.db "DELETE FROM user WHERE login='admin';"
# 启动 Grafanaroot@Prom ~# systemctl start grafana-server`启动后会自动创建 admin 用户,默认密码 admin`
# 验证root@Prom ~# curl -s -u admin:admin "http://localhost:3000/api/org" | jq{ "id": 1, "name": "Main Org.", "address": { "address1": "", "address2": "", "city": "", "zipCode": "", "state": "", "country": "" }}
配置 Prometheus 数据源

WebUI 操作路径:连接 → 添加新连接 → 搜索 → Prometheus → 添加新的数据源 → 填 URL http://10.0.0.10:9090 → Save & Test
验证数据源连通性(走 Grafana 代理查 Prometheus)# 新版用 health API 验证连通性:/api/datasources/uid/{uid}/health
1)动态拿 uidroot@Prom ~# Prom_UID=$(curl -s -u admin:kpyun123 "http://localhost:3000/api/datasources" | jq -r ".[0].uid")
2)用 health API 验证root@Prom ~# curl -s -u admin:kpyun123 "http://localhost:3000/api/datasources/uid/$Prom_UID/health" | jq -r ".status"OK✅️ 数据源已连接导入第三方 Dashboard


- 查询模板ID 站点:https://grafana.com/grafana/dashboards
WebUI 操作路径(Grafana 13.x):
(1)顶部菜单 仪表盘 → 新建 → Import dashboard

(2)上传 JSON 文件 或者 填模板 ID 1860 → 点 Load(加载) → 选数据源 prometheus → Import

Prometheus 监控主流中间件
监控 Windows 主机

- exporters 列表链接:直接
Ctrl + F搜索即可

- GitHub 项目地址:https://github.com/prometheus-community/windows_exporter
- Prometheus 社区为 Windows 系统提供的 exporter,暴露 CPU/内存/磁盘/网络/进程等指标
1)被监控端(Windows)下载运行 windows_exporter# cmd 窗口运行,默认暴露 9182 端口http://<Windows-IP>:9182/metrics

2)Prometheus server 配置监控目标root@Prom ~# vim /etc/prometheus/prometheus.yml... - job_name: "kpyun-windows-exporter" # job 名称自定义 metrics_path: "/metrics" # 被监控路径 scheme: "http" # 协议 static_configs: - targets: ["192.168.18.15:9182"] # 注意缩进
3)热加载配置文件 + targets 验证root@Prom ~# curl -X POST http://10.0.0.10:9090/-/reloadroot@Prom ~# curl -s "http://localhost:9090/api/v1/query" --data-urlencode "query=up" | jq -r ".data.result[] | \"\(.metric.job) | \(.metric.instance) | \(.value[1])\"" | grep windowskpyun-windows-exporter | 192.168.18.15:9182 | 1
4)Grafana 导入模板 ID23847 / 21697
监控 Zookeeper 集群
1️⃣ ZK 启用 metrics 接口(7000 端口)
1)修改 zoo.cfg,追加 Prometheus Metrics Exporter 配置root@Elk01 ~# vim /usr/local/apache-zookeeper-3.8.6-bin/conf/zoo.cfg...# https://prometheus.io Metrics ExportermetricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvidermetricsProvider.httpHost=0.0.0.0metricsProvider.httpPort=7000metricsProvider.exportJvmInfo=true
2)同步配置文件到其他节点root@Elk01 ~# scp /usr/local/apache-zookeeper-3.8.6-bin/conf/zoo.cfg 10.0.0.7:/usr/local/apache-zookeeper-3.8.6-bin/conf/root@Elk01 ~# scp /usr/local/apache-zookeeper-3.8.6-bin/conf/zoo.cfg 10.0.0.8:/usr/local/apache-zookeeper-3.8.6-bin/conf/
3)三台重启 zookeeperroot@Elk01 ~# systemctl restart zookeeperroot@Elk02 ~# systemctl restart zookeeperroot@Elk03 ~# systemctl restart zookeeper
4)验证 7000 端口root@Elk01 ~# ss -lnt | grep 7000LISTEN 0 50 *:7000 *:*✅️ 三台 7000 全部监听2️⃣ 访问 ZK 的 metrics
1)验证 metrics 暴露root@Prom ~# curl -s http://10.0.0.6:7000/metrics | wc -l756root@Prom ~# curl -s http://10.0.0.6:7000/metrics | head -5# HELP follower_sync_time follower_sync_time# TYPE follower_sync_time summaryfollower_sync_time{quantile="0.5",} NaNfollower_sync_time_count 2.0follower_sync_time_sum 64.0✅️ ZK 指标正常暴露3️⃣ Prometheus 配置监控 ZK
1)prometheus.yml 追加 zookeeper jobroot@Prom ~# vim /etc/prometheus/prometheus.yml - job_name: "kpyun-zookeeper-cluster" static_configs: metrics_path: "/metrics" scheme: "http" - targets: - 10.0.0.6:7000 - 10.0.0.7:7000 - 10.0.0.8:7000
2)热加载 + 验证root@Prom ~# curl -X POST http://10.0.0.10:9090/-/reloadroot@Prom ~# curl -s "http://localhost:9090/api/v1/query" --data-urlencode "query=up" | jq -r ".data.result[] | \"\(.metric.job) | \(.metric.instance) | \(.value[1])\"" | grep zookeeperkpyun-zookeeper-cluster | 10.0.0.6:7000 | 1kpyun-zookeeper-cluster | 10.0.0.7:7000 | 1kpyun-zookeeper-cluster | 10.0.0.8:7000 | 1
3)Grafana 导入模板 ID:10465(ZooKeeper by Prometheus)✅️ ZK 监控完成
监控 Kafka 集群
1️⃣ 启动 Kafka 集群
1)三台启动 Kafka(Elk01/02/03 已装 Kafka 3.9.2 ZK 模式)root@Elk01 ~# kafka-server-start.sh -daemon $KAFKA_HOME/config/server.propertiesroot@Elk01 ~# systemctl status kafka● kafka.service - Apache Kafka Server Loaded: loaded (/etc/systemd/system/kafka.service; enabled; preset: enabled) Active: active (running) since Tue 2026-08-11 20:21:40 CST;`补充了一个systemd服务文件`root@Elk01 ~# ss -lnt | grep 9092LISTEN 0 50 *:9092 *:*# 三台都执行,Kafka 9092 全部监听 ✅️2️⃣ 部署 kafka-exporter

- GitHub 项目地址:https://github.com/danielqsj/kafka_exporter
1)下载并解压 kafka_exporter(官方源)root@Elk01 ~# mkdir -p /server/pkgs/ && cd /server/pkgs/root@Elk01 /server/pkgs# wget https://github.com/danielqsj/kafka_exporter/releases/download/v1.9.0/kafka_exporter-1.9.0.linux-amd64.tar.gz
2)解压二进制到 /usr/local/bin/root@Elk01 ~# tar tf /server/pkgs/kafka_exporter-1.9.0.linux-amd64.tar.gzkafka_exporter-1.9.0.linux-amd64/ # 目录kafka_exporter-1.9.0.linux-amd64/LICENSE # 证书kafka_exporter-1.9.0.linux-amd64/kafka_exporter # 只有这个有用root@Elk01 ~# tar xf /server/pkgs/kafka_exporter-1.9.0.linux-amd64.tar.gz -C /usr/local/bin/ kafka_exporter-1.9.0.linux-amd64/kafka_exporter --strip-components=1`解压 Kafka Exporter 并直接提取可执行文件到目标目录`# 只解压压缩包内的这一个文件(而不是全部文件)--strip-components=1 # 去掉路径中的第一级目录root@Elk01 ~# ls /usr/local/bin/ | grep kafka_exporter
3)编写 systemd 服务(只需在 1 台机器上部署,如 Elk01)root@Elk01 ~# cat > /etc/systemd/system/kafka_exporter.service <<"EOF"[Unit]Description=Kafka ExporterAfter=network-online.target
[Service]Type=simpleExecStart=/usr/local/bin/kafka_exporter --kafka.version="3.9.2" --kafka.server=10.0.0.6:9092 --web.listen-address=":9308" --web.telemetry-path="/metrics"# --kafka.version: 匹配 Kafka 版本号,避免不兼容告警# --kafka.server: 指定任意一个 broker 即可,exporter 自动发现集群Restart=on-failure
[Install]WantedBy=multi-user.targetEOF
4)启动并验证root@Elk01 ~# systemctl daemon-reload && systemctl enable --now kafka_exporterroot@Elk01 ~# ss -lnt | grep 9308LISTEN 0 4096 *:9308 *:*✅️ 9308 已监听📌 监控 Kafka 集群,只需部署 1 个 exporter 即可
kafka_exporter 和 systemd 服务都只在一台机器上部署(这里选 Elk01),不需要每台 broker 都装
原理:--kafka.server=10.0.0.6:9092 只要指定任意一个 broker,exporter 会自动发现整个集群的所有 broker
| 对比 | node-exporter | kafka_exporter |
|---|---|---|
| 部署数量 | 每台被监控机都要装(3 台) | 整个集群只装 1 个(1 台) |
| 监控对象 | 单机自身的系统指标 | 整个 Kafka 集群的 broker/topic/消费组 |
| 原因 | node-exporter 无状态,只暴露本机数据 | exporter 通过 broker 发现整个集群 |
验证:部署 1 个 exporter 后,kafka_brokers 3 → 说明它已经看到了全部 3 个 broker
systemd 服务同理:kafka_exporter.service 只在一台机器上存在,Prometheus 也只需配置 1 个 target(10.0.0.6:9308)
3️⃣ 验证 kafka-exporter 与配置监控
1)访问 kafka metricsroot@Prom ~# curl -s http://10.0.0.6:9308/metrics | grep -E "^kafka_brokers|^kafka_topic_partitions" | head -5kafka_brokers 3kafka_topic_partitions{topic="__consumer_offsets"} 50kafka_topic_partitions{topic="kpyun-test"} 1✅️ 检测到 3 个 broker,topic 分区信息齐全
2)prometheus.yml 追加 kafka jobroot@Prom ~# vim /etc/prometheus/prometheus.yml - job_name: "kpyun-kafka-exporter" metrics_path: "/metrics" scheme: "http" static_configs: - targets: - 10.0.0.6:9308
3)热加载 + 验证root@Prom ~# curl -X POST http://10.0.0.10:9090/-/reloadroot@Prom ~# curl -s "http://localhost:9090/api/v1/query" --data-urlencode "query=up" | jq -r ".data.result[] | \"\(.metric.job) | \(.metric.instance) | \(.value[1])\"" | grep kafkakpyun-kafka-exporter | 10.0.0.6:9308 | 1
4)Grafana 导入模板 ID:21078(KAFKA Dashboard CN)、7589(Kafka Exporter Overview)✅️ Kafka 监控完成
监控 ElasticSearch 集群

📌 exporter 与 ES 集群的关系(中介模式)
exporter 的作用:把 ES 集群的各种指标(健康状态、节点、索引、分片…)暴露到一个 HTTP 接口 /metrics,供 Prometheus 拉取
为什么要经过 exporter,不能直接监控 ES? 因为 Prometheus 不能直接访问 ES 集群(ES 的 API 是 JSON 格式、还带认证),而 exporter 负责:
- ① 连接 ES 集群(
--es.uri=https://elastic:passwd@10.0.0.7:9200) - ② 把 ES 的内部指标翻译成 Prometheus 能识别的
/metrics文本格式 - ③ 暴露在独立端口(如
:9114),等 Prometheus 来拉
监控链路:
关键:监控时不能指定 ES 集群端口,而是指定 exporter 暴露的端口
# ❌ 错误:直接指 ES 集群端口(Prometheus 读不懂 JSON,也过不了认证)targets: ["10.0.0.7:9200"]
# ✅ 正确:指 exporter 暴露的 /metrics 端口(中介翻译好了)targets: ["10.0.0.7:9114"]🌰 类比:exporter 就像房屋中介——你想找房东(ES 数据),但你不能直接闯进房东家(ES 认证/格式不兼容)
中介(exporter)替你对接房东,把房源信息整理成统一格式,你只需要找中介(访问 /metrics)就行
同样的道理适用于所有 exporter:node-exporter(Linux 系统)、kafka_exporter(Kafka 集群)、cadvisor(Docker 容器)——它们都是”被监控对象 → Prometheus”之间的翻译官
1️⃣ 检查 ES 集群状态
1)验证 ES 集群(本环境 ES7 HTTPS + 账号认证)root@Prom ~# curl -s -u elastic:passwd -k https://10.0.0.6:9200/_cat/nodes10.0.0.6 62 61 1 0.05 0.06 0.07 cdfhilmrstw - Elk0110.0.0.8 73 60 1 0.10 0.10 0.08 cdfhilmrstw * Elk0310.0.0.7 76 43 2 0.00 0.00 0.00 cdfhilmrstw - Elk02✅️ 三节点 ES 集群正常2️⃣ 部署 elasticsearch-exporter
1)下载并解压 elasticsearch_exporter(官方源)root@Elk02 ~# cd /server/pkgs/root@Elk02 /server/pkgs# wget https://github.com/prometheus-community/elasticsearch_exporter/releases/download/v1.11.0/elasticsearch_exporter-1.11.0.linux-amd64.tar.gz
2)解压二进制root@Elk02 ~# tar tf /server/pkgs/elasticsearch_exporter-1.11.0.linux-amd64.tar.gz......elasticsearch_exporter-1.11.0.linux-amd64/elasticsearch_exporter`同理只有这个对我们有用`root@Elk02 ~# tar xf /server/pkgs/elasticsearch_exporter-1.11.0.linux-amd64.tar.gz -C /usr/local/bin/ elasticsearch_exporter-1.11.0.linux-amd64/elasticsearch_exporter --strip-components=1root@Elk02 ~# ls /usr/local/bin/ | grep elasticsearch_exporter
3)编写 systemd 服务(ES 是 HTTPS + 账号认证)root@Elk02 ~# cat > /etc/systemd/system/es_exporter.service <<"EOF"[Unit]Description=Elasticsearch ExporterAfter=network-online.target
[Service]Type=simpleExecStart=/usr/local/bin/elasticsearch_exporter --es.uri="https://elastic:passwd@10.0.0.7:9200" --web.listen-address=":9114" --web.telemetry-path="/metrics" --es.ssl-skip-verify# --es.uri: 账号:密码@任意一个 ES 节点# --es.ssl-skip-verify: 跳过 HTTPS 证书校验(自签证书)Restart=on-failure
[Install]WantedBy=multi-user.targetEOF
4)启动并验证root@Elk02 ~# systemctl daemon-reload && systemctl enable --now es_exporterroot@Elk02 ~# ss -lnt | grep 9114LISTEN 0 4096 *:9114 *:*✅️ 9114 已监听📌 ES 集群也是只需部署 1 个 exporter 即可
和 Kafka 一样,ES exporter 只部署在一台节点(这里选 Elk02),透过它看到整个集群的状态
原理:--es.uri 指定任意一个 ES 节点,ES 的集群级 API(health/nodes 等)在任何节点查询都返回整个集群的信息
# 在 Elk02 上查到的就是整个集群的状态elasticsearch_cluster_health_status{cluster="My-Elk",color="green"} 1elasticsearch_cluster_health_number_of_data_nodes{cluster="My-Elk"} 3# 👆 3 = 整个集群 3 个数据节点,不只是 Elk02 自己生产环境怎么监控? 也是部署 1 个即可(连任意一个 ES 节点) 集群很大时也可以多部署几个做冗余/负载均衡(Prometheus 配多个 target),但不是必需——1 个就能反映集群全貌
3️⃣ 验证与配置监控
1)访问 ES metrics(集群健康状态)root@Prom ~# curl -s http://10.0.0.7:9114/metrics | grep "^elasticsearch_cluster_health_status"elasticsearch_cluster_health_status{cluster="My-Elk",color="green"} 1elasticsearch_cluster_health_status{cluster="My-Elk",color="red"} 0elasticsearch_cluster_health_status{cluster="My-Elk",color="yellow"} 0✅️ 集群绿色,无红色和黄色故障
2)prometheus.yml 追加 es jobroot@Prom ~# vim /etc/prometheus/prometheus.yml - job_name: "kpyun-es-exporter" metrics_path: "/metrics" scheme: "http" static_configs: - targets: - 10.0.0.7:9114
3)热加载 + 验证root@Prom ~# curl -X POST http://10.0.0.10:9090/-/reloadroot@Prom ~# curl -s "http://localhost:9090/api/v1/query" --data-urlencode "query=up" | jq -r ".data.result[] | \"\(.metric.job) | \(.metric.instance) | \(.value[1])\"" | grep eskpyun-es-exporter | 10.0.0.7:9114 | 1
4)Grafana 导入模板 ID:14191(Elasticsearch Exporter Quickstart and Dashboard)✅️ ES 监控完成
监控 Docker(cadvisor)

- GitHub 项目地址:https://github.com/google/cadvisor
1️⃣ 部署 cadvisor
cadvisor(Container Advisor)是 Google 开源的容器资源监控工具,负责暴露 Docker 容器的 CPU/内存/网络指标
cadvisor 官方提供两种获取方式:
- ① 直接拉取官方镜像
gcr.io/cadvisor/cadvisor-amd64(国内被墙,需配代理) - ② 下载编译好的二进制,自己
docker build成镜像(✅️ 本篇采用,天然避开 gcr.io)
1)Ubuntu 桌面下载 cAdvisor 二进制(编译好的可执行文件,不是源码)jiuzhao@Ubuntu 下载$ file cadvisor-v0.60.5-linux-amd64cadvisor-v0.60.5-linux-amd64: ELF 64-bit LSB executable, x86-64, statically linked# 静态链接的 ELF,不依赖任何运行库,直接拷进镜像就能跑
2)编写 Dockerfile(把二进制封进精简基础镜像)jiuzhao@Ubuntu 下载$ mkdir -p cadvisor-image && cd ./cadvisor-imagejiuzhao@Ubuntu cadvisor-image$ mv ../cadvisor-v0.60.5-linux-amd64 ./cadvisor && chmod +x ./cadvisorjiuzhao@Ubuntu cadvisor-image$ cat > Dockerfile <<"EOF"FROM alpine:3.20# 精简基础镜像,镜像体积最小COPY cadvisor /usr/bin/cadvisor# 把二进制拷进镜像EXPOSE 8080# 对外暴露监控端口HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ CMD wget -q -O /dev/null http://localhost:8080/healthz || exit 1# 健康检查:访问 /healthz,失败则标记 unhealthyENTRYPOINT ["cadvisor"]# 容器启动直接执行 cadvisorEOF'容器跑起来 = 这个二进制跑起来,所以只需一个 ENTRYPOINT'
3)构建镜像jiuzhao@Ubuntu cadvisor-image$ sudo docker build -t cadvisor:0.60.5 $(pwd)-t cadvisor:0.60.5 # 指定 镜像名:标签...Successfully built 688fa4f0720cSuccessfully tagged cadvisor:0.60.5✅️ 镜像构建成功
4)导出镜像(save → tar.gz)jiuzhao@Ubuntu 下载$ sudo docker save cadvisor:0.60.5 > cadvisor-0.60.5.tar.gzjiuzhao@Ubuntu 下载$ ls -lh cadvisor-0.60.5.tar.gz-rw-rw-r-- 1 jiuzhao jiuzhao 22M Aug 12 09:46 cadvisor-0.60.5.tar.gz'拿到这个文件,任何装了 docker 的机器都能用'
5)传给 Docker 虚拟机并导入(load 是 save 的逆操作)jiuzhao@Ubuntu 下载$ scp cadvisor-0.60.5.tar.gz Docker:/rootroot@Docker ~# docker load -i cadvisor-0.60.5.tar.gzLoaded image: cadvisor:0.60.5# load 把 tar.gz 还原成镜像,与 save 一一对应root@Docker ~# docker images | grep cadvisorREPOSITORY IMAGE ID CREATED SIZEcadvisor:0.60.5 688fa4f0720c 70.1MB 22.5MB✅️ 镜像导入成功,和官方 gcr.io 镜像用法完全一致'自己构建的镜像,再也不依赖 gcr.io,天然避开拉镜像被墙的问题'3️⃣ 运行测试容器(制造监控对象)
1)运行测试容器root@Docker ~# docker run -d -it --name c1 alpine:3.20.2root@Docker ~# docker ps -aCONTAINER ID IMAGE STATUS NAMES010732f721e7 alpine:3.20.2 Up 3 seconds c15ac200763fb4 wordpress Up 16 seconds wp1d1ed7bd3880 mysql Up 16 seconds db✅️ Docker VM 已有运行中的容器2️⃣ 运行 cadvisor
1)运行 cadvisor 容器(挂载主机关键目录,18080 映射到容器 8080)root@Docker ~# docker run \ --volume=/:/rootfs:ro \ --volume=/var/run:/var/run:ro \ --volume=/sys:/sys:ro \ --volume=/var/lib/docker/:/var/lib/docker:ro \ --volume=/dev/disk/:/dev/disk:ro \ -p 18080:8080 \ --detach=true \ --name=cadvisor \ --privileged \ --device=/dev/kmsg \ --restart=unless-stopped \ cadvisor:0.60.5 \ --docker_only=true \ --containerd=/var/run/docker/containerd/containerd.sock \ --store_container_labels=true📌 cadvisor 的运行参数拆解
cadvisor = 一台”只读会计”——它不自己开账本,而是靠挂载宿主机目录去”借账本”读数据
① 一堆 --volume 是 cadvisor 的”眼睛”(每个都 :ro 只读,读完就暴露到 /metrics,自己不存):
| 挂载 | 相当于 cadvisor 在偷看什么 |
|---|---|
--volume=/:/rootfs:ro | 整个宿主机文件系统(系统概况) |
--volume=/var/run:/var/run:ro | docker 运行时 socket(知道有哪些容器在跑) |
--volume=/sys:/sys:ro | 内核信息(CPU/内存使用率) |
--volume=/var/lib/docker/:...:ro | docker 存储目录(容器磁盘占用) |
--volume=/dev/disk/:/dev/disk:ro | 磁盘设备(磁盘 IO) |
② 熟悉的选项(和普通 docker 一样):
| 选项 | 等价写法 | 作用 |
|---|---|---|
-p 18080:8080 | 端口映射 | 宿主 18080 → 容器 8080 |
--detach=true | -d | 后台运行 |
--name=cadvisor | 容器名 | |
--restart=unless-stopped | 开机自启 |
③ 两个权限选项(cadvisor 特有):
| 选项 | 作用 |
|---|---|
--privileged | 特权模式:要读宿主机 /sys /proc 等敏感内核信息,必须开 |
--device=/dev/kmsg | 把宿主内核日志设备挂进容器,读内核消息(不加会报警告) |
④ 三个 Docker 集成参数( 💡自构建 cadvisor 必加,关键):
| 选项 | 作用 |
|---|---|
--docker_only=true | 只监控 Docker 容器,过滤宿主机 cgroup 噪音 |
--containerd=...containerd.sock | 核心参数:cadvisor 通过 Docker 内置 containerd socket 发现容器;⚠️Docker 29.x 的 containerd.sock 在 /var/run/docker/containerd/不指定 → cadvisor 找默认 /run/containerd/containerd.sock → 找不到 → 容器读不到(模板无数据) |
--store_container_labels=true | 保留容器标签(image/name),供 Grafana 模板使用 |
🌰 一句话记忆:cadvisor = 只读会计——5 个 --volume 借宿主机的账本(系统/容器/CPU/磁盘),--privileged 给特殊权限能翻敏感账本,--containerd 是拿到”容器清单”的门钥匙,-p 18080 是报表窗口
2)验证容器与端口root@Docker ~# docker ps | grep cadvisorcadvisor:0.60.5 "cadvisor --docker_o…" Up ... 0.0.0.0:18080->8080/tcp cadvisor
3)访问 cadvisor metricsroot@Docker ~# curl -s http://10.0.0.9:18080/metrics | wc -l3285✅️ cadvisor 暴露约 3285 行容器指标
http://10.0.0.9:18080/

3️⃣ Prometheus 配置监控 Docker
1)prometheus.yml 追加 cadvisor jobroot@Prom ~# vim /etc/prometheus/prometheus.yml - job_name: "kpyun-docker-cadvisor" metrics_path: "/metrics" scheme: "http" static_configs: - targets: - 10.0.0.9:18080
2)热加载 + 验证root@Prom ~# curl -X POST http://10.0.0.10:9090/-/reloadroot@Prom ~# curl -s "http://localhost:9090/api/v1/query" --data-urlencode "query=up" | jq -r ".data.result[] | \"\(.metric.job) | \(.metric.instance) | \(.value[1])\"" | grep dockerkpyun-docker-cadvisor | 10.0.0.9:18080 | 1
3)Grafana 导入模板 ID:10619(Docker Container & Host Metrics)✅️ Docker 监控完成
💡 cadvisor 面板不显示数据的优化案例
- Running containers 优化:
count(last_over_time(container_last_seen{image!=""}[30s]))- ⚠️ 时间窗口必须 ≥ Prometheus 的
scrape_interval(15s)才有样本
- ⚠️ 时间窗口必须 ≥ Prometheus 的
- 将面板的
Calculation(计算)字段设置为Last *即可 - 保存 Dashboard:若不保存,刷新页面后所有配置丢失!

📌 模板 10619 的节点级面板显示 “无数据” 是正常的
模板 10619 是”容器 + 节点”两层监控:
- 容器级面板(CPU/Memory per Container)用 cadvisor 的
container_*指标 → ✅ 正常显示 - 节点级面板(CPU Usage on Node / Available Memory / Free Disk / System Load)用
node_*指标(来自 node-exporter)→ ⚠️ 没装 node-exporter 就显示 “无数据”
Prometheus 监控服务的流程

📌 Prometheus 监控服务完整流程
(1)被监控端需要暴露 metrics 指标(装 exporter) (2)prometheus server 端配置要监控的目标(prometheus.yml 加 job、服务发现) (3)热加载配置文件(curl -X POST /-/reload) (4)检查 Prometheus WebUI 验证配置是否生效(targets UP) (5)grafana 导入模板 ID (6)grafana 的 Dashboard 出图展示 (7)配置相应的告警规则(Alertmanager)
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!















