Zabbix 7.0 LTS 双机部署实录
手上两台云主机跑了大半年,一直是裸奔状态——没监控、没告警,全靠时不时登上去 top 一眼。周末抽了半天把 Zabbix 搭起来,一台做服务端,一台做被监控机。
环境:两台都是 Ubuntu 24.04,Zabbix 用 7.0 这个 LTS 版本。
最终架构
┌─────────────────────────┐
浏览器 ────────▶│ Server A │
│ Nginx :8081 │
│ PHP-FPM 8.3 │
│ Zabbix Server :10051 │
│ MariaDB 10.11 │
│ Zabbix Agent (监控自身) │
└────────────┬────────────┘
│ 轮询 :10050
▼
┌─────────────────────────┐
│ Server B │
│ Zabbix Agent 2 │
└─────────────────────────┘Server A 装全套(Server + Web + 数据库),Server B 只装一个 Agent。Server B 不跑数据库,内存占用很低,1G 内存的机器也够。
下文出现的地址统一用占位符,实际部署时替换成自己的:
| 占位符 | 说明 |
|---|---|
203.0.113.10 | Server A 公网 IP |
198.51.100.20 | Server B 公网 IP |
zabbix.example.com | 指向 Server A 的域名 |
ZBX_DB_PASS | Zabbix 数据库密码,自己换 |
动手前先定三件事
这三件事如果装到一半再改,返工成本很高,先想清楚。
一、数据库用 MySQL 还是 MariaDB。 官方文档默认写的是 MySQL,我一开始也打算照做。结果发现 Server A 只有 2G 内存,而且上面还跑着别的东西,空闲内存不到 900M。MySQL 8.0 的默认配置光 InnoDB 缓冲池就要吃掉几百兆,装完大概率被 OOM Killer 干掉。所以换成了 MariaDB——同源、协议兼容、内存开销小一截,配上一份低内存参数就能稳住。
二、Web 端口。 Zabbix 官方的 Nginx 配置模板默认监听 80。但如果你的机器上已经跑了别的东西占了 80,别急着把它停掉腾地方——Zabbix 完全可以挂在别的端口上,改一行配置的事。我这次就是因为 80/443 已经被 Caddy 占着,把 Zabbix 挪到了 8081,两者互不干扰。
三、版本选 LTS。 Zabbix 的版本号分 LTS 和标准版。7.0 是 LTS,支持到 2029 年,够用很久了。追最新的标准版,支持周期可能只有一年半,不值当。
第一步:先看看机器上已经有什么
这一步很多人跳过,我建议别跳。尤其是云主机,镜像里往往预装了你不知道的东西。
# 系统版本和架构
lsb_release -d
uname -m
# 内存、磁盘、CPU
free -h
df -h /
nproc
# 时区
timedatectl
# 谁在占端口
sudo ss -tlnp这次就是靠最后一条命令发现 Server A 的 80 和 443 早就被一个反向代理占了,8080 上还挂着 Docker 容器。如果当时闷头装下去,Nginx 启动直接就会因为端口冲突失败。
输出里如果看到一堆不认识的进程,先别慌着清理。搞清楚它们干什么的再说,很多是云厂商的监控组件或者你自己以前部署的服务。
顺手把时区设对,Zabbix 的图表时间轴会用到:
sudo timedatectl set-timezone Asia/ShanghaiServer A(一):装数据库
sudo apt update
sudo apt install -y mariadb-server mariadb-client装完先别急着启动,把低内存参数写进去。MariaDB 在 Ubuntu 上会读 /etc/mysql/mariadb.conf.d/ 下的所有 .cnf 文件,新建一个:
sudo tee /etc/mysql/mariadb.conf.d/99-zabbix-lowmem.cnf > /dev/null <<'EOF'
[mysqld]
innodb_buffer_pool_size = 128M
innodb_log_file_size = 48M
innodb_flush_log_at_trx_commit = 2
innodb_file_per_table = 1
innodb_default_row_format = dynamic
max_connections = 60
table_open_cache = 400
tmp_table_size = 32M
max_heap_table_size = 32M
performance_schema = OFF
log_bin_trust_function_creators = 1
character-set-server = utf8mb4
collation-server = utf8mb4_bin
EOF几个参数说明一下:
innodb_buffer_pool_size从默认的 128M 起步,内存充足的话可以往上加。2G 的机器就别贪心。performance_schema = OFF能省几十兆,对小型监控场景没什么影响。innodb_default_row_format = dynamic是 Zabbix 的硬性要求,MariaDB 10.2 以后默认就是这个值,写上是图个保险。log_bin_trust_function_creators = 1是为了后面导入建库脚本时不被二进制日志卡住。
如果你的机器内存有 8G 以上,把 innodb_buffer_pool_size 提到 1G 甚至 2G 都行,性能会好很多。然后启动:
sudo systemctl enable --now mariadb
sudo systemctl status mariadbServer A(二):装 Zabbix 服务端
加官方源。注意源包的版本号里带着系统代号,Ubuntu 24.04 就是 ubuntu24.04:
cd /tmp
wget https://repo.zabbix.com/zabbix/7.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_latest_7.0+ubuntu24.04_all.deb
sudo dpkg -i zabbix-release_latest_7.0+ubuntu24.04_all.deb
sudo apt update装组件:
sudo apt install -y \
zabbix-server-mysql \
zabbix-frontend-php \
zabbix-nginx-conf \
zabbix-sql-scripts \
zabbix-agent这几个包各管什么:
zabbix-server-mysql—— 服务端主程序zabbix-frontend-php—— Web 界面。虽然名字带 php,但里面并不含 PHP 运行环境,apt会自动把php-fpm作为依赖装上zabbix-nginx-conf—— Nginx 的配置模板zabbix-sql-scripts—— 建库用的 SQL 脚本zabbix-agent—— 顺手装上,用来监控服务端自己
7.0 把 SQL 脚本单独拆成了zabbix-sql-scripts包。6.0 及以前这些脚本是塞在zabbix-server-mysql里的,路径也不一样。照着旧教程做会找不到文件。
Server A(三):建库导表
登录数据库:
sudo mariadb在 SQL 提示符里执行:
CREATE DATABASE zabbix CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
CREATE USER 'zabbix'@'localhost' IDENTIFIED BY 'ZBX_DB_PASS';
GRANT ALL PRIVILEGES ON zabbix.* TO 'zabbix'@'localhost';
SET GLOBAL log_bin_trust_function_creators = 1;
FLUSH PRIVILEGES;
EXIT;字符集必须是 utf8mb4 配 utf8mb4_bin,这是 Zabbix 的硬要求,用 utf8mb4_general_ci 会在导入时报错。
导入表结构。脚本是 gzip 压缩的,直接用 zcat 管道喂给客户端:
zcat /usr/share/zabbix-sql-scripts/mysql/server.sql.gz \
| mariadb --default-character-set=utf8mb4 -uzabbix -p'ZBX_DB_PASS' zabbix导入过程视机器性能而定,我这边 200 多张表用了十几秒。
导完把刚才开的那个参数关掉:
sudo mariadb -e "SET GLOBAL log_bin_trust_function_creators = 0;"确认一下结果,正常应该有 200 张以上的表:
sudo mariadb -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='zabbix';"Server A(四):改配置
服务端配置
编辑 /etc/zabbix/zabbix_server.conf,DBName 和 DBUser 装包时已经填好了,要找的是 DBPassword——它默认是注释掉的:
DBName=zabbix
DBUser=zabbix
DBPassword=ZBX_DB_PASS改完可以这样确认:
sudo grep -E '^(DBName|DBUser|DBPassword)=' /etc/zabbix/zabbix_server.confNginx 配置
zabbix-nginx-conf 会生成 /etc/nginx/conf.d/zabbix.conf,但里面 listen 和 server_name 两行是注释状态,必须手动放开,否则 Nginx 加载后不监听任何端口。
sudo sed -i 's|^#\s*listen\s*8080;| listen 8081;|' /etc/nginx/conf.d/zabbix.conf
sudo sed -i 's|^#\s*server_name\s*example.com;| server_name _;|' /etc/nginx/conf.d/zabbix.conf模板里写的占位端口是 8080,按自己情况改。server_name 填 _ 表示接受任意 Host,后面要绑域名再换成具体域名。
改完检查语法:
sudo nginx -t跳过 Web 安装向导
正常流程是启动服务后打开浏览器,走一遍 Web 安装向导。但那样每次部署都要手工点一遍,不方便自动化。
Zabbix 的判断逻辑很简单:/etc/zabbix/web/zabbix.conf.php 存在就跳过向导。所以我们直接把这个文件写出来:
sudo tee /etc/zabbix/web/zabbix.conf.php > /dev/null <<'PHPEOF'
<?php
$DB['TYPE'] = 'MYSQL';
$DB['SERVER'] = 'localhost';
$DB['PORT'] = '0';
$DB['DATABASE'] = 'zabbix';
$DB['USER'] = 'zabbix';
$DB['PASSWORD'] = 'ZBX_DB_PASS';
$DB['SCHEMA'] = '';
$DB['ENCRYPTION'] = false;
$DB['KEY_FILE'] = '';
$DB['CERT_FILE'] = '';
$DB['CA_FILE'] = '';
$DB['VERIFY_HOST'] = false;
$DB['CIPHER_LIST'] = '';
$ZBX_SERVER = 'localhost';
$ZBX_SERVER_PORT = '10051';
$ZBX_SERVER_NAME = 'Zabbix';
$IMAGE_FORMAT_DEFAULT = IMAGE_FORMAT_PNG;
PHPEOF注意 $DB['TYPE'] 这里填 MYSQL,即便底层是 MariaDB——因为 Zabbix 把 MariaDB 归在 MySQL 家族里,两侧驱动是共用的。
权限要设对,这个文件里有数据库密码:
sudo chown www-data:www-data /etc/zabbix/web/zabbix.conf.php
sudo chmod 640 /etc/zabbix/web/zabbix.conf.phpPHP 时区
PHP 不设时区会在日志里刷警告,顺手加上:
echo 'date.timezone = Asia/Shanghai' \
| sudo tee /etc/php/8.3/fpm/conf.d/99-zabbix-timezone.iniUbuntu 24.04 自带的 PHP 是 8.3,版本号对不上就 ls /etc/php/ 看一眼。
Server A(五):配置 Agent 并启动
Zabbix Agent 装完默认的 Server 是 127.0.0.1,服务端监控自己正好用这个值,确认一下就行:
grep -E '^(Server|ServerActive|Hostname)=' /etc/zabbix/zabbix_agentd.conf然后启动全部服务:
sudo systemctl daemon-reload
sudo systemctl restart php8.3-fpm
sudo systemctl restart zabbix-server zabbix-agent nginx
sudo systemctl enable zabbix-server zabbix-agent nginx php8.3-fpm mariadb注意 php-fpm 要先于 zabbix-server 重启,因为 Nginx 通过 unix socket 连它,顺序反了第一次请求可能 502。
检查状态:
for s in mariadb php8.3-fpm nginx zabbix-server zabbix-agent; do
printf '%-16s %s\n' "$s" "$(systemctl is-active $s)"
done五个都是 active 才算过。
Server A(六):验证
端口有没有起来:
sudo ss -tlnp | grep -E ':10051|:8081'Web 能不能访问:
curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://127.0.0.1:8081/
curl -s http://127.0.0.1:8081/ | grep -oE '<title>[^<]*</title>'如果标题是 Zabbix 而不是安装向导的标题,说明配置文件生效了。
最直接的办法是调一次 API,能返回版本号就说明 Server、数据库、Web 三者这条链路全通了:
curl -s -X POST http://127.0.0.1:8081/api_jsonrpc.php \
-H 'Content-Type: application/json-rpc' \
-d '{"jsonrpc":"2.0","method":"apiinfo.version","params":{},"id":1}'正常返回:
{"jsonrpc":"2.0","result":"7.0.31","id":1}服务端到这就完事了。默认账号是 Admin / zabbix,第一次登录后会强制改密码。
Server B:装 Agent
被监控机只需要装 Agent,不用数据库也不用 Web。
cd /tmp
wget https://repo.zabbix.com/zabbix/7.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_latest_7.0+ubuntu24.04_all.deb
sudo dpkg -i zabbix-release_latest_7.0+ubuntu24.04_all.deb
sudo apt update
sudo apt install -y zabbix-agent27.0 提供了两个 Agent:老的 C 语言 zabbix-agent,和新的 Go 语言 zabbix-agent2。新机器直接用 zabbix-agent2,支持更多内置插件,性能也更好。
改配置 /etc/zabbix/zabbix_agent2.conf,三个关键项:
Server=203.0.113.10
ServerActive=203.0.113.10:10051
Hostname=web-b-01Server是被动模式的白名单——服务端可以主动来连这台机器的 10050 端口。填服务端的 IP。ServerActive是主动模式的目标地址,Agent 会把数据推过去。Hostname必须全局唯一,而且要和在 Web 界面里添加主机时填的名字完全一致,否则主动模式的数据会因为对不上号被丢弃。
配置里的 Hostname 默认取系统主机名。云主机的主机名通常是 iZxxxxxx 这种随机串,又长又难记,建议手动改成有意义的名字。
启动:
sudo systemctl enable --now zabbix-agent2
sudo systemctl status zabbix-agent2自测一下:
zabbix_agent2 -t agent.ping返回 [s|1] 就正常。
打通网络:这一步最容易卡住
Zabbix 的监控数据流有两个方向,取决于你用哪种模式:
| 模式 | 数据流 | 需要放行的端口 |
|---|---|---|
| 被动 | 服务端 → 被监控机 | 被监控机入站 10050 |
| 主动 | 被监控机 → 服务端 | 服务端入站 10051 |
云服务器的安全组默认是不放行这两个端口的,很多人装完发现 Web 界面里主机一直亮红,八成是这里。
这次踩的坑更绕一点:两台机器虽然都是同一个云厂商,但分属不同的 VPC,内网根本不通:
# 在 Server A 上查内网地址
ip -4 -o addr show | awk '{print $2, $4}'
# eth0 10.0.0.16/22
# 而 Server B 是 172.16.0.89/18网段完全对不上,只能走公网。所以必须去控制台放行安全组。
我选的是被动模式,只放行一条规则:
方向:入站
协议端口:TCP:10050
来源:203.0.113.10/32
策略:允许来源写成 /32 只放行服务端那一台机器,比 0.0.0.0/0 安全得多。被动模式下 Agent 端口没必要对整个互联网开放。
如果服务端和被监控机都在内网且互通,把 Server 填成服务端的内网地址,就能完全绕开公网和安全组。放行之后,先在服务端上装个测试工具验证:
sudo apt install -y zabbix-getzabbix-get 是一个独立的命令行工具,它做的事情和 Zabbix Server 采集数据时一模一样:按 Zabbix 协议去连 Agent 的 10050 端口取值。用它测试比在 Web 界面里猜要快得多。
zabbix_get -s 198.51.100.20 -p 10050 -k agent.ping返回 1 说明通了。再多取几个指标确认:
zabbix_get -s 198.51.100.20 -p 10050 -k system.hostname
zabbix_get -s 198.51.100.20 -p 10050 -k 'system.cpu.load[all,avg1]'
zabbix_get -s 198.51.100.20 -p 10050 -k 'vm.memory.size[available]'
zabbix_get -s 198.51.100.20 -p 10050 -k 'vfs.fs.size[/,free]'如果这里就报 Timeout 或者 Connection refused,别去 Web 界面折腾了,问题百分之百在网络层:
- 端口有没有在监听 —— 去被监控机跑
ss -tlnp | grep 10050 - 系统防火墙 ——
sudo ufw status,有的话sudo ufw allow from 203.0.113.10 to any port 10050 proto tcp - 云安全组 —— 就是上面说的那条规则
添加主机
图形界面操作:登录后进 数据采集 → 主机 → 创建主机。
- 主机名称:必须和 Agent 配置里的
Hostname一致 - 主机群组:选
Linux servers - 接口:选
Agent,IP 填198.51.100.20,端口10050 - 模板:搜
Linux by Zabbix agent,关联上
保存后等一分钟左右,主机列表里那一列可用性会从灰色变成绿色。
用 API 添加适合批量或者写进脚本。核心就三步:登录拿 token、查出模板和主机组的 ID、创建主机。
API=http://127.0.0.1:8081/api_jsonrpc.php
# 登录,拿到 token
TOKEN=$(curl -s -X POST $API -H 'Content-Type: application/json-rpc' \
-d '{"jsonrpc":"2.0","method":"user.login","params":{"username":"Admin","password":"你的密码"},"id":1}' \
| python3 -c 'import sys,json; print(json.load(sys.stdin)["result"])')
# 查模板 ID
curl -s -X POST $API -H 'Content-Type: application/json-rpc' \
-d "{\"jsonrpc\":\"2.0\",\"method\":\"template.get\",\"params\":{\"filter\":{\"host\":[\"Linux by Zabbix agent\"]},\"output\":[\"templateid\",\"host\"]},\"auth\":\"$TOKEN\",\"id\":1}"
# 查主机组 ID
curl -s -X POST $API -H 'Content-Type: application/json-rpc' \
-d "{\"jsonrpc\":\"2.0\",\"method\":\"hostgroup.get\",\"params\":{\"filter\":{\"name\":[\"Linux servers\"]},\"output\":[\"groupid\",\"name\"]},\"auth\":\"$TOKEN\",\"id\":1}"拿到两个 ID 后创建主机:
curl -s -X POST $API -H 'Content-Type: application/json-rpc' \
-d "{\"jsonrpc\":\"2.0\",\"method\":\"host.create\",\"params\":{
\"host\":\"web-b-01\",
\"interfaces\":[{\"type\":1,\"main\":1,\"useip\":1,\"ip\":\"198.51.100.20\",\"dns\":\"\",\"port\":\"10050\"}],
\"groups\":[{\"groupid\":\"2\"}],
\"templates\":[{\"templateid\":\"10001\"}]
},\"auth\":\"$TOKEN\",\"id\":1}"接口的 type 字段有讲究:1 是 Zabbix Agent,2 是 SNMP,3 是 IPMI,4 是 JMX。填错了接口就采集不到数据。
主机建完,用 API 查一下采集状态:
curl -s -X POST $API -H 'Content-Type: application/json-rpc' \
-d "{\"jsonrpc\":\"2.0\",\"method\":\"host.get\",\"params\":{
\"filter\":{\"host\":[\"web-b-01\"]},
\"selectInterfaces\":[\"ip\",\"port\",\"available\"]
},\"auth\":\"$TOKEN\",\"id\":1}"available 字段的含义:0 是还没检测,1 可用,2 不可用。有个细节是——服务端不是实时检测的,默认最快也要一分钟才轮询一次。改完配置别急着下结论,等一分钟再看。
给 Web 加一层 HTTPS(可选)
Zabbix 的 Web 界面走的是明文 HTTP,登录密码也是明文传输。如果机器有公网 IP,强烈建议套一层 HTTPS。
用 Caddy 最省事,证书申请和续期全自动:
sudo apt install -y caddy编辑 /etc/caddy/Caddyfile:
zabbix.example.com {
reverse_proxy 127.0.0.1:8081 {
header_up Host {host}
header_up X-Real-IP {remote_host}
}
}前提是域名已经解析到这台机器的公网 IP,且 80、443 端口能通——Caddy 要通过 80 端口完成 ACME 验证来签发证书。
sudo systemctl reload caddy如果前面 Zabbix 已经占了 80 端口,记得把它改回 8081,让 Caddy 独占 80/443。
验证:
curl -s -o /dev/null -w 'HTTP %{http_code}\n' https://zabbix.example.com/
echo | openssl s_client -connect zabbix.example.com:443 \
-servername zabbix.example.com 2>/dev/null | openssl x509 -noout -datesCaddy 的 reload 依赖管理 API。如果配置里写了admin off,reload 会直接失败,这时改用systemctl restart caddy。代价是所有站点中断一两秒。
踩过的坑
安全组没放行,卡了最久。 表现是 Web 界面里主机一直是红的,available 显示 2。第一反应会去查 Agent 配置,其实应该反过来查网络。养成习惯:zabbix_get 能通再谈后面的事,通不了就是网络问题。
两台机器不同 VPC,内网完全不通用。 以为同一个云厂商就能走内网,实际网段都对不上。查内网地址用 ip -4 -o addr show 一眼就能看出来。
Nginx 配置模板里的 listen 是注释状态。 zabbix-nginx-conf 生成的配置文件,listen 和 server_name 默认都被 # 注释掉了,不手动放开就什么都不会监听,而且 Nginx 启动还不报错。
DBPassword 默认注释。 zabbix_server.conf 里 DBPassword 是注释状态,改了密码忘了填这里,服务端启动时会连不上库。
Agent 的 Hostname 和 Web 里填的主机名必须一致。 主动模式下对不上号,数据会被静默丢弃,日志里也不一定有明显的报错。
改完配置等服务端刷新。 Zabbix Server 有配置缓存,打开或关闭主机的监控项后不会立即生效,默认要等一分钟。
内存小的机器一定要调数据库参数。 这事没有商量余地。不调的话 MySQL/MariaDB 的默认配置很可能在半夜被 OOM Killer 干掉,而且白天完全看不出来。
附录:常用文件与命令
服务端文件
| 路径 | 用途 |
|---|---|
/etc/zabbix/zabbix_server.conf | 服务端主配置 |
/etc/zabbix/web/zabbix.conf.php | Web 界面数据库配置 |
/etc/nginx/conf.d/zabbix.conf | Nginx 站点配置 |
/etc/php/8.3/fpm/pool.d/zabbix.conf | PHP-FPM 进程池 |
/var/log/zabbix/zabbix_server.log | 服务端日志 |
/usr/share/zabbix-sql-scripts/mysql/server.sql.gz | 建库脚本 |
Agent 文件
| 路径 | 用途 |
|---|---|
/etc/zabbix/zabbix_agent2.conf | Agent 配置 |
/var/log/zabbix/zabbix_agent2.log | Agent 日志 |
排错顺序
# 1. 服务在不在
systemctl status zabbix-server
# 2. 端口在不在
ss -tlnp | grep -E '10051|10050'
# 3. 网络通不通(在服务端执行)
zabbix_get -s <被监控机IP> -p 10050 -k agent.ping
# 4. 数据库连不连得上
mariadb -uzabbix -p"$(sudo grep ^DBPassword= /etc/zabbix/zabbix_server.conf | cut -d= -f2)" zabbix -e "SELECT 1"
# 5. 看日志
tail -50 /var/log/zabbix/zabbix_server.log
tail -50 /var/log/nginx/error.log重启顺序
改了配置之后按这个顺序来,能避免大部分莫名其妙的报错:
sudo systemctl restart php8.3-fpm
sudo systemctl restart zabbix-server zabbix-agent nginx改的是数据库配置的话,先重启 mariadb 再重启 zabbix-server。