上周帮团队从零搭监控平台,对方开口第一句就是:Zabbix 那么重,部署文档那么长,真能用 Docker 跑起来吗?我没有直接回答,而是顺手在测试机上敲了一份 docker-compose,20 分钟不到,一套带历史数据、告警推送、Windows 客户端接入的 Zabbix 7.0 平台就完整跑起来了。这篇我就把整套方案拆开讲:为什么用容器化方式部署,编排文件怎么设计,部署完最容易翻车的细节在哪,以及企业里最高频的几个监控场景(Windows GPU、Oracle、虚拟机)怎么接入。适合三类人参考:刚接触 Zabbix 的运维新手、打算把监控迁到容器环境的团队、以及正准备给服务器补一套告警体系的开发者。
1. 为什么我选择用 Docker 跑 Zabbix
1.1 Zabbix 的组件到底有多"重"
Zabbix 和大多数轻量监控工具不太一样,它不是单个二进制文件就能搞定的事。一套标准的生产环境通常包含 Zabbix Server(负责数据采集和策略计算)、数据库(PostgreSQL 或 MySQL)、Web 前端(Nginx/Apache + PHP)、Agent/Agent2(客户端采集),规模大了还要加 Proxy 做分布式采集和缓冲区。也就是说,裸机部署至少要装 4 到 5 个组件,而且每个组件的依赖都可能和操作系统自带的软件包冲突。
我第一次裸装 Zabbix 时,就死在 PHP 版本和 Nginx 配置上。操作系统默认的 PHP 版本偏老,Zabbix 7.0 要求 PHP 8.0 以上,为了升级 PHP 又牵动了一堆系统库,最后整整折腾了半天才看到一个正常的登录页面。后来在 Docker 环境下重新部署,这些依赖问题全部被镜像隔离掉了,每个组件各跑各的容器,互不干扰,这才意识到容器化对 Zabbix 这种多组件系统来说,价值远比想象中大。
1.2 Docker 与裸机安装的客观对比
工具选型很多人纠结,其实把两者的差异列成表格就清楚了。我从安装速度、依赖隔离、升级回滚、数据持久化、团队门槛等几个维度做了对比:
| 对比项 | 裸机/包管理器安装 | Docker 部署 |
|---|---|---|
| 安装耗时 | 新手 2~6 小时,常被依赖问题卡住 | 拉镜像 + 编排,通常 20~40 分钟 |
| 依赖隔离 | 与系统 PHP、库版本互相影响 | 镜像自带依赖,互不干扰 |
| 升级回滚 | 升级需停服务,回滚靠备份 | 换 tag 即可升级,保留旧 tag 随时回退 |
| 数据持久化 | 数据在本地目录,路径统一 | 必须挂 volume,否则容器删除数据即失 |
| 多实例隔离 | 一台机器只方便跑一套 | 多套环境通过独立网络与卷隔离 |
| 运维门槛 | 熟悉系统服务管理即可 | 需要理解 compose、网络、卷等概念 |
从表格能看出来,Docker 最大的优势是把"环境一致性"这个老大难问题解决了。同一份编排文件,在 Ubuntu、openEuler、CentOS 上跑出来的结果完全一样,不会再出现"你这机器能跑,换一台就报错"的情况。
1.3 哪些场景不建议容器化
当然,凡事都有边界。如果你的节点规模已经到几千台,或者团队里没有熟悉 Docker 网络、存储、安全隔离的人,我更建议使用官方提供的 Zabbix 一体机方案或者裸机部署,让专业工具做专业事。容器化适合中小规模、组件快速交付、以及需要频繁验证新版本的场景。
还有一个常见误区:容器不是免费午餐。Zabbix Server 和数据库如果放在同一个宿主机上,内存竞争、磁盘 IO 竞争依然存在,编排文件写不好反而更容易出问题。所以我的建议是:先评估你的场景规模,再决定用不用 Docker。
2. 部署前的环境准备:镜像加速与目录规划
2.1 软硬件要求
Zabbix 对资源的要求取决于监控节点数量和采集频率,但即便只是测试环境,也不要给得太抠。以我常用的配置为例:CPU 2 核起步,内存 4G(测试)或 8G(生产建议),磁盘 20G 以上。数据库历史数据增长很快,尤其你启用了大量触发器且保留周期较长时,磁盘空间要预留足够。
操作系统方面,Ubuntu 22.04/24.04、Debian 12、openEuler、Rocky Linux 都跑过,没有本质区别。Docker Engine 版本建议 20.10 以上,因为新版 Zabbix 镜像和 Compose 语法对旧版本兼容性不好。如果你在 Windows 上做本地验证,安装 Docker Desktop 之后注意给 WSL2 分配足够的内存,默认 2G 跑 Zabbix 全家桶会非常吃力。
2.2 解决 Docker 镜像下载慢的问题
部署 Zabbix 第一个卡点往往不是配置,而是镜像拉不下来。zabbix-server 的镜像大约 700MB 到 1GB,PostgreSQL 镜像也不小,在默认源下经常超时。解决办法是配置 registry mirror,也就是镜像加速器。
操作方式很简单,编辑/etc/docker/daemon.json:
{ "registry-mirrors": [ "https://docker.m.daocloud.io", "https://docker.1panel.live", "https://docker.mirrors.ustc.edu.cn" ] }改完重启 Docker:
sudo systemctl daemon-reload sudo systemctl restart docker注意:镜像加速器的可用性在不同时间段会有变化,如果某个地址失效,换成列表里的其他地址即可。这一步只影响 Docker Hub 镜像的拉取速度,不影响业务流量。
配置完成后,可以先用一个小镜像验证加速是否生效:
docker pull hello-world实测下来,加速生效后 Zabbix 系列镜像的拉取时间能从几十分钟缩短到几分钟。这是 Docker 部署 Zabbix 流程里最不起眼但最容易卡壳的一步,建议部署前先处理好。
2.3 目录规划与数据卷
Zabbix 的数据分为配置数据、历史数据、告警脚本、Web 配置几类。Docker 场景下,我习惯把项目文件统一放在/opt/zabbix,里面放docker-compose.yml和.env文件。数据库数据不直接挂载宿主机目录,而是用命名卷(named volume),由 Docker 统一管理。
这么设计的原因有三:第一,命名卷的读写性能比绑定挂载目录更稳定,避免数据库 IO 异常;第二,升级时不会不小心覆盖数据目录;第三,备份时直接通过docker run --rm -v zabbix-db-data:/data -v /backup:/backup alpine tar czf /backup/zabbix-db.tar.gz /data就能打包,不污染宿主机目录结构。
3. docker-compose 编排 Zabbix 7.0 全家桶
3.1 数据库选型:PostgreSQL 还是 MySQL
Zabbix 官方支持 PostgreSQL 和 MySQL 两种后端,我在生产环境里两种都用过,结论是:如果没有历史包袱,优先选 PostgreSQL。原因有两方面:一是 Zabbix Server 本身就是在 PostgreSQL 上开发最久、测试最充分的,很多分区、清理策略在 PG 上执行更稳定;二是 MySQL 8.0 在部分地区部署时容易遇到字符集、排序规则不匹配的问题,虽然都能调,但多一事不如少一事。
如果你的团队对 MySQL 非常熟,或者上层平台已经统一要求 MySQL,那选 MySQL 也没问题,只需把 compose 里的镜像从zabbix-server-pgsql换成zabbix-server-mysql,数据库镜像换成mysql:8.0,再对齐MYSQL_USER、MYSQL_PASSWORD这类变量即可。
3.2 完整编排文件
这是我在 4C8G 测试机上验证过的完整 compose 文件,组件包含 PostgreSQL、Zabbix Server、Zabbix Web(Nginx + PHP)、Zabbix Agent2:
version: "3.8" services: postgres: image: postgres:16-alpine container_name: zabbix-postgres restart: always environment: POSTGRES_USER: zabbix POSTGRES_PASSWORD: zabbix_pwd POSTGRES_DB: zabbix volumes: - zabbix-db-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U zabbix"] interval: 10s timeout: 5s retries: 5 networks: - zabbix-net zabbix-server: image: zabbix/zabbix-server-pgsql:7.0-ubuntu-7.0 container_name: zabbix-server restart: always environment: DB_SERVER_HOST: postgres POSTGRES_USER: zabbix POSTGRES_PASSWORD: zabbix_pwd POSTGRES_DB: zabbix ZBX_STARTPOLLERS: "5" ZBX_STARTPREPROCESSORS: "3" ports: - "10051:10051" depends_on: postgres: condition: service_healthy networks: - zabbix-net zabbix-web: image: zabbix/zabbix-web-nginx-pgsql:7.0-ubuntu-7.0 container_name: zabbix-web restart: always environment: ZBX_SERVER_HOST: zabbix-server DB_SERVER_HOST: postgres POSTGRES_USER: zabbix POSTGRES_PASSWORD: zabbix_pwd POSTGRES_DB: zabbix PHP_TZ: Asia/Shanghai ZBX_SERVER_NAME: "企业监控平台" ports: - "8080:8080" depends_on: - zabbix-server networks: - zabbix-net zabbix-agent: image: zabbix/zabbix-agent2:7.0-ubuntu-7.0 container_name: zabbix-agent restart: always environment: ZBX_SERVER_HOST: zabbix-server ZBX_HOSTNAME: "zabbix-server" ZBX_SERVER_PORT: "10051" network_mode: host pid: host privileged: true volumes: - /:/rootfs:ro networks: zabbix-net: driver: bridge volumes: zabbix-db-data:这个文件里有一个容易忽略的点:zabbix-agent我这里是用容器监控 Docker 宿主机本身,所以用了network_mode: host和pid: host,并挂载了宿主机根目录为只读。如果你只是想给 Zabbix Server 自己挂一个 Agent 做测试,不需要这么复杂,删掉这几行、把它放进zabbix-net网络并映射10050:10050即可。
3.3 环境变量逐项说明
新手最容易在环境变量上翻车,我把关键变量整理出来:
| 变量名 | 作用 | 建议值 |
|---|---|---|
| DB_SERVER_HOST | 数据库主机名 | 对应 compose 服务名 postgres |
| POSTGRES_USER / MYSQL_USER | 数据库用户 | 统一为 zabbix |
| POSTGRES_PASSWORD / MYSQL_PASSWORD | 数据库密码 | 生产环境使用强密码 |
| POSTGRES_DB / MYSQL_DATABASE | 数据库名 | zabbix |
| ZBX_SERVER_HOST | Web 端连接的 Server 地址 | zabbix-server |
| PHP_TZ | Web 前端时区 | Asia/Shanghai |
| ZBX_SERVER_NAME | 页面右上角显示的平台名称 | 自定义 |
| ZBX_STARTPOLLERS | 轮询器进程数,影响采集并发 | 按节点规模调整 |
PHP_TZ这个变量特别重要。很多容器默认时区是 UTC,如果你不设置,告警时间会比北京时间慢 8 小时,排查问题时非常误事。另外,ZBX_STARTPOLLERS默认值是 1,如果监控节点超过几十台,建议调到 5 左右,否则队列会堆积,触发器响应变慢。
3.4 启动、验证与首次登录
在/opt/zabbix目录下执行:
docker compose up -d第一次启动会自动拉取镜像,根据网络情况可能需要几分钟到十几分钟。启动完成后,通过日志确认没有报错:
docker compose ps docker logs -f zabbix-server日志中看到类似server started的信息,说明 Server 已经正常运行。浏览器访问http://<服务器IP>:8080,默认账号是admin,默认密码是zabbix。首次登录后第一件事就是修改默认密码,这个不用我多提醒。
登录后可以先去"数据采集 → 主机"页面,能看到我刚才部署的zabbix-agent对应的宿主机,可监控项已经有一大堆了。到这里,一套基础的 Zabbix 7.0 平台就搭建完成了,剩下的工作就是接入你想监控的目标。
4. 刚跑起来的头一天,最容易踩的 5 个坑
4.1 时区不一致导致告警时间错乱
先说时区,这是 90% 的新手都会遇到但一开始完全注意不到的问题。如果你的 compose 文件里没有设置PHP_TZ,Zabbix Web 界面会显示 UTC 时间,告警消息里的时间也全部是 UTC。而 Server 容器自己的系统时区可能是 UTC,数据库时间也是 UTC,三者看似一致,但和你本地的北京时间一对比就差 8 小时。
解决方式是在所有相关容器里统一时区。Web 容器设置PHP_TZ=Asia/Shanghai,Server 容器可以通过环境变量TZ=Asia/Shanghai设置,PostgreSQL 容器同理。每次部署完,建议先去"报表 → 系统信息"里看一眼时间显示是否正确,再继续后面的操作。
4.2 内存被 PostgreSQL 和 Server 吃满
Zabbix Server 和 PostgreSQL 都是内存大户。PostgreSQL 16 默认配置下shared_buffers可能是 128MB,但连接数一多,实际内存占用轻松超过 1G。Zabbix Server 在启用大量 poller、preprocessor 和 alert manager 后,内存也会稳步上涨。
如果你的测试机只有 4G 内存,跑一段时间后很容易出现容器被 OOM Killer 杀掉的情况。表现是docker compose ps显示容器状态为Exited,或者看系统日志出现out of memory。
我的处理方式是:在 compose 里给每个容器设置内存限制,比如:
deploy: resources: limits: memory: 2G同时在 PostgreSQL 的启动命令里适当调低shared_buffers,例如加到/etc/postgresql/postgresql.conf里改为shared_buffers = 256MB(生产环境按物理内存的 1/4 左右调整)。另外,监控节点数量不要一上来就拉满,先接 10 台机器跑一天,观察内存趋势再决定是否扩容。
4.3 10050/10051 端口不通,Agent 失联
Zabbix 的端口问题非常经典,搞清楚之后很多排查就顺畅了。10051 是 Zabbix Server 的监听端口,Agent 主动向 Server 上报数据时走这个端口;10050 是 Agent 的监听端口,Server 需要获取被监控主机数据时,走这个端口去连 Agent。
很多人在服务器上把 10050/10051 都放开了,但在本机测试 Agent 仍然显示不可达。这时候要先想清楚你的网络模式:如果 Agent 和 Server 都在同一台机器的 Docker bridge 网络里,它们之间走的是容器网络,和宿主机防火墙没关系;如果你要监控的是外部物理机,那才需要确保宿主机防火墙放开对应端口。
排查命令也顺手给出来:
telnet <agent-ip> 10050 telnet <server-ip> 10051如果宿主机有firewalld或ufw,记得把端口加到白名单,同时注意 Docker 的 iptables 规则有时会绕过这些管理工具,表现是"防火墙关了就能通,开着就不通",这种时候要从容器网络和系统防火墙两个层面同时排查。
4.4 容器删除后监控历史全丢
这个坑是最痛的。如果你在部署时没有给 PostgreSQL 配置命名卷,而是直接用容器默认的存储层,一旦执行docker compose down甚至docker rm zabbix-postgres,历史监控数据全部消失,而且恢复成本极高。
解决方式就是我前面编排文件里已经写的volumes: zabbix-db-data。这样即使容器删掉重建,只要卷还在,数据就还在。升级 Zabbix 版本前,强烈建议先备份数据库卷,命令是:
docker run --rm -v zabbix-db-data:/data -v /backup:/backup alpine tar czf /backup/zabbix-db-$(date +%F).tar.gz -C /data .恢复时把这个 tar 包解压到新卷就行。别看这一步简单,关键时刻能救你一命。
4.5 版本 tag 混乱导致升级困难
Docker 镜像的 tag 选择是有讲究的。latesttag 虽然省事,但每次docker compose pull都可能拉到一个不兼容的新版本,尤其在 Zabbix 主版本升级时,Server、Web、Agent 的版本不一致会导致 Web 界面提示"前端与 Server 版本不匹配"。
我的做法是:生产环境固定使用完整的版本 tag,例如7.0-ubuntu-7.0。升级时手动修改 tag 并逐个组件升级,先升级数据库备份,再升级 Server,最后升级 Web,避免四个组件一起 restart 带来的风险。Docker 的编排能力是为了让你升级方便,而不是让你无脑追新。
5. 实战:用 Zabbix 监控 Windows GPU
5.1 为什么 GPU 监控正在变成刚需
现在很多企业的服务器不只是跑数据库和 Web 服务,还承担模型推理、视频转码、渲染等任务。GPU 一旦故障或者显存打满,直接影响业务质量。前阵子帮一个朋友排查训练任务反复失败的问题,最终定位到 GPU 利用率长期 100%、显存溢出,但整个平台没有任何告警。所以把 GPU 纳入监控范围,其实是很多团队的刚需。
5.2 Windows 上安装 Agent2 并开启性能计数器
Windows 主机接入 Zabbix,首选 Zabbix Agent2。官方下载对应版本的 Windows amd64 安装包,安装时填上 Zabbix Server 的 IP 和主机名即可。安装完成后,服务会以 Windows 服务方式启动,默认监听 10050 端口。
要让 GPU 数据能被读取,Windows 系统需要启用性能计数器。正常情况下 NVIDIA 驱动安装后会自带GPU Engine、GPU Adapter Memory等性能计数器对象,你可以先在perfmon(性能监视器)里确认这些计数器存在。如果看不到,说明驱动安装不完整,重新安装 NVIDIA 驱动并勾选相关组件即可。
5.3 模板导入与计数器取值
Zabbix 官方模板库里有 GPU 相关的模板,但 Windows GPU 监控更多是自己配置"性能计数器"监控项。在 Web 界面新建监控项,键值用内置的perf_counter键。
取 GPU 利用率的时候,计数器路径一般是:
\GPU Engine(*)\Utilization Percentage键值写法如下:
perf_counter["\GPU Engine(*)\Utilization Percentage"]这个键会把所有 GPU 引擎实例的利用率做聚合,适合只有一张 GPU 的情况。如果你的机器是多卡,建议先到perfmon里确认具体的实例名,例如pid_2204_phys_0,再用具体实例名去配置,避免统计数据不准。
显存使用率的计数器一般是:
\GPU Process Memory(*)\Dedicated Usage你可以把这两个键分别配置成GPU 利用率和GPU 显存占用,再配合触发器(比如利用率持续 5 分钟大于 90% 且显存占用超过 90%)生成告警。
5.4 中文系统下计数器名称的坑
这里要特别提醒:中文版 Windows 的性能计数器名称可能是本地化的,比如"Utilization Percentage"会显示成"利用率百分比"。Zabbix 通过perf_counter读取计数值时,要求键里的计数器名称必须是英文。如果你直接复制perfmon里看到的名称就填进去,监控项会一直报"参数错误"或取不到值。
解决方式有两种:一种是在 Windows 上修改区域设置或者添加英文语言包,但动静比较大;另一种是到英文资料里查准官方计数器名称,硬编码到键值里。我在实践中更推荐第二种,稳定且不依赖系统设置。如果你不确定自己的计数器名称,可以先到cmd里执行:
typeperf "\GPU Engine(*)\Utilization Percentage"如果可以正常输出数据,说明这个名称是可用的,再填到 Zabbix 里就不容易出错。
6. 实战:Oracle 与虚拟机监控怎么接
6.1 Oracle 通过 ODBC 接入
Zabbix 监控 Oracle 数据库的主流方式是 ODBC。原理并不复杂:Zabbix Server 通过 unixODBC 驱动连接 Oracle 实例,然后执行官方模板里定义好的 SQL 采集表空间、会话数、等待事件等指标。
实际操作里有一个麻烦点:像 Oracle 这种数据库,Server 容器默认并没有它的驱动。你需要先拉取一个基础镜像,然后在容器内安装 Oracle Instant Client(basic 和 odbc 两个包)和 unixODBC,再把自定义镜像跑起来。步骤大概是这样:
# 进入 zabbix-server 容器 docker exec -it zabbix-server bash # 安装 unixODBC 和 curl(容器可能需要 apt 更新) apt-get update && apt-get install -y unixodbc unixodbc-dev # 将下载好的 Oracle instant client 解压到 /opt/oracle # 配置 /etc/odbc.ini,新增 Oracle ODBC 数据源配置好之后,在 Zabbix Web 端对目标 Oracle 主机导入官方模板Oracle by ODBC,然后在主机宏里配置{$ORACLE_DSN}、{$ORACLE_USER}、{$ORACLE_PASSWORD}。模板会自动根据连接字符串去采集数据。
这个场景最容易翻车的是 ODBC 驱动版本和数据库版本不匹配。如果 Oracle 是 19c,建议使用 Instant Client 19.x 系列;如果版本跨度太大,连接时会出现字符集或协议不兼容的报错。所以自定义镜像时,版本尽量和数据库保持一致。
6.2 虚拟机监控:vCenter 模板还是 Agent
虚拟机监控有两条路线,很多人搞混。如果你有 vCenter,Zabbix 7.0 自带的 VMware 监控模板可以直接通过 vCenter 的 API 采集集群级别信息,包括 CPU 就绪时间、内存超分、数据存储使用率、虚拟机在线状态等。配置方式是先把 vCenter 作为一台主机加进来,主机接口填 vCenter 的 IP,然后选择模板VMware,再配置宏{$VMWARE.URL}、{$VMWARE.USER}、{$VMWARE.PASSWORD}。
如果只是几台虚拟机,没有建 vCenter,或者虚拟化平台不是 VMware,那直接在虚拟机内部装 Zabbix Agent 更简单,采集到的 CPU、内存、磁盘、网络数据更贴近操作系统真实状态。
6.3 两种方案的适用场景
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 有 vCenter,需要看集群级别资源情况 | VMware 模板 | 能拿到宿主机和集群视角的数据 |
| 只有少量虚拟机,关心 VM 内部状态 | 虚拟机内装 Agent | 部署简单,数据精确到进程级别 |
| 混合环境(VMware + KVM + 物理机) | Agent 为主 | 统一走 Agent 接入,不用关心底层虚拟化平台 |
| 虚拟机异常重启、宕机监测 | VMware 模板或 SNMP | 虚拟机内部 Agent 在系统崩溃时无法上报 |
方案|选择逻辑
如果你的 VM 只是跑常规业务,建议先装 Agent 把"可用性 + 基础资源"跑通,再考虑是否接 vCenter。一套监控平台最怕一上来就想监控所有东西,反而什么都配不齐。
7. 把告警真正跑通:邮件与钉钉推送
7.1 Zabbix 告警链路的基础认知
监控平台不告警,就等于没有监控。Zabbix 的告警链路可以简单理解为三步:触发器产生"问题事件" → 动作(Action)匹配到这个事件 → 通过媒介类型把消息发送给你。很多人配置告警失败,往往是因为只配了触发器,没有配"动作",或者动作里没有正确关联用户和媒介。
配置告警前,先在"告警 → 触发器"里确认你已经有一个触发器是可用的,并且能触发"已生成问题"事件。然后去配置媒介类型和用户媒介,最后配置动作把三部分串起来。
7.2 SMTP 邮件告警配置
邮件告警是最基础的媒介类型。在 Zabbix Web 界面,导航到"告警 → 媒介类型 → Email",配置 SMTP 服务器、端口、SSL/TLS 方式和认证信息。以常见的企业邮箱为例:
- SMTP 服务器:smtp.example.com
- SMTP 服务器端口:465(SSL)或 587(STARTTLS)
- SMTP 认证:开启,填入发件邮箱账号和授权码(不是登录密码,是邮箱服务商给的专用授权码)
配置完以后,先在媒介类型列表里"测试"一下,给某个邮箱发送测试邮件,确认能收到再继续。然后把邮件媒介添加到你的用户账号下,收件人填你的邮箱地址。最后配置"动作":在告警 → 动作 → 触发器的动作里,新建动作,条件设置为"触发器严重性 ≥ 警告",操作选择"发送消息"并指定发送到之前配置过媒介的用户。
这里有个经验:初始阶段把告警条件放宽,先确保链路通,再逐渐收紧。比如先把所有严重级别都发到自己的测试邮箱,跑两天确认告警频率和数据准确性,再细化条件。
7.3 钉钉群机器人推送
国内团队用钉钉或企业微信居多,以钉钉自定义机器人为例。在钉钉群中添加一个自定义机器人,会得到一个 Webhook 地址。安全设置常见的是加签方式,这种方式在请求时需要把时间戳和密钥拼接签名后作为参数带上。
Zabbix 7.0 内置了通用的 Webhook 媒介类型,但钉钉加签的加密流程需要一点改造。最稳妥的做法是使用自定义脚本,在 Zabbix Server 容器内放置一个告警脚本,核心逻辑是用 curl 把消息 POST 到钉钉 Webhook。脚本大致逻辑:
#!/bin/bash WEBHOOK_URL="https://oapi.dingtalk.com/robot/send?access_token=xxxx" MESSAGE="$1" curl -H "Content-Type: application/json" -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"$MESSAGE\"}}" "$WEBHOOK_URL"然后把脚本挂到/usr/lib/zabbix/alertscripts/目录,在 Zabbix 的媒介类型里新增一个"脚本"类型媒介,脚本参数填{ALERT.SUBJECT} {ALERT.MESSAGE}。动作配置和邮件类似,只是媒介选成这个脚本。
需要注意的是,容器重启后脚本文件可能丢失,如果不想每次重新复制,建议把脚本目录做成绑定挂载,例如在 compose 里加:
volumes: - /opt/zabbix/alertscripts:/usr/lib/zabbix/alertscripts:ro这样宿主机上的脚本修改后容器内立即可用,确实省心很多。另外钉钉机器人的安全设置建议开启"自定义关键词",比如关键词设置为"Zabbix",这样消息里只要包含该关键词就能正常推送,否则可能被平台限流。
7.4 告警风暴的治理思路
告警跑通之后,下一个必然遇到的问题就是告警风暴。某个服务抖动一次,关联主机上的十几个监控项全部触发,邮箱和钉钉瞬间被刷屏,真正重要的问题反而被淹没。
治理告警风暴最直接的手段是配置触发器的依赖关系。比如主机宕机时,它上面所有服务级触发器都会跟着触发,这时在服务级触发器上设置"依赖主机的可用性触发器",一旦主机不可用,服务级触发器就不会重复产生问题事件。操作路径是:触发器详情 → 依赖触发器 → 选择目标触发器。这个配置建好以后,告警量会立刻下降一大截。
另外,维护窗口非常值得利用。每次发布窗口或计划重启期间,提前在 Zabbix 中创建维护周期,选择对应主机和时段,维护期间不会发送任何告警。这样既不会漏掉关键异常,也不会被计划内操作刷屏。最后,条件允许的话建议开启告警升级功能,5 分钟无响应自动升级到上级负责人,比单纯刷屏高效得多。
把邮件和钉钉都跑通后,我一般会做一次完整的告警链路演练:手动停掉一台测试机的 Agent,等触发器生成问题事件,确认邮件、钉钉都能收到告警,再启动 Agent 确认恢复通知正常。链路验证通过之后,这套 Docker 部署的 Zabbix 平台才算是真正具备"企业级监控与告警"的交付能力了。
最后分享一点个人体会:Docker 部署 Zabbix 最大的价值不是快,而是把精力从"安装环境"挪到"配置监控"上。我见过太多团队在裸机安装那一步就消耗了一整天,而用容器化方案,一下午就能把主机的 CPU、内存、磁盘、网络流量全部拉起来,再把告警链路验通。生产环境接入时别贪多,先把一条"采集 → 触发器 → 动作 → 告警推送"的闭环跑稳,再逐个接入更多主机和数据库,每一步都有据可查,平台才能真正成为团队的基础设施,而不是又一个需要被监控的"新负担"。