目录
3、配置 Prometheus 连接 Alertmanager
一、软件包获取
1、prometheus 软件包获取

2、node_exporter 采集代理软件包获取

二、环境准备
1、主机清单
一共三台虚拟机,网络配置如下:
| 主机名 | IP | 监控情况 |
| openEuler100 | 192.168.254.100/24 | 监控服务+被监控主机 |
| openEuler101 | 192.168.254.101/24 | 被监控主机 |
| openEuler102 | 192.168.254.102/24 | 被监控主机 |
2、网络配置
三台都配置
su - root
vi /etc/sysconfig/network-scripts/ifcfg-ens33
# 更新如下内容,没有的新增,有的变更
# ip地址根据主机清单进行变更
################
BOOTPROTO=static
IPADDR=192.168.254.100
GATEWAY=192.168.254.2
NETMASK=255.255.255.0
DNS=8.8.8.8
################
# 重启网卡或者重启主机,使网络配置生效
systemctl restart NetworkManager
# 检查网络配置是否成功变更
ip a

3、关闭防火墙
三台都配置
su - root
systemctl stop firewalld
systemctl disable firewalld
# 查看防火墙是否关闭
systemctl status firewalld
4、关闭selinux
三台都配置
su - root
# 临时关闭 selinux
setenforce 0
# 永久关闭 SELinux(需要重启主机)
vi /etc/selinux/config
# 更改SELINUX
#############
SELINUX=disabled
#############
# 查看 selinux 状态
sestatus

5、配置主机名称和host配置
主机名称配置(三台都配置)
su - root
hostnamectl set-hostname 新主机名
hosts文件配置(三台都配置)
su - root
vi /etc/hosts
# hosts文件末尾加入如下配置
####################
192.168.254.100 openEuler100
192.168.254.101 openEuler101
192.168.254.102 openEuler102
####################
6、检查主机间的网络通信
确保3台主机间能相互 ping 通
ping openEuler100
ping openEuler101
ping openEuler102
7、创建用户和组
三台都操作
su - root
useradd prometheus
passwd prometheus
三、部署Prometheus
1、上传软件包
上传所需的软件包到 prometheus 账户根目录下。
node_exporter 的安装包上传到需要被监控的主机上,我这边三台主机都是被监控目标,所以三台主机都上传了。
prometheus 的安装包上传到要部署监控服务的主机上,我这边只有 openEuler 主机需要部署。
Prometheus 自身不采集主机级指标(如 CPU、内存、磁盘等),需依赖 node_exporter 提供这些数据。

2、prometheus 安装包解压
只在openEuler100主机上操作
su - prometheus
tar -zxvf prometheus-3.4.1.linux-amd64.tar.gz
mv prometheus-3.4.1.linux-amd64 prometheus
3、node_exporter 安装包解压
三台主机都操作
su - prometheus
tar -zxvf node_exporter-1.9.1.linux-amd64.tar.gz
mv node_exporter-1.9.1.linux-amd64 node_exporter
4、修改 prometheus.yml 配置文件
仅在 openEuler100 主机上操作
su - prometheus
cd /home/prometheus/prometheus
cp prometheus.yml prometheus.yml.bak
vi prometheus.yml
配置修改后如下:
# my global config
global:
scrape_interval: 15s # 服务状态拉取频率
evaluation_interval: 15s # 执行规则频率
# Alertmanager configuration
alerting:
alertmanagers:
- static_configs:
- targets:
# - alertmanager:9093
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
# - "first_rules.yml"
# - "second_rules.yml"
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
# 监控Prometheus服务状态
- job_name: "prometheus"
static_configs:
- targets: ["openEuler100:9090"]
labels:
app: "prometheus"
# 监控主机资源(需提前运行node_exporter)
- job_name: "node"
static_configs:
- targets:
- "openEuler100:9100"
- "openEuler101:9100"
- "openEuler102:9100"
labels:
app: "node"
5、prometheus 服务启动
openEuler100 主机上操作
su - prometheus
cd prometheus
mkdir logs
mkdir shell
mkdir run
# 编写一个启动脚本
vi shell/start.sh
chmod 75o start.sh
# 编写一个停止脚本
vi stop.sh
chmod 750 stop.sh
# 启动 prometheus 进程
sh /home/prometheus/prometheus/shell/start.sh
start.sh 内容如下:
#!/bin/bash
# 配置部分
PROM_USER="prometheus"
PROM_HOME="/home/prometheus"
PROM_BIN="$PROM_HOME/prometheus/prometheus"
CONFIG_FILE="$PROM_HOME/prometheus/prometheus.yml"
LOG_DIR="$PROM_HOME/prometheus/logs"
LOG_FILE="$LOG_DIR/prometheus.log"
PID_DIR="$PROM_HOME/prometheus/run"
PID_FILE="$PID_DIR/prometheus.pid"
init() {
# 检查日志目录是否存在
if [ ! -d ${LOG_DIR} ]; then
mkdir -p ${LOG_DIR}
fi
# 检查run目录是否存在
if [ ! -d ${PID_DIR} ]; then
mkdir -p ${PID_DIR}
fi
# 检查是否以prometheus用户运行
if [ "$(whoami)" != "$PROM_USER" ]; then
echo "错误:本脚本必须使用 $PROM_USER 用户执行!"
echo "请使用:sudo -u $PROM_USER $0"
exit 1
fi
# 检查程序是否已运行
if pgrep -u "$PROM_USER" -f "$PROM_BIN" >/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:Prometheus 已在运行!" | tee -a "$LOG_FILE"
exit 2
fi
# 检查必要文件
if [ ! -f "$PROM_BIN" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:可执行文件 $PROM_BIN 不存在!" | tee -a "$LOG_FILE"
exit 3
fi
if [ ! -f "$CONFIG_FILE" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:配置文件 $CONFIG_FILE 不存在!" | tee -a "$LOG_FILE"
exit 4
fi
}
prometheus_start() {
# 启动Prometheus
echo "============================================" >> "$LOG_FILE"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 正在启动 Prometheus..." | tee -a "$LOG_FILE"
cd "$PROM_HOME/prometheus" || exit 5
nohup "$PROM_BIN" \
--config.file="$CONFIG_FILE" \
--web.listen-address=":9090" \
>> "$LOG_FILE" 2>&1 &
# 记录PID
echo $! > "$PID_FILE"
# 检查是否启动成功
sleep 3
if pgrep -u "$PROM_USER" -f "$PROM_BIN" >/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 启动成功!PID: $(cat "$PID_FILE")" | tee -a "$LOG_FILE"
exit 0
else
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:Prometheus 启动失败!" | tee -a "$LOG_FILE"
exit 6
fi
}
init
prometheus_start
stop.sh 脚本内容如下:
#!/bin/bash
# 配置部分(需与启动脚本保持一致)
PROM_USER="prometheus"
PROM_HOME="/home/prometheus"
PROM_BIN="$PROM_HOME/prometheus/prometheus"
LOG_DIR="$PROM_HOME/prometheus/logs"
LOG_FILE="$LOG_DIR/prometheus.log"
PID_DIR="$PROM_HOME/prometheus/run"
PID_FILE="$PID_DIR/prometheus.pid"
init() {
# 检查日志目录是否存在
if [ ! -d ${LOG_DIR} ]; then
mkdir -p ${LOG_DIR}
fi
# 检查run目录是否存在
if [ ! -d ${PID_DIR} ]; then
mkdir -p ${PID_DIR}
fi
# 检查是否以prometheus用户运行
if [ "$(whoami)" != "$PROM_USER" ]; then
echo "错误:本脚本必须使用 $PROM_USER 用户执行!"
echo "请使用:sudo -u $PROM_USER $0"
exit 1
fi
# 检查PID文件是否存在
if [ ! -f "$PID_FILE" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:PID文件 $PID_FILE 不存在" | tee -a "$LOG_FILE"
return 1
fi
# 检查进程是否运行
if ! pgrep -u "$PROM_USER" -f "$PROM_BIN" >/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:Prometheus 进程未运行" | tee -a "$LOG_FILE"
return 2
fi
}
prometheus_stop() {
echo "============================================" >> "$LOG_FILE"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 正在停止 Prometheus..." | tee -a "$LOG_FILE"
# 从PID文件获取进程ID
PID=$(cat "$PID_FILE" 2>/dev/null)
if [ -z "$PID" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:无法读取有效的PID" | tee -a "$LOG_FILE"
exit 3
fi
# 优雅终止进程
kill -SIGTERM "$PID" 2>/dev/null
# 等待最多10秒
TIMEOUT=10
while [ $TIMEOUT -gt 0 ]; do
if ! pgrep -u "$PROM_USER" -f "$PROM_BIN" >/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 停止成功!原PID: $PID" | tee -a "$LOG_FILE"
rm -f "$PID_FILE"
exit 0
fi
sleep 1
TIMEOUT=$((TIMEOUT - 1))
done
# 强制终止(如果优雅终止失败)
kill -SIGKILL "$PID" 2>/dev/null
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:已强制终止 Prometheus (PID: $PID)" | tee -a "$LOG_FILE"
rm -f "$PID_FILE"
exit 0
}
# 主流程
init
prometheus_stop
6、访问 prometheus 服务的web界面
IP:http://192.168.254.100:9090/targets
192.168.254.100 是部署的 prometheus 服务主机的 IP 地址。

下图是我们查看我们配置的目标健康情况,其中 prometheus 的健康情况是正常的。node 节点健康情况还没有发现,因为对应主机的 node_exporter 进程没有启动。

7、node_exporter 采集代理进程启动
所有主机都操作
su - prometheus
cd node_exporter
mkdir shell
# 创建启动脚本
vi shell/start.sh
chmod 750 start.sh
# 创建停止脚本
vi shell/stop.sh
chmod 750 stop.sh
# 执行启动脚本
sh /home/prometheus/node_exporter/shell/start.sh
start.sh 脚本内容如下:
#!/bin/bash
# 配置部分
EXPORTER_USER="prometheus"
EXPORTER_HOME="/home/prometheus"
EXPORTER_BIN="$EXPORTER_HOME/node_exporter/node_exporter"
LOG_DIR="$EXPORTER_HOME/node_exporter/logs"
LOG_FILE="$LOG_DIR/node_exporter.log"
PID_DIR="$EXPORTER_HOME/node_exporter/run"
PID_FILE="$PID_DIR/node_exporter.pid"
init() {
# 检查是否以prometheus用户运行
if [ "$(whoami)" != "$EXPORTER_USER" ]; then
echo "错误:本脚本必须使用 $EXPORTER_USER 用户执行!"
echo "请使用:sudo -u $EXPORTER_USER $0"
exit 1
fi
# 检查日志目录是否存在
if [ ! -d ${LOG_DIR} ]; then
mkdir -p ${LOG_DIR}
fi
# 检查run目录是否存在
if [ ! -d ${PID_DIR} ]; then
mkdir -p ${PID_DIR}
fi
# 检查程序是否已运行
if pgrep -u "$EXPORTER_USER" -f "$EXPORTER_BIN" >/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:node_exporter 已在运行!" | tee -a "$LOG_FILE"
exit 2
fi
# 检查可执行文件
if [ ! -f "$EXPORTER_BIN" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:可执行文件 $EXPORTER_BIN 不存在!" | tee -a "$LOG_FILE"
exit 3
fi
}
exporter_start() {
echo "============================================" >> "$LOG_FILE"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 正在启动 node_exporter..." | tee -a "$LOG_FILE"
cd "$EXPORTER_HOME/node_exporter" || exit 4
nohup "$EXPORTER_BIN" \
--web.listen-address=":9100" \
>> "$LOG_FILE" 2>&1 &
# 记录PID
echo $! > "$PID_FILE"
chmod 644 "$PID_FILE"
# 检查是否启动成功
sleep 2
if pgrep -u "$EXPORTER_USER" -f "$EXPORTER_BIN" >/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 启动成功!PID: $(cat "$PID_FILE")" | tee -a "$LOG_FILE"
exit 0
else
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:node_exporter 启动失败!" | tee -a "$LOG_FILE"
exit 5
fi
}
init
exporter_start
stop.sh 脚本内容如下:
#!/bin/bash
# 配置部分(与启动脚本一致)
EXPORTER_USER="prometheus"
EXPORTER_HOME="/home/prometheus"
EXPORTER_BIN="$EXPORTER_HOME/node_exporter/node_exporter"
LOG_DIR="$EXPORTER_HOME/node_exporter/logs"
LOG_FILE="$LOG_DIR/node_exporter.log"
PID_DIR="$EXPORTER_HOME/node_exporter/run"
PID_FILE="$PID_DIR/node_exporter.pid"
init() {
# 检查是否以prometheus用户运行
if [ "$(whoami)" != "$EXPORTER_USER" ]; then
echo "错误:本脚本必须使用 $EXPORTER_USER 用户执行!"
echo "请使用:sudo -u $EXPORTER_USER $0"
exit 1
fi
# 检查日志目录是否存在
if [ ! -d ${LOG_DIR} ]; then
mkdir -p ${LOG_DIR}
fi
# 检查run目录是否存在
if [ ! -d ${PID_DIR} ]; then
mkdir -p ${PID_DIR}
fi
# 检查PID文件是否存在
if [ ! -f "$PID_FILE" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:PID文件 $PID_FILE 不存在" | tee -a "$LOG_FILE"
return 1
fi
# 检查进程是否运行
if ! pgrep -u "$EXPORTER_USER" -f "$EXPORTER_BIN" >/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:node_exporter 进程未运行" | tee -a "$LOG_FILE"
return 2
fi
}
exporter_stop() {
echo "============================================" >> "$LOG_FILE"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 正在停止 node_exporter..." | tee -a "$LOG_FILE"
PID=$(cat "$PID_FILE" 2>/dev/null)
if [ -z "$PID" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:无法读取有效的PID" | tee -a "$LOG_FILE"
exit 3
fi
# 优雅终止
kill -SIGTERM "$PID" 2>/dev/null
# 等待最多5秒(node_exporter通常快速退出)
TIMEOUT=5
while [ $TIMEOUT -gt 0 ]; do
if ! pgrep -u "$EXPORTER_USER" -f "$EXPORTER_BIN" >/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 停止成功!原PID: $PID" | tee -a "$LOG_FILE"
rm -f "$PID_FILE"
exit 0
fi
sleep 1
TIMEOUT=$((TIMEOUT - 1))
done
# 强制终止
kill -SIGKILL "$PID" 2>/dev/null
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:已强制终止 node_exporter (PID: $PID)" | tee -a "$LOG_FILE"
rm -f "$PID_FILE"
exit 0
}
init
exporter_stop
8、再次访问 prometheus 的web界面
http://192.168.254.100:9090/targets
此时健康状态都检测到了

四、Grafana 部署
1、软件包下载
方式一:如下命令执行,仅在 openEuler100 主机上下载就行
su - prometheus
wget https://dl.grafana.com/enterprise/release/grafana-enterprise-10.3.5.linux-amd64.tar.gz
tar -zxvf grafana-enterprise-10.3.5.linux-amd64.tar.gz
mv grafana-v10.3.5 grafana
方式二:去网站下载,然后把包上传到指定目录下
地址:grafana下载地址

2、启动 Grafana 服务
仅在openEuler100主机上操作
su - prometheus
cd grafana
mkdir shell
vi shell/start.sh
chmod 750 shell/start.sh
vi shell/stop.sh
chmod 750 shell/stop.sh
sh shell/start.sh
start.sh 脚本内容如下:
#!/bin/bash
# 配置部分
GRAFANA_USER="prometheus"
GRAFANA_HOME="/home/prometheus/grafana"
GRAFANA_BIN="$GRAFANA_HOME/bin/grafana"
CONFIG_FILE="$GRAFANA_HOME/conf/defaults.ini"
LOG_DIR="$GRAFANA_HOME/logs"
LOG_FILE="$LOG_DIR/grafana.log"
PID_DIR="$GRAFANA_HOME/run"
PID_FILE="$PID_DIR/grafana.pid"
init() {
# 检查是否以 prometheus 用户运行
if [ "$(whoami)" != "$GRAFANA_USER" ]; then
echo "错误:本脚本必须使用 $GRAFANA_USER 用户执行!"
echo "请使用:sudo -u $GRAFANA_USER $0"
exit 1
fi
# 检查日志目录是否存在
if [ ! -d ${LOG_DIR} ]; then
mkdir -p ${LOG_DIR}
fi
# 检查run目录是否存在
if [ ! -d ${PID_DIR} ]; then
mkdir -p ${PID_DIR}
fi
# 检查程序是否已运行
if pgrep -u "$GRAFANA_USER" -f "$GRAFANA_BIN" >/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:Grafana 已在运行!" | tee -a "$LOG_FILE"
exit 2
fi
# 检查可执行文件和配置文件
if [ ! -f "$GRAFANA_BIN" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:可执行文件 $GRAFANA_BIN 不存在!" | tee -a "$LOG_FILE"
exit 3
fi
if [ ! -f "$CONFIG_FILE" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:未找到配置文件 $CONFIG_FILE,将使用默认配置!" | tee -a "$LOG_FILE"
fi
}
grafana_start() {
echo "============================================" >> "$LOG_FILE"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 正在启动 Grafana..." | tee -a "$LOG_FILE"
"$GRAFANA_BIN" server \
--config="$CONFIG_FILE" \
--homepath="$GRAFANA_HOME" \
--pidfile="$PID_FILE" \
>> "$LOG_FILE" 2>&1 &
# 检查是否启动成功
sleep 5 # Grafana启动较慢,需延长等待时间
if pgrep -u "$GRAFANA_USER" -f "$GRAFANA_BIN" >/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 启动成功!PID: $(cat "$PID_FILE")" | tee -a "$LOG_FILE"
exit 0
else
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:Grafana 启动失败!" | tee -a "$LOG_FILE"
exit 4
fi
}
init
grafana_start
stop.sh 脚本内容如下:
#!/bin/bash
# 配置部分(与启动脚本一致)
GRAFANA_USER="prometheus"
GRAFANA_HOME="/home/prometheus/grafana"
GRAFANA_BIN="$GRAFANA_HOME/bin/grafana"
CONFIG_FILE="$GRAFANA_HOME/conf/defaults.ini"
LOG_DIR="$GRAFANA_HOME/logs"
LOG_FILE="$LOG_DIR/grafana.log"
PID_DIR="$GRAFANA_HOME/run"
PID_FILE="$PID_DIR/grafana.pid"
init() {
# 检查是否以 prometheus 用户运行
if [ "$(whoami)" != "$GRAFANA_USER" ]; then
echo "错误:本脚本必须使用 $GRAFANA_USER 用户执行!"
echo "请使用:sudo -u $GRAFANA_USER $0"
exit 1
fi
# 检查日志目录是否存在
if [ ! -d ${LOG_DIR} ]; then
mkdir -p ${LOG_DIR}
fi
# 检查run目录是否存在
if [ ! -d ${PID_DIR} ]; then
mkdir -p ${PID_DIR}
fi
# 检查PID文件是否存在
if [ ! -f "$PID_FILE" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:PID文件 $PID_FILE 不存在" | tee -a "$LOG_FILE"
return 1
fi
# 检查进程是否运行
if ! pgrep -u "$GRAFANA_USER" -f "$GRAFANA_BIN" >/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:Grafana 进程未运行" | tee -a "$LOG_FILE"
return 2
fi
}
grafana_stop() {
echo "============================================" >> "$LOG_FILE"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 正在停止 Grafana..." | tee -a "$LOG_FILE"
PID=$(cat "$PID_FILE" 2>/dev/null)
if [ -z "$PID" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:无法读取有效的PID" | tee -a "$LOG_FILE"
exit 3
fi
# 优雅终止
kill -SIGTERM "$PID" 2>/dev/null
# 等待最多15秒(Grafana关闭可能较慢)
TIMEOUT=15
while [ $TIMEOUT -gt 0 ]; do
if ! pgrep -u "$GRAFANA_USER" -f "$GRAFANA_BIN" >/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 停止成功!原PID: $PID" | tee -a "$LOG_FILE"
rm -f "$PID_FILE"
exit 0
fi
sleep 1
TIMEOUT=$((TIMEOUT - 1))
done
# 强制终止
kill -SIGKILL "$PID" 2>/dev/null
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:已强制终止 Grafana (PID: $PID)" | tee -a "$LOG_FILE"
rm -f "$PID_FILE"
exit 0
}
init
grafana_stop
3、访问 grafana web界面
http://192.168.254.100:3000/login
默认账户 admin 密码 admin

4、grafana 与 prometheus 对接
(1)添加数据源

选择我们的时间序列数据库

配置我们的 Prometheus 服务地址,在 prometheus.yml 文件中配置的是 9090 端口


其它的暂时不用配置,选择保存

此时数据源添加成功了

(2)添加仪表盘
选择创建仪表盘

为了更方便我们可以点击 import 导入仪表盘。仪表盘模板可以先到 grafana.com 获取。

grafana.com 中选择心仪的仪表盘

点击复制 仪表盘id

回到创建界面,点击导入

粘贴刚才的id,点击 load

选择数据源,点击导入

监控情况如下:

(3)展示
后续可以按下图路径找到我们的仪表盘

五、为 prometheus 添加告警规则
prometheus web中目前是没有规则的,我们需要给它添加规则。
1、修改prometheus.yml 配置
仅在openEuler100主机上操作
su - prometheus
cd prometheus
mkdir rules
# 编写一个常用的告警规则
vi rules/sys_rules.yml
# 编写 prometheus.yml 配置
vi prometheus.yml
# 服务需要重新启动生效
./shell/stop.sh
./shell/start.sh
prometheus.yml 配置更改如下,指明规则文件

sys_rule.yml 配置如下:
groups:
- name: host_monitoring
rules:
# 1. 磁盘空间监控(排除临时文件系统)
- alert: HighDiskUsage
expr: |
100 * (1 - (node_filesystem_avail_bytes{fstype=~"ext4|xfs|btrfs", mountpoint!~"/tmp|/run|/var/run|/dev/shm"} / node_filesystem_size_bytes{fstype=~"ext4|xfs|btrfs"}))
> 85
for: 10s
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} 磁盘空间不足 (挂载点: {{ $labels.mountpoint }})"
description: "磁盘使用率 {{ $value | humanize }}% (阈值: 85%)"
# 2. CPU 使用率监控
- alert: HighCpuUsage
expr: |
100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
> 90
for: 1m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} CPU 使用率过高"
description: "1分钟平均CPU使用率 {{ $value | humanize }}% (阈值: 90%)"
# 3. 内存使用监控(使用 MemAvailable 更准确)
- alert: HighMemoryUsage
expr: |
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes))
* 100 > 90
for: 1m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} 内存不足"
description: "内存使用率 {{ $value | humanize }}% (阈值: 90%)"
# 4. 磁盘 I/O 负载监控
- alert: HighDiskIoLoad
expr: |
avg by(instance) (irate(node_disk_io_time_weighted_seconds_total[1m])) * 100
> 90
for: 5m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} 磁盘 I/O 负载过高"
description: "5分钟平均磁盘 I/O 负载 {{ $value | humanize }}% (阈值: 90%)"
# 5. 服务器存活监控
- alert: InstanceDown
expr: up{job="node"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} 服务器宕机"
description: "该节点已超过 1 分钟未上报数据"
2、访问 Prometheus 的 web 界面
http://192.168.254.100:9090/rules

3、尝试制造告警
更改 /home/prometheus/prometheus/rules/sys_rules.yml 中阈值,调小一点。

再次登录web界面就可以发现告警了

4、rule 参数说明
| 参数 | 必填 | 说明 |
|---|---|---|
groups[].name | 是 | 规则组名称 |
alert | 是 | 告警名称(唯一标识) |
expr | 是 | PromQL 表达式,定义触发条件 |
for | 否 | 持续时间(默认 0,立即触发) |
labels | 否 | 附加标签(如 severity、service) |
annotations | 否 | 告警详情(支持模板变量) |
六、结合 alertmanager 进行使用
Prometheus 中的 Alertmanager 是一个独立的组件,用于处理和管理由 Prometheus 触发的告警(Alerts)。它的主要作用是 去重、分组、路由和发送告警通知,确保告警信息能够高效、有序地传递给正确的接收者(如邮件、Slack、PagerDuty、Webhook 等)。
1、软件包下载

2、安装
仅在 openEuler100 主机上操作(部署Prometheus服务的主机)
将 alertmanager 软件包上传到 /home/prometheus 目录下并解压
su - prometheus
tar -zxvf alertmanager-0.28.1.linux-amd64.tar.gz
mv alertmanager-0.28.1.linux-amd64 alertmanager
3、配置 Prometheus 连接 Alertmanager
仅在 openEuler100 主机上操作
su - prometheus
vi prometheus/prometheus.yml
# 重启 prometheus 服务
sh prometheus/shell/stop.sh
sh prometheus/shell/start.sh

openEuler100 是alertmanager 所安装的主机
prometheus.yml 配置如下:
# my global config
global:
scrape_interval: 15s # 服务状态拉取频率
evaluation_interval: 15s # 执行规则频率
# Alertmanager configuration
alerting:
alertmanagers:
- static_configs:
- targets:
- "openEuler100:9093"
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
- "/home/prometheus/prometheus/rules/sys_rules.yml"
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
# 监控Prometheus服务状态
- job_name: "prometheus"
static_configs:
- targets: ["openEuler100:9090"]
labels:
app: "prometheus"
# 监控主机资源(需提前运行node_exporter)
- job_name: "node"
static_configs:
- targets:
- "openEuler100:9100"
- "openEuler101:9100"
- "openEuler102:9100"
labels:
app: "node"
4、配置alertmanager的启动和停止脚本
仅openEuler100 主机操作
su - prometheus
mkdir -pv /home/prometheus/alertmanager/shell
vi alertmanager/shell/start.sh
vi alertmanager/shell/stop.sh
chmod 750 alertmanager/shell/start.sh
chmod 750 alertmanager/shell/stop.sh
start.sh 脚本内容如下:
#!/bin/bash
# 配置部分
ALERTMANAGER_USER="prometheus"
ALERTMANAGER_HOME="/home/prometheus"
ALERTMANAGER_BIN="$ALERTMANAGER_HOME/alertmanager/alertmanager"
ALERTMANAGER_CONFIG="$ALERTMANAGER_HOME/alertmanager/alertmanager.yml"
LOG_DIR="$ALERTMANAGER_HOME/alertmanager/logs"
LOG_FILE="$LOG_DIR/alertmanager.log"
PID_DIR="$ALERTMANAGER_HOME/alertmanager/run"
PID_FILE="$PID_DIR/alertmanager.pid"
init() {
# 检查是否以 prometheus 用户运行
if [ "$(whoami)" != "$ALERTMANAGER_USER" ]; then
echo "错误:本脚本必须使用 $ALERTMANAGER_USER 用户执行!"
echo "请使用:sudo -u $ALERTMANAGER_USER $0"
exit 1
fi
# 检查日志目录是否存在
if [ ! -d "$LOG_DIR" ]; then
mkdir -p "$LOG_DIR"
fi
# 检查 run 目录是否存在
if [ ! -d "$PID_DIR" ]; then
mkdir -p "$PID_DIR"
fi
# 检查程序是否已运行
if pgrep -u "$ALERTMANAGER_USER" -f "$ALERTMANAGER_BIN" >/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:alertmanager 已在运行!" | tee -a "$LOG_FILE"
exit 2
fi
# 检查可执行文件
if [ ! -f "$ALERTMANAGER_BIN" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:可执行文件 $ALERTMANAGER_BIN 不存在!" | tee -a "$LOG_FILE"
exit 3
fi
# 检查配置文件
if [ ! -f "$ALERTMANAGER_CONFIG" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:配置文件 $ALERTMANAGER_CONFIG 不存在!" | tee -a "$LOG_FILE"
exit 4
fi
}
alertmanager_start() {
echo "============================================" >> "$LOG_FILE"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 正在启动 alertmanager..." | tee -a "$LOG_FILE"
cd "$ALERTMANAGER_HOME/alertmanager" || exit 5
nohup "$ALERTMANAGER_BIN" \
--config.file="$ALERTMANAGER_CONFIG" \
--storage.path="$ALERTMANAGER_HOME/alertmanager/data" \
--web.listen-address=":9093" \
>> "$LOG_FILE" 2>&1 &
# 记录 PID
echo $! > "$PID_FILE"
chmod 644 "$PID_FILE"
# 检查是否启动成功
sleep 2
if pgrep -u "$ALERTMANAGER_USER" -f "$ALERTMANAGER_BIN" >/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 启动成功!PID: $(cat "$PID_FILE")" | tee -a "$LOG_FILE"
exit 0
else
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:alertmanager 启动失败!" | tee -a "$LOG_FILE"
exit 6
fi
}
init
alertmanager_start
stop.sh 脚本内容如下:
#!/bin/bash
# 配置部分(需与启动脚本一致)
ALERTMANAGER_USER="prometheus"
ALERTMANAGER_HOME="/home/prometheus"
ALERTMANAGER_BIN="$ALERTMANAGER_HOME/alertmanager/alertmanager"
PID_DIR="$ALERTMANAGER_HOME/alertmanager/run"
PID_FILE="$PID_DIR/alertmanager.pid"
LOG_DIR="$ALERTMANAGER_HOME/alertmanager/logs"
LOG_FILE="$LOG_DIR/alertmanager.log"
init() {
# 检查是否以 prometheus 用户运行
if [ "$(whoami)" != "$ALERTMANAGER_USER" ]; then
echo "错误:本脚本必须使用 $ALERTMANAGER_USER 用户执行!"
echo "请使用:sudo -u $ALERTMANAGER_USER $0"
exit 1
fi
# 检查日志目录是否存在
if [ ! -d "$LOG_DIR" ]; then
mkdir -p "$LOG_DIR"
fi
# 检查 run 目录是否存在
if [ ! -d "$PID_DIR" ]; then
mkdir -p "$PID_DIR"
fi
# 检查 PID 文件是否存在
if [ ! -f "$PID_FILE" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:PID 文件 $PID_FILE 不存在!" | tee -a "$LOG_FILE"
exit 2
fi
}
alertmanager_stop() {
echo "============================================" >> "$LOG_FILE"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 正在停止 alertmanager..." | tee -a "$LOG_FILE"
# 读取 PID 并杀死进程
PID=$(cat "$PID_FILE")
if kill -TERM "$PID" 2>/dev/null; then
# 等待进程退出
sleep 2
if pgrep -u "$ALERTMANAGER_USER" -f "$ALERTMANAGER_BIN" >/dev/null; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:优雅停止失败,尝试强制终止..." | tee -a "$LOG_FILE"
kill -9 "$PID" 2>/dev/null
fi
rm -f "$PID_FILE"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 停止成功!原 PID: $PID" | tee -a "$LOG_FILE"
exit 0
else
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 错误:停止失败(进程可能已退出)" | tee -a "$LOG_FILE"
exit 3
fi
}
init
alertmanager_stop
5、alertmanager 告警通知配置
alertmanager 有很多功能,我们先实现一个告警通知功能.
仅在openEuler100主机操作
su - prometheus
vi alertmanager/alertmanager.yml
alertmanager.yml 配置如下:
global:
resolve_timeout: 5m # 当告警状态为已解决后,等待多长时间才宣布告警已解决
smtp_smarthost: 'smtp.qq.com:465' # SMTP服务器地址和端口
smtp_from: 'xxxxx@qq.com' # 发件人邮箱
smtp_auth_username: 'xxxxx@qq.com' # SMTP认证用户名
smtp_auth_password: 'xxxxxx' # SMTP认证密码
smtp_require_tls: false # 是否启用TLS加密
smtp_hello: 'qq.com' # 添加 HELO 标识
route:
group_by: ['alertname'] # 按这些标签分组
group_wait: 30s # 初次等待时间
group_interval: 5m # 组内间隔
repeat_interval: 3h # 重复间隔
receiver: 'qq_email-notifications'
receivers:
- name: 'qq_email-notifications'
email_configs:
- to: 'xxxxx@qq.com'
send_resolved: true # 发送解决通知
headers:
subject: '[ALERT] {{ .CommonLabels.alertname }} on {{ .CommonLabels.instance }}'
其中qq邮箱的 smtp 认证密码获取方法如下:
登录qq邮箱->设置->账号与安全->安全设置->生成授权码(即认证密码)

6、启动 alertmanager
su - prometheus
sh alertmanager/shell/start.sh
7、验证
由于我们在第五步,制造了一个告警,此时prometheus web界面是有告警的

登录alertmanager的界面:http://openEuler100:9093/ 也收到了对应告警
等了一会,qq邮箱也收到了告警


3万+

被折叠的 条评论
为什么被折叠?



