prometheus+grafana+alertmanager安装部署

目录

一、软件包获取

1、prometheus 软件包获取

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

二、环境准备

1、主机清单

2、网络配置

3、关闭防火墙

4、关闭selinux

5、配置主机名称和host配置

6、检查主机间的网络通信

7、创建用户和组

三、部署Prometheus 

1、上传软件包

2、prometheus 安装包解压

3、node_exporter 安装包解压

4、修改 prometheus.yml 配置文件

5、prometheus 服务启动

6、访问 prometheus 服务的web界面

7、node_exporter 采集代理进程启动

8、再次访问 prometheus 的web界面

四、Grafana 部署

1、软件包下载

2、启动 Grafana 服务

3、访问 grafana web界面

4、grafana 与 prometheus 对接

(1)添加数据源

(2)添加仪表盘

(3)展示

五、为 prometheus 添加告警规则

​1、修改prometheus.yml 配置

2、访问 Prometheus 的 web 界面

3、尝试制造告警

4、rule 参数说明

六、结合 alertmanager 进行使用

1、软件包下载

2、安装

3、配置 Prometheus 连接 Alertmanager

4、配置alertmanager的启动和停止脚本

5、alertmanager 告警通知配置

6、启动 alertmanager 

7、验证


一、软件包获取

1、prometheus 软件包获取

下载地址

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

下载地址

二、环境准备

1、主机清单

一共三台虚拟机,网络配置如下:

主机名IP监控情况
openEuler100192.168.254.100/24监控服务+被监控主机
openEuler101192.168.254.101/24被监控主机
openEuler102192.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告警名称(唯一标识)
exprPromQL 表达式,定义触发条件
for持续时间(默认 0,立即触发)
labels附加标签(如 severityservice
annotations告警详情(支持模板变量)

六、结合 alertmanager 进行使用

Prometheus 中的 Alertmanager 是一个独立的组件,用于处理和管理由 Prometheus 触发的告警(Alerts)。它的主要作用是 去重、分组、路由和发送告警通知,确保告警信息能够高效、有序地传递给正确的接收者(如邮件、Slack、PagerDuty、Webhook 等)。

1、软件包下载

下载地址:Download | Prometheus

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邮箱也收到了告警

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值