ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Zabbix 7.0 报错排查实战:从部署到告警的故障处理指南

Zabbix 7.0 报错排查实战:从部署到告警的故障处理指南 前阵子在一台 Rocky Linux 9.8 上部署 Zabbix 7.0按官方步骤初始化数据库时直接被一个报错拍在脸上access denied for user replace_userlocalhost (using password: YES)。当时第一反应是“这什么情况我明明还没创建用户”后来一看是自己复制的 SQL 模板里还留着占位符没替换干净。这种报错对老手来说可能扫一眼就能定位但对刚接触 Zabbix 的人来说卡个半天很正常。这些年用 Zabbix 做监控踩过的坑不少报错也见过一大堆正好借这个机会整理一份实战向的报错集锦。这篇文章不打算把官方文档再抄一遍而是挑那些在实际环境里反复出现、网上搜起来答案零零散散的问题把排查链路完整走一遍。覆盖范围包括安装部署、Server 端状态异常、Agent 采集链路、监控项失效、钉钉告警联动以及一些“看着没报错但其实很危险”的隐性故障。无论你是在搭建阶段还是日常维护阶段或者准备 Zabbix 面试这份东西应该都能派上用场。1. 安装部署期的经典报错从 replace_user 数据库权限说起1.1 access denied for user replace_userlocalhost 的根源先说说开头那个报错。replace_user不是真实存在的用户而是官方安装文档或自动化脚本在生成 SQL 初始化语句时留下的占位符。你拿到手的是这种模板CREATE DATABASE zabbix CHARACTER SET utf8mb4 COLLATE utf8mb4_bin; CREATE USER replace_userlocalhost IDENTIFIED BY replace_password; GRANT ALL PRIVILEGES ON zabbix.* TO replace_userlocalhost;如果直接复制执行MySQL 里确实会生成一个叫replace_user的账号。但更常见的情况是安装脚本只把数据库建好了后面配置/etc/zabbix/web/zabbix.conf.php时却填了你自己定义的用户名和密码两边对不上自然就报access denied。排查时可以分三步走先确认数据库端到底有没有这个账号SELECT user, host FROM mysql.user WHERE user IN (zabbix, replace_user);再确认连接命令走的是哪个 hostlocalhost和127.0.0.1在 MySQL 授权里是两个不同实体有时候账号只授权了localhost但 Zabbix 前端或 Server 用127.0.0.1去连也会报同样错误。最后检查密码里有没有特殊字符。如果密码里有$、#、%这类字符在命令行里又没做转义复制到配置文件时可能已经被 shell 处理过一遍实际存入的密码根本不是你以为的那个。提示初始化数据库前先把 SQL 里的占位符全部全局替换掉不要手动一个字段一个字段改。用sed -i s/replace_user/zabbix/g; s/replace_password/你的强密码/g db.sql这种命令一次性处理能避免很多低级问题。1.2 Rocky Linux 9.8 装 Zabbix 7.0 时三个容易忽略的依赖点Zabbix 7.0 在 Rocky Linux 9.8 上安装时官方仓库的 RPM 包会自动拉依赖但有几个点经常被忽略导致前端页面能打开、却提示缺模块。第一个是 PHP 版本。Rocky Linux 9 默认带的是 PHP 8.0Zabbix 7.0 要求 PHP 8.0 以上理论上满足。但如果之前手动装过其他版本的 PHP或者启用了多个软件仓库版本可能被顶到 8.2/8.3而 Zabbix 前端对 PHP 版本有兼容性校验。遇到这种情况先看前端安装页顶部警告再执行php -v确认版本必要时通过dnf module reset php和dnf module enable php:8.0把版本固定在系统默认版本上。第二个是 PHP 扩展。Zabbix 7.0 前端至少需要php-bcmath、php-mbstring、php-gd、php-xml、php-ldap。很多人装完只装了php和php-fpm打开安装页看到一大堆红色警告其中一个常见的就是PHP ldap module missing。没有 LDAP 需求的话可以不用管但如果前端要求必须通过就执行dnf install -y php-bcmath php-mbstring php-gd php-xml php-ldap第三个是 SELinux。Rocky Linux 默认 enforcing 模式安装完 Zabbix Server 启动没问题但前端访问数据库或写入临时文件时会被拦住。最直接的判断方法是查看/var/log/audit/audit.log里有没有denied关键字确认是 SELinux 拦截后再用setsebool -P httpd_can_network_connect 1放通 Apache 到数据库或后端的网络连接。不要一上来就setenforce 0那是图省事后面重启一次就忘了监控就断了。1.3 前端安装页报 Unable to connect to database 的处理如果你已经完成向导但前端后续打开时报Database error: Unable to connect to database这不是 MySQL 服务挂了就是 Zabbix 前端配置文件里的数据库凭据不对。Zabbix 前端的数据库连接配置放在/etc/zabbix/web/zabbix.conf.php里面只有三样东西数据库主机、数据库名、账号密码。我的排查习惯是先看数据库进程systemctl status mariadb mysqladmin -u zabbix -p ping如果数据库没问题就对比配置文件里的$DB[USER]、$DB[PASSWORD]和 MySQL 里实际账号是否一致。这里有个隐蔽坑Zabbix Server 本身也读一套数据库配置路径是/etc/zabbix/zabbix_server.conf里面也有DBUser和DBPassword。前端连接用的是一套Server 进程用的又是另一套如果只改了前端配置Server 能连上数据库但前端连不上或者反过来报错信息会完全不同。遇到“数据库连接异常”类报错两边的配置文件都要检查一遍。2. “Zabbix server is not running”不要急着无脑重启2.1 这个红色提示可能来自哪一层前端页面顶部飘红提示Zabbix server is not running是运维圈里最常见也最容易误判的告警。很多人一看这个提示直接systemctl restart zabbix-server重启完暂时绿了过几天又飘红然后陷入死循环。实际情况是这个提示说的是“前端拿不到 Server 运行状态”而不是“进程一定挂了”。Zabbix Server 每秒钟都会向内部的共享内存写入状态数据前端通过一个叫status的接口读取。如果 Server 进程活着但在大量处理数据、线程卡死、数据库连接阻塞状态数据写不进共享内存前端一样会判断为未运行。先看看进程到底在不在ps -ef | grep zabbix_server ss -lntp | grep 10051进程还在的话再去日志里找根因日志路径默认在/var/log/zabbix/zabbix_server.log。我遇到过很多次的情况是日志里持续出现History cache is 80% full或者History cache is full过一阵子前端就飘红了。2.2 缓存与数据库连接耗尽最容易被忽视的淹死现场Zabbix Server 有几块共享内存缓存CacheSize配置和数据缓存、HistoryCacheSize历史数据缓存、TrendCacheSize趋势数据缓存。这些值在zabbix_server.conf里默认都比较保守新装好直接跑几百台设备、几万个监控项时缓存很容易打满。缓存打满后Server 处理采集数据的效率断崖式下降历史数据来不及写入数据库队列越积越长最终前端状态读取超时就报not running。遇到这种情况先查日志确认是不是缓存告警再对监控项规模做个估算。我习惯按 1 个监控项约占用 50 到 100 字节共享内存来粗算50000 个监控项的话HistoryCacheSize配 128M 以上比较稳。调参公式是# 缓存大小配置示例 CacheSize256M HistoryCacheSize128M TrendCacheSize64M同时还要检查 MySQL 连接数。Zabbix Server 默认数据库连接池大小是DBMaxEscalation、HistoryCacheSize这些参数控制不了连接池连接池由StartPollers、StartTrappers、StartDiscoverers这些进程数决定。进程越多数据库连接就越多。如果 MySQL 的max_connections不够Server 日志会报Cannot connect to database或Too many connections。这时不是盲目调小进程数而是先看show processlist;里 Zabbix 用户建立了多少连接把max_connections调整到合理值或者减少不必要的 poller 进程。注意调缓存和连接池参数不是越大越好。共享内存太大会导致系统内存吃紧进程数太多会让 MySQL 负载飙升。生产环境改完一个参数至少要观察一个采集周期通常 1 到 5 分钟。2.3 poller 不够用的量化判断StartPollers是负责主动采集监控项的进程数。当队列里大量监控项出现延迟而缓存和数据库都健康时很可能是 poller 不够了。Zabbix 前端“报表”菜单里有一个队列页面能直接看到某个 Zabbix Server 上延迟超过多少秒的监控项数量。如果看到堆积项持续增长先把StartPollers从默认的 5 调到 10 或 20观察队列是否回落。但这里有一个容易混淆的场景很多监控项变慢不是 poller 不够而是某个目标主机响应慢一个 poller 被卡在那里等超时。比如有个网络设备 SNMP 超时时间设置成 30 秒这 30 秒内这个 poller 就废了。所以看到队列堆积先按监控项排序找出那几个延迟最高的目标优先优化超时时间和重试次数而不是一上来就堆 poller。2.4 日志里常见却容易被误读的进程记录Zabbix Server 异常退出后会在/var/run/zabbix/目录下残留 pid 文件。重新启动时如果旧 pid 文件还在而那个 pid 已经不复存在服务管理器可能会误判“服务已经在运行”。你在systemctl start zabbix-server时看到失败但ps里又找不到进程大概率就是 pid 文件脏了。处理方式很简单rm -f /var/run/zabbix/zabbix_server.pid systemctl start zabbix-server这种问题常出现在强制 kill、虚拟机快照回滚、磁盘写满等异常场景之后。磁盘写满这个因素特别容易被忽略zabbix_server.log和 MySQL 的 binlog 都在同一块磁盘上磁盘满了Server 启动时无法写入日志就会启动失败但报错信息可能非常隐晦。先df -h看一眼磁盘再排查其他能省不少时间。3. Agent 采集链路报错连不上、空响应、数据悬空3.1 Get value from agent failed——从 zabbix_get 排查端口和配置新主机加入 Zabbix 后监控项数据一直是灰色点开“最新数据”看到报错Get value from agent failed: cannot connect to [192.0.2.10]:10050。这种问题我一般直接拿zabbix_get在 Server 端做连通性测试zabbix_get -s 192.0.2.10 -p 10050 -k system.cpu.load[all,avg1]如果返回Connection refused说明 Agent 端口没监听或者防火墙挡了。在 Agent 主机上查ss -lntp | grep 10050端口没监听先确认 Agent 进程是否启动再确认配置文件中没有写ListenIP127.0.0.1。有人为了安全把 Agent 绑定在回环地址上结果 Server 端从外网来取数据怎么都连不上。如果端口正常但zabbix_get返回failed to accept an incoming connection: connection from ... rejected那问题基本出在 Agent 配置文件里的Server指令。这个指令本意是“允许哪些 IP 来主动拉取数据”但很多人把它和ServerActiveAgent 往哪台 Server 推送数据搞混。Server要填 Zabbix Server 的 IP不能填 Agent 自己的 IP。填反了或者留空就会看到“连接被拒绝”的报错。3.2 received empty response from zabbix_agentd主动模式下的常见问题zabbix_get能连上端口但返回received empty response from zabbix_agentd这个报错在从被动模式切到主动模式时特别常见。Zabbix 7.0 的 Agent 默认配置是主动模式配置文件里有ServerActive指定 Server 地址。如果是主动模式Agent 会主动连 Server 的 10051 端口Server 端监控项的“类型”也要选成“Zabbix 主动式”。如果 Server 端监控项类型还停留在“Zabbix agent”被动式但 Agent 端主动模式把数据发到了 Server 的 trapper 端口两边没对上就可能出现空响应。还有一种情况是 Agent 端执行某个自定义 key 时执行时间超过了Timeout。Zabbix 7.0 默认Timeout3也就是 Agent 执行脚本最多等 3 秒超过后就杀掉脚本返回空响应。我跑过一些比较重的脚本比如从日志文件里统计耗时的命令经常要十几秒这时候必须把 Agent 的 Timeout 调到 10 甚至 30同时把监控项的“超时时间”也调高两边都要改只改一边没用。3.3 时间不同步带来的“采集到了但没数据”Zabbix 监控项数据有时图上有大段缺口zabbix_get手动执行却一切正常这就是典型的时间不同步问题。Agent 端采集数据后会带一个本机时间戳Server 端在写入历史数据时如果发现时间戳偏离当前时间太多会直接丢弃或标记为无效数据。换句话说你“采到了”但 Server 不认。排查方法很简单在 Server 和 Agent 上分别执行date看看两个时间差多少。超过个位数秒就有问题。统一用 NTP 或 chrony 同步时间systemctl enable --now chronyd chronyc sources另外Zabbix 前端、Server、数据库最好都在一个时区不然图形时间轴和告警时间看着会非常别扭。3.4 Agent 主动连 Server 时容易漏掉的防火墙放行被动模式下只有 Server 连接 Agent 的 10050 端口但主动模式下是 Agent 连接 Server 的 10051 端口。很多环境只在防火墙放行了 10050完全没管 10051结果主机部分监控项能通主动类型监控项全部失败。我自己踩过这个坑新主机加进来zabbix_get测通所有 key但在“最新数据”里看到主动模式监控项半天没反应日志里是 Agent 一直在重连 Server 的 10051。放行端口后10 秒内数据全出来了。有时是云安全组或公司防火墙策略的问题记住一个原则被动模式放行 Server 到 Agent 的 10050主动模式放行 Agent 到 Server 的 10051代理场景还要放行 10051 之外的 trapper 端口。4. Item became not supported监控项失效的归类排查4.1 找到 not supported 的第一现场Item became not supported是 Zabbix 里最磨人的一类报错因为它把所有失败原因都藏在“不支持”这个笼统的状态里。排查第一步永远是先拿到具体的错误原因路径有三个“监测 - 最新数据”里按状态筛选“不支持”点开监控项详情会直接给出错误信息。这是最直观的入口。“配置 - 主机 - 监控项”里点开对应监控项最下面的“信息”字段也会显示失败原因。Zabbix Server 日志里搜not supported关键字能看到最近更新为不支持状态的上下文。大多数时候错误信息里已经写清楚了原因比如Cannot read data from filesystem、Timeout while executing a shell script、No Such Instance currently exists at this OID。真正难的是拿到错误信息之后怎么处理。4.2 key、参数、权限、超时四类原因实例我按实际遇到的概率把这四类排了个顺序Key 写错。比如磁盘空间监控要用vfs.fs.size[/,free]有人会写成vfs.fs.size[free]或者网卡流量把net.if.in[eth0]写成net.if.in[0]。这类错误往往在监控项创建后立刻变成 not supported。参数类型不对。Zabbix 的 key 参数是有类型的有的参数要字符串有的要数字有的要是带引号的宏。自定义脚本类的 key 更明显比如 Agent 端脚本里$1取的是字符串但监控项里传了整数脚本解析直接空指针。权限不足。Agent 默认以zabbix用户运行很多系统文件或脚本它没有权限读取。比如监控/var/log/messages里的关键字zabbix 用户对/var/log目录往往没有读取权限。此时要么把 zabbix 用户加入相应组要么用sudo配合visudo配置白名单。注意 sudo 这里有个坑Zabbix 执行脚本时没有终端默认Defaults requiretty会拦掉需要在 sudoers 里加上Defaults:zabbix !requiretty。超时。Agent 端脚本执行超过TimeoutServer 端 HTTP agent 或 SNMP 请求超过设定的超时时间。这类报错信息里通常带Timeout while executing a shell script。解决办法是调大 Agent 的 Timeout 和对应监控项的超时时间同时优化脚本本身不要指望靠无限调大参数过日子。4.3 LLD 后来发现为空的排查细节自动发现规则LLD报 not supported 或者“发现结果为空”问题通常集中在三个位置发现的 key 在目标上能不能拿到数据、返回的 JSON 结构是不是 LLD 期望的格式、宏变量是否引用一致。Zabbix 7.0 里很多模板自带的发现规则写的是诸如vfs.fs.discovery这种内置 key一般没什么问题。但自定义脚本做发现时脚本打印的内容必须是 JSON 数组比如[{{#IFNAME}:eth0,{#IFTYPE}:1},{{#IFNAME}:eth1,{#IFTYPE}:1}]如果你在 LLD 规则宏里写的引用名和脚本返回的键名不一致比如脚本返回{#IFNAME}但规则里写的是{#IFACE}那生成出来的监控项 key 就会带上空的宏值直接 not supported。这个查起来特别费劲因为它不报第一现场的错你看到的是“宏解析失败”或生成出的 key 是net.if.in[]这种空参数。提示自定义 LLD 时脚本先在 Agent 端手动跑一遍确认输出 JSON再放到监控项里测。不要直接在 Server 端反复试浪费的时间够写十个脚本。4.4 值映射与单位导致的“有值却是错误值”有些监控项状态是支持supported的但数据明显不对。最典型的是网络流量单位混淆Linux 下/proc/net/dev拿到的字节数Zabbix 内置模板一般会帮你做单位换算但自定义监控项时经常忘掉“B/s”和“bit/s”的 8 倍关系。监控项单位写成B/s数据是换算过的不写单位图形里数字看起来就大得离谱。值映射问题则容易出在告警上。很多厂商或自定义模板返回的是数字状态码比如 0 表示正常1 表示异常但没配值映射告警消息里显示“1”不显示“异常”值班的人还得翻文档。这个不算报错但属于监控项配置不完整。把这些数据和模板导入后一定要顺手检查值映射和单位尤其从第三方网上下载的模板几乎每个都要改一遍。5. 告警联动报错钉钉通道悄悄挂了之后5.1 从 zabbix_server.log 中追查无法发送告警Zabbix 7.0 联动钉钉用得非常多但告警通道出问题有个特点它不会把监控项打成 not supported也不会让 Server 进程崩溃只会悄无声息地在告警动作里留下一条失败记录。很多人是在值班群里发现“为什么这个告警没收到”时才开始排查。第一步看 Zabbix Server 日志里有没有和报警相关的错误信息grep -i alert /var/log/zabbix/zabbix_server.log | tail -50常见报错有cannot send alert notification、No media defined for user、Script execution failed。这些信息能帮你确定问题出在哪个环节。5.2 钉钉机器人的加签与关键词在 Zabbix 7.0 里的收发验证Zabbix 7.0 内置钉钉告警媒介也可以在告警动作里配置自定义脚本。用内置 Webhook 时要确认钉钉机器人安全设置里选的是“自定义关键词”还是“加签”。如果选“加签”Webhook 配置里需要把加签密钥填进去如果选“自定义关键词”告警消息正文必须包含关键词否则钉钉会直接拒收。我遇到过一种情况脚本测试手动跑能发出消息但 Zabbix 触发告警时发不出去。原因就是脚本从 Zabbix 读取的告警消息里不含关键词钉钉 API 返回keywords not in content。解决方式是在消息模板里加上关键词或者在钉钉机器人安全设置里改用“加签”方式避免关键词匹配问题。5.3 脚本排直通道的技巧如果你的环境用自定义脚本方式发钉钉建议先把脚本单独拿出来手动以zabbix用户执行一遍sudo -u zabbix /usr/lib/zabbix/alertscripts/dingding.sh test message脚本能跑通再看 Zabbix 告警动作里写的脚本参数对不对。Zabbix 调用告警脚本时会按顺序传入三个参数收件人地址、消息主题、消息内容。不同版本的 Zabbix 对这三个参数的传递方式略有差异如果脚本里写死了参数位置很容易错位。另外脚本日志一定要留。echo $(date) $1 $2 $3 /tmp/dingding_alert.log这个习惯能帮你省掉大量“到底执行了没有”的猜疑。我见过很多次告警脚本执行失败就是因为 Python 脚本里 import 了系统环境里不存在的模块而手动以 root 执行时用的又是另一个 Python 环境验证通过实际跑起来却报错。6. 那些看起来没报错其实很要命的隐性故障6.1 历史数据表膨胀与 housekeeper 跟进Zabbix 运行一年后即使页面不报错也会慢慢变卡。最常见的原因是历史数据表膨胀。Zabbix 默认由 housekeeper 定期清理过期数据但这个机制有个硬伤如果数据量太大清理速度跟不上写入速度表会越撑越大MySQL 的 IO 持续拉高最终影响整个 Server 性能。排查时看 MySQL 里最大的表SELECT table_name, ROUND(((data_length index_length) / 1024 / 1024), 2) AS size_mb FROM information_schema.tables WHERE table_schema zabbix ORDER BY size_mb DESC LIMIT 10;如果history或history_uint表特别大就要考虑调整监控项的历史数据保留时间默认 90 天对很多场景过长了或者干脆做分区表。Zabbix 7.0 对分区表的支持已经比较完善但分区操作涉及数据库结构调整务必在维护窗口操作。还有一个经常被忽略的点housekeeper 本身的进程数。zabbix_server.conf里StartHousekeepers默认是 1数据量大的环境可以调到 2 或 4清理速度会有明显提升。6.2 时区导致的告警时间偏差这是一个“看着没报错但实际很坑”的问题。如果 Zabbix Server 所在系统的时区是 UTC而你的预期是北京时间那告警消息里的所有时间都比实际慢 8 小时。告警内容是正常的数据也是正常的但值班人员看到时间不对很容易误判。处理方式很简单系统层面统一成 Asia/Shanghai同时在 PHP-FPM 和 Zabbix 前端配置里也要把时区设置成一致。前端时区在/etc/zabbix/web/zabbix.conf.php里有$DB[TIMEZONE]要和系统时区保持同步。顺手把 MySQL 的会话时区也看一下因为写入历史数据时某些聚合函数会依赖数据库时区。6.3 新设备没有自动纳入监控LLD 间隔与模板覆盖问题监控跑得越久越容易在“新增主机”这个动作上翻车。很多人手动添加主机后只填了 IP 和模板就完事忘了模板里的自动发现规则有执行周期。Zabbix 7.0 模板里的 LLD 规则默认间隔是 1 小时也就是说新加的设备要等最多 1 小时才会被发现项填充完毕。如果刚加完机就去看监控项发现全是空的就会误以为“模板坏了”或者“报错了”。还有更隐蔽的如果你在主机关联了多个模板两个模板里有同名监控项或同名 LLD 规则后加载的模板会覆盖先加载的配置。这在导入第三方模板时特别常见。Zabbix 不会给你弹任何报错但数据表现会非常奇怪。排查方法是逐个模板检查主机上的监控项来源看看同名项到底来自哪个模板。6.4 Agent 端运行时间过长导致的高水位假象有时候图上有数据但数据曲线忽高忽低怀疑监控项出错。按我的经验很多“假报错”其实是 Agent 端脚本执行时间不确定导致采样间隔抖动。比如一个自定义脚本监控某个服务的并发连接数脚本本身执行需要 1 到 5 秒不定监控项设置为 30 秒采样一次但脚本执行时间不稳定导致每次取数间隔不是均匀的 30 秒画出来的曲线就有毛刺。解决思路是调整采集间隔或者把脚本里不必要的耗时操作缓存起来。Zabbix 有数据预处理功能可以在 Server 端做“改变采样频率”或“简单变化率”等处理但最根本的还是让 Agent 端返回数据的时间稳定。这个不解决后续写告警阈值很容易被毛刺误触发。一些实操感受这些年做监控排障我最大的感受是Zabbix 报错本身不可怕可怕的是报错来之前没有任何上下文。所以我现在每部署一套 Zabbix都会先做一个环境信息核对表把 Agent 的Server和ServerActive、Server 的CacheSize、数据库连接池、防火墙端口、时间同步状态全部记下来。排查问题时先核对这张表把环境变量排除掉再去看具体报错效率会高很多。如果你刚接触 Zabbix也不用被上面这些报错吓到。大部分问题都是配置层面的只要理解了被动与主动采集的区别、键值参数的格式要求、日志路径排查思路就能建立起来。下次再遇到 not supported 或者 server is not running别急着重启先去日志里翻 10 分钟答案大概率就在那里。
返回列表