Prometheus监控 & Grafana可视化

11728 字
59 分钟
Prometheus监控 & Grafana可视化
Prometheus监控 & Grafana可视化

Prometheus监控 && Grafana可视化#

[TOC]


环境规划#

我们完成了 ElasticStack 全链路 + Kafka 集群的部署 本篇落地 Prometheus 监控体系,覆盖 Linux 主机与主流中间件

虚拟机IP配置角色
Prom10.0.0.102C/2GPrometheus server + Grafana
node110.0.0.22C/2Gnode-exporter 被监控机
node210.0.0.112C/2Gnode-exporter 被监控机 + stress 压测机
node310.0.0.122C/2Gnode-exporter 被监控机
Elk0110.0.0.62C/2GZK + Kafka + ES 监控目标
Elk0210.0.0.72C/2GZK + Kafka + ES 监控目标 + ES exporter
Elk0310.0.0.82C/2GZK + Kafka + ES 监控目标
Docker10.0.0.92C/3Gcadvisor 容器监控
Note

📌 主机说明

  • Prom / node1 / node2 / node3 为本篇新建:Prom 走 Ubuntu 云镜像,node 系列走 Rocky.img 传统镜像路线
  • Elk01/02/03 与 Docker VM 复用之前章节的机器,本篇只往上面装 exporter

Prometheus 架构图解#

官网介绍
官网介绍

Prometheus架构图解
Prometheus架构图解

Prometheus 是一款开源的监控系统,可以监控主流的中间件、操作系统、硬件设备、网络设备等 相比 zabbix,Prometheus 的强项是对容器和微服务的监控更加方便

  • 2012 年产品问世,2016 年加入 CNCF,是 CNCF 第二个毕业项目
  • 采用 Go 语言编写

push 数据

钉钉/企微/邮箱

拉取数据源

拉取 metrics

拉取 metrics

拉取 metrics

拉取 metrics

接收 push

用户

Prometheus Server

采集+存储+查询

Alertmanager

告警

Grafana

Dashboard展示

node-exporter

Linux指标

Kafka exporter

消息队列

ES exporter

搜索引擎

cadvisor

容器指标

Pushgateway

自定义监控

push 数据

钉钉/企微/邮箱

拉取数据源

拉取 metrics

拉取 metrics

拉取 metrics

拉取 metrics

接收 push

用户

Prometheus Server

采集+存储+查询

Alertmanager

告警

Grafana

Dashboard展示

node-exporter

Linux指标

Kafka exporter

消息队列

ES exporter

搜索引擎

cadvisor

容器指标

Pushgateway

自定义监控

相关组件的作用#

组件作用
Prometheus Server① 采集目标数据 ② 存储到本地或远端数据库 ③ 提供 WebUI 查询接口
Grafana将 Prometheus 作为数据源,提供 Dashboard 数据展示
Pushgateway自定义监控,支持无法被主动抓取的任务
Alertmanager告警功能,支持钉钉、企业微信、邮箱等
exporters被监控端,负责暴露各类指标

二进制部署 Prometheus#

版本下载
版本下载

Terminal window
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 ~/.bashrc
root@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/prometheus
LICENSE NOTICE prometheus prometheus.yml promtool
root@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/prometheus
root@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/prometheus
root@Prom ~# prometheus --version
prometheus, 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.2

systemd 托管#

① 编写 systemd 服务文件#

Terminal window
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.target
EOF

② 服务文件参数详解#

参数含义默认值
--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数据体积上限 512MB0(不限制)
--web.max-connections=65535最大并发连接数512
--web.read-timeout=5mHTTP 读超时5m
--query.timeout=10s查询超时2m
--query.max-concurrency=20最大并发查询20
--log.level=info日志级别info
--log.format=json日志格式logfmt
Important

Prometheus 二进制自己就是前台常驻进程,敲下去就一直占住终端 所以用 Type=simple——systemd 拉起即成功,不用猜、不用等 ⚠️ 若误配 forking,systemd 会傻等一个不存在的 fork 子进程 → 启动超时

Warning

⚠️ 热加载只能用 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

③ 启动并验证#

Terminal window
1)创建数据与日志目录(systemd 参数里指定的路径)
root@Prom ~# mkdir -p /var/lib/prometheus /var/log/prometheus
'数据目录: --storage.tsdb.path 指定; 日志目录: &>> 重定向目标, 不存在会导致启动失败'
2)重载 + 启动 + 开机自启
root@Prom ~# systemctl daemon-reload
root@Prom ~# systemctl enable --now prometheus
root@Prom ~# systemctl is-active prometheus
active
3)验证端口
root@Prom ~# ss -lnt | grep 9090
LISTEN 0 4096 *:9090 *:*
✅️ 9090 端口已监听
4)查看日志(文件方案)
root@Prom ~# tail -f /var/log/prometheus/prometheus.log
Starting rule manager...

数据目录#

Terminal window
1)验证默认数据目录(不带参数启动会建在哪)
root@Prom ~# prometheus --help | grep -i 'storage\.tsdb\.path'
--storage.tsdb.path="data/"
# 官方默认:当前目录下的 data/ 子目录
Important

📌 结论:数据目录是 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#

Important

📌 WebUI 地址:http://10.0.0.10:9090/

Prometheus WebUI 首页
Prometheus WebUI 首页

Terminal window
1)健康检查
root@Prom ~# curl -s http://localhost:9090/-/healthy
Prometheus 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 脚本实现一键安装 / 卸载

Terminal window
# 目录结构(脚本 + 软件包 + 下载目录)
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一键卸载只清部署痕迹,保留脚本和软件包
Terminal window
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# ls
download install-prometheus-server.sh
root@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
Tip

💡 卸载保留设计:remove 只清理”部署产物”(服务/二进制/配置/数据/日志) 保留”安装材料”(脚本 + download 里的软件包)→ 下次 install 直接复用,免下载

脚本完整内容#

install-prometheus-server.sh
#!/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 变量,避免硬编码 amd64
TMPDIR=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.0
PORT=9090
# 主机名(安装完成提示用)
HOSTNAME=`hostname`
# 加载操作系统的 ID 变量(如 centos、ubuntu),用于判断系统类型
. /etc/os-release
OS_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.target
EOF
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 $1

Prometheus 监控 Linux 主机#

node-exporter 是 Prometheus 官方开源的一款用来暴露 Linux 系统指标的组件 包括但不限于 CPU、内存、磁盘、网络、文件系统、负载情况等

部署 node-exporter(node1/2/3 三台)#

Terminal window
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.gz
jiuzhao@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.target
EOF
4)启动并验证
[root@node1 ~]# systemctl daemon-reload && systemctl enable --now node-exporter
[root@node1 ~]# systemctl is-active node-exporter
active
[root@node1 ~]# journalctl -u node-exporter | tail -1
msg="TLS is disabled." http2=false address=[::]:9100
`这个日志只是陈述状态:告知你"我监听在 9100,用的是 HTTP 明文,没开 TLS 加密"`
# node-exporter 默认不启用 TLS——它是内网采集指标用的,用 HTTP 明文就够了
[root@node1 ~]# node_exporter --version
node_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
Note

💡 node-exporter 不需要单独的数据目录和重定向日志文件

  • node-exporter 是无状态的纯采集器,它只是读取系统指标并暴露在 /metrics,自己不存储任何数据
    • 数据被 Prometheus server 拉走,存到 Prometheus 的 /var/lib/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 实现一键安装 / 卸载

Terminal window
# 目录结构(脚本 + 软件包 + 下载目录)
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-exporter
active
✅️ 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

脚本完整内容#

install-node-exporter.sh
#!/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.0
PORT=9100
HOSTNAME=`hostname`
# 加载操作系统 ID 变量,用于判断系统类型
. /etc/os-release
OS_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 Exporter
Documentation=https://prometheus.io/docs/introduction/overview/
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
Restart=on-failure
RestartSec=3
LimitNOFILE=65535
ExecStart=${BIN_DIR}/node_exporter \
--web.telemetry-path="/metrics" \
--web.listen-address=${HOSTIP}:${PORT}
[Install]
WantedBy=multi-user.target
EOF
# 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#

Terminal window
1)从 Prom 服务器拉取被监控机的指标
root@Prom ~# cat >> /etc/hosts << 'EOF'
10.0.0.2 node1
10.0.0.11 node2
10.0.0.12 node3
EOF
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 ===
1274
node_boot_time_seconds 1.786327974e+09
=== node2 ===
1274
node_boot_time_seconds 1.786327975e+09
=== node3 ===
1274
node_boot_time_seconds 1.786327977e+09
✅️ 每台暴露 1274 行系统指标

Prometheus 配置监控 Linux 主机#

Terminal window
1)修改 prometheus.yml,追加 node-exporter 的 job
root@Prom ~# vim /etc/prometheus/prometheus.yml
scrape_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 | 1
kpyun-node-exporter | 10.0.0.2:9100 | 1
kpyun-node-exporter | 10.0.0.11:9100 | 1
kpyun-node-exporter | 10.0.0.12:9100 | 1
# value=1 表示该 target 采集正常 ✅️
Tip

WebUI 查看:http://10.0.0.10:9090/targets kpyun-node-exporter 全部 UP

Prometheus targets 页面
Prometheus targets 页面


PromQL 语句初体验#

PromQL(Prometheus Query Language)是 Prometheus 自带的查询语言

Terminal window
[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
`指标名 + 当前值`
Note

带标签的指标示例:

Terminal window
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,但分位值在客户端算好
Tip

💡 重点掌握 gauge 和 counter(最常用),histogram/summary 了解概念即可

Terminal window
1)gauge 类型:当前值,所见即所得
# 查询:直接输指标名,回车即返回当前值
node_boot_time_seconds
# 结果:每个节点一行,gauge 就是当前这一刻的值,启动时间不会自己增加
10.0.0.2:9100 = 1786246395
10.0.0.11:9100 = 1786246477
10.0.0.12:9100 = 1786246477
Note
  • 使用自带的 WebUI 进行查询
Terminal window
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])
Important

📌 counter 为什么配 rate(),而不是直接看值?

直接查 counter 得到的是累计总数(一个跑了 3 个月的进程可能有几百万),看不出”现在忙不忙” rate(counter[1m]) 把最近 1 分钟平均一下 → 才知道当前每秒多少请求(QPS),这才是运维关心的

Terminal window
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
Note

💡 为什么要用分位值,而不是平均值?

假设 12<30>~12<35> 大面积服务无法响应,其余时间正常 用平均值算,5 分钟延迟被 24 小时平均后可以忽略不计,运维发现不了故障 histogram_quantile() 只采样短时间范围,能及时暴露毛刺 → 分位值比平均值更能发现问题

PromQL 常见操作符#

Terminal window
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/5
10+20
Tip

💡 操作符 5 种,WebUI 查询框直接粘贴即可

操作符含义例子
=精确匹配cpu="0"
=~正则匹配mode=~"i.*"
!=精确排除cpu!="0"
!~正则排除mode!~"i.*"
+ - * /算术运算100/5

PromQL 常见函数(stress 压测实战)#

💡 压力测试 node2

Terminal window
1)node2 安装 stress
[root@node2 ~]# dnf install -y epel-release
[root@node2 ~]# dnf install -y stress
[root@node2 ~]# stress --version
stress 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 使用率

Terminal window
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.3075841462342854
10.0.0.11:9100 = 100
10.0.0.12:9100 = 0.21954860806182586
✅️ PromQL 函数正确反映真实压测状态!
Note

📌 公式拆解

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%)

💡 每个节点的运行时长

Terminal window
1)运行时长(分钟)
# node_boot_time_seconds 是"启动时间戳"(节点开机那一刻的 Unix 时间,gauge 不随时间变)
# time() 是"当前时间戳",两者相减 = 该节点已运行了多久(uptime)
(time() - node_boot_time_seconds) / 60
# /60:秒 → 分钟(运行了多少分钟)
# 结果:每个节点已运行多少分钟
10.0.0.2:9100 = 665.7
10.0.0.11:9100 = 665.6
10.0.0.12:9100 = 665.6
2)想显示为小时:/3600(秒 → 小时)
(time() - node_boot_time_seconds) / 3600
# 结果:每个节点已运行多少小时
10.0.0.2:9100 = 11.1
Note

💡 Prometheus WebUI 的两个痛点

  • 临时性:查询数据是临时的,关闭页面重新打开后并不会保存,该页面主要用来临时调试
  • 学习成本:需要学习 PromQL 语法,新手比较痛苦

综上所述,Prometheus 的 WebUI 对新手学习并不友好 → 因此需要 Grafana 图形化展示


图形化展示 Prometheus 数据#

Grafana 是一款开源的图形化展示工具,支持从多个数据源读取数据 包括但不限于 Prometheus、MySQL、ElasticSearch、PostgreSQL 等主流数据库

13.1.3版本
13.1.3版本

Grafana 环境安装(Prom 服务器,Ubuntu 系统)#

Terminal window
1)安装依赖包
root@Prom ~# apt-get install -y adduser libfontconfig1 musl
# Grafana .deb 包的依赖
2)下载 grafana enterprise
root@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-server
root@Prom ~# systemctl enable --now grafana-server
root@Prom ~# ss -lnt | grep 3000
LISTEN 0 4096 *:3000 *:*
✅️ 3000 端口已监听

访问 Grafana WebUI#

Important

📌 WebUI 地址:http://10.0.0.10:3000/

默认用户名密码均为 admin,首次登录会提示修改密码

Grafana 登录页
Grafana 登录页

Terminal window
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 ✔
# 启动 Grafana
root@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';"
# 启动 Grafana
root@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": ""
}
}

更改语言 &#x26; 主题
更改语言 & 主题

配置 Prometheus 数据源#

Grafana 添加 Prometheus 数据源
Grafana 添加 Prometheus 数据源

Tip

WebUI 操作路径:连接 → 添加新连接 → 搜索 → Prometheus → 添加新的数据源 → 填 URL http://10.0.0.10:9090 → Save & Test

Terminal window
验证数据源连通性(走 Grafana 代理查 Prometheus)
# 新版用 health API 验证连通性:/api/datasources/uid/{uid}/health
1)动态拿 uid
root@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#

官方模板
官方模板

两种方式导入
两种方式导入

Tip

WebUI 操作路径(Grafana 13.x): (1)顶部菜单 仪表盘 → 新建 → Import dashboard

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

Node Exporter Full Dashboard 总览
Node Exporter Full Dashboard 总览


Prometheus 监控主流中间件#

监控 Windows 主机#

image-20260811162215880
image-20260811162215880

Terminal window
1)被监控端(Windows)下载运行 windows_exporter
# cmd 窗口运行,默认暴露 9182 端口
http://<Windows-IP>:9182/metrics

![](./Prom01/2026-08-11 171123.png)

Terminal window
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/-/reload
root@Prom ~# curl -s "http://localhost:9090/api/v1/query" --data-urlencode "query=up" | jq -r ".data.result[] | \"\(.metric.job) | \(.metric.instance) | \(.value[1])\"" | grep windows
kpyun-windows-exporter | 192.168.18.15:9182 | 1
4)Grafana 导入模板 ID
23847 / 21697

监控window主机
监控window主机

监控 Zookeeper 集群#

1️⃣ ZK 启用 metrics 接口(7000 端口)

Terminal window
1)修改 zoo.cfg,追加 Prometheus Metrics Exporter 配置
root@Elk01 ~# vim /usr/local/apache-zookeeper-3.8.6-bin/conf/zoo.cfg
...
# https://prometheus.io Metrics Exporter
metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider
metricsProvider.httpHost=0.0.0.0
metricsProvider.httpPort=7000
metricsProvider.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)三台重启 zookeeper
root@Elk01 ~# systemctl restart zookeeper
root@Elk02 ~# systemctl restart zookeeper
root@Elk03 ~# systemctl restart zookeeper
4)验证 7000 端口
root@Elk01 ~# ss -lnt | grep 7000
LISTEN 0 50 *:7000 *:*
✅️ 三台 7000 全部监听

2️⃣ 访问 ZK 的 metrics

Terminal window
1)验证 metrics 暴露
root@Prom ~# curl -s http://10.0.0.6:7000/metrics | wc -l
756
root@Prom ~# curl -s http://10.0.0.6:7000/metrics | head -5
# HELP follower_sync_time follower_sync_time
# TYPE follower_sync_time summary
follower_sync_time{quantile="0.5",} NaN
follower_sync_time_count 2.0
follower_sync_time_sum 64.0
✅️ ZK 指标正常暴露

3️⃣ Prometheus 配置监控 ZK

Terminal window
1)prometheus.yml 追加 zookeeper job
root@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/-/reload
root@Prom ~# curl -s "http://localhost:9090/api/v1/query" --data-urlencode "query=up" | jq -r ".data.result[] | \"\(.metric.job) | \(.metric.instance) | \(.value[1])\"" | grep zookeeper
kpyun-zookeeper-cluster | 10.0.0.6:7000 | 1
kpyun-zookeeper-cluster | 10.0.0.7:7000 | 1
kpyun-zookeeper-cluster | 10.0.0.8:7000 | 1
3)Grafana 导入模板 ID:10465(ZooKeeper by Prometheus)
✅️ ZK 监控完成

监控zookeeper集群
监控zookeeper集群

监控 Kafka 集群#

1️⃣ 启动 Kafka 集群

Terminal window
1)三台启动 Kafka(Elk01/02/03 已装 Kafka 3.9.2 ZK 模式)
root@Elk01 ~# kafka-server-start.sh -daemon $KAFKA_HOME/config/server.properties
root@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 9092
LISTEN 0 50 *:9092 *:*
# 三台都执行,Kafka 9092 全部监听 ✅️

2️⃣ 部署 kafka-exporter

kafka-exporter
kafka-exporter

Terminal window
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.gz
kafka_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 Exporter
After=network-online.target
[Service]
Type=simple
ExecStart=/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.target
EOF
4)启动并验证
root@Elk01 ~# systemctl daemon-reload && systemctl enable --now kafka_exporter
root@Elk01 ~# ss -lnt | grep 9308
LISTEN 0 4096 *:9308 *:*
✅️ 9308 已监听
Note

📌 监控 Kafka 集群,只需部署 1 个 exporter 即可

kafka_exporter 和 systemd 服务都只在一台机器上部署(这里选 Elk01),不需要每台 broker 都装 原理:--kafka.server=10.0.0.6:9092 只要指定任意一个 broker,exporter 会自动发现整个集群的所有 broker

对比node-exporterkafka_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 与配置监控

Terminal window
1)访问 kafka metrics
root@Prom ~# curl -s http://10.0.0.6:9308/metrics | grep -E "^kafka_brokers|^kafka_topic_partitions" | head -5
kafka_brokers 3
kafka_topic_partitions{topic="__consumer_offsets"} 50
kafka_topic_partitions{topic="kpyun-test"} 1
✅️ 检测到 3 个 broker,topic 分区信息齐全
2)prometheus.yml 追加 kafka job
root@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/-/reload
root@Prom ~# curl -s "http://localhost:9090/api/v1/query" --data-urlencode "query=up" | jq -r ".data.result[] | \"\(.metric.job) | \(.metric.instance) | \(.value[1])\"" | grep kafka
kpyun-kafka-exporter | 10.0.0.6:9308 | 1
4)Grafana 导入模板 ID:21078(KAFKA Dashboard CN)、7589(Kafka Exporter Overview)
✅️ Kafka 监控完成

监控kafka集群
监控kafka集群

监控 ElasticSearch 集群#

Important

📌 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 来拉

监控链路:

拉取 /metrics

翻译 ES 指标

Prometheus

elasticsearch_exporter

:9114

ES 集群

:9200 HTTPS+认证

拉取 /metrics

翻译 ES 指标

Prometheus

elasticsearch_exporter

:9114

ES 集群

:9200 HTTPS+认证

关键:监控时不能指定 ES 集群端口,而是指定 exporter 暴露的端口

Terminal window
# ❌ 错误:直接指 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 集群状态

Terminal window
1)验证 ES 集群(本环境 ES7 HTTPS + 账号认证)
root@Prom ~# curl -s -u elastic:passwd -k https://10.0.0.6:9200/_cat/nodes
10.0.0.6 62 61 1 0.05 0.06 0.07 cdfhilmrstw - Elk01
10.0.0.8 73 60 1 0.10 0.10 0.08 cdfhilmrstw * Elk03
10.0.0.7 76 43 2 0.00 0.00 0.00 cdfhilmrstw - Elk02
✅️ 三节点 ES 集群正常

2️⃣ 部署 elasticsearch-exporter

Terminal window
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=1
root@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 Exporter
After=network-online.target
[Service]
Type=simple
ExecStart=/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.target
EOF
4)启动并验证
root@Elk02 ~# systemctl daemon-reload && systemctl enable --now es_exporter
root@Elk02 ~# ss -lnt | grep 9114
LISTEN 0 4096 *:9114 *:*
✅️ 9114 已监听
Note

📌 ES 集群也是只需部署 1 个 exporter 即可

和 Kafka 一样,ES exporter 只部署在一台节点(这里选 Elk02),透过它看到整个集群的状态 原理:--es.uri 指定任意一个 ES 节点,ES 的集群级 API(health/nodes 等)在任何节点查询都返回整个集群的信息

Terminal window
# 在 Elk02 上查到的就是整个集群的状态
elasticsearch_cluster_health_status{cluster="My-Elk",color="green"} 1
elasticsearch_cluster_health_number_of_data_nodes{cluster="My-Elk"} 3
# 👆 3 = 整个集群 3 个数据节点,不只是 Elk02 自己

生产环境怎么监控? 也是部署 1 个即可(连任意一个 ES 节点) 集群很大时也可以多部署几个做冗余/负载均衡(Prometheus 配多个 target),但不是必需——1 个就能反映集群全貌

3️⃣ 验证与配置监控

Terminal window
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"} 1
elasticsearch_cluster_health_status{cluster="My-Elk",color="red"} 0
elasticsearch_cluster_health_status{cluster="My-Elk",color="yellow"} 0
✅️ 集群绿色,无红色和黄色故障
2)prometheus.yml 追加 es job
root@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/-/reload
root@Prom ~# curl -s "http://localhost:9090/api/v1/query" --data-urlencode "query=up" | jq -r ".data.result[] | \"\(.metric.job) | \(.metric.instance) | \(.value[1])\"" | grep es
kpyun-es-exporter | 10.0.0.7:9114 | 1
4)Grafana 导入模板 ID:14191(Elasticsearch Exporter Quickstart and Dashboard)
✅️ ES 监控完成

监控elasticsearch集群
监控elasticsearch集群

监控 Docker(cadvisor)#

1️⃣ 部署 cadvisor

cadvisor(Container Advisor)是 Google 开源的容器资源监控工具,负责暴露 Docker 容器的 CPU/内存/网络指标

cadvisor 官方提供两种获取方式:

  • ① 直接拉取官方镜像 gcr.io/cadvisor/cadvisor-amd64(国内被墙,需配代理)
  • ② 下载编译好的二进制,自己 docker build 成镜像(✅️ 本篇采用,天然避开 gcr.io)
Terminal window
1)Ubuntu 桌面下载 cAdvisor 二进制(编译好的可执行文件,不是源码)
jiuzhao@Ubuntu 下载$ file cadvisor-v0.60.5-linux-amd64
cadvisor-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-image
jiuzhao@Ubuntu cadvisor-image$ mv ../cadvisor-v0.60.5-linux-amd64 ./cadvisor && chmod +x ./cadvisor
jiuzhao@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,失败则标记 unhealthy
ENTRYPOINT ["cadvisor"]
# 容器启动直接执行 cadvisor
EOF
'容器跑起来 = 这个二进制跑起来,所以只需一个 ENTRYPOINT'
3)构建镜像
jiuzhao@Ubuntu cadvisor-image$ sudo docker build -t cadvisor:0.60.5 $(pwd)
-t cadvisor:0.60.5 # 指定 镜像名:标签
...
Successfully built 688fa4f0720c
Successfully tagged cadvisor:0.60.5
✅️ 镜像构建成功
4)导出镜像(save → tar.gz)
jiuzhao@Ubuntu 下载$ sudo docker save cadvisor:0.60.5 > cadvisor-0.60.5.tar.gz
jiuzhao@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:/root
root@Docker ~# docker load -i cadvisor-0.60.5.tar.gz
Loaded image: cadvisor:0.60.5
# load 把 tar.gz 还原成镜像,与 save 一一对应
root@Docker ~# docker images | grep cadvisor
REPOSITORY IMAGE ID CREATED SIZE
cadvisor:0.60.5 688fa4f0720c 70.1MB 22.5MB
✅️ 镜像导入成功,和官方 gcr.io 镜像用法完全一致
'自己构建的镜像,再也不依赖 gcr.io,天然避开拉镜像被墙的问题'

3️⃣ 运行测试容器(制造监控对象)

Terminal window
1)运行测试容器
root@Docker ~# docker run -d -it --name c1 alpine:3.20.2
root@Docker ~# docker ps -a
CONTAINER ID IMAGE STATUS NAMES
010732f721e7 alpine:3.20.2 Up 3 seconds c1
5ac200763fb4 wordpress Up 16 seconds wp
1d1ed7bd3880 mysql Up 16 seconds db
✅️ Docker VM 已有运行中的容器

2️⃣ 运行 cadvisor

Terminal window
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
Note

📌 cadvisor 的运行参数拆解

cadvisor = 一台”只读会计”——它不自己开账本,而是靠挂载宿主机目录去”借账本”读数据

① 一堆 --volume 是 cadvisor 的”眼睛”(每个都 :ro 只读,读完就暴露到 /metrics,自己不存):

挂载相当于 cadvisor 在偷看什么
--volume=/:/rootfs:ro整个宿主机文件系统(系统概况)
--volume=/var/run:/var/run:rodocker 运行时 socket(知道有哪些容器在跑)
--volume=/sys:/sys:ro内核信息(CPU/内存使用率)
--volume=/var/lib/docker/:...:rodocker 存储目录(容器磁盘占用)
--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 是报表窗口

Terminal window
2)验证容器与端口
root@Docker ~# docker ps | grep cadvisor
cadvisor:0.60.5 "cadvisor --docker_o…" Up ... 0.0.0.0:18080->8080/tcp cadvisor
3)访问 cadvisor metrics
root@Docker ~# curl -s http://10.0.0.9:18080/metrics | wc -l
3285
✅️ cadvisor 暴露约 3285 行容器指标
http://10.0.0.9:18080/

cadvisor Web页面
cadvisor Web页面

各种指标
各种指标

3️⃣ Prometheus 配置监控 Docker

Terminal window
1)prometheus.yml 追加 cadvisor job
root@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/-/reload
root@Prom ~# curl -s "http://localhost:9090/api/v1/query" --data-urlencode "query=up" | jq -r ".data.result[] | \"\(.metric.job) | \(.metric.instance) | \(.value[1])\"" | grep docker
kpyun-docker-cadvisor | 10.0.0.9:18080 | 1
3)Grafana 导入模板 ID:10619(Docker Container & Host Metrics)
✅️ Docker 监控完成

运行容器数
运行容器数

Note

💡 cadvisor 面板不显示数据的优化案例

  • Running containers 优化:count(last_over_time(container_last_seen{image!=""}[30s]))
    • ⚠️ 时间窗口必须 ≥ Prometheus 的 scrape_interval(15s)才有样本
  • 将面板的 Calculation(计算) 字段设置为 Last * 即可
  • 保存 Dashboard:若不保存,刷新页面后所有配置丢失!

监控docker
监控docker

Note

📌 模板 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
监控应用的流程Prometheus

Important

📌 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)

文章分享

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

相关文章智能推荐
1
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、变量、表格制作、备份与恢复
2
Prometheus存储实战 && HTTPS认证 && 黑盒监控
Prometheus监控VictoriaMetrics单机部署+remote_write远端存储,Prometheus启用HTTPS+Basic Auth认证,node-exporter黑白名单,标签管理(relabel/metric_relabel),blackbox-exporter HTTP/ICMP/TCP黑盒探测,Grafana存储迁移到MySQL
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
Zookeeper优化与Kafka集群实战
ES集群ZK JVM 调优与 zkUI 图形化管理,Kafka 消息队列单点/集群部署、生产者消费者验证、常用术语与脚本、消费者组 rebalance、丢数据原理(ISR/LEO/HW)、JVM 与参数优化、Kafbat UI 图形化管理
Profile Image of the Author
久棹
不是先学好了再干,而是先干起来再学习,干中学!
分类
站点统计
文章
115
分类
15
标签
272
总字数
306,562
运行时长
0 天
最后活动
0 天前
文章目录