# 监控服务器搭建文档(Prometheus + Zabbix + Grafana 源码安装)
编写日期:2026-07-06 | 最近更新:2026-07-22(按第 13 章踩坑记录回填正文流程;重写第 14 章:外网地址探测 + Alertmanager 完整安装流程)
操作系统:CentOS 7.9(x86_64)
部署原则:所有组件统一安装到/data目录下;数据库(MySQL)与 Docker 数据目录均落在/data。
Prometheus / Grafana / Zabbix 采用源码/二进制方式部署,数据库使用 Docker 部署。
⚠️ CentOS 7.9 特别说明(务必先读)
CentOS 7 已于 2024-06-30 EOL(停止维护),官方 mirror 已下线,直接 yum install 会报 Could not resolve host: mirror.centos.org。另外 Zabbix 6.4 已 EOL 下架,本文改用 6.0.47 LTS(前端要 PHP 7.4+,CentOS 7 自带 5.4 过旧)。关键处理点:
| 坑 | 说明 | 解决方案(文档已含) |
|---|---|---|
| yum 源失效 | 官方 mirror 下线 | 切换到 vault.centos.org 源(3.1) |
| glibc 2.17 | CentOS 7 内核/glibc 较旧 | Prometheus/Grafana 用官方静态二进制,可正常运行;Grafana 建议用 10.x/11.x LTS 早期版,个别最新版可能要求更高 glibc |
| gcc 4.8.5 | 编译 Zabbix 6.4 偏旧 | 建议用 devtoolset-9(SCL)提供 gcc 9,避免编译报错(8.1) |
| PHP 5.4 | Zabbix 6.4 前端要 PHP 7.4+ | 用 Remi 源装 PHP 7.4(8.6) |
| MySQL 8.0 | 无本地安装,走 Docker | 不受宿主机版本影响 ✅ |
目录
- 整体架构与端口规划
- 目录规划(/data 布局)
- 2.1 挂载数据盘到 /data(第一步,先做)
- 系统环境准备
- 安装 Docker(数据目录落在 /data)
- Docker 部署数据库(MySQL for Zabbix)
- 源码安装 Prometheus
- 源码安装 Grafana
- 源码安装 Zabbix
- 组件集成
- 被监控主机接入(安装 Zabbix Agent)
- 启动顺序与验证
- 常见问题排查
- 实战部署踩坑记录(本次真实部署问题汇总)
- New API 主备集群(Docker)Prometheus 监控与钉钉告警
1. 整体架构与端口规划
┌─────────────────────────────────────────┐
│ 监控服务器 (Linux) │
│ │
被监控主机 ──node_exporter──► Prometheus (9090) ──┐ │
被监控主机 ──zabbix-agent───► Zabbix Server (10051)│ │
│ ▼ │
│ Grafana (3000) │
│ ┌───────────────┴──────────┐ │
│ │ Docker: MySQL (3306) │ │
│ │ → Zabbix / Grafana 数据 │ │
│ └──────────────────────────┘ │
└─────────────────────────────────────────┘
| 组件 | 端口 | 部署方式 | 说明 |
|---|---|---|---|
| Prometheus | 9090 | 二进制源码 | 指标采集与存储 |
| Grafana | 3000 | 二进制源码 | 可视化展示 |
| Zabbix Server | 10051 | 源码编译 | 传统监控 Server |
| Zabbix Web | 8080 | 源码 + PHP | Zabbix 前端(Nginx/Apache) |
| Zabbix Agent | 10050 | 源码编译 | 本机被监控代理 |
| MySQL | 3306 | Docker | Zabbix / Grafana 后端数据库 |
| node_exporter | 9100 | 二进制 | 主机指标导出(可选) |
| mysqld-exporter | 9104 | Docker | MySQL 指标导出(Prometheus 抓取) |
2. 目录规划(/data 布局)
所有内容统一放在 /data,结构如下:
/data
├── docker/ # Docker 根目录(data-root)
│ └── ... # 镜像、容器、volume
├── db/ # 数据库持久化数据
│ ├── mysql/ # MySQL 数据文件
│ └── mysql-conf/ # MySQL 自定义配置(my.cnf)
├── prometheus/
│ ├── prometheus-2.53.0/ # 解压后的程序目录
│ ├── data/ # TSDB 数据
│ ├── conf/ # prometheus.yml 等配置
│ └── mysqld-exporter/ # mysqld-exporter 的 docker-compose
├── grafana/
│ ├── grafana-11.1.0/ # 程序目录
│ ├── data/ # Grafana 数据
│ ├── logs/ # 日志
│ └── conf/ # 自定义配置
├── zabbix/
│ ├── zabbix-6.0.47/ # 源码目录(6.4 已 EOL,用 6.0 LTS)
│ ├── server/ # 安装前缀 (sbin/bin/etc)
│ └── web/ # 前端 PHP 文件
├── src/ # 各类下载的源码包/二进制包临时存放
├── blackbox-exporter/ # Prometheus HTTP 黑盒探测配置
├── alertmanager/ # Alertmanager 配置与持久化数据
└── dingtalk/ # 钉钉 Webhook 适配器配置
创建目录:
sudo mkdir -p /data/{docker,db/mysql,db/mysql-conf,src}
sudo mkdir -p /data/prometheus/{data,conf,mysqld-exporter}
sudo mkdir -p /data/grafana/{data,logs,conf}
sudo mkdir -p /data/zabbix/{server,web}
sudo mkdir -p /data/{blackbox-exporter,alertmanager,dingtalk}/conf
⚠️ 上面的
mkdir请在数据盘已挂载到/data之后执行,见下一节 §2.1。
2.1 挂载数据盘到 /data(第一步,先做)
由于所有组件、数据库、Docker 数据都落在 /data,务必先把独立数据盘挂载到 /data 并配置开机自动挂载,否则重启后数据盘不挂载会导致数据"消失"或服务起不来。
(1)识别数据盘
# 查看所有磁盘,确认数据盘设备名(如 /dev/sdb、/dev/vdb、/dev/nvme1n1)
lsblk
fdisk -l
示例:系统盘为
/dev/sda,新加的数据盘为/dev/sdb(无分区、无挂载点)。下方以/dev/sdb为例,请按实际替换。
(2)分区(单分区占满整盘)
单盘 ≤2TB 用 fdisk(MBR) 即可;磁盘 >2TB 必须用 GPT(parted),见下方备选。
# 方式 A:fdisk(≤2TB)
sudo fdisk /dev/sdb <<'EOF'
n
p
1
w
EOF
# 生成 /dev/sdb1
# 方式 B:parted(>2TB,GPT)
# sudo parted -s /dev/sdb mklabel gpt
# sudo parted -s /dev/sdb mkpart primary xfs 0% 100%
(3)格式化(CentOS 7.9 默认文件系统 xfs)
sudo mkfs.xfs -f /dev/sdb1
# 如偏好 ext4: sudo mkfs.ext4 /dev/sdb1
(4)挂载并写入 /etc/fstab(开机自动挂载)
# 先创建挂载点(若不存在)
sudo mkdir -p /data
# 用 UUID 挂载(比设备名更稳妥,避免盘符漂移)
UUID=$(sudo blkid -s UUID -o value /dev/sdb1)
echo "数据盘 UUID = ${UUID}"
# 写入 fstab(xfs 示例)
echo "UUID=${UUID} /data xfs defaults,noatime 0 0" | sudo tee -a /etc/fstab
# 挂载全部 fstab 条目并验证
sudo mount -a
df -hT /data # 应看到 /dev/sdb1 挂载在 /data,类型 xfs
(5)验证
lsblk # /data 下应挂着 sdb1
df -hT | grep /data # 确认容量与文件系统正确
✅ 确认
df -hT /data显示的是数据盘容量(而非系统盘)后,再回到上面执行mkdir建子目录、继续 §3 及后续安装。
⚠️ 若mount -a报错,先不要重启(fstab 写错会导致无法正常启动),核对 UUID 与文件系统类型后再试。
3. 系统环境准备
以下命令以 root 或 sudo 执行,均为 CentOS 7.9 命令。
3.1 切换 YUM 源到 vault(必做)
CentOS 7 EOL 后官方镜像下线,先把 yum 源指向归档站 vault.centos.org:
# 备份原有仓库
sudo mkdir -p /etc/yum.repos.d/bak
sudo mv /etc/yum.repos.d/CentOS-*.repo /etc/yum.repos.d/bak/ 2>/dev/null
# 写入 vault 源
sudo tee /etc/yum.repos.d/CentOS-Vault.repo >/dev/null <<'EOF'
[base]
name=CentOS-7.9 Base - vault
baseurl=https://vault.centos.org/7.9.2009/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
[updates]
name=CentOS-7.9 Updates - vault
baseurl=https://vault.centos.org/7.9.2009/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
[extras]
name=CentOS-7.9 Extras - vault
baseurl=https://vault.centos.org/7.9.2009/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
EOF
# 安装 EPEL(同样走归档/阿里镜像)
sudo yum install -y https://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm 2>/dev/null || \
sudo yum install -y epel-release
sudo yum clean all && sudo yum makecache
如服务器在国内,可把
vault.centos.org换成https://mirrors.aliyun.com/centos-vault/7.9.2009/提速。
3.2 基础工具
sudo yum install -y wget curl vim tar gcc gcc-c++ make git \
net-tools lsof pcre-devel
3.3 关闭 SELinux(测试环境建议关闭,生产按需)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
3.4 防火墙放行端口
for p in 3000 9090 9100 10050 10051 3306 8080; do
sudo firewall-cmd --permanent --add-port=${p}/tcp
done
sudo firewall-cmd --reload
3.5 创建运行用户(非 root 运行组件,更安全)
sudo useradd -M -s /sbin/nologin prometheus
sudo useradd -M -s /sbin/nologin grafana
sudo useradd -M -s /sbin/nologin zabbix
4. 安装 Docker(/data)
数据库用 Docker 部署,Docker 的数据目录(镜像/容器/卷)要落在 /data/docker。
4.1 安装 Docker 引擎
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# 使用阿里云 Docker 源(CentOS 7 官方源亦可,但国内建议阿里)
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
CentOS 7.9 内核 3.10 满足 Docker 运行要求;
docker-compose-plugin提供docker composev2 子命令。
4.2 将 Docker 数据目录指向 /data/docker
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json >/dev/null <<'EOF'
{
"data-root": "/data/docker",
"log-driver": "json-file",
"log-opts": { "max-size": "100m", "max-file": "3" },
"registry-mirrors": [
"https://docker.1ms.run",
"https://docker.xuanyuan.me",
"https://dockerproxy.net",
"https://docker.m.daocloud.io"
]
}
EOF
4.3 启动并验证
sudo systemctl enable --now docker
docker info | grep "Docker Root Dir" # 应显示 /data/docker
docker info | grep -A5 "Registry Mirrors" # 确认镜像加速生效(拉镜像超时必查,见 §13.1)
docker version
5. Docker 部署数据库(MySQL for Zabbix)
数据持久化到 /data/db/mysql。这里用 MySQL 8.0(Zabbix 6.4 支持),Grafana 也可复用同一实例(另建库)。
5.1 启动 MySQL 容器
docker run -d \
--name monitor-mysql \
--restart=always \
-p 3306:3306 \
-v /data/db/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD='ChangeMe_Root@2026' \
-e TZ=Asia/Shanghai \
mysql:8.0 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_bin \
--default-authentication-plugin=mysql_native_password \
--log_bin_trust_function_creators=1
说明:Zabbix 要求
utf8mb4_bin排序规则,且导入 schema 时需要log_bin_trust_function_creators=1。
5.2 创建 Zabbix / Grafana 数据库与账号
docker exec -i monitor-mysql mysql -uroot -p'ChangeMe_Root@2026' <<'SQL'
-- Zabbix
CREATE DATABASE zabbix CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
CREATE USER 'zabbix'@'%' IDENTIFIED BY 'Zabbix_Pass@2026';
GRANT ALL PRIVILEGES ON zabbix.* TO 'zabbix'@'%';
-- Grafana(可选,Grafana 也可用自带 SQLite)
CREATE DATABASE grafana CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'grafana'@'%' IDENTIFIED BY 'Grafana_Pass@2026';
GRANT ALL PRIVILEGES ON grafana.* TO 'grafana'@'%';
FLUSH PRIVILEGES;
SQL
6. 源码安装 Prometheus
Prometheus 官方提供预编译二进制(Go 静态编译),生产推荐用官方二进制包;若需从源码编译,见 6.4。
6.1 下载与解压到 /data
cd /data/src
VER=2.53.0
wget https://github.com/prometheus/prometheus/releases/download/v${VER}/prometheus-${VER}.linux-amd64.tar.gz
tar -zxf prometheus-${VER}.linux-amd64.tar.gz -C /data/prometheus/
mv /data/prometheus/prometheus-${VER}.linux-amd64 /data/prometheus/prometheus-${VER}
6.2 配置文件
cat > /data/prometheus/conf/prometheus.yml <<'EOF'
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
# 主机监控(在被监控机部署 node_exporter:9100)
- job_name: 'node'
static_configs:
- targets: ['localhost:9100']
EOF
sudo chown -R prometheus:prometheus /data/prometheus
6.3 systemd 托管
sudo tee /etc/systemd/system/prometheus.service >/dev/null <<EOF
[Unit]
Description=Prometheus
After=network.target
[Service]
User=prometheus
Group=prometheus
ExecStart=/data/prometheus/prometheus-2.53.0/prometheus \\
--config.file=/data/prometheus/conf/prometheus.yml \\
--storage.tsdb.path=/data/prometheus/data \\
--web.listen-address=0.0.0.0:9090 \\
--web.enable-lifecycle
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now prometheus
访问:http://<服务器IP>:9090
6.4(可选)从源码编译
# 需要 Go 1.21+
cd /data/src
git clone https://github.com/prometheus/prometheus.git
cd prometheus
git checkout v2.53.0
make build # 生成 prometheus / promtool 二进制
cp prometheus promtool /data/prometheus/prometheus-2.53.0/
6.5(可选)node_exporter 主机指标
cd /data/src
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.1/node_exporter-1.8.1.linux-amd64.tar.gz
tar -zxf node_exporter-1.8.1.linux-amd64.tar.gz -C /data/prometheus/
# 用 systemd 托管,监听 :9100
systemd 服务文件(监听 :9100):
sudo tee /etc/systemd/system/node_exporter.service >/dev/null <<'EOF'
[Unit]
Description=Node Exporter
After=network.target
[Service]
ExecStart=/data/prometheus/node_exporter-1.8.1.linux-amd64/node_exporter \
--collector.systemd \
--collector.processes \
--web.listen-address=:9100
Restart=always
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
curl -s http://localhost:9100/metrics | head -5 # 验证
Grafana 中文仪表盘导入见 §9.3.4(推荐 ID 8919)。
7. 源码安装 Grafana
Grafana 官方提供独立二进制包(standalone),解压即用,是"源码/二进制"部署到 /data 的推荐方式。
CentOS 7.9 兼容性:Grafana 为 Go 静态编译,依赖极少,10.x / 11.x 在 glibc 2.17 上均可正常运行。本文用 11.1.0;若遇到极个别版本报 glibc 版本过低,可回退到10.4.xLTS。
7.1 下载与解压到 /data
cd /data/src
VER=11.1.0
wget https://dl.grafana.com/oss/release/grafana-${VER}.linux-amd64.tar.gz
tar -zxf grafana-${VER}.linux-amd64.tar.gz -C /data/grafana/
mv /data/grafana/grafana-v${VER} /data/grafana/grafana-${VER}
7.2 自定义配置(数据/日志/DB 落到 /data)
cat > /data/grafana/conf/custom.ini <<'EOF'
[paths]
data = /data/grafana/data
logs = /data/grafana/logs
plugins = /data/grafana/data/plugins
[server]
http_addr = 0.0.0.0
http_port = 3000
# 使用 Docker MySQL 作为后端(可选,不配则默认 SQLite)
[database]
type = mysql
host = 127.0.0.1:3306
name = grafana
user = grafana
password = Grafana_Pass@2026
EOF
sudo chown -R grafana:grafana /data/grafana
7.3 systemd 托管
sudo tee /etc/systemd/system/grafana.service >/dev/null <<EOF
[Unit]
Description=Grafana
After=network.target docker.service
[Service]
User=grafana
Group=grafana
WorkingDirectory=/data/grafana/grafana-11.1.0
ExecStart=/data/grafana/grafana-11.1.0/bin/grafana server \\
--homepath=/data/grafana/grafana-11.1.0 \\
--config=/data/grafana/conf/custom.ini
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now grafana
访问:http://<服务器IP>:3000,默认账号 admin / admin(首次登录强制改密)。
8. 源码安装 Zabbix
Zabbix Server 需要从源码 ./configure && make 编译。
8.1 安装编译依赖
CentOS 7.9 自带 gcc 4.8.5,编译 Zabbix 6.4 建议使用 SCL 提供的 gcc 9:
# 1) 安装编译依赖库
sudo yum install -y gcc make automake pkgconfig \
mysql-devel libxml2-devel net-snmp-devel libcurl-devel \
pcre2-devel openssl-devel libevent-devel zlib-devel
# 2) 安装 devtoolset-9(gcc 9),编译时启用
sudo yum install -y centos-release-scl
# SCL 源同样 EOL,需切 vault
sudo sed -i 's|^mirrorlist=|#mirrorlist=|g; s|^# *baseurl=http://mirror.centos.org|baseurl=https://vault.centos.org|g' \
/etc/yum.repos.d/CentOS-SCLo-scl*.repo
sudo yum install -y devtoolset-9-gcc devtoolset-9-gcc-c++
# 临时启用 gcc9(仅当前 shell 生效,编译 Zabbix 前执行)
source /opt/rh/devtoolset-9/enable
gcc --version # 确认 9.x
若本机没有 MySQL 客户端库,
mysql-devel提供mysql_config供--with-mysql链接。
CentOS 7 的pcre2-devel在 base 源即可安装;Zabbix 6.4 需要 PCRE2。
8.2 下载源码到 /data 并编译
cd /data/src
# ⚠️ Zabbix 6.4 已 EOL 下架(cdn 会 404),CentOS 7.9 请用 6.0 LTS 最新版
VER=6.0.47
wget https://cdn.zabbix.com/zabbix/sources/stable/6.0/zabbix-${VER}.tar.gz
tar -zxf zabbix-${VER}.tar.gz -C /data/zabbix/
cd /data/zabbix/zabbix-${VER}
# ⚠️ CentOS 7.9:编译前先启用 gcc9,否则可能编译报错
source /opt/rh/devtoolset-9/enable
./configure \
--prefix=/data/zabbix/server \
--enable-server \
--enable-agent \
--with-mysql \
--with-net-snmp \
--with-libcurl \
--with-libxml2 \
--with-openssl
make -j$(nproc)
make install
编译产物在 /data/zabbix/server/(sbin/zabbix_server、sbin/zabbix_agentd、etc/)。
💡
VER只是当前 shell 的临时变量,换终端 / 新开会话会丢失(见 §13.3)。下载、解压、编译请在同一次会话中连续执行;会话中断后先重新VER=6.0.47再继续。
8.3 导入数据库 schema(导入到 Docker MySQL)
⚠️ 导入前必须确认 MySQL 已开启
log_bin_trust_function_creators=1(容器启用了 binlog 时,导入触发器/存储过程会报ERROR 1419 SUPER privilege)。用 root 动态打开:
bash docker exec -i monitor-mysql mysql -uroot -p'ChangeMe_Root@2026' \ -e "SET GLOBAL log_bin_trust_function_creators=1;"
cd /data/zabbix/zabbix-6.0.47/database/mysql
ls # 先确认文件名:6.0 源码包是 schema.sql / images.sql / data.sql 三个文件
# 依次导入(顺序不能错)——一条 cat 管道也可以
cat schema.sql images.sql data.sql | \
docker exec -i monitor-mysql mysql -uzabbix -p'Zabbix_Pass@2026' zabbix
# 导入完成后可关闭 log_bin_trust_function_creators(可选)
docker exec -i monitor-mysql mysql -uroot -p'ChangeMe_Root@2026' \
-e "SET GLOBAL log_bin_trust_function_creators=0;"
验证导入成功:
bash docker exec -it monitor-mysql mysql -uzabbix -p'Zabbix_Pass@2026' zabbix \ -e "SELECT * FROM dbversion; SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='zabbix';"
dbversion有一行、表数 170+ 即成功。
若导入中途报错后需重来,先删库重建再导,避免"表已存在":
DROP DATABASE zabbix; CREATE DATABASE zabbix CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
8.4 配置 Zabbix Server
cat > /data/zabbix/server/etc/zabbix_server.conf <<'EOF'
LogFile=/data/zabbix/server/zabbix_server.log
PidFile=/data/zabbix/server/zabbix_server.pid
DBHost=127.0.0.1
DBName=zabbix
DBUser=zabbix
DBPassword=Zabbix_Pass@2026
DBPort=3306
ListenPort=10051
Timeout=30
EOF
sudo chown -R zabbix:zabbix /data/zabbix
8.5 systemd 托管 Zabbix Server / Agent
# Server
sudo tee /etc/systemd/system/zabbix-server.service >/dev/null <<EOF
[Unit]
Description=Zabbix Server
After=network.target docker.service
[Service]
Type=forking
User=zabbix
Group=zabbix
ExecStart=/data/zabbix/server/sbin/zabbix_server -c /data/zabbix/server/etc/zabbix_server.conf
PIDFile=/data/zabbix/server/zabbix_server.pid
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
# Agent(本机被监控)
sudo tee /etc/systemd/system/zabbix-agent.service >/dev/null <<EOF
[Unit]
Description=Zabbix Agent
After=network.target
[Service]
Type=forking
User=zabbix
Group=zabbix
ExecStart=/data/zabbix/server/sbin/zabbix_agentd -c /data/zabbix/server/etc/zabbix_agentd.conf
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now zabbix-server zabbix-agent
8.6 部署 Zabbix Web 前端(PHP)
Zabbix 6.4 前端要求 PHP 7.4+,而 CentOS 7.9 自带 PHP 5.4,必须用 Remi 源 安装 PHP 7.4,配合 Nginx + PHP-FPM。
# 1) 安装 Remi 源并启用 PHP 7.4
sudo yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm
sudo yum install -y yum-utils
sudo yum-config-manager --enable remi-php74
# 2) 安装 Nginx + PHP 7.4 及 Zabbix 前端所需扩展
sudo yum install -y nginx \
php php-fpm php-mysqlnd php-gd php-bcmath \
php-mbstring php-xml php-ldap php-json php-gettext
php -v # 确认 7.4.x
# 3) 拷贝前端文件到 /data
# ⚠️ 必须拷贝 ui/ 目录"里面"的文件,不能多套一层 ui/,否则 nginx 报 403(见 §13.4)
cp -r /data/zabbix/zabbix-6.0.47/ui/* /data/zabbix/web/
ls -l /data/zabbix/web/index.php # 确认入口文件直接在 web/ 下
sudo chown -R nginx:nginx /data/zabbix/web
sudo chmod 755 /data /data/zabbix /data/zabbix/web
Remi 源在 CentOS 7 上仍可用(PHP 7.4 归档包保留)。若
remi-php74启用失败,可改用remi-php80(Zabbix 6.4 同样支持 PHP 8.0)。
Nginx 站点配置(/etc/nginx/conf.d/zabbix.conf):
server {
listen 8080;
server_name _;
root /data/zabbix/web;
index index.php;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000; # 或 unix:/run/php-fpm/www.sock
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
PHP 需调整(/etc/php.ini):
max_execution_time = 300
memory_limit = 256M
post_max_size = 32M
upload_max_filesize = 16M
max_input_time = 300
date.timezone = Asia/Shanghai
启动并按向导安装:
sudo systemctl enable --now php-fpm nginx
# ⚠️ 每次修改 php.ini 后必须 restart 才生效(向导预检查失败的最常见原因,见 §13.5)
sudo systemctl restart php-fpm
浏览器访问 http://<服务器IP>:8080,按向导填写 DB(127.0.0.1 / zabbix / 密码),完成安装。默认后台账号 Admin / zabbix。
⚠️ 向导最后一步若报「无法创建配置文件」,是 php-fpm 运行用户对
web/conf/无写权限(见 §13.8):
bash sudo mkdir -p /data/zabbix/web/conf sudo chown -R nginx:nginx /data/zabbix/web/conf # php-fpm 运行用户,默认 nginx
点「完成」后收回权限:sudo chmod 644 /data/zabbix/web/conf/zabbix.conf.php。也可以点「下载配置文件」手动放入该目录。
8.7 通过已有 nginx 主备集群对外提供访问(两种方案)
线上通常已有 nginx 主备(keepalived + VIP)做统一入口。Zabbix 前端接入有两种方案:
| 方案 | 前端文件位置 | 特点 | 适用 |
|---|---|---|---|
| A. 反向代理 | 监控服务器 :8080 |
主备 nginx 只做 proxy_pass,不解析 PHP,维护简单 | 推荐 |
| B. 前端直部署 | 主备两台 nginx 本机 | 前端 + php-fpm 跑在主备两台,仅 DB / Server 回连监控机 | 本次实战采用 |
方案 A:反向代理
Zabbix 前端已在监控服务器 8080 端口跑起来(§8.6)。用已有的一套 nginx 主备服务器(keepalived + VIP)做反向代理,用户通过 VIP 访问,nginx 把请求 proxy_pass 转发到后端 8080。这一层只做代理和高可用,不解析 PHP。
用户访问 http://VIP
│
┌────────┴────────┐ keepalived VIP 漂移
▼ ▼
┌───────────────────┐ ┌───────────────────┐
│ nginx 主 (MASTER) │ │ nginx 备 (BACKUP) │ ← 纯反向代理,两台配置相同
│ proxy_pass ↓ │ │ proxy_pass ↓ │
└─────────┬─────────┘ └─────────┬─────────┘
└──────────┬──────────┘
▼ proxy_pass
监控服务器 Zabbix 前端 http://<监控服务器IP>:8080
(1)反向代理配置(主、备两台内容完全一致)
放到各自 nginx 的站点目录(yum 版 /etc/nginx/conf.d/zabbix-proxy.conf,编译版放主配置 http{} 的 include 目录):
upstream zabbix_backend {
server <监控服务器IP>:8080; # 后端 Zabbix 前端(如 172.16.1.30:8080)
keepalive 16;
}
server {
listen 80;
server_name zabbix.example.com; # 换成你的域名;无域名可用 _ 直接走 VIP
client_max_body_size 32m; # Zabbix 配置导入/上传需要,别漏
location / {
proxy_pass http://zabbix_backend;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; # 前端识别 http/https 靠它
proxy_connect_timeout 10s;
proxy_read_timeout 300s; # 与 PHP max_execution_time 对齐
proxy_send_timeout 300s;
}
}
⚠️ 主备两台都要放这份配置并各自 reload:
bash nginx -t && nginx -s reload # 编译版:/usr/local/nginx/sbin/nginx -t && ... -s reload
(2)后端放行 8080 给主备两台
监控服务器防火墙 / 云安全组放行 8080 给主、备 nginx 的 IP(含 VIP):
for ip in <主nginx_IP> <备nginx_IP> <VIP>; do
firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address=${ip}/32 port port=8080 protocol=tcp accept"
done
firewall-cmd --reload
(3)HTTPS(可选)
若代理层做 SSL 终结,把 listen 80 改成 listen 443 ssl; 并加证书,后端仍用 http 的 8080;同时 X-Forwarded-Proto $scheme 保留,让 Zabbix 前端生成正确的 https 链接。可再加一个 listen 80 的 server 做 301 跳转到 https。
(4)验证
# 在主/备 nginx 机分别测到后端连通
nc -zv <监控服务器IP> 8080
# 浏览器访问 http://VIP (或域名),应正常打开 Zabbix 登录页
说明:反向代理不涉及 Zabbix 的
zabbix.conf.php,所以主备切换对前端会话的影响与 §13.9 相同(默认切换后需重新登录一次)。
方案 B:前端直接部署在 nginx 主备集群(本次实战采用)
本次实战前端未装在监控服务器,而是放在已有业务的 nginx 主备集群上。要点(来自 §13.9 实战记录):
- php-fpm 必须与 nginx 同机(从本地磁盘读 PHP 文件),所以主备两台都要部署
ui/*+ php-fpm,配置一致(按 §8.6 在两台各执行一遍)。 fastcgi_pass指向 nginx 本机的 php-fpm(127.0.0.1:9000),不是监控服务器。- 安装向导里 Database host / Zabbix server host 填监控服务器内网 IP(如
172.16.1.30),不是 localhost。 - 监控服务器防火墙 / 云安全组放行 3306、10051 给主、备两台 IP(含 VIP):
bash for ip in <主nginx_IP> <备nginx_IP> <VIP>; do sudo firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address=${ip}/32 port port=3306 protocol=tcp accept" sudo firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address=${ip}/32 port port=10051 protocol=tcp accept" done sudo firewall-cmd --reload - 生成的
zabbix.conf.php手动同步到另一台:scp /data/zabbix/web/conf/zabbix.conf.php root@<备机IP>:/data/zabbix/web/conf/,否则切到备机会重新弹安装向导。 - 会话默认存 PHP 本地,主备切换后需重新登录一次(数据不丢);要无感切换需共享 session(DB/Redis),非强需求不建议一开始就上。
- 编译版 nginx 配置在
/usr/local/nginx/conf/,改动前先备份(主备机上可能有其他线上业务),nginx -t通过再reload。
9. 组件集成
9.1 Grafana 接入 Prometheus 数据源
- 登录 Grafana → Connections → Data sources → Add data source → Prometheus
- URL 填
http://localhost:9090→ Save & Test - 导入 Dashboard:Node Exporter Full(ID
1860)等
9.2 Grafana 接入 Zabbix 数据源
Grafana 只是展示层,通过 Zabbix API 读数据(不直连数据库),所以升级 Grafana 不影响 Zabbix / Prometheus 本身,它们照常运行。
(1)安装 Zabbix 插件(在监控服务器 VM-1-30)
# 以 grafana 用户身份装,避免生成 root 属主文件导致权限错误(见 §13.11)
sudo -u grafana /data/grafana/grafana-11.6.0/bin/grafana cli \
--pluginsDir /data/grafana/data/plugins \
plugins install alexanderzobnin-zabbix-app
systemctl restart grafana
路径里的版本目录换成实际的(
ls /data/grafana/)。
无外网时离线装:下载alexanderzobnin-zabbix-app.zip解压到/data/grafana/data/plugins/,然后chown -R grafana:grafana /data/grafana/data/plugins再重启。
(2)⚠️ 版本兼容性(关键,务必先确认)
Zabbix 插件对 Grafana 版本有硬性要求,不匹配会导致前端白屏报 Minified React error #130(见 §13.12)。安装后先核对:
grep -i grafanaDependency /data/grafana/data/plugins/alexanderzobnin-zabbix-app/plugin.json
/data/grafana/grafana-*/bin/grafana server -v
例如插件 6.4.1 要求 grafanaDependency >= 11.6.0。若你的 Grafana 低于该版本,二选一:
- 升级 Grafana(推荐):见 §13.12 的升级步骤(CentOS 7.9 建议升到刚好满足的 11.6.x,不要直接上 13.x,glibc 2.17 会报 GLIBC not found)。
- 降插件版本:grafana cli plugins install alexanderzobnin-zabbix-app <兼容版本>。
(3)在 Zabbix 建只读 API 账号(供 Grafana 用)
不要用 Admin 直接接。Zabbix Web 里:
1. 用户 → 用户群组 → 创建用户群组(如 grafana-ro),对要展示的主机组授 读(Read) 权限。
2. 用户 → 用户 → 创建用户:用户名 grafana、设密码、群组选 grafana-ro、角色选 User role。
(4)Grafana 添加数据源
- ⚙ Plugins 搜
Zabbix→ Enable 启用。 - Connections → Data sources → Add data source → Zabbix。
- 填写:
- URL:
http://<Zabbix前端IP或VIP>/api_jsonrpc.php(走前端 8080 则http://<前端IP>:8080/api_jsonrpc.php) - Zabbix API details:Username
grafana/ 对应密码 - Trends:开启(大时间范围查询更快)
- Save & test → 显示
Zabbix API version: 6.0.x即成功。
⚠️ 监控服务器(Grafana)要能访问 Zabbix 前端地址;不通则在前端/代理放行端口给监控服务器 IP。
(5)出图(推荐用随附的定制模板)
本文档目录随附两个已按 Zabbix 6.0 Linux by Zabbix agent 模板调好、全中文的 Grafana 仪表盘 JSON,导入即用:
| 文件 | 用途 |
|---|---|
grafana-zabbix-linux-dashboard.json |
单台深度:切 Host 看一台的全部细节(概览仪表 + CPU各态/负载/内存/磁盘/网络/磁盘IO/Swap/中断/错误丢包 + 磁盘·内存横条) |
grafana-zabbix-all-servers.json |
全局总览:一屏看所有服务器,每台一行(repeat by host,行内 CPU/内存仪表 + 磁盘横条 + 内存使用横条 + CPU各态/负载/网络/内存/Swap/进程) |
导入步骤:
1. Grafana → Dashboards → New → Import
2. 上传 JSON 或粘贴内容 → Load
3. 数据源选 DS_ZABBIX(你的 Zabbix 数据源)→ Import
4. 顶部 Group 选主机组、Host 选主机(总览页 Host 选 All)
5. 改过 JSON 重新导入时勾选 Overwrite 覆盖
也可手动自建:New Dashboard → Add panel → 数据源选 Zabbix → 依次选 Group / Host / Item。
💡 Item 名匹配技巧:grafana-zabbix 按 item 名(非 key)模糊匹配,用不带前缀的正则(如
/CPU .* time/、/: Space utilization/)即可,不管 item 是否带Linux:前缀都能命中。
数据显示 N/A / No data 的排查顺序(本次实战验证,见 §13.13):
1. 顶部变量没选:Group 和 Host 是级联的——必须先选 Group,Host 下拉才有值,不选就全 N/A。
2. 数据源/权限:数据源 Save&test 是否 Zabbix API version 6.0.x;grafana 只读账号是否在用户群组里对该主机组授了 读 权限(在"用户"页改无效,必须在"用户群组"里,见 §13.13)。
3. Zabbix 端有无数据:监测→最新数据有值?可用性 ZBX 图标绿?/data/zabbix/server/bin/zabbix_get -s <IP> -k system.cpu.load 能取到值?
4. 社区模板 item 名不匹配:从 grafana.com 导入的老仪表盘(如葡语版)item 名对不上你的模板,全 N/A——改用随附模板或用 Explore(Item 填 /.*/)确认真实 item 名后重选。
9.3 Prometheus 监控 MySQL(mysqld-exporter)
§5 部署的 MySQL 容器自身也需要被监控(QPS、连接数、InnoDB 缓冲池、慢查询等),通过 mysqld-exporter 把 MySQL 内部指标转成 Prometheus 格式。
MySQL (3306) ──采集──► mysqld-exporter (9104) ──scrape──► Prometheus (9090) ──► Grafana (3000)
Docker Docker 二进制 二进制
9.3.1 创建 MySQL 监控账号
mysqld-exporter 用一个最小权限账号读 MySQL 内部表,不要用 root:
docker exec -i monitor-mysql mysql -uroot -p'ChangeMe_Root@2026' <<'SQL'
CREATE USER 'monitor'@'%' IDENTIFIED BY 'Monitor_Pass@2026'
WITH MAX_USER_CONNECTIONS 5;
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'monitor'@'%';
GRANT SELECT ON performance_schema.* TO 'monitor'@'%';
FLUSH PRIVILEGES;
SELECT User, Host FROM mysql.user WHERE User = 'monitor';
SQL
只授
PROCESS/REPLICATION CLIENT/SELECT,限 5 个并发连接,最小权限原则。
9.3.2 Docker Compose 部署 mysqld-exporter
在 /data/prometheus/mysqld-exporter/ 下创建 docker-compose.yml:
services:
mysqld-exporter:
image: prom/mysqld-exporter:v0.16.0
container_name: mysqld-exporter
restart: unless-stopped
ports:
- "9104:9104"
environment:
# DSN 格式:用户:密码@tcp(主机:端口)/
# 同 Docker 网络用容器名 monitor-mysql;不同网络改 host.docker.internal 或宿主 IP
DATA_SOURCE_NAME: "monitor:Monitor_Pass@2026@tcp(monitor-mysql:3306)/"
command:
- "--collect.info_schema.tables"
- "--collect.info_schema.innodb_metrics"
- "--collect.info_schema.processlist"
- "--collect.info_schema.tables.databases=*"
- "--collect.global_status"
- "--collect.global_variables"
- "--collect.binlog_size"
- "--collect.perf_schema.eventsstatements"
- "--collect.perf_schema.eventswaits"
- "--collect.perf_schema.file_events"
- "--collect.perf_schema.file_instances"
- "--collect.perf_schema.indexiowaits"
- "--collect.perf_schema.tableiowaits"
- "--collect.perf_schema.tablelocks"
启动并验证:
cd /data/prometheus/mysqld-exporter
docker compose up -d
docker compose logs -f mysqld-exporter # 看到 "Listening on :9104" 即成功
# 验证 mysql_up=1 表示 exporter 已连上 MySQL
curl -s http://localhost:9104/metrics | grep "^mysql_up"
⚠️
DATA_SOURCE_NAME里的monitor-mysql是 MySQL 容器名,两个容器要在同一个 Docker 网络才能用容器名互访。若不在同网络:
- 方案 A:在 docker-compose 里加networks:让两个容器加入同一自定义网络
- 方案 B:改用宿主机内网 IP(如172.16.1.30:3306)
- 方案 C:用host.docker.internal(Linux 需配extra_hosts: ["host.docker.internal:host-gateway"])
9.3.3 接入 Prometheus 抓取
编辑 /data/prometheus/conf/prometheus.yml,在 scrape_configs 下追加:
- job_name: 'mysql'
scrape_interval: 15s
static_configs:
- targets: ['localhost:9104']
reload Prometheus(§6.3 启动参数带 --web.enable-lifecycle 才能用此接口):
curl -X POST http://localhost:9090/-/reload
打开 http://<服务器IP>:9090/targets,确认 mysql 这个 job 状态是 UP。
9.3.4 Grafana 导入中文仪表盘
MySQL 监控(必装):
| Dashboard ID | 名称 | 说明 |
|---|---|---|
| 17320 | Mysqld Exporter Dashboard CN | StarsL.cn 出品,全中文,专为 mysqld-exporter 设计 |
导入步骤:Grafana → Dashboards → New → Import → 输入 17320 → Load → 数据源选 Prometheus → Import。
打开后顶部下拉选 MySQL 实例(默认 localhost:9104),即可看到:
- QPS / TPS
- 用户连接数
- InnoDB 缓冲池命中率与内存使用
- 慢查询数
- 表占用空间 Top 10
- Processlist 列表
主机监控(推荐补一个,独立的中文仪表盘):
| Dashboard ID | 名称 | 说明 |
|---|---|---|
| 8919 | Node Exporter for Prometheus Dashboard | StarsL.cn 出品,全中文,主机 CPU/内存/磁盘/网络 |
⚠️ Node Exporter 中文版 ID 是 8919,不是 11074(11074 是同作者的英文版 EN)。导入 8919 后顶部
$node变量选172.16.1.30:9100(你的 node_exporter 实例)即可。若某个面板提示 "Plugin not found"(饼图),装一下:
docker exec -it grafana grafana-cli plugins install grafana-piechart-panel && systemctl restart grafana(Grafana 用 Docker 时把grafana换成对应容器名)。
17320 仪表盘部分面板 No data 的排查:
1. exporter 采集项没开全:对照 §9.3.2 的 command: 列表,缺哪个补哪个,重启容器
2. $node_host 变量配错:17320 里 CPU 使用率面板用了 node_cpu_seconds_total,但变量默认从 mysql_up 拉 instance → 改 Settings → Variables → node_host,把 Metric 改成 node_uname_info,Label filters 清空
3. MariaDB 专属 metric:个别面板用了 MariaDB 才有的指标(如 userstats),MySQL 拉不到属正常,忽略即可
9.3.5 MySQL 配置优化(my.cnf)
挂载自定义 my.cnf 给 MySQL 容器,开启 performance_schema、慢查询日志、InnoDB 调优。
/data/db/mysql-conf/my.cnf:
[mysqld]
# ===== 基础 =====
character-set-server = utf8mb4
collation-server = utf8mb4_bin
default-storage-engine = InnoDB
# ===== 连接数 =====
max_connections = 500 # 看业务量调整
max_connect_errors = 10000
wait_timeout = 600 # 10 分钟空闲断开
interactive_timeout = 600
# ===== InnoDB 核心(innodb_buffer_pool_size 按物理内存 ~70% 调)=====
innodb_buffer_pool_size = 2G
innodb_buffer_pool_instances = 8
innodb_redo_log_capacity = 1G # MySQL 8.0.30+ 替代 innodb_log_file_size
innodb_log_buffer_size = 64M
innodb_flush_log_at_trx_commit = 2 # 2=每秒刷盘(性能), 1=每次提交刷(安全)
innodb_flush_method = O_DIRECT # 绕过 OS 缓存,Linux 必开
innodb_io_capacity = 2000 # SSD 设 2000+,HDD 设 200
innodb_io_capacity_max = 4000
innodb_read_io_threads = 8
innodb_write_io_threads = 8
innodb_file_per_table = 1
# ===== 临时表/排序缓冲 =====
tmp_table_size = 64M
max_heap_table_size = 64M
sort_buffer_size = 4M
join_buffer_size = 4M
# ===== Binlog =====
log_bin = mysql-bin
binlog_format = ROW
binlog_expire_logs_seconds = 604800 # 7 天自动清理
max_binlog_size = 512M
sync_binlog = 0 # 0=系统决定(性能), 1=每次刷(安全)
log_bin_trust_function_creators = 1
# ===== 慢查询(日志放数据卷,不要放 /var/log/mysql,否则容器起不来,见 §13.14)=====
slow_query_log = 1
slow_query_log_file = /var/lib/mysql/slow.log
long_query_time = 2
log_queries_not_using_indexes = 1
log_slow_admin_statements = 1
# ===== Performance Schema(mysqld-exporter 的 perf_schema 采集依赖这个)=====
performance_schema = ON
# ===== 其他 =====
skip_name_resolve = 1 # 禁止 DNS 反向解析,加速连接
explicit_defaults_for_timestamp = 1
# ⚠️ lower_case_table_names 不能在已有数据上改!保持默认 0,见 §13.15
sql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
把 §5.1 的 docker run 迁移到 docker-compose 管理(推荐),新建 /data/db/mysql-conf/docker-compose.yml:
services:
mysql:
image: mysql:8.0
container_name: monitor-mysql
restart: always
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: "ChangeMe_Root@2026"
TZ: "Asia/Shanghai"
volumes:
- /data/db/mysql:/var/lib/mysql
- /data/db/mysql-conf/my.cnf:/etc/mysql/conf.d/my.cnf:ro # 自定义配置
command:
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_bin"
- "--log_bin_trust_function_creators=1"
无痛替换原容器(bind mount 数据不会丢):
cd /data/db/mysql-conf
docker stop monitor-mysql && docker rm monitor-mysql
docker compose up -d
docker logs -f monitor-mysql # 看到 "ready for connections" 即成功
⚠️
innodb_buffer_pool_size按物理内存调整:8G 内存设6G,16G 设12G,32G 设24G。CentOS 7.9 + 4G 内存机器保守设2G。
9.3.6 日志查看方式
# MySQL 错误日志(走 stderr,docker logs 直接看)
docker logs monitor-mysql
# 慢查询日志(写在数据卷里,MySQL 自动创建文件)
tail -f /data/db/mysql/slow.log
# mysqld-exporter 日志
docker logs mysqld-exporter
10. 被监控主机接入(安装 Zabbix Agent)
要监控一台 Linux 主机,需在目标主机装 agent 并指向 Zabbix Server,再在 Web 添加主机。
① 目标主机安装 agent(CentOS 7 示例)
rpm -Uvh https://repo.zabbix.com/zabbix/6.0/rhel/7/x86_64/zabbix-release-latest-6.0.el7.noarch.rpm
yum clean all && yum install -y zabbix-agent
无外网时,拷贝监控服务器编译好的
/data/zabbix/server/sbin/zabbix_agentd+ 配置过去用。
② 配置 /etc/zabbix/zabbix_agentd.conf
Server=<监控服务器IP> # 被动模式:允许该 server 采集
ServerActive=<监控服务器IP> # 主动模式:主动上报
Hostname=web-node-01 # 本机唯一名,与 Web 添加的主机名一致
systemctl enable --now zabbix-agent
# 放行 10050 给监控服务器
firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address=<监控服务器IP>/32 port port=10050 protocol=tcp accept"
firewall-cmd --reload
云服务器安全组同样放行 10050。
③ 监控服务器侧验证连通
/data/zabbix/server/bin/zabbix_get -s <被监控主机IP> -k system.cpu.load # 返回数值即通
④ Zabbix Web 添加主机
1. 数据采集 → 主机 → 创建主机
2. 主机名称=web-node-01;模板选 Linux by Zabbix agent(被动,推荐);主机群组选/建 Linux servers;接口加 Agent,IP=被监控主机 IP,端口 10050
3. 添加后约 1~2 分钟,可用性 ZBX 图标转绿,监测→最新数据出现指标即成功
⑤ 推荐模板与阈值宏
- 首选 Linux by Zabbix agent(被动);agent 在 NAT 后用 Linux by Zabbix agent active(主动)
- 常用阈值宏(主机→宏 里覆盖):{$MEMORY.UTIL.MAX}(内存%默认90)、{$VFS.FS.PUSED.MAX.WARN/CRIT}(磁盘%默认80/90)、{$LOAD_AVG_PER_CPU.MAX.WARN}(每CPU负载默认1.5)
11. 启动顺序与验证
11.1 推荐启动顺序
Docker (MySQL) → Zabbix Server → Zabbix Agent → Prometheus → Grafana → Nginx/PHP
11.2 验证清单
# Docker & MySQL
docker ps | grep monitor-mysql
docker exec -it monitor-mysql mysql -uzabbix -p'Zabbix_Pass@2026' -e "SHOW DATABASES;"
# 服务状态
systemctl status prometheus grafana zabbix-server zabbix-agent nginx php-fpm
# 端口监听
ss -tlnp | egrep '9090|3000|10051|10050|3306|8080'
| 检查项 | 访问地址 | 预期 |
|---|---|---|
| Prometheus | http://IP:9090/targets | targets UP |
| Grafana | http://IP:3000 | 登录页 |
| Zabbix Web | http://IP:8080 | 登录页;登录后顶部无 "Zabbix server is not running" 红字(有则 server 未启动,见 §13.10) |
| MySQL | docker exec 进容器查库 |
库存在 |
12. 常见问题排查
| 现象 | 排查方向 |
|---|---|
df -hT /data 显示的是系统盘 / 数据没落到数据盘 |
数据盘未挂载或挂载到了别处,重新执行 §2.1 的挂载步骤,确认在 mkdir 子目录之前已挂好 |
重启后 /data 空了、服务起不来 |
fstab 未配置或 UUID 写错,数据盘没自动挂载;lsblk 核对后修正 /etc/fstab |
mount -a 报错 |
fstab 条目写错(UUID/文件系统类型),先别重启,核对后再试,避免开机进救援模式 |
yum install 报 Could not resolve mirror.centos.org |
CentOS 7 EOL,未切 vault 源,见 3.1 |
centos-release-scl 装完 SCL 源仍 404 |
SCL 源也 EOL,需按 8.1 的 sed 命令把 baseurl 改到 vault.centos.org |
| PHP 版本仍是 5.4 / Zabbix 前端校验不过 | 未启用 Remi 的 remi-php74,见 8.6 |
Zabbix make 报 C 语法/头文件错误 |
未 source /opt/rh/devtoolset-9/enable 启用 gcc9 |
Grafana 启动报 GLIBC_2.xx not found |
该 Grafana 版本要求更高 glibc,回退到 10.4.x LTS |
docker info 的 Root Dir 不是 /data/docker |
检查 /etc/docker/daemon.json 后 systemctl restart docker;若已有旧数据需迁移 /var/lib/docker |
Zabbix schema 导入报 function creators |
确认容器启动参数带 --log_bin_trust_function_creators=1 |
| Zabbix Server 起不来,日志报连不上 DB | 检查 zabbix_server.conf 的 DBHost=127.0.0.1、端口、密码;确认 MySQL 容器已 -p 3306:3306 |
./configure 报缺 mysql |
安装 mysql-devel / libmysqlclient-dev,或指定 --with-mysql=/usr/bin/mysql_config |
| Grafana 无法连 MySQL | 确认 grafana 库/账号已建,collation 用 utf8mb4_unicode_ci |
| 端口访问不通 | 检查防火墙(firewalld/ufw)、SELinux、云安全组 |
| Prometheus targets DOWN | 被监控端 node_exporter/agent 是否启动、端口是否放行 |
13. 实战部署踩坑记录(本次真实部署问题汇总)
本章按部署顺序记录本次在 CentOS 7.9(腾讯云 VM)实际踩到的问题、报错原文与解决办法,供复现和排错参考。
13.1 Docker 拉镜像超时
- 报错:
docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled ... (Client.Timeout exceeded) - 原因:国内服务器直连 Docker Hub 超时。
- 解决:配置
/etc/docker/daemon.json的registry-mirrors(多源并列,见 §4.2),systemctl restart docker后docker info | grep -A5 "Registry Mirrors"确认生效,再docker pull mysql:8.0。 - 注意:公共加速器时效性强(如中科大 ustc 已停),一次配多个;实在不行给 Docker 单独配代理。
13.2 Zabbix 6.4 源码包 404 下载失败
- 报错:
wget ... zabbix-6.4.15.tar.gz→ERROR 404: Not Found;随后tar报Cannot open: No such file or directory。 - 原因:Zabbix 6.4 已 EOL,官方 stable 目录整个下架,现仅保留
6.0、7.0、7.4分支。 - 解决:改用 6.0 LTS 最新版 6.0.47(对 CentOS 7.9 + PHP 7.4 最友好):
bash VER=6.0.47 wget https://cdn.zabbix.com/zabbix/sources/stable/6.0/zabbix-${VER}.tar.gz
13.3 ${VER} 变量丢失导致 cd 失败
- 现象:
cd /data/zabbix/zabbix-${VER}报No such file or directory,路径里${VER}未展开或为空。 - 原因:
VER=...是当前 shell 的临时变量,换终端 / 新开会话就没了;或上一步 wget 失败根本没解压出目录。 - 解决:wget、tar、cd 保持在同一次会话连续执行;换窗口后先重新
VER=6.0.47。
13.4 前端 nginx 报 403(directory index forbidden)
- 报错(nginx error.log):
directory index of "/data/zabbix/web/" is forbidden - 原因:nginx 配置生效、
root正确,但目录下没有index.php→ 退化成列目录被拒。根因是前端文件没拷对(目录空,或多套了一层ui/)。 - 解决:
bash ls -l /data/zabbix/web/index.php # 确认入口文件在不在 # 若文件在 web/ui/ 下(多一层),拉平: cp -r /data/zabbix/web/ui/* /data/zabbix/web/ && rm -rf /data/zabbix/web/ui - 附:编译版 nginx(
/usr/local/nginx)用nginx -T | grep "listen 8080"确认配置真的加载了;文件属主改成 php-fpm 运行用户,/data /data/zabbix /data/zabbix/web每层 755。
13.5 安装向导预检查 PHP 项失败
- 现象:预检查页
max_input_time当前 60、要求 300、失败(其余 PHP 项同理)。 - 解决:改
php.ini(php -i | grep "Loaded Configuration File"定位实际文件),按 §8.6 的表调好max_execution_time / max_input_time / post_max_size / upload_max_filesize / memory_limit / date.timezone,然后systemctl restart php-fpm(不重启不生效),刷新页面重试。
13.6 配置数据库连接:未找到表 dbversion
- 报错(向导):
无法确定当前 Zabbix 数据库版本:未找到表 "dbversion"。 - 理解:这是能连上库、但库是空的(schema 没导入)——网络/账号/密码其实都是通的。
- 解决:回监控服务器执行 §8.3 导入 schema,导入成功后向导「下一步」即过。
13.7 schema 导入报 ERROR 1419(SUPER privilege)
- 报错:
ERROR 1419 (HY000) at line 2124: You do not have the SUPER privilege and binary logging is enabled ... - 原因:MySQL 开了 binlog,导入触发器/存储过程需要
log_bin_trust_function_creators=1,容器创建时漏了该参数。 - 解决(注意已导入半截,要删库重建再导):
bash # 1) root 打开开关(动态生效) docker exec -i monitor-mysql mysql -uroot -p'ChangeMe_Root@2026' \ -e "SET GLOBAL log_bin_trust_function_creators=1;" # 2) 删库重建 docker exec -i monitor-mysql mysql -uroot -p'ChangeMe_Root@2026' \ -e "DROP DATABASE zabbix; CREATE DATABASE zabbix CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;" # 3) 重新导入 schema→images→data cd /data/zabbix/zabbix-6.0.47/database/mysql cat schema.sql images.sql data.sql | \ docker exec -i monitor-mysql mysql -uzabbix -p'Zabbix_Pass@2026' zabbix - 根治:
docker run时带--log_bin_trust_function_creators=1(§5.1)。
13.8 安装向导最后一步:无法创建配置文件
- 报错(向导):
无法创建配置文件,提示手动保存为/data/zabbix/web/conf/zabbix.conf.php。 - 原因:php-fpm 用户对
web/conf/目录无写权限。 - 解决(二选一):
- A:
mkdir -p /data/zabbix/web/conf && chown -R <php-fpm用户> /data/zabbix/web/conf && chmod 755 ...后点「完成」;装完chmod 644 conf/zabbix.conf.php收回权限。 - B:点「下载配置文件」,
scp到/data/zabbix/web/conf/再点「完成」。
13.9 前端部署在远程 nginx 主备集群的要点
本次前端未装在监控服务器,而是放在已有业务的 nginx 主备集群上,要点:
- php-fpm 必须与 nginx 同机(从本地磁盘读 PHP 文件),所以主备两台都要部署
ui/*+ php-fpm,配置一致。 fastcgi_pass指向 nginx 本机的 php-fpm(127.0.0.1:9000),不是监控服务器。- 向导里 Database host / Zabbix server host 填监控服务器内网 IP(如
172.16.1.30),不是 localhost。 - 监控服务器防火墙 / 云安全组要放行 3306、10051 给主、备两台 IP(含 VIP)。
- 生成的
zabbix.conf.php手动同步到另一台:scp .../conf/zabbix.conf.php root@<备机>:/data/zabbix/web/conf/,否则切到备机会重新弹安装向导。 - 会话默认存 php 本地,主备切换后需重新登录一次(数据不丢);要无感切换需共享 session(DB/Redis),非强需求不建议一开始就上。
- 编译版 nginx 配置在
/usr/local/nginx/conf/,改动前先备份(这台有one.ixiaozu.cn等线上业务),nginx -t通过再reload。
13.10 登录后提示 "Zabbix server is not running"
- 现象:前端能登录(
Admin / zabbix),但顶部红字告警 server 未运行。 - 原因:前端只是 Web,后端
zabbix_server进程还没启动。 - 解决:在监控服务器按 §8.4 配好
zabbix_server.conf、§8.5systemctl enable --now zabbix-server,红字即消失。
13.11 Grafana 装插件报 permission denied
- 报错:
Failed to install plugin ... open /data/grafana/data/plugins: permission denied(Web 装插件 status=500)。 - 原因:Grafana 以
grafana用户运行,但/data/grafana目录属主是 root(用 root 建的目录),写不进去。 - 解决:
bash chown -R grafana:grafana /data/grafana chmod 755 /data /data/grafana systemctl restart grafana
之后重装。用 CLI 装时也要sudo -u grafana,否则又生成 root 属主文件;离线解压装完同样要chown -R grafana:grafana。
13.12 Grafana 页面白屏 / Minified React error #130(插件与版本不兼容)
- 报错:打开 Zabbix 插件页
An unexpected error happened+Minified React error #130,堆栈含alexanderzobnin-zabbix-datasource/module.js。 - 原因:Zabbix 插件版本与 Grafana 版本不兼容。查插件要求:
bash grep -i grafanaDependency /data/grafana/data/plugins/alexanderzobnin-zabbix-app/plugin.json # 例:">=11.6.0-0",而当前 Grafana 11.1.0 < 11.6.0 → 崩溃 - 解决(升级 Grafana,推荐;CentOS 7.9 升到刚好满足的 11.6.x,勿直接上 13.x):
```bash
# 0) 备份(降级不可逆)
cp -a /data/grafana/data /data/grafana/data.bak.$(date +%F)
docker exec monitor-mysql mysqldump -uroot -p'ChangeMe_Root@2026' grafana \
> /data/src/grafana-db-$(date +%F).sql # 若用 MySQL 后端
# 1) 下载并解压 11.6.0
cd /data/src
VER=11.6.0
wget https://dl.grafana.com/oss/release/grafana-${VER}.linux-amd64.tar.gz
tar -zxf grafana-${VER}.linux-amd64.tar.gz -C /data/grafana/
mv /data/grafana/grafana-v${VER} /data/grafana/grafana-${VER} 2>/dev/null
chown -R grafana:grafana /data/grafana/grafana-${VER}
# 2) systemd 指向新目录并重启
sed -i 's/grafana-11.1.0/grafana-11.6.0/g' /etc/systemd/system/grafana.service
systemctl daemon-reload && systemctl restart grafana
# 3) 验证(重点看 glibc)
systemctl status grafana --no-pager | head -8
journalctl -u grafana -n 40 --no-pager | grep -iE "GLIBC|error|version"
``
- **若报GLIBC_2.xx not found**:说明该 Grafana 版本在 CentOS 7 跑不了,回滚(把 sed 改回grafana-11.1.0)并改走「降插件版本」:grafana cli plugins install alexanderzobnin-zabbix-app <兼容旧版>。
- **注意**:升级 Grafana 只换自身二进制,/data/grafana/data(仪表盘/插件/配置)保留;**不影响 Zabbix、Prometheus**(Grafana 只是通过数据源读它们的数据)。改完记得**强刷浏览器**清缓存。
- **本次实测**:CentOS 7.9 升级到 **Grafana 11.6.0 正常运行,无 GLIBC 报错**,插件页恢复正常。启动日志里的Adding GroupVersion ... to ResourceManager是 11.x 新架构的正常输出;升级后浏览器旧会话会出现401 token needs to be rotated`,强刷/重新登录即可,非故障。
13.13 Grafana 仪表盘全是 N/A / No data
按数据流 agent → Server → MySQL → API → Grafana 从上游往下逐层排查:
- 只读账号权限没生效(最隐蔽):现象是数据源 Save&test 成功,但仪表盘 Host 下拉空、全 N/A。原因是给用户配主机权限的位置错了——Zabbix 提示「权限只能被指派给用户群组」,必须在 用户 → 用户群组 → 该群组 → 主机权限 里对主机组授 读(Read),在"用户"页配无效。
- 顶部变量级联没选:
Group和Host是级联的,先选 Group,Host 才有值;不选 Host 全 N/A。总览页 Host 要选 All。 - 社区仪表盘 item 名不匹配:从 grafana.com 导入的老仪表盘(如葡语
Uso de CPU那种)panel 写死的 item 名和 Zabbix 6.0Linux by Zabbix agent模板(Linux: CPU idle time等)对不上,全 N/A。用本文档随附的定制模板,或用 Explore(Item 填/.*/)确认真实 item 名后在 panel 里重选。 - 验证数据链路:Grafana 左侧 Explore → 数据源 Zabbix → Group/Host 选好 → Item
/.*/,能列出几十个 item 并出数据,即证明链路 100% 正常,问题必在仪表盘(变量或 item 名)。 - 时间范围:
Last 5 minutes有时擦边,拉到Last 1 hour。
13.14 MySQL 容器死循环重启(my.cnf 日志目录权限)
- 现象:
docker logs monitor-mysql反复打印Entrypoint script for MySQL Server 8.0.46 started.+Switching to dedicated user 'mysql',每 30 秒一次,无任何错误信息 - 原因:
my.cnf里把log_error指向了/var/log/mysql/error.log,但容器内该目录不存在或非 root 用户无写权限。MySQL 切换到mysql用户后写日志失败,直接退出,restart: always又拉起,形成死循环 - 解决:从
my.cnf删除log_error配置项,让 MySQL 错误日志走 stderr(docker logs直接看);慢查询日志放/var/lib/mysql/slow.log(数据卷里,一定有写权限,MySQL 自动创建文件) - 延伸:如果非要把日志挂到宿主机,需提前
mkdir -p /data/db/mysql-log && chown 999:999 /data/db/mysql-log(mysql 用户 uid=999),并在 docker-compose 里加- /data/db/mysql-log:/var/log/mysql。CentOS 7 若 SELinux 是 Enforcing 还需chcon -Rt svirt_sandbox_file_t /data/db/mysql-log,否则即使属主对了也写不进去
13.15 MySQL 启动报 Different lower_case_table_names settings
- 报错:
[ERROR] [MY-011087] Different lower_case_table_names settings for server ('1') and data dictionary ('0').+Data Dictionary initialization failed - 原因:
my.cnf里设了lower_case_table_names = 1,但原有数据是用默认值0初始化的。MySQL 8.0 不允许在已有数据上改这个值(5.7 可以,8.0 改了数据字典机制) - 解决:从
my.cnf删除(或注释掉)lower_case_table_names配置项,保持默认0 - 延伸:如果业务强需求
lower_case_table_names = 1(如表名大小写不敏感),只能在首次初始化时设——即清空/data/db/mysql重新建库,所有数据丢失,仅适用于全新部署
13.16 MySQL 启动 warning:innodb_log_file_size / default_authentication_plugin 已弃用
- 现象:MySQL 8.0.30+ 启动日志打印 warning,但不影响启动
- 解决:用新参数替代
innodb_log_file_size = 512M→innodb_redo_log_capacity = 1G(8.0.30 起用单一参数替代innodb_log_file_size×innodb_log_files_in_group)default_authentication_plugin = mysql_native_password→authentication_policy = mysql_native_password- 注意:
binlog_format同样已弃用(MySQL 8.0 默认 ROW),保留不报错但可以删
13.17 Grafana 17320 仪表盘 CPU 使用率面板 No data
- 现象:导入 17320 后大部分面板有数据,唯独 "CPU 使用率" 面板空白
- 原因:该面板查询用了
node_cpu_seconds_total(来自 node_exporter),但仪表板的$node_host变量默认从mysql_upmetric 拉 instance,自然拉不到 node_exporter 的实例 - 解决:Settings → Variables → 编辑
node_host: - Type: Query
- Data source: Prometheus
- Query type: Label values
- Label:
instance - Metric:
node_uname_info(不是mysql_up) - Label filters: 清空(删掉 vendor/account/group/name 这些 MySQL 专属标签)
- Regex:
/(.*:.*)/(保留默认) - 简化方案:单台机器直接用 Constant 类型,Value 填
172.16.1.30(你的 node_exporter IP) - 更优方案:导入独立的 Node Exporter 中文仪表盘 ID 8919,分两个仪表盘:17320 看 MySQL,8919 看主机资源,互不干扰
13.18 Node Exporter 中文仪表盘 ID 易混淆
- 现象:导入 11074 后发现全是英文,不是预期的中文版
- 原因:StarsL.cn 同作者出品了两个版本,名字相似容易搞错:
11074= Node Exporter Dashboard EN 20201010(英文版)❌8919= Node Exporter for Prometheus Dashboard(中文版)✅- 解决:删掉 11074,重新导入 8919
- 延伸:StarsL.cn 系列配套中文仪表盘(风格统一,推荐都用):
- MySQL → 17320
- 主机 → 8919
- Redis → 17507
14. New API 主备集群(Docker)Prometheus 监控与钉钉告警
现状与前提
- New API 已通过 Docker 部署为主备集群(主、备两台节点,容器名new-api),对外统一通过外网地址(域名 / 外网 VIP,本文以https://newapi.example.com为例)访问。
- 监控服务器上尚未安装 Alertmanager,本章包含它从零安装的完整流程(§14.4)。
- 本章只新增监控与告警,不改动任何已有 New API、MySQL、Redis、nginx 配置。本章新增组件(除 cAdvisor / node_exporter 装在 New API 节点上,其余都装在监控服务器):
组件 部署方式 作用 blackbox_exporter Docker 经外网地址探测 /api/status(可用性 / 时延)Alertmanager Docker(§14.4 新装) 告警分组、路由、静默、恢复通知 prometheus-webhook-dingtalk Docker(§14.4 新装) 把告警转成钉钉群机器人消息 cAdvisor + node_exporter(可选) Docker / 二进制 容器与主机资源指标
用户 ──► https://newapi.example.com ──► nginx 主备入口 ──► New API 主/备节点(Docker)
监控服务器 Prometheus
├── blackbox_exporter ──外网探测──► https://newapi.example.com/api/status (统一入口链路)
│ ──► 主节点外网地址 /api/status (定位单点故障)
│ ──► 备节点外网地址 /api/status
├── cAdvisor(可选) ──► 两台节点 :8080 容器 CPU / 内存
└── node_exporter(可选) ──► 两台节点 :9100 主机 CPU / 内存 / 磁盘
告警链路:Prometheus ──告警规则──► Alertmanager ──webhook──► 钉钉适配器 ──► 钉钉群机器人
展示链路:Grafana ──► Prometheus
为什么用黑盒探测而不是应用内部指标:不依赖 New API 版本内部的指标名,应用升级不会导致监控失效;探测走外网地址,覆盖 DNS → nginx 主备 → 后端容器的完整真实访问链路,与用户实际体验一致。
14.1 部署 blackbox_exporter(黑盒探测,监控服务器)
blackbox_exporter 部署在监控服务器,由它经外网向 New API 的 /api/status 发起探测。先确认监控服务器能访问外网目标:
curl -sS -o /dev/null -w '%{http_code} %{time_total}s\n' https://newapi.example.com/api/status
# 期望输出:200 0.xxxs
(1)创建探测模块配置
sudo mkdir -p /data/blackbox-exporter/conf
sudo tee /data/blackbox-exporter/conf/blackbox.yml >/dev/null <<'EOF'
modules:
newapi_status:
prober: http
timeout: 10s
http:
method: GET
valid_status_codes: [200]
fail_if_body_not_matches_regexp:
- '"success"[[:space:]]*:[[:space:]]*true'
EOF
sudo docker run -d \
--name blackbox-exporter \
--restart unless-stopped \
--network host \
-v /data/blackbox-exporter/conf/blackbox.yml:/config/blackbox.yml:ro \
quay.io/prometheus/blackbox-exporter:latest \
--config.file=/config/blackbox.yml
容器用
--network host,监听9115。探测走外网,要求宿主机 DNS 与外网出口正常;quay.io拉取慢可先配镜像加速(§4.2)。
验证(应返回 probe_success 1):
curl -s 'http://127.0.0.1:9115/probe?target=https://newapi.example.com/api/status&module=newapi_status' | grep probe_success
14.2(可选)在两台 New API 节点部署 cAdvisor + node_exporter
(1)cAdvisor(容器指标)
docker run -d \
--name cadvisor \
--restart unless-stopped \
--privileged \
--network host \
-v /:/rootfs:ro \
-v /var/run:/var/run:rw \
-v /sys:/sys:ro \
-v /var/lib/docker:/var/lib/docker:ro \
swr.cn-north-4.myhuaweicloud.com/ddn-k8s/gcr.io/cadvisor/cadvisor:v0.49.1
(2)node_exporter(主机指标)
两台节点按 §6.5 安装并启动 node_exporter(监听 9100)。
⚠️ 这两类采集是 Prometheus 直连节点 IP:端口。若监控服务器与 New API 节点之间只能走外网,需改用节点外网 IP,并在安全组 / 防火墙仅对监控服务器出口 IP 放行
8080(cAdvisor)和9100(node_exporter)。若网络策略不允许,可整节跳过:可用性告警不受影响,只是少了容器 / 主机资源面板。
14.3 Prometheus 增加采集任务与告警规则
在 /data/prometheus/conf/prometheus.yml 顶部已有配置后补充以下内容。请把占位符替换为实际的外网地址:
https://newapi.example.com→ New API 统一入口域名(用户实际访问地址)<主节点外网地址>/<备节点外网地址>→ 两台节点各自的外网访问地址(外网 IP 或域名,含端口)
alerting指向的127.0.0.1:9093(Alertmanager)将在 §14.4 安装,先配上即可,装完自动生效。
alerting:
alertmanagers:
- static_configs:
- targets: ['127.0.0.1:9093']
rule_files:
- /data/prometheus/conf/rules/newapi-alerts.yml
scrape_configs:
# ……保留原有 prometheus、node 等 job ……
# 分别探测主、备 New API 节点;可定位是哪台异常
- job_name: blackbox-newapi-node
metrics_path: /probe
params:
module: [newapi_status]
static_configs:
- targets:
- http://<主节点外网地址>/api/status # 如 http://1.2.3.4:3000/api/status
- http://<备节点外网地址>/api/status # 如 http://5.6.7.8:3000/api/status
labels:
service: newapi
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: 127.0.0.1:9115
# 探测用户实际访问的 nginx VIP/域名,验证完整入口链路
- job_name: blackbox-newapi-vip
metrics_path: /probe
params:
module: [newapi_status]
static_configs:
- targets: ['https://newapi.example.com/api/status']
labels:
service: newapi
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: 127.0.0.1:9115
# 以下两个 job 仅当按 §14.2 部署了 cAdvisor / node_exporter 时才配置
- job_name: cadvisor-newapi
static_configs:
- targets: ['<主节点IP>:8080', '<备节点IP>:8080']
- job_name: node-newapi
static_configs:
- targets: ['<主节点IP>:9100', '<备节点IP>:9100']
创建规则目录与告警规则文件:
sudo mkdir -p /data/prometheus/conf/rules
sudo tee /data/prometheus/conf/rules/newapi-alerts.yml >/dev/null <<'EOF'
groups:
- name: newapi-alerts
rules:
- alert: NewApiNodeDown
expr: probe_success{job="blackbox-newapi-node"} == 0
for: 2m
labels:
severity: critical
service: newapi
annotations:
summary: "New API 节点不可用"
description: "{{ $labels.instance }} 的 /api/status 连续 2 分钟探测失败。"
- alert: NewApiAllNodesDown
expr: sum(probe_success{job="blackbox-newapi-node"}) < 1
for: 1m
labels:
severity: critical
service: newapi
annotations:
summary: "New API 主备节点全部不可用"
description: "主、备节点均未通过 /api/status 健康检查。"
- alert: NewApiVipDown
expr: probe_success{job="blackbox-newapi-vip"} == 0
for: 2m
labels:
severity: critical
service: newapi
annotations:
summary: "New API 统一访问入口不可用"
description: "{{ $labels.instance }} 连续 2 分钟探测失败,请检查 nginx VIP、DNS、证书和后端。"
- alert: NewApiHighLatency
expr: probe_duration_seconds{job=~"blackbox-newapi-node|blackbox-newapi-vip"} > 3
for: 5m
labels:
severity: warning
service: newapi
annotations:
summary: "New API 健康检查响应慢"
description: "{{ $labels.instance }} 响应时长 {{ $value | printf \"%.2f\" }} 秒,持续超过 3 秒。"
- alert: NewApiCadvisorDown
expr: up{job="cadvisor-newapi"} == 0
for: 3m
labels:
severity: warning
service: newapi
annotations:
summary: "New API 节点 cAdvisor 不可达"
description: "{{ $labels.instance }}:8080 无法采集 Docker 容器指标。"
- alert: NewApiHostCpuHigh
expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{job="node-newapi",mode="idle"}[5m])) * 100) > 90
for: 10m
labels:
severity: warning
service: newapi
annotations:
summary: "New API 节点 CPU 使用率过高"
description: "{{ $labels.instance }} CPU 使用率持续 10 分钟高于 90%。"
- alert: NewApiHostMemoryHigh
expr: (1 - node_memory_MemAvailable_bytes{job="node-newapi"} / node_memory_MemTotal_bytes{job="node-newapi"}) * 100 > 90
for: 10m
labels:
severity: warning
service: newapi
annotations:
summary: "New API 节点内存使用率过高"
description: "{{ $labels.instance }} 内存使用率持续 10 分钟高于 90%。"
EOF
sudo -u prometheus /data/prometheus/prometheus-2.53.0/promtool check config /data/prometheus/conf/prometheus.yml
sudo systemctl reload prometheus
prometheus.yml只能保留一个顶层scrape_configs、alerting和rule_files。若已有同名顶层项,将本节相应内容合并进去,不要重复创建。
在 Prometheus 的 Status → Targets 中确认 blackbox-newapi-node、blackbox-newapi-vip(以及可选的 cadvisor-newapi、node-newapi)均为 UP。
14.4 安装 Alertmanager 与钉钉告警适配器(本次新装)
监控服务器上尚未安装 Alertmanager,本节是从零安装的完整流程。告警链路由两个容器组成:
- Alertmanager:接收 Prometheus 推送的告警,负责分组、去重、路由、恢复通知;
- prometheus-webhook-dingtalk:Alertmanager 通过通用 Webhook 调用它,它再按钉钉机器人协议(支持加签
secret)把消息发到群里。参考:Prometheus 官方 Webhook 集成说明、适配器项目。
14.4.1 创建钉钉自定义机器人
在目标钉钉群:群设置 → 智能群助手 → 添加机器人 → 自定义机器人。
- 安全设置建议选加签,复制 Webhook URL 与
SEC...密钥;若公司策略要求,也可同时设置关键字Prometheus。 - 不要把 URL 或
SEC密钥提交到 Git、截图或公开文档。
14.4.2 创建目录与配置文件
在监控服务器执行:
sudo mkdir -p /data/alertmanager/{conf,data}
sudo mkdir -p /data/dingtalk/conf
创建 /data/dingtalk/conf/config.yml:
targets:
newapi:
url: https://oapi.dingtalk.com/robot/send?access_token=<钉钉机器人Token>
secret: SEC<钉钉机器人加签密钥>
创建 /data/alertmanager/conf/alertmanager.yml:
global:
resolve_timeout: 5m
route:
receiver: dingtalk-newapi
group_by: [alertname, service, instance]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receivers:
- name: dingtalk-newapi
webhook_configs:
- url: http://dingtalk-webhook:8060/dingtalk/newapi/send
send_resolved: true
14.4.3 编写 docker-compose.yml(Alertmanager + 钉钉适配器)
创建 /data/alertmanager/docker-compose.yml:
services:
alertmanager:
image: quay.io/prometheus/alertmanager:latest
container_name: alertmanager
restart: unless-stopped
ports:
- "127.0.0.1:9093:9093"
volumes:
- /data/alertmanager/conf/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
- /data/alertmanager/data:/alertmanager
command:
- --config.file=/etc/alertmanager/alertmanager.yml
- --storage.path=/alertmanager
- --web.enable-lifecycle
depends_on:
- dingtalk-webhook
dingtalk-webhook:
image: timonwong/prometheus-webhook-dingtalk:v2.1.0
container_name: dingtalk-webhook
restart: unless-stopped
volumes:
- /data/dingtalk/conf/config.yml:/etc/prometheus-webhook-dingtalk/config.yml:ro
command:
- --config.file=/etc/prometheus-webhook-dingtalk/config.yml
- --web.enable-ui
14.4.4 启动、校验并接入 Prometheus
cd /data/alertmanager
docker compose up -d
docker ps --filter name=alertmanager --filter name=dingtalk-webhook
# 配置校验(应输出 SUCCESS)
docker exec alertmanager amtool check-config /etc/alertmanager/alertmanager.yml
# 确认 prometheus.yml 已含 alerting 配置(§14.3 已加),并重载生效
grep -A3 '^alerting' /data/prometheus/conf/prometheus.yml
curl -X POST http://localhost:9090/-/reload
# Prometheus 侧确认告警链路:
# http://<监控服务器IP>:9090/alerts 查看规则状态
# http://<监控服务器IP>:9090/api/v1/alertmanagers 应能看到 127.0.0.1:9093
# Alertmanager 自身 Web UI(仅监听本机,需 SSH 转发或在服务器本地访问):
# http://127.0.0.1:9093
14.4.5 告警链路测试(验证钉钉通知)
临时停止主节点 new-api 容器,等待 2 分钟,钉钉群应收到 NewApiNodeDown;若同时停掉备节点,1 分钟后应收到 NewApiAllNodesDown。随后恢复容器,应收到恢复通知。
# 在对应 New API 节点执行,测试完成立即恢复
docker stop new-api
docker start new-api
14.5 Grafana 展示与常用 PromQL
Grafana 添加(或复用)Prometheus 数据源后,新建 New API 主备集群监控 仪表盘。推荐面板:
| 面板 | PromQL |
|---|---|
| 主备节点可用性 | probe_success{job="blackbox-newapi-node"} |
| VIP/域名可用性 | probe_success{job="blackbox-newapi-vip"} |
| 健康检查响应时延 | probe_duration_seconds{job=~"blackbox-newapi-node|blackbox-newapi-vip"} |
| New API 容器 CPU | sum by (instance) (rate(container_cpu_usage_seconds_total{job="cadvisor-newapi",name=~".*new-api.*"}[5m])) * 100 |
| New API 容器内存 | sum by (instance) (container_memory_working_set_bytes{job="cadvisor-newapi",name=~".*new-api.*"}) |
| 节点 CPU 使用率 | 100 - avg by (instance) (rate(node_cpu_seconds_total{job="node-newapi",mode="idle"}[5m])) * 100 |
| 节点内存使用率 | (1 - node_memory_MemAvailable_bytes{job="node-newapi"} / node_memory_MemTotal_bytes{job="node-newapi"}) * 100 |
14.6 运维检查清单
# 两节点:确认容器健康、查看日志
docker ps --filter name=new-api
docker logs --tail=100 new-api
curl -s http://127.0.0.1:3000/api/status
# Prometheus 服务器:确认黑盒探测自身可用
curl -G 'http://127.0.0.1:9115/probe' \
--data-urlencode 'target=https://newapi.example.com/api/status' \
--data-urlencode 'module=newapi_status'
# 配置变更后验证并热加载 Prometheus
sudo -u prometheus /data/prometheus/prometheus-2.53.0/promtool check config /data/prometheus/conf/prometheus.yml
sudo systemctl reload prometheus
附:版本对照(本文所用)
| 组件 | 版本 |
|---|---|
| 操作系统 | CentOS 7.9.2009 (x86_64) |
| Docker CE | 最新稳定 |
| MySQL | 8.0 |
| Prometheus | 2.53.0 |
| node_exporter | 1.8.1 |
| mysqld-exporter | v0.16.0 |
| blackbox_exporter | 官方稳定版(生产固定镜像标签) |
| cAdvisor | 官方稳定版(生产固定镜像标签) |
| Alertmanager | 官方稳定版(生产固定镜像标签) |
| 钉钉适配器 | prometheus-webhook-dingtalk v2.1.0 |
| New API | calciumion/new-api(生产固定镜像标签) |
| Grafana | 11.6.0(需 ≥ 插件 grafanaDependency;CentOS 7.9 勿上 13.x) |
| Zabbix | 6.0.47 LTS(6.4 已 EOL 下架) |
| gcc(编译用) | 9(devtoolset-9) |
| PHP(前端用) | 7.4(Remi 源) |
⚠️ 文档中所有密码(
ChangeMe_Root@2026、Zabbix_Pass@2026、Grafana_Pass@2026、Monitor_Pass@2026)为示例,上线前务必替换为强密码,并妥善保管。