
刚把一套Zabbix 7.0的自定义Linux监控模板从测试环境搬到生产整个过程比预想中折腾也积累了不少值得记下来的东西。这套模板用的是Agent Active模式监控项覆盖CPU、内存、磁盘、网卡并且磁盘和网卡都走自动发现无论主机上挂了几块盘、几张网卡只要把模板挂到主机上监控项会自动补齐完全不用手工一条条加item。如果你也在用Zabbix 7.0配置过官方Linux模板之后觉得大而全、难落地或者你手头机器处在防火墙策略比较严的网络分区想少开端口那这篇经验总结应该对你有用。文章里我会把模板怎么设计、自动发现规则怎么配、Agent端怎么联调、踩过哪些坑一次说清楚。1. 模板方案与核心思路1.1 为什么没有直接套用官方 Linux 模板Zabbix 7.0 安装完之后自带一套Linux by Zabbix agent active这套官方模板质量没问题但真正用到生产环境时还是有几个让我不太舒服的地方。第一是监控项太多。官方模板覆盖了文件系统、网络接口、CPU、内存、系统信息、日志等一大堆内容挂上去之后如果主机数量一多服务器压力和前端图表加载都会明显上去。很多监控项其实在具体业务场景里用不到比如你不关心系统日志数量或者不需要采集每个CPU核心的详细状态那这些item就是纯浪费。第二是命名风格不一定和内部标准匹配。不同团队对监控项名称有自己的约定比如CPU Load Average还是cpu.load.avg1告警通知里需要展示的文案也不一样。直接用官方模板后面要改命名、改单位、改阈值反而比从零建一个还麻烦。第三是官方模板是一套“大而全”的参考模板为了覆盖所有情况参数和预处理都写得非常保守。一旦出问题你很难快速定位是哪些监控项在报错。自定义模板的好处是精简、可控这个模板里每个item都是Need的每个自动发现规则都有明确过滤条件出现异常时一眼就能找到问题。这里要说明一下我讲的“自定义模板”不是要去写什么UserParameter扩展Agent采集能力而是利用Zabbix Agent已经内置的标准Key重新组织成一个适合自己的模板。真正需要自定义采集脚本的场景可以在模板里加上UserParameter对应监控项这属于另外的话题。1.2 Agent Active 模式解决什么问题Zabbix Agent有两种数据上报模式被动模式Passive和主动模式Active。被动模式下Zabbix Server主动连接Agent的10050端口去拉数据。主动模式下Agent反而会定时连接Server的10051端口领取监控项列表再主动把结果推回来。两者看起来只是“谁发起连接”的差别但在真实网络环境里差别非常大。对比项Passive 被动模式Active 主动模式连接发起方Server - AgentAgent - ServerAgent 监听端口10050不需要Server 监听端口不需要10051Trapper防火墙要求需要放行所有Agent入站端口只需Agent能访问Server的10051大批量主机扩展Server需要持续轮询压力大Agent自报数据适合大规模部署跨网段/NAT环境部署麻烦天然适合我最初是在一套比较敏感的网络环境里做这套模板的Agent和Server之间隔了好几层防火墙被动模式要开放一堆入站规则运维那边审批周期非常长。改成Active模式之后只需要在Server侧放行10051端口Agent能主动访问Server就行入站端口不用动部署审批一下子轻松很多。还有一点Zabbix 7.0的官方模板本身就有Active版本说明这个方向也是官方推荐的标准化做法。对于几十台、上百台Linux主机主动模式能明显降低Server端的轮询压力。1.3 自动发现的价值在哪里自动发现也就是Zabbix里的Low-Level DiscoveryLLD是这套模板的灵魂。磁盘和网卡这类监控对象是随机器配置变化的有些机器只有一块系统盘加一块数据盘有些机器插了五六块磁盘网卡更是五花八门千兆、万兆、多队列虚拟网卡应有尽有。如果不做自动发现每一台新主机上线时都要打开Zabbix前端手工添加磁盘监控项、网卡监控项、触发器一台机器至少十几分钟。如果机器配置不一样甚至要手动确认每个挂载点和网卡名非常容易漏配。自动发现规则的工作原理是Agent执行一个Discovery Key返回一段JSON格式的宏列表Zabbix Server拿到后为数组中每个元素自动生成对应的监控项。比如磁盘发现Keyvfs.fs.discovery返回值里会带{#FSNAME}、{#FSTYPE}、{#FSDESCR}这些宏Server遍历一遍就为每个挂载点生成监控项原型对应的实例。这是典型的“让机器替你干活”的思路也是Zabbix在高主机量时还能维持简洁配置的核心机制。模板里我做磁盘和网卡自动发现CPU自动发现作为可选规则原因稍后实操部分细说。2. 监控项与关键机制拆解2.1 监控项统一规划模板里的监控项我按照“系统基础信息、CPU、内存、磁盘、网卡”几个组来规划。每个监控项的Key、名称、单位都遵循同一套命名风格这样以后导入到别的主机或是别人接手维护也能一眼看懂。基础信息部分保留了三样东西agent.ping监控Agent存活状态主动模式下同样可以用这个Key做可用性数据system.uptime系统运行时长配合告警能判断主机是不是发生过重启system.hostname主机名方便在前端直接看出监控数据来源。CPU部分我做整体监控和可选的核心级监控。整体监控用负载和利用率两条线负载用system.cpu.load[all,avg1]和system.cpu.load[all,avg5]利用率用计算Item算出来。为什么要两个维度负载是运行队列长度代表系统整体“忙不忙”利用率是CPU时间片占用比例代表“忙到什么程度”。两个指标同时看才能区分一台机器是因为高并发导致的高负载还是因为某个死循环进程打满了CPU。内存部分就是四个基础采集项vm.memory.size[total]、vm.memory.size[available]再加一个内存利用率计算Item。很多人会习惯用vm.memory.size[used]但要注意这个值和free命令看到的used不完全一致因为used通常等于total减available而available里已经包含了可回收的缓存部分所以更推荐用available来计算真实可用内存。磁盘和网卡因为配置不固定全部走自动发现规则不在基础监控项里固定写死。2.2 三个自动发现规则的设计第一个自动发现规则是磁盘挂载点发现使用Keyvfs.fs.discovery。这个Key返回当前系统所有挂载点信息包括根分区、数据盘、内存文件系统等。如果不过滤Zabbix会把proc、sysfs、overlay、tmpfs这些虚拟文件系统全部当成监控对象监控项会大量膨胀而且很多虚拟文件系统每次读取数值都在变不具备告警价值。所以在发现规则里必须做过滤器。我的原则是直接排除掉虚拟文件和临时文件系统再通过宏给一些特殊情况留出口。第二个自动发现规则是网卡发现使用Keynet.if.discovery。它会返回系统中所有网络接口包括物理网卡、虚拟网卡、回环接口、Docker网桥等。生产环境里Docker启动后会多出docker0、veth开头的一系列虚拟网卡这些接口大部分不用监控流量所以过滤规则里要排除掉回环、Docker网桥、虚拟网卡等。第三个自动发现规则是CPU核心发现使用Keysystem.cpu.discovery。这个规则不是必须的但如果你想看到每个核心的使用率它很有用。它会为每个逻辑CPU生成一个监控项。物理机核数多、逻辑核心三四十个以上时这会产生大量监控项所以我在模板里默认保留但实际使用时可以禁用。2.3 计算监控项怎么搭监控项里比较难理解的是“计算Item”。CPU利用率和内存利用率我都用了计算Item而不是直接让Agent计算。原因是Agent侧提供的关键Key多数是基础数值比如system.cpu.util[total,idle]返回空闲百分比vm.memory.size[available]返回可用内存字节数。如果直接把空闲百分比当告警指标语义非常别扭。用计算Item的好处是可以在Zabbix Server侧拿到多个采集值之后统一换算并且表达式里的阈值、模板引用都还能用宏控制。CPU利用率表达式我写成这样100 - last(/Custom Linux Active 7.0/system.cpu.util[total,idle])它的含义是取当前CPU空闲率用100减掉之后得到使用率。单位设置成%。内存利用率表达式100 - (last(/Custom Linux Active 7.0/vm.memory.size[available]) / last(/Custom Linux Active 7.0/vm.memory.size[total]) * 100)这个表达式同样是用100减去可用内存占比得到已用内存占比。需要注意表达式里的模板名要和你实际创建的模板名完全一致否则Zabbix会提示找不到监控项。如果你改了模板名表达式里也要同步更新。计算Item本身不占用Agent连接它是纯Server端计算但引用的基础数据仍然来自主动模式Agent所以整体模型还是Active模式。2.4 Agent 主动模式的底层流程理解主动模式的数据上报流程对排查问题特别有帮助。Agent进程启动后会先根据配置文件里的ServerActive地址连接Zabbix Server的10051端口向Server注册自己的Hostname获取属于这个主机的active checks列表。拿到列表之后Agent按照设定的更新间隔执行各个监控项再把结果批量推送给Server。Server端的Trapper进程接收数据写入历史数据库。这里要注意主动模式下的“注册”依赖Hostname与前端主机名一致。如果Agent配置里写的是Hostnameweb01而Zabbix前端的主机名写的是Web01大小写不一致会导致Agent拿不到任何检查项。实际操作中这个大小写问题是我见过最常见的数据空白原因。另外Server端如果同时接收大量Active Agent数据默认的Trapper进程数量可能需要调大。在zabbix_server.conf里可以调整StartTrappers参数这个参数就是并发接收Agent上报的能力一般一台Server接管几百台Agent问题不大但如果上千台就要注意了。3. 模板落地实操3.1 创建模板与全局宏登录Zabbix 7.0 Web界面依次进入“配置 - 模板 - 创建模板”。模板名称建议带版本信息我用的是Custom Linux Active 7.0所属群组单独建一个Templates/Custom方便和官方模板区分。创建完模板后第一件事是把宏配上后面所有过滤器、阈值都可以引用这些宏。我在模板里预置了下面这几个全局宏宏名称默认值用途{$FS.FSTYPE.EXCLUDE}^(tmpfs|devtmpfs|overlay|proc|sysfs|securityfs|cgroup|pstore|configfs|tracefs|debugfs|mqueue|hugetlbfs|fusectl)$磁盘发现时排除的虚拟文件系统类型{$FS.NAME.EXCLUDE}^(/var/lib/docker.*|/snap.*|/var/snap.*)$磁盘发现时排除的挂载点关键字{$NET.IF.EXCLUDE}^(lo|docker.*|veth.*|br-.*|virbr.*|tun.*|tap.*)$网卡发现时排除的接口名{$DISK.PUSED.MAX.WARN}80磁盘使用率告警阈值{$DISK.PUSED.MAX.HIGH}90磁盘使用率严重阈值{$CPU.LOAD.MAX}4负载告警阈值按机器规格自行调整宏的好处是模板固定一套主机级别可以单独改。比如某台机器是特殊负载磁盘使用率告警阈值想从80改成85只需要在主机上覆盖这个宏不用复制整个模板。3.2 添加基础监控项在模板的“监控项”页面点击创建监控项。第一个是Agent存活监控名称Agent ping类型选择“Zabbix agent (active)”Key写agent.ping信息类型选择“数字无正负”勾选“更新间隔”默认30秒。这个监控项虽然简单但它是所有告警的基础如果它断掉说明Agent和Server之间连接已经出现了问题。接下来是系统信息。添加system.uptime单位加上uptime可以让Zabbix自动格式化显示天时分秒。再添加一个system.hostname信息类型选“字符”用于在监控项数据里直接看到主机名。然后添加CPU负载监控项Key选择system.cpu.load[all,avg1]和system.cpu.load[all,avg5]信息类型都是“数字浮点”单位留空。负载值没有单位它代表的是运行队列长度这个值需要按机器核数来评估不能拿固定数值套用所有机器。CPU利用率监控项用计算Item。名称我写成CPU utilization类型选择“计算”表达式就是前面提到的100 - last(...)信息类型“数字浮点”单位%。这样监控项页面上就会有一个直接可读的CPU使用率数值告警阈值可以直接基于它配置。内存部分添加vm.memory.size[total]、vm.memory.size[available]两个基础采集项信息类型“数字无正负”单位B。再创建一个计算ItemMemory utilization单位%。注意单位选B之后Zabbix会自动以B、KB、MB、GB的格式显示不需要自己换算。3.3 磁盘自动发现配置在“自动发现规则”页面点击创建。名称Discover filesystems类型选择“Zabbix agent (active)”Key填vfs.fs.discovery。创建后先别急着加监控项原型先配置过滤器。我加了两个过滤条件逻辑关系选择“AND”条件一{#FSTYPE}不匹配正则{$FS.FSTYPE.EXCLUDE}条件二{#FSNAME}不匹配正则{$FS.NAME.EXCLUDE}。过滤器的作用范围是整个发现规则它的过滤逻辑是Zabbix Server拿到Agent返回的JSON数组后逐个判断每个元素是否满足条件如果任何一个条件不满足这个挂载点就不会被生成监控项。可以先用命令在Agent上手动查看发现返回的数据确认宏名是否和过滤器一致zabbix_agent2 -t vfs.fs.discovery正常输出会是类似这样的JSON结构{data:[ {{#FSNAME}:/,{#FSTYPE}:ext4,{#FSDESCR}:root}, {{#FSNAME}:/data,{#FSTYPE}:xfs,{#FSDESCR}:/data} ]}确认过滤器没问题之后进入“监控项原型”页面创建磁盘监控。我建了四个原型文件系统总大小Key为vfs.fs.size[{#FSNAME},total]单位B文件系统已用大小Key为vfs.fs.size[{#FSNAME},used]单位B文件系统可用大小Key为vfs.fs.size[{#FSNAME},free]单位B文件系统使用率Key为vfs.fs.size[{#FSNAME},pused]单位%。注意原型名称里必须带{#FSNAME}比如Disk used space on {#FSNAME}这样生成的每个监控项名称会根据实际挂载点变成/、/data等一眼就能分辨。触发原型也配两个分别对应80%和90%两个严重级别。表达式写法last(/Custom Linux Active 7.0/vfs.fs.size[{#FSNAME},pused]) {$DISK.PUSED.MAX.WARN}这样模板挂到新主机后每多一个数据盘告警规则也会自动多一份完全不用手动加。3.4 网卡自动发现配置网卡发现规则创建方式和磁盘基本一致。名称Discover network interfaces类型“Zabbix agent (active)”Key填net.if.discovery。过滤条件只用一个{#IFNAME}不匹配正则{$NET.IF.EXCLUDE}。我的排除宏里默认排除了docker、veth、br-这些虚拟接口。为什么这么严格因为生产环境里Docker容器频繁重启的时候veth接口名会不断变如果每个接口都监控数据库里会产生大量僵尸监控项前端列表也会被刷屏。网卡监控项原型我用了两个入站流量Key为net.if.in[{#IFNAME}]单位Bps出站流量Key为net.if.out[{#IFNAME}]单位Bps。这里有个特别容易踩的坑net.if.in这个Key返回的已经是每秒字节数了。Agent内部会自己读取/proc/net/dev两次并计算差值所以不要再在预处理里套“变化率”或者“差值”否则数据会变成0或者出现数据延迟。我自己第一次配的时候就想当然加了变化率预处理结果所有网卡流量全部是0排查了半天才发现是重复计算。如果你习惯用比特/秒来展示可以在监控项预处理里加一个“自定义倍数”乘8单位改成bps。不过我个人习惯保留Bps方便和系统层面sar、iftop这些工具的字节数直接对比。3.5 CPU 自动发现可选CPU核心级监控我也做成了自动发现。发现规则名称Discover CPU coresKey填system.cpu.discovery。监控项原型名称CPU core {#CPU.NUMBER} utilizationKey为system.cpu.util[{#CPU.NUMBER},idle]由于这个Key返回的是空闲率而我希望展示使用率所以在预处理里加了一段JavaScriptreturn 100 - parseFloat(value);信息类型“数字浮点”单位%。这个规则在物理机上很值得开尤其是排查性能问题时能直观看到是哪个核心被打满。但虚拟机/容器场景慎用因为宿主机核数和虚拟机核数不对等而且核数越多监控项数量越大。我通常的做法是模板里创建这个规则但默认在主机上禁用需要的时候再启用。3.6 Agent 端与 Server 端联调模板建好之后需要把模板关联到具体主机。在主机配置里把模板Custom Linux Active 7.0链接上去然后在Agent配置文件中确认主动模式参数。以Zabbix Agent 2为例配置文件关键参数如下Server127.0.0.1 ServerActive10.0.0.20:10051 Hostnameweb01参数说明Server是允许被动模式连接的Server地址如果你只使用主动模式这个参数写上本机地址即可不需要真的开放防火墙ServerActive是Agent主动上报的Server地址和端口这里必须是Server端口的10051Hostname必须和Zabbix前端创建的主机名完全一致。如果不想在每台机器上手动写死Hostname可以采用HostnameItemsystem.hostname这种方式让Agent自动取系统主机名作为上报身份。但前提是Zabbix前端的主机名必须和系统Hostname一致否则匹配不上。修改配置文件后重启Agentsystemctl restart zabbix-agent2查看Agent日志确认是否成功获取到Active Checkstail -f /var/log/zabbix/zabbix_agent2.log日志里如果出现类似active check ... not found这样的信息基本就是Hostname不一致或者模板里的监控项Key在Agent上不存在。Server端通常不需要额外配置但如果你要接管的主机非常多建议在Zabbix Server配置里调大Trapper进程数StartTrappers200然后重启Zabbix Server。改这个参数前先评估当前并发量不要盲目调大以免占用过多进程资源。4. 常见问题与排查实录4.1 数据一直不过来主动模式下最典型的现象是主机已经在Zabbix前端关联了模板主机状态显示“已启用”但“最新数据”里一片空白。这种问题90%出在连接链路和Hostname匹配上。排查顺序我建议按下面来在Agent所在机器上测试到Server的10051端口连通性telnet 10.0.0.20 10051如果端口不通就是网络或防火墙问题。主动模式要求Agent能访问Server的Trapper端口而不是要求Server能访问Agent的10050。查看Agent日志。日志里如果显示no active checks说明Agent根本没有从Server拉到监控项列表。这时检查ServerActive地址、端口、Hostname大小写以及前端主机是否应用了模板。去Zabbix Server端看日志tail -f /var/log/zabbix/zabbix_server.log | grep web01如果Server日志里没有这个主机的上报记录说明请求根本没到Server如果有记录但没入库可能是Trapper进程满了或者数据库写入异常。4.2 磁盘和网卡发现规则不生效发现规则配置了但“监控项”列表里没有自动生成的磁盘监控项这种情况多半是过滤正则写错。先不要猜直接在Agent上执行发现命令看原始JSONzabbix_agent2 -t vfs.fs.discovery zabbix_agent2 -t net.if.discovery看输出的JSON结构和宏值再去“自动发现规则”里套一遍过滤条件。最容易犯的错误是正则在测试工具里能匹配但放到Zabbix过滤器里就失效。原因是Zabbix的过滤条件里有“匹配正则表达式”和“不匹配正则表达式”两种选项而且默认区分大小写。如果填的是“不匹配”但正则写反效果就完全颠倒。另一个常见问题是宿主机上挂载了很多overlay、tmpfs这样的虚拟文件系统。如果过滤条件只排除部分FSTYPE剩下的overlay还是会被监控。建议把平时容易遇到的虚拟类型都写进排除宏里宁可排除严格一点也不要在生产环境看到几百个无用的tmpfs监控项。4.3 监控项数值不对CPU负载单位容易理解错但还有一个更隐蔽的问题CPU使用率如果用的是空闲率反推计算Item模板名不匹配系统会直接显示“不支持的监控项”。表达式里引用的模板名必须是实际模板名不能写错大小写和空格。网卡流量显示为0前面已经提过往往是在预处理里重复做了“变化率”。net.if.in本身已经换算成每秒字节数再加一次差值当然会出错。如果仍然坚持要展示bit/s就用“自定义倍数”乘8这会直接作用于已经算好的字节数。磁盘容量如果显示成特别大的数字先看单位是不是设成了B。vfs.fs.size[{#FSNAME},pused]这个模式返回的是0到100之间的百分比单位要设%而total、used、free模式返回的是字节单位要设B。这两类单位一旦混用前端展示的图表数值就会非常奇怪。4.4 模板在实际使用中的避坑习惯这套模板上线后我给自己定了几个使用习惯。每新建一台Linux主机固定流程就是在前端主机里关联模板在Agent配置里写对Hostname然后到“最新数据”里检查agent.ping是否有值。如果10分钟内没数据先看日志再碰网络不要盲目重启服务因为大部分主动模式问题都出在Hostname和网络端口上。模板版本问题也很重要。每次改模板我都会导出XML备份再存到Git仓库里。Zabbix模板本质上是一段结构化的XML配置改动一次导出一次就能非常清楚看到历史变更。尽量别在模板里写死过多个性参数能用宏就不要用固定值宏可以做到“模板一套、主机各自覆盖”后期维护省非常多事。另外我后来把所有自定义Agent监控项都加了统一前缀比如custom.linux.*。如果以后要在这个模板里扩展自己的采集脚本每个Key都带上前缀和官方Key区分排查问题时能立刻判断是哪个来源的数据。最后分享一点个人体会做了这套Zabbix 7.0自定义Linux监控模板之后我最大的感觉是监控模板不是一个建完就能放着不管的东西它需要跟着业务和机器类型持续演进。官方模板虽然大而全但真正用得上的监控项可能只有三分之一与其保留一堆无用的历史数据和监控项原型不如花半天时间建一个精简、可控、带自动发现的模板后面运维会轻松很多。我后来把模板推广到了好几批机器上凡是新的Linux主机上线只要关联Custom Linux Active 7.0半小时内磁盘、网卡、CPU、内存监控全部自动出来。最直接的收获是再也不用每台机器手工点“添加监控项”了排错时间也大大缩短。这个模板目前还在迭代比如后续准备加上TCP连接数、进程存活这类常用监控项也会继续保持自动发现和宏统一管理的原则。