做监控选型这件事,我一直有个观点:能用跑起来的方案很多,能一直扛到几百台设备、几亿条指标还不给运维添乱的方案,才是真正值得抄作业的方案。这次要聊的这套部署,就是用 nginx 做 Web 前端入口,mysql 存配置和资产数据,elasticsearch 接走海量历史指标,最后用 zabbix 完成数据采集和可视化的完整落地过程。
我为什么会这么搭?因为最常规的“一键装 zabbix”方案默认是 Apache + MySQL 全塞一台机,前几十台服务器监控完全没问题,但等历史数据涨到几千万条之后,MySQL 的 history 表会越来越臃肿,前端刷个图表都卡,Apache 的内存占用又在那边雪上加霜。把 nginx、mysql、elasticsearch 这三者重新分工之后,Zabbix 才真正能按“采集、存储、展示”的职责拆开跑。这篇文章不会只给安装命令,我会把为什么要这样选型、版本怎么匹配、数据到底怎么流动、以及我实际部署时踩过的坑全部倒出来。
1. 这套组合的定位:为什么偏偏是 nginx + mysql + elasticsearch 陪 zabbix 跑
1.1 Zabbix 默认组合的短板
先说说最普遍的情况。用官方仓库安装 Zabbix 时,默认依赖会带上 Apache 和 PHP,数据库安装 MySQL 或 MariaDB,整个前端由 Apache 托管。这个组合在小规模监控里非常省心,因为 Zabbix 官方对这个路径的测试最充分,装完几乎不用改太多东西。
但监控规模一旦上来,问题会集中在两个地方。
第一是 Apache 的资源占用。Apache 默认的 prefork 模型对 PHP 支持很直接,但每个进程的内存开销不小,在高并发访问前端页面或者大量客户端同时拉取图表时,内存会肉眼可见地飙升。而 nginx 处理静态资源和反向代理的能力更强,事件驱动模型天然适合做 Web 入口,所以我更愿意用 nginx 替代 Apache 托管 Zabbix 前端。
第二是 MySQL 存储历史数据的压力。Zabbix 默认把所有采集到的数值都写入 MySQL 的 history_uint、history_str 等表,以及聚合后的 trends 表。监控项越多、采集频率越高,这些表增长越快。到后期不仅磁盘占用大,前端查询图表时会直接执行数据库聚合查询,一旦索引命中不好,页面就卡死。这个问题的本质,是关系型数据库并不适合存储这种海量、时序化、几乎不需要事务的监控历史数据。
所以答案是:让 MySQL 回归它最擅长的事——存 Zabbix 的配置、主机、模板、用户等结构化数据;让 Elasticsearch 去承担那些写多读少、按时间范围检索的历史指标。nginx 只负责把 PHP 前端跑利索。三个组件各管一段,整体就顺了。
1.2 三个组件在数据链路里各管哪一段
可以把整个 Zabbix 监控系统的数据链路理解为一条流水线:
- Zabbix Agent 或 SNMP 等协议采集到的原始指标,先进入 Zabbix Server 的采集进程;
- Zabbix Server 把配置类数据写入 MySQL,把历史指标转发给 Elasticsearch(如果配置了 ES 存储);
- 用户访问 Zabbix Web 前端时,nginx 把请求交给 PHP-FPM 处理,PHP 从前端读配置、从 ES 读历史数据,最终渲染成图表和仪表盘。
换句话说,nginx、mysql、elasticsearch 并不是三个并列的都要直接参与采集,而是分别承接了展示、配置、历史数据三段职责。这套架构最大的好处是:任何一段出了问题,都不至于让整个监控系统瘫痪。比如 ES 挂了,Zabbix Server 依然能采集数据并写入内存或 MySQL(未配置成功时),前端画图会丢失历史指标,但还能看到主机列表。
1.3 这套架构适合什么样的监控规模
我个人的判断是:如果只是监控十几台服务器,用默认的 Apache + MySQL 完全够,没必要上 ES,反而增加运维成本。但当你遇到这几类情况,就可以考虑切换:
- 监控设备超过 100 台,监控项超过 5000 个;
- 采集频率比较高,比如关键指标每 10 秒一次;
- 需要保存半年甚至一年的历史数据,并且要支持前端快速查询;
- 你想在后期用 Kibana 对监控指标做更自由的检索和分析。
标题里带着 nginx、mysql、elasticsearch,说明面对的已经是需要“可扩展”的监控架构,而不是练手 Demo。这套组合我用下来,最明显的感觉是前端图表响应速度比之前快了非常多,MySQL 的磁盘占用也不再被 history 表拖垮。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 装机前的准备:版本搭配、资源配置、基础环境检查
2.1 版本矩阵怎么选
版本选择是这套部署里最先要拍板的事情。我这次的落地环境是 Rocky Linux 8,组件版本如下:
| 组件 | 版本 | 说明 |
|---|---|---|
| Zabbix | 6.0 LTS | 当前最稳的长期支持版,支持 ES 历史存储 |
| MySQL | 8.0 | Zabbix 6.0 官方支持的数据库之一 |
| Elasticsearch | 7.17.x | Zabbix 6.0 对 ES 8 的兼容还不够完善,7.17 最稳 |
| nginx | 1.20+ | 发行版自带即可 |
| PHP | 7.4 | 由 Zabbix 前端包自动安装,满足 7.2.5+ 要求 |
这里要特别啰嗦一句:如果你非要上 Zabbix 7.0 LTS,那么 Elasticsearch 用 8.x 是完全没问题的,官方支持列表已经覆盖。但如果用的是 Zabbix 6.0,建议老老实实选 ES 7.17。ES 8 默认开启了安全认证,Zabbix 6.0 对这套认证体系的支持并不成熟,光是把认证配通就够折腾半天,没必要一上来就给自己上强度。我在测试环境里试过一次 Zabbix 6.0 配 ES 8,结果是服务能启动但写入鉴权始终有异常,最后退回 7.17 一切正常。这也是很多教程不提醒的坑。
2.2 服务器拆分和资源底限
我按照三个角色的独立部署来演示,实际生产中可以把 MySQL 和 ES 合并到一台机器,但独立部署对排查问题更友好:
- node1 10.0.0.8:Zabbix Server + nginx + PHP-FPM,2C4G 起步;
- node2 10.0.0.9:MySQL 8.0,2C4G,数据盘独立;
- node3 10.0.0.10:Elasticsearch 7.17,2C4G,数据盘建议 200G 起。
ES 的 JVM 堆内存按官方建议不要超过物理内存的一半,也不要超过 31GB。4G 内存的机器我一般给 2G 堆,config/jvm.options 里设置 -Xms2g -Xmx2g。机器内存小的话,es 会很吃紧,所以最低 4G 是认真的底线。
如果你是在一台机器上全装,那至少 8C16G。别用 2G 内存的机器硬上全套,否则 ES 启动都可能会因为内存不足被 systemd 干掉。
2.3 基础环境:源、时区、防火墙、SELinux
这套部署涉及的组件多,基础环境统一处理一下能省掉后期一堆诡异问题。
时区和时间同步是第一优先级。Zabbix 对时间偏差极其敏感,时间不同步会导致“节点不可达”“数据时间戳异常”等乱七八糟的假故障。我统一用 chrony 做时间同步,并且保证所有节点指向同一组 NTP 服务器。
防火墙端口方面,按这个清单放行:
| 端口 | 用途 | 放行方向 |
|---|---|---|
| 80 | nginx Web 入口 | node1 入站 |
| 10051 | Zabbix Server 接收 Agent 数据 | node1 入站 |
| 10050 | Zabbix Agent 等待被采集 | 被监控机入站 |
| 3306 | MySQL | node2 入站,仅允许 node1 访问 |
| 9200 | Elasticsearch HTTP | node3 入站,仅允许 node1 访问 |
SELinux 在 Rocky 8 上默认是 enforcing,Zabbix 官方提供了对应的 SELinux 策略包,但 nginx 连后端 PHP-FPM、Zabbix Server 外连 ES 这些动作还是可能被拦。我自己的习惯是在内网监控环境直接把 SELinux 设为 permissive,省得排查权限问题。如果你公司的安全基线要求必须 enforcing,那就得装 zabbix-selinux-policy 并且单独放行 nginx 的网络连接。
3. MySQL 部署:先把配置库立起来
3.1 安装并初始化 MySQL
Rocky 8 默认仓库里是 MariaDB,要装 MySQL 8.0 得用官方源:
bash复制dnf install -y https://dev.mysql.com/get/mysql80-community-release-el8-7.noarch.rpm
dnf install -y mysql-server
systemctl enable mysqld
systemctl start mysqld
MySQL 8.0 首次启动后,临时 root 密码会写到 /var/log/mysqld.log:
bash复制grep 'temporary password' /var/log/mysqld.log
拿到临时密码后执行 mysql_secure_installation,把 root 密码改掉、移除匿名用户、禁止 root 远程登录,这些安全操作建议全部做完。MySQL 不是公网服务,只在内网使用,但密码策略和访问控制还是要认真对待,尤其要限定只能由 Zabbix Server 所在节点来连接。
3.2 建库建用户与导入 schema
MySQL 准备好之后,创建 Zabbix 数据库和专门账号。这里字符集要用 utf8mb4,避免监控项名称或自定义数据里出现中文时乱码:
sql复制CREATE DATABASE zabbix CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
CREATE USER 'zabbix'@'10.0.0.8' IDENTIFIED BY 'YourStrongPass';
GRANT ALL PRIVILEGES ON zabbix.* TO 'zabbix'@'10.0.0.8';
FLUSH PRIVILEGES;
接下来导入官方 schema。Zabbix 6.0 的 SQL 脚本在 zabbix-sql-scripts 包里,导入命令是:
bash复制zcat /usr/share/zabbix-sql-scripts/mysql/server.sql.gz | mysql -uzabbix -pYourStrongPass -h10.0.0.9 zabbix
导入过程会创建一百多张表,包括 hosts、items、history、trends 等。这里要注意,即便后面配置了 Elasticsearch 存储历史数据,Zabbix 的 MySQL 库里依然会有 history 和 trends 表,只是没有新数据写入而已。导入完成后可以看一眼表数量:
bash复制mysql -uzabbix -p -h10.0.0.9 -e "use zabbix; show tables;"
如果能看到一长串表,说明 schema 导入没问题。
3.3 几个必须做的数据库参数调整
MySQL 装完不是直接就能配合 Zabbix 跑得很舒服的,至少要调整这几项参数。修改 /etc/my.cnf 的 [mysqld] 段:
ini复制innodb_buffer_pool_size = 2G
innodb_log_file_size = 512M
max_connections = 1024
innodb_buffer_pool_size 是最关键的参数,它决定 InnoDB 在内存里能缓存多少数据页。Zabbix 的配置查询很频繁,但如果缓存过小就会疯狂磁盘 IO。一般设置为机器物理内存的 50%~70%,我这台 4G 机器给了 2G。
max_connections 默认 151 在监控场景不够用。Zabbix Server 会有多个 poller 进程同时连接数据库,再加上前端查询连接,很容易超过默认值。建议起步 1024,如果监控规模更大再往上加。
还有一点容易忽略:MySQL 8.0 默认开启了 binlog,如果你不是要做主从,建议把 binlog 过期时间调短或者直接关闭,不然 Zabbix 写入量一大,binlog 会疯狂占磁盘。
4. Elasticsearch 部署:把历史数据从 MySQL 里解放出来
4.1 为什么需要 ES 参与存储
可能有人会问:趋势数据用 MySQL 加上分区表不也能凑合吗?确实能,但分区表只能解决单表过大的问题,解决不了查询性能随数据量增长而劣化的问题。ES 底层用的是倒排索引加列式存储,对按时间范围、按 metric 名称检索的历史数据非常友好。Zabbix 前端画图表时,本质上是“给定时间范围,拉取某个 item 的一堆数据点”,这个查询模式落在 ES 上比落在 MySQL 上快得多。
另一个隐藏红利是,有了 ES 之后,你可以用 Kibana 直接查监控指标,做更灵活的聚合分析,比如把某个应用的所有节点 CPU 使用率拉出来对比。这是 Zabbix 内置图表不好实现的需求。
4.2 单机部署 ES 7.17 的关键配置
我在 node3 上用 RPM 方式安装 ES 7.17:
bash复制rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
cat > /etc/yum.repos.d/elasticsearch.repo <<'EOF'
[elasticsearch-7.x]
name=Elasticsearch repository for 7.x packages
baseurl=https://artifacts.elastic.co/packages/7.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
EOF
dnf install -y elasticsearch-7.17.16
安装完成后编辑 /etc/elasticsearch/elasticsearch.yml,最核心的几项:
yaml复制cluster.name: zabbix-es
node.name: node-3
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 10.0.0.10
http.port: 9200
discovery.type: single-node
xpack.security.enabled: false
discovery.type: single-node 是单机部署的关键,不加这个参数 ES 会因为找不到其他节点而启动报错。xpack.security.enabled: false 是为了让 Zabbix 6.0 不做认证直连,因为我前面已经强调过版本兼容,这里保持最简单模式。
JVM 堆内存单独在 /etc/elasticsearch/jvm.options.d/ 下创建一个文件,比如 heap.options:
code复制-Xms2g
-Xmx2g
设置完启动并验证:
bash复制systemctl enable elasticsearch
systemctl start elasticsearch
curl http://10.0.0.10:9200
能返回带 cluster_name 和 tagline 的 JSON 就说明 ES 已经正常对外服务了。
4.3 启动验证与索引生命周期规划
ES 自身起来之后,还应该做两件事:确认磁盘和索引分片配置、准备好索引生命周期策略。
Zabbix 写入 ES 的索引名默认是 zabbix-2024.06.15 这种按日期区分的格式,一天一个索引。如果不管索引生命周期,几个月后 ES 的数据目录会被塞爆。我建议在 Zabbix Server 启动前,先把索引生命周期策略和索引模板创建好。
创建一个只保留 30 天的策略:
bash复制curl -X PUT "http://10.0.0.10:9200/_ilm/policy/zabbix_30d" -H 'Content-Type: application/json' -d'
{
"policy": {
"phases": {
"hot": {
"actions": {}
},
"delete": {
"min_age": "30d",
"actions": {
"delete": {}
}
}
}
}
}'
再创建一个匹配 zabbix-* 的索引模板,把分片数、副本数和 ILM 策略绑上去:
bash复制curl -X PUT "http://10.0.0.10:9200/_template/zabbix" -H 'Content-Type: application/json' -d'
{
"index_patterns": ["zabbix-*"],
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0,
"index.lifecycle.name": "zabbix_30d"
}
}'
这里副本数设置为 0 是因为单机部署没有第二个节点可以放副本,如果 ES 是集群模式,建议至少 1。分片数保持 1 就够,ES 的分片一旦建立很难调整,别上来就拆 5 个分片,纯属浪费。
5. Zabbix Server 与前端组装:nginx + PHP-FPM 手工接管
5.1 安装 zabbix-server 并配置数据库连接
在 node1 上安装 Zabbix 6.0 的官方仓库和组件。Rocky 8 下:
bash复制rpm -Uvh https://repo.zabbix.com/zabbix/6.0/rhel/8/x86_64/zabbix-release-6.0-4.el8.noarch.rpm
dnf clean all
dnf install -y zabbix-server-mysql zabbix-web-mysql zabbix-nginx-conf zabbix-sql-scripts zabbix-agent
注意 zabbix-web-mysql 包会带着 PHP 和 php-fpm 一起装进来,zabbix-nginx-conf 提供一个现成的 nginx 站点配置模板,这步之后不用单独再手动写前端文件。
修改 /etc/zabbix/zabbix_server.conf 里的数据库连接配置:
ini复制DBHost=10.0.0.9
DBName=zabbix
DBUser=zabbix
DBPassword=YourStrongPass
然后先启动一次 Zabbix Server,确认数据库连接没问题:
bash复制systemctl start zabbix-server
如果启动失败,去看 /var/log/zabbix/zabbix_server.log,错误信息里会直接告诉你数据库认证失败还是网络不通。这一步没有通过之前不要往后走。
5.2 让 zabbix_server 把历史数据写进 ES 的核心参数
这是我全文最想让人抄走的部分。在同一个配置文件里追加这几行:
ini复制HistoryStorageURL=http://10.0.0.10:9200
HistoryStorageTypes=uint,dbl,str,log,text
HistoryStorageDateIndex=1
HistoryStorageTypes 表示哪些数据类型要存 ES,我这里写全了所有的历史数据类型。HistoryStorageDateIndex=1 表示索引名按日期拆分,也就是 zabbix-2024.06.15 这个格式。如果没有这个参数,Zabbix 默认会用一个固定的 zabbix 索引,数据全挤在一个索引里,性能会差很多。
配置完成后重启:
bash复制systemctl restart zabbix-server
然后立刻回 ES 端验证:
bash复制curl -s "http://10.0.0.10:9200/_cat/indices?v" | grep zabbix
如果顺利,你会看到类似 zabbix-2024.06.15 的索引已经出现,并且 docs.count 在缓慢增长。这一步完成,说明 Zabbix 数据采集链路里最关键的“历史数据落 ES”已经打通。
5.3 nginx + PHP-FPM 的配置要点
zabbix-nginx-conf 包给出的模板在 /etc/nginx/conf.d/zabbix.conf,默认监听 8080 端口,需要改一下才能用默认的 HTTP 80 端口访问:
nginx复制server {
listen 80;
server_name zabbix.local;
root /usr/share/zabbix;
index index.php;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_read_timeout 300;
}
}
这里最关键的坑点是 fastcgi_pass 的目标要和 php-fpm 实际监听的地址一致。Zabbix 在 RHEL 系上安装时,php-fpm 的配置文件 /etc/php-fpm.d/zabbix.conf 默认监听 127.0.0.1:9000,所以 nginx 用这个地址是没错的。但如果你的 php-fpm 是系统自带的 www.conf 在跑,监听的可能就是 unix socket,那这里就得改成对应的 socket 路径。
php-fpm 池的进程用户也值得检查一下。Zabbix 的 php-fpm 配置默认用 apache 用户跑,但 nginx 的 worker 进程是 nginx 用户。如果你用的是 unix socket 方式通信,可能出现权限对不上导致 502。改成 TCP 的 9000 端口通信可以绕开文件权限问题,这就是我为什么模板里直接用 127.0.0.1:9000。
5.4 PHP 参数调整与浏览器端安装向导
Zabbix 前端的 PHP 运行要求比较明确,必须改 /etc/php.ini 里的几项:
ini复制max_execution_time = 300
max_input_time = 300
post_max_size = 16M
memory_limit = 256M
date.timezone = Asia/Shanghai
改完重启 php-fpm 和 nginx:
bash复制systemctl restart php-fpm
systemctl restart nginx
这时浏览器访问 http://10.0.0.8,会进入 Zabbix 的安装向导。第一步是检查 PHP 环境是否满足要求,缺哪个扩展就装哪个。第二步填写数据库连接信息,数据库地址填 10.0.0.9,用户和密码就是前面建的 zabbix 账号。第三步确认服务器名称等信息,最终生成配置文件写到 /etc/zabbix/web/zabbix.conf.php。
整个向导走完,Zabbix 前端就能登录了,默认账号是 Admin,密码 zabbix。登录后第一件事是改成自己的强密码。
6. 从 Agent 到可视化:验证数据流确实走了 ES
6.1 安装配置 Agent
前面部署的都是服务端,现在拿一台被监控的机器装 agent。我以一台 Ubuntu 服务器为例:
bash复制wget https://repo.zabbix.com/zabbix/6.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_6.0-4+ubuntu20.04_all.deb
dpkg -i zabbix-release_6.0-4+ubuntu20.04_all.deb
apt update
apt install -y zabbix-agent
编辑 /etc/zabbix/zabbix_agentd.conf:
ini复制Server=10.0.0.8
ServerActive=10.0.0.8
Hostname=web01
Server 是允许谁被动来采集数据,ServerActive 是 agent 主动向哪个 Zabbix Server 上报数据。这两项都要写对,否则会出现在线状态正常但数据一直不采集的怪现象。重启 agent:
bash复制systemctl restart zabbix-agent
记得在被监控机器上放行 10050 端口的入站。
6.2 Web 界面添加主机与监控项
登录 Zabbix Web 控制台,进入“数据采集 → 主机”,点击“创建主机”。主机名称填 web01,可见名称随意,群组选一个已有的,Agent 接口 IP 填被监控机器的地址,端口默认 10050。
接着在“模板”栏里搜索 Linux by Zabbix agent,添加进去。这个模板带了 CPU、内存、磁盘、网络等一整套现成的监控项和触发器,省去了手工一个一个配置监控项的麻烦。保存之后过一两分钟,主机的“可用性”应该变成绿色,监控项开始源源不断采集数据。
如果你要监控的是交换机、防火墙这种网络设备,可以在“模板”里找 SNMP 相关模板,配合设备的 SNMP 团体名或 v3 凭据即可。标题里提到的“zabbix 监控交换机配置”,本质上就是主机类型选 SNMP,剩下的事情交给模板。这篇文章以服务器 agent 为主,SNMP 思路是一样的。
6.3 验证 Elasticsearch 索引和 MySQL 数据对比
这一步是我认为最有价值的验证动作。添加主机并产生监控数据之后,回到 ES 看索引:
bash复制curl -s "http://10.0.0.10:9200/_cat/indices?v" | grep zabbix
你会看到 zabbix-2024.06.15 索引的 docs 数量在快速增长,这证明历史数据确实进了 ES。再去 MySQL 里查一下 history_uint 表:
bash复制mysql -uzabbix -p -h10.0.0.9 -e "select count(*) from zabbix.history_uint;"
你会发现这个表的行数几乎不动,只有 Zabbix 内部某些元数据写入在触发少量变化。这就是最直观的证据:MySQL 不再是历史数据的储存点,ES 已经成功接管了这条链路。
前端图表此时也能正常展示,因为 Zabbix 前端会通过 Zabbix Server 的 ES 连接去读取历史数据,这个流程对用户完全透明。
6.4 仪表盘和告警通道的基本玩法
监控系统光有数据采集不够,可视化仪表盘和告警才是真正让运维省心的地方。Zabbix 的“仪表盘”支持拖拽式布局,可以把关键主机的 CPU、内存、磁盘 IO 图表放在一屏。我的建议是先创建一个“基础设施总览”仪表盘,把每台核心主机的 CPU 使用率、可用内存、根分区使用率这几个最关键的图放上去,比每次点进主机详情看方便得多。
告警方面,Zabbix 6.0 内置了钉钉、企业微信等媒体类型,也可以配置邮箱告警。以钉钉为例,需要先创建一个钉钉机器人,拿到 Webhook 地址,然后在“告警 → 媒体类型”里填好,再给对应用户添加告警媒介,最后给触发器配置动作。热词里出现了“zabbix 钉钉”,说明这是很多人关心的功能,但要注意钉钉机器人的安全设置里如果加签了,需要在媒体类型配置里把加签密钥也填上,否则会一直报签名错误。
7. 实测中踩过的坑与调优清单
7.1 ES 连接失败导致 Zabbix Server 起不来
我在第一次配置 HistoryStorageURL 之后,重启 Zabbix Server,发现服务一直启动失败,日志里报的是 ES 连接超时。当时第一反应是 ES 没起来,但 curl ES 是通的。后来排查发现,是 Zabbix Server 启动时如果配置了 ES 存储,会立刻尝试建立连接,如果 ES 部署在独立机器且防火墙没放行 9200 端口,就会报错。
解决办法是先把 node1 到 node3 的 9200 端口在防火墙里放行,再启动 Zabbix Server。这个坑提醒我:所有跨节点的依赖,都要先验证网络连通性,再配置到应用里。如果你按我前面的步骤先验证了 ES 的 HTTP 接口,再启动 Zabbix Server,就不会踩到。
7.2 PHP-FPM socket 权限和 502 问题
另一个典型问题是装完 nginx 后访问前端出现 502 Bad Gateway。我在 RHEL 系上遇到的是 php-fpm 的 listen 配置在 zabbix.conf 池里是 TCP 9000,但 nginx 模板的 fastcgi_pass 默认指向的是 unix socket,导致 nginx 找不到 PHP-FPM 的监听入口。
这种问题排查方法很简单:先 ss -lntp | grep 9000 看 php-fpm 是否监听,再确认 nginx 配置里的 fastcgi_pass 地址和端口完全一致。如果两者不一致,改 nginx 配置而不是改 php-fpm,因为官方 zabbix-nginx-conf 包提供的模板就是按 TCP 9000 写的。我不推荐新手去改 unix socket 权限,因为涉及 nginx 用户和 php-fpm 用户一致性的问题,绕一圈远不如直接 TCP 稳定。
7.3 ES 磁盘被索引打满:必须配 ILM
ES 的索引膨胀速度比想象中快很多。我在测试环境里跑了半天,看 _cat/indices 发现索引大小已经有 2GB,如果放任不管,一个月的数据量足以把 500G 磁盘吃光。ILM 策略不是可选项,而是必选项。前面第 4.3 节已经给出了创建策略和模板的命令,这里我要强调一个顺序:一定要在 Zabbix Server 写入数据之前把模板建好,否则已经创建的索引不会套用模板里的 ILM 策略。
如果你启动比较早,索引已经创建了,可以删掉当天的 zabbix-* 索引,让 Zabbix 自动重新创建,新索引就会套用模板。删除索引会丢一小段历史数据,在测试环境可以接受,生产环境要谨慎。
7.4 最终调优参数表
把整套架构稳定跑起来之后,我的核心参数配置如下:
| 组件 | 参数 | 推荐值 | 说明 |
|---|---|---|---|
| MySQL | innodb_buffer_pool_size | 内存的 50%~70% | 尽量缓存配置查询 |
| MySQL | max_connections | 1024 | 避免连接数耗尽 |
| ES | -Xms/-Xmx | 物理内存的一半 | 不超过 31G |
| ES | number_of_replicas | 1(集群)/ 0(单机) | 单机设 0 省空间 |
| Zabbix Server | StartPollers | 10 | 采集并发数,按主机量调 |
| Zabbix Server | CacheSize | 256M | 配置缓存,避免频繁读 DB |
| nginx | fastcgi_read_timeout | 300 | 防止图表查询超时 |
| PHP | max_execution_time | 300 | Zabbix 向导强制要求 |
这套参数在我目前约 150 台设备、每天大约 8000 万条历史指标的监控环境里跑得很稳。Zabbix Server 内存占用约 3G,MySQL 稳定在 2G,ES 有 20G 分给 JVM,整体没有出现瓶颈。如果你的监控规模更大,优先扩 ES 节点而不是继续加大单机配置,ES 集群化之后查询能力几乎线性增长,这也是这套架构最值得投资的地方。
最后再分享一个大实话:这套架构的迁移不是把 MySQL 一换就完事,核心在于让团队理解“配置库”和“历史库”的区别。我在迁移初期,同事总习惯去 MySQL 里查历史数据,后来把 Kibana 的搜索面板丢给他们,才真正扭转过来。任何架构调整,工具的落地只是第一步,让所有人习惯新的数据访问方式,才是这套部署真正发挥价值的时刻。
