Zabbix 面试题
30 道题- 分类
- 可观测性
- 子分类
- metrics
- 题目数
- 30 道
1 Zabbix 核心架构和核心组件是什么?
答案:
Zabbix 是一款企业级开源分布式监控解决方案,由 Server、Agent、Proxy、Web 前端和数据库五大核心组件构成,支持 SNMP、IPMI、JMX、Agent、Trapper、HTTP Agent 等多种采集协议,擅长主机、网络设备、数据库、应用服务的统一监控。
核心架构:
graph TD
A["Zabbix Server
核心进程 + 告警引擎 + 数据库读写"] -->|读写历史数据| B[(数据库
MySQL/PostgreSQL/TimescaleDB)]
C["Zabbix Agent / Agent 2"] -->|主动/被动推送指标| A
D["Zabbix Proxy"] -->|汇聚后转发| A
E["SNMP/IPMI/JMX 设备"] -->|轮询采集| A
F["Trapper/HTTP Agent
(主动推送)"] -->|推送| A
A -->|告警动作| G["Action 升级
邮件/Webhook/IM"]
H["Web 前端 PHP"] -->|API/RPC| A
I["用户/运维"] -->|可视化与配置| H
核心组件职责:
| 组件 | 职责 | 关键特性 |
|---|---|---|
| Zabbix Server | 核心进程,负责轮询/接收指标、触发器评估、告警发送、与数据库交互 | 多进程模型:poller、trapper、housekeeper、alerter、escalator 等 |
| Zabbix Agent | 部署在被监控主机上的采集程序 | Zabbix Agent(C 语言)/ Zabbix Agent 2(Go 重写,插件化) |
| Zabbix Proxy | 分布式场景下代替 Server 收集区域数据,统一上报 | 缓解 Server 压力,跨机房/网络隔离场景必备 |
| Web 前端 | PHP 实现的可视化与配置界面 | 配置主机、模板、触发器、仪表盘;调用 API |
| 数据库 | 持久化配置、历史、趋势、事件 | MySQL、PostgreSQL、TimescaleDB(PostgreSQL 扩展) |
与 Prometheus 架构的本质区别:
| 维度 | Zabbix | Prometheus |
|---|---|---|
| 核心定位 | 中心化的多协议监控平台 | Pull 模型时序数据库 + 告警评估 |
| 采集模型 | Agent/SNMP/IPMI/Trapper 多元采集,Server 主导 | 主要 Pull 模式,Exporter 解耦 |
| 数据模型 | 主机-监控项-触发器强类型 | 指标名 + 多维 Label,无类型约束 |
| 告警评估 | Server 内置触发器表达式 | Prometheus 评估规则 + Alertmanager 路由 |
| 分布式 | Proxy 中转 + 6.0+ HA cluster | 联邦 / Thanos / Cortex / Mimir |
2 Zabbix 监控数据流是怎样的?一个监控项从采集到入库再到告警的完整链路是什么?
答案:
Zabbix 的数据流覆盖"采集→缓存→处理→入库→评估→告警"六个阶段,每个阶段都有专门的进程负责。这种流水线设计让 Server 在百万级 NVPS(每秒新值数)规模下仍能稳定运行。
完整数据流:
flowchart LR
A1["被监控端
(Agent/SNMP/IPMI)"] -->|1. 推送/拉取| A2["Zabbix Server
poller/trapper 接收"]
A2 -->|2. 写入 Cache| A3["History Cache
(内存环形缓冲)"]
A3 -->|3. 同步器处理| A4["Configuration Cache
DBSync/VC sync"]
A4 -->|4. 触发器评估| A5["Trigger Engine
评估表达式"]
A5 -->|5. 命中触发器| A6["Action 引擎
执行告警动作"]
A5 -.未命中.-> A7[(数据库
历史/趋势表)]
A3 -->|6. flush 周期| A7
A7 -->|7. Housekeeper| A8[(清理过期数据)]
各阶段关键进程:
| 阶段 | 进程 | 职责 |
|---|---|---|
| 采集 | poller / trapper / snmp / ipmi / jmx | 多协议接收/拉取指标 |
| 缓存 | History Cache | 内存缓冲新采集值,避免直接打 DB |
| 同步 | syncer(configuration syncer) | 周期性把 DB 配置同步到内存缓存 |
| 评估 | trigger engine(escalator/alerts) | 按时间窗口评估触发器表达式 |
| 入库 | history syncer / dbsyncer | 把缓存值批量写入 history/trends 表 |
| 清理 | housekeeper | 删除过期历史与事件 |
关键参数:
HistoryCacheSize=128M # 历史缓存大小(建议 128M-1G)
HistoryIndexCacheSize=32M # 索引缓存
TrendCacheSize=64M # 趋势缓存
ValueCacheSize=256M # 值缓存(SNMP 等指标)
CacheUpdateFrequency=60 # 配置同步周期
HousekeepingFrequency=1 # 清理频率(小时)
典型时序:
T+0s 采集到新值,写入 History Cache
T+0s 同步到 ValueCache,触发器引擎评估
T+5s flush 周期到达,批量写入 DB history 表
T+1h Housekeeper 删除超过保留期的历史
3 Zabbix Server 的进程模型是怎样的?常见进程类型和作用是什么?
答案:
Zabbix Server 采用多进程(多类型 worker)模型,每类进程负责特定功能,进程数量通过配置文件独立调优。这种设计既能并行处理大规模采集,也能在某个进程类型成为瓶颈时单独扩容(按类型 fork 多个 worker)。
进程类型与职责:
| 进程 | 数量配置 | 职责 |
|---|---|---|
| poller | StartPollers | 通用主动轮询(Agent、HTTP Agent) |
| trapper | StartTrappers | 接收 Trapper 主动推送(10051 端口) |
| snmp poller | StartSNMPPollers | SNMP 协议轮询 |
| ipmi poller | StartIPMIPollers | IPMI 协议轮询(带外管理) |
| jmx poller | StartJMXPollers | JMX 监控 JVM 应用 |
| icmp pinger | StartPingers | fping 主机存活检测 |
| http poller | StartHTTPPollers | HTTP Agent / Web 场景 |
| history syncer | HistorySyncer | 把缓存值写入 history/trends 表 |
| configuration syncer | ConfigSyncer | 周期性把配置同步到内存 |
| housekeeper | - | 清理过期历史/事件/审计 |
| alerter | StartAlerters | 发送告警动作(邮件/SMS) |
| escalator | StartEscalators | 告警升级流程(按步骤) |
| lld worker | StartLLD | 低层级发现(Low-Level Discovery) |
| task manager | - | 远程命令、脚本、立即检查任务 |
| preprocessor | StartPreprocessors | 预处理步骤(正则、JS、自定义) |
| discoverer | StartDiscoverers | 网络自动发现(IP 段扫描) |
| timer | - | 周期/间隔维护的定时器 |
进程数调优原则:
poller 数 ≈ NVPS / 1000 (经验公式,每 poller 约 1k NVPS)
trapper 数 ≥ 主动 Agent 数量 / 10
http poller 数 ≈ 活跃 Web 场景数 / 50
SNMP 设备多时加大 StartSNMPPollers
JMX 应用多时加大 StartJMXPollers
配置示例:
# /etc/zabbix/zabbix_server.conf
StartPollers=20
StartTrappers=10
StartPingers=5
StartHTTPPollers=5
StartSNMPPollers=10
StartIPMIPollers=2
StartJMXPollers=5
StartLLD=5
StartAlerters=5
StartEscalators=5
StartPreprocessors=10
HistorySyncer=8
判断进程瓶颈:
# 内部监控项 zabbix[process,<type>,<mode>,<state>]
# 例如:zabbix[process,poller,avg,busy] > 75% 表示 poller 繁忙
zabbix_get -s localhost -k 'zabbix[process,poller,avg,busy]'
zabbix_get -s localhost -k 'zabbix[queue]'
4 主机(Host)、主机组(Host Group)、模板(Template)、监控项(Item)、触发器(Trigger)的关系是什么?
答案:
Zabbix 的对象模型围绕"主机-模板-监控项-触发器"四元组展开,模板是核心抽象单元,支持复用、继承、链接到多台主机。理解这套模型是设计可维护监控体系的基础。
对象关系图:
graph TD
A["Host Group
主机组(如 DB、Web)"] --> B["Host
主机(IP/Agent 接口)"]
B -->|Link| C["Template
模板"]
C -->|包含| D["Item
监控项"]
C -->|包含| E["Trigger
触发器"]
C -->|包含| F["Graph / Dashboard
图形与仪表盘"]
C -->|包含| G["Discovery Rule
LLD 规则"]
C -->|继承| H["Template Parent
父模板"]
D -->|定义| I["Key: vfs.fs.size
Type: Zabbix Agent"]
E -->|表达式| J["{last} > 90
持续 5m"]
B -->|继承宏| K["Host Macro
{$DISK_THRESHOLD}"]
C -->|模板宏| L["Template Macro
{$DEFAULT_THRESHOLD}"]
关键概念:
| 概念 | 作用 | 关键属性 |
|---|---|---|
| Host | 被监控实体 | 主机名、IP、Agent 接口、SNMP 接口、IPMI 接口、所属主机组 |
| Host Group | 主机逻辑分组 | 用于权限分配、批量操作、维护期 |
| Template | 监控项/触发器/图形的可复用单元 | 可包含 Item、Trigger、Graph、Dashboard、LLD、宏 |
| Item | 单一指标的采集定义 | Key、Type、Interval、History、Trends、Applications |
| Trigger | 告警判定逻辑 | 表达式、严重等级、标签、依赖 |
| Macro | 变量替换 | 用户宏({$…}),支持 7 级优先级 |
| LLD | 自动发现 | 自动创建 Item/Trigger 原型 |
模板继承与链接:
Template Module Linux (基础模板)
├─ Template Module Linux CPU
├─ Template Module Linux Memory
├─ Template Module Linux Filesystems (LLD)
└─ Template Module Linux Network Interfaces (LLD)
主机 web-01 链接到 Template Module Linux
→ 自动继承所有子模板、Item、Trigger、LLD
实操建议:
- 按应用类型划分模板(如 MySQL、Redis、Nginx、Linux 基础),不按业务项目划分
- 主机只链接模板,避免在主机上独立写 Item/Trigger(可维护性差)
- 宏优先用模板级,主机级只覆盖例外值
5 Zabbix 与 Prometheus 等云原生监控方案的本质区别是什么?
答案:
Zabbix 是"中心化、多协议适配、对象模型驱动"的传统企业监控平台;Prometheus 是"Pull 模式时序数据库 + 告警评估 + 生态驱动"的云原生监控体系。两者在数据模型、采集范式、扩展方式、定位上有本质区别。
核心差异对比:
| 维度 | Zabbix | Prometheus |
|---|---|---|
| 诞生背景 | 传统企业 IT 基础设施监控 | 云原生(Kubernetes 时代) |
| 核心定位 | 中心化的多协议监控平台 | 时序数据库 + 告警评估引擎 |
| 采集模型 | Server 主导(推 + 拉),多协议(Agent/SNMP/IPMI/Trapper) | Pull 模型为主 + Pushgateway 补充 + Remote Write |
| 数据模型 | 主机-Item-Trigger 强类型对象 | 指标名 + Label 多维,无类型约束 |
| 存储 | MySQL/PostgreSQL/TimescaleDB(行式/混合) | 自研 TSDB(块式) |
| 告警评估 | Server 内置触发器 + Action 升级 | 规则文件 + Alertmanager 路由 |
| 可视化 | 自带 Dashboard + Grafana 集成 | 主要依赖 Grafana |
| 扩展方式 | 自定义 Key、自定义脚本、Agent 2 插件 | Exporter(任何语言)+ 远程写入 |
| 云原生适配 | 通过 Zabbix Agent + HTTP Agent 支持,需手动配置 | 天然适配 K8s Service/Pod 自动发现 |
| K8s 场景 | 可用但非首选 | 行业标准 |
适用场景对比:
Zabbix 优势场景:
- 传统 IDC(物理机、网络设备、存储)
- 大量 SNMP/IPMI 设备(交换机、路由器、BMC)
- 中小规模业务(数千到数万台主机)
- 需要开箱即用的告警升级/值班
- 数据库、中间件、应用有官方模板
Prometheus 优势场景:
- Kubernetes / Service Mesh / 微服务
- 容器化业务(Pod 生命周期短)
- 多维标签聚合分析(按 Service/Env/Region)
- 大规模时序聚合(PromQL 灵活)
- 与 Grafana / Loki / Tempo 生态集成
融合趋势:
现代监控栈:
指标: Prometheus / VictoriaMetrics / Thanos
日志: Loki / ELK / OpenSearch
追踪: Tempo / Jaeger / SkyWalking
传统: Zabbix(保留对物理设备/网络/中间件的统一监控)
→ Zabbix 与 Prometheus 长期并存,互为补充
6 Zabbix Agent 与 Zabbix Agent 2 有什么区别?
答案:
Zabbix Agent 是 C 语言编写的传统采集程序;Zabbix Agent 2 是 Zabbix 4.4+ 引入的 Go 语言重写版本,采用插件化架构,性能和扩展性大幅提升。两者在 6.0+ 共存,新部署建议优先 Agent 2。
核心差异:
| 维度 | Zabbix Agent (C) | Zabbix Agent 2 (Go) |
|---|---|---|
| 开发语言 | C | Go |
| 引入版本 | 1.x | 4.4(实验),5.0+(生产可用) |
| 架构 | 单进程,单一配置文件 | 多插件并行,goroutine 调度 |
| 并发采集 | 串行(被动模式下每连接一线程) | 原生并发,单连接内多指标并行 |
| 协议 | Zabbix 私有协议 | Zabbix 协议 + 自定义协议 |
| 扩展方式 | UserParameter / Loadable Modules | 插件(Plugin),官方提供 30+ 插件 |
| 采集间隔 | 被动模式由 Server 控制 | 可独立调度(go runtime 优势) |
| 资源占用 | 内存极小(约 1-2 MB) | 内存稍大(约 10-30 MB) |
| 适用规模 | 中小规模 | 大规模、高并发 |
| 二进制名 | zabbix_agentd | zabbix_agent2 |
官方内置插件(Agent 2):
Agent 2 内置插件:
- PostgreSQL / MySQL / Oracle / MSSQL / MongoDB
- Redis / Memcached / RabbitMQ / Kafka / MQTT
- Docker / systemd / Ceph / Proxmox
- HTTP / ICMP / SNMP / Modbus / Smart
- FilePath / Directory / LogFile / WindowsEventLog
- ... (持续扩展)
配置差异:
# /etc/zabbix/zabbix_agent2.conf (Agent 2)
Plugins.PostgreSQL.Sessions.<SessionName>.URI=postgresql://user:pass@host:5432/db
Plugins.Redis.Sessions.<SessionName>.URI=redis://host:6379
# /etc/zabbix/zabbix_agentd.conf (传统 Agent)
UserParameter=mysql.questions,mysqladmin -uroot status | awk '{print $6}'
监控项示例:
# Agent 2 使用插件 Key (内置)
postgresql.ping[session1]
redis.info[session1,used_memory]
mysql.custom.query[session1,"SHOW GLOBAL STATUS LIKE 'Threads_connected'"]
# 传统 Agent 需 UserParameter 自定义
mysql.questions
迁移建议:
- 新部署:直接用 Agent 2
- 存量 C-Agent:可平滑迁移,关键监控项需重新规划 Key(插件 Key 与 UserParameter 不通用)
- 特殊场景(如极小内存、资源敏感嵌入式):仍可考虑传统 Agent
7 Zabbix Agent 主动模式与被动模式的区别?什么场景用哪个?
答案:
被动模式(Passive)由 Server/Proxy 主动向 Agent 拉取数据;主动模式(Active)由 Agent 周期主动连接 Server/Proxy 推送数据。两种模式各有适用场景,大规模监控通常两者结合使用。
模式对比:
sequenceDiagram
participant S as Zabbix Server/Proxy
participant A as Zabbix Agent
rect rgb(240, 248, 255)
Note over S,A: 被动模式
S->>A: agent.ping
A-->>S: 响应
S->>A: agent.version
A-->>S: 响应
S->>A: vfs.fs.size[/,free]
A-->>S: 1024
end
rect rgb(255, 248, 240)
Note over S,A: 主动模式
A->>S: agent.hostname / 主动注册
S-->>A: 响应配置
A->>S: active checks: host:port
S-->>A: 返回要采集的 Item 列表
loop 周期采集
A->>S: send data: key=value
S-->>A: 确认
end
end
详细对比:
| 维度 | 被动模式 (Passive) | 主动模式 (Active) |
|---|---|---|
| 连接发起方 | Server/Proxy | Agent |
| Server 端口 | 10051 | 10051 |
| Agent 监听 | 10050 | 无需监听(出站连接) |
| 防火墙要求 | 需 Agent 端入站可达 10050 | 只需 Agent 出站可达 Server 10051 |
| NAT 友好 | 差 | 优 |
| Agent 配置 | Server=<Server IP> | ServerActive=<Server IP> |
| Server 端间隔 | 由 Server 端 Update interval 控制 | 由 Agent 端 RefreshActiveChecks 控制刷新频率 |
| 数据延迟 | 与 Server 调度一致 | 取决于 Agent 主动推送周期 |
| Item 类型 | Zabbix Agent / SNMP / IPMI / JMX | Zabbix Agent (Active) / Trapper / Log |
| 适合规模 | 小到中等规模 | 大规模、跨 NAT、移动设备 |
| 日志监控 | 不支持 | 支持(log, log.count, logrt, eventlog) |
配置示例:
# /etc/zabbix/zabbix_agentd.conf
# 被动模式(必须配置)
Server=192.168.1.100
ListenPort=10050
ListenIP=0.0.0.0
# 主动模式(必须配置)
ServerActive=192.168.1.100:10051
HostnameItem=system.hostname
RefreshActiveChecks=120
# 同时启用:可减少 Server 轮询压力
Item 类型选择:
Item Type:
Zabbix agent → 被动
Zabbix agent (active) → 主动
SNMP agent → 被动
IPMI agent → 被动
JMX agent → 被动
Zabbix trapper → 主动推送(由 Agent/Script sender)
Zabbix aggregate → 计算型
HTTP agent → 被动
最佳实践:
- 内网主机:被动 + 主动并用(日志类必须主动)
- 跨防火墙/NAT:仅用主动
- 大规模(> 5000 Agent):优先主动模式,降低 Server 轮询压力
- 日志监控(log、log.count、logrt):必须用主动模式
8 Zabbix 如何使用 SNMP 监控?工作原理和关键配置是什么?
答案:
SNMP(Simple Network Management Protocol)是网络设备(交换机、路由器、打印机、存储)的事实标准协议。Zabbix 通过 snmp poller 进程按 OID(对象标识符)轮询设备 MIB 中的指标,实现对网络设备的统一监控。
SNMP 监控原理:
sequenceDiagram
participant Z as Zabbix Server/Proxy
participant D as SNMP 设备(交换机)
Note over Z,D: SNMP v2c 轮询
Z->>D: GET OID 1.3.6.1.2.1.2.2.1.10.2 (ifInOctets.2)
D-->>Z: 返回端口 2 入口流量
Z->>D: GET OID 1.3.6.1.2.1.2.2.1.16.2 (ifOutOctets.2)
D-->>Z: 返回端口 2 出口流量
Note over Z,D: 速率计算
Z->>Z: delta(value) / interval = bps
SNMP 版本对比:
| 版本 | 安全 | 性能 | 适用 |
|---|---|---|---|
| v1 | 社区名(明文) | 低 | 老旧设备 |
| v2c | 社区名(明文) | 高(支持 GetBulk) | 主流网络设备 |
| v3 | 用户认证(MD5/SHA)+ 加密(DES/AES) | 较高 | 金融/高安全场景 |
Zabbix SNMP 关键配置:
# /etc/zabbix/zabbix_server.conf
StartSNMPPollers=10
SNMPTrapperFile=/tmp/zabbix_traps.tmp
# 时间相关参数(超时与重试)
Timeout=3
SNMPTimeout=1 # 覆盖全局 Timeout
# 单设备并发(避免拖垮)
MaxConcurrentChecksPerPoller=10
Zabbix 主机 SNMP 接口配置:
Host Configuration:
SNMP interface: 192.168.1.1:161
Use bulk requests (SNMPv2c/v3): ✓
SNMP version: SNMPv2c
Community: public
典型监控项 Key:
# 通用 OID 形式
IF-MIB::ifInOctets.2 # 端口 2 入口字节
IF-MIB::ifOutOctets.2 # 端口 2 出口字节
SNMPv2-MIB::sysName.0 # 设备名
HOST-RESOURCES-MIB::hrStorageSize.1 # 存储大小
HOST-RESOURCES-MIB::hrStorageUsed.1 # 存储已用
# 计算速率(Zabbix 触发器)
{host:net.if.in[ifInOctets.2].change(60)} > 100000000 # 入流量 > 100MB/min
SNMP Trap 接收:
# 1. Zabbix 配置 snmptrapd
cat /etc/snmp/snmptrapd.conf
# traphandle default /usr/sbin/zabbix_trap_receiver.pl
# 或者用 snmptrapd 内置方式(Zabbix 5.0+)
disableAuthorization yes
traphandle default /usr/sbin/zabbix_trap_receiver
# 2. Zabbix Server 启用 trapper
StartSNMPTrapper=1
SNMPTrapperFile=/tmp/zabbix_traps.tmp
# 3. 创建 Item: Type = SNMP trap
常用网络设备模板:
Template SNMP Interfaces # 通用接口流量(LLD 自动发现)
Template SNMP Generic # 通用 OID 监控
Template SNMP OS Linux # 主机资源
Template SNMP OS Cisco # Cisco 设备
Template SNMP OS Huawei # 华为设备
Template SNMP OS H3C # H3C 设备
性能优化:
- 启用
Use bulk requests(GetBulk 一次取多 OID) - 调整
Timeout与SNMPTimeout,网络抖动时增大重试 - 高频率采集时增大
StartSNMPPollers - OID 历史用宏抽取(如
{#SNMPINDEX}替换硬编码)
9 Zabbix 如何监控硬件带外管理(IPMI)?适用哪些场景?
答案:
IPMI(Intelligent Platform Management Interface)是服务器带外管理标准,独立于 OS 运行,通过 BMC(Baseboard Management Controller)提供温度、电压、风扇、电源、传感器等硬件级健康数据。Zabbix 通过 ipmi poller 进程定期轮询 BMC 的 IPMI/Sensor 数据。
IPMI 监控原理:
graph LR
A["Zabbix Server
(ipmi poller)"] -->|"IPMI 协议 (UDP 623)"| B["BMC
独立固件"]
B --> C["CPU 温度"]
B --> D["风扇转速"]
B --> E["电源状态"]
B --> F["电压"]
B --> G["机箱入侵"]
B --> H["内存 ECC 错误"]
B --> I["磁盘 SMART"]
IPMI 监控项类型:
IPMI 监控项示例(标准模板):
- ipmi.sensor[CPU1 Temp]
- ipmi.sensor[System Temp]
- ipmi.sensor[Power Supply 1]
- ipmi.sensor[FAN1 Speed]
- ipmi.sensor[+12V]
- ipmi.sensor[Chassis Intrusion]
关键配置:
# /etc/zabbix/zabbix_server.conf
StartIPMIPollers=5
# /etc/zabbix/zabbix_agentd.conf
# IPMI 由 Server 端直接轮询 BMC,无需 Agent
# Agent 端无需配置
主机 IPMI 接口配置:
Host Configuration:
IPMI interface: 10.0.0.1:623
IPMI sensor: # 默认不填,自动发现
IPMI authentication algorithm: Default
IPMI privilege level: Operator
IPMI username: zabbix
IPMI password: ********
适用场景:
✔ 必须 IPMI 监控的场景:
- 物理机/裸金属服务器(核心生产)
- 温度异常敏感的高密度机房
- 硬件故障预警(CPU 过热、内存 ECC、电源失效)
- 静默故障捕获(系统挂掉后 Agent 无法上报,IPMI 仍可报告)
✘ 不适合 IPMI 的场景:
- 虚拟机(无 BMC)
- 云主机(厂商 API 替代)
- 网络设备(用 SNMP)
- 嵌入式/工控机
IPMI 性能与稳定性:
- IPMI 协议本身较慢(每次请求需认证),单次超时建议 5-10s
- BMC 抗压能力弱,并发采集需限制
StartIPMIPollers数量 - 部分老旧 BMC 固件存在已知漏洞,建议独立网段 + ACL 限制
- 关键服务器配合 IPMI Watchdog(系统无响应时自动重启)
与 Redfish 的关系:
- IPMI:传统协议,基于 UDP 623
- Redfish:现代 REST API 标准(JSON over HTTP),DMTF 推动
- Zabbix 5.0+ 已支持 Redfish(通过 HTTP Agent),逐步替代 IPMI
- 新部署服务器优先使用 Redfish
10 Zabbix Trapper 和 HTTP Agent 是什么?什么时候用主动推送?
答案:
Trapper 是 Zabbix 提供的"主动推送"协议,业务方通过 zabbix_sender 或自定义协议向 Server 10051 端口推送数据;HTTP Agent 通过 HTTP/HTTPS 拉取数据,扩展对 RESTful API、JSON、XML 的支持。两者覆盖了"无法 Agent 主动采集"的场景。
Trapper 工作原理:
sequenceDiagram
participant A as 业务脚本/客户端
participant S as Zabbix Server
participant DB as 数据库
Note over A,S: Trapper 主动推送
A->>S: zabbix_sender -z server -s host -k trap.item -o "value"
S->>S: trapper 进程接收
S->>DB: 写入 history 表
Note over A,S: 批量推送(更高效)
loop 多 Item
A->>A: 构造 sender data file
A->>S: zabbix_sender -T -i data.txt
S-->>A: 处理结果统计
end
Trapper 关键配置:
# /etc/zabbix/zabbix_server.conf
StartTrappers=5
TrapperTimeout=30
# Item Type 配置(Web UI):
Type: Zabbix trapper
Key: trap.queue.depth
Type of information: Numeric (unsigned)
zabbix_sender 用法:
# 单值推送
zabbix_sender -z 192.168.1.100 -s "web-01" -k trap.queue.depth -o 42
# 批量推送(推荐)
cat > /tmp/data.txt <<EOF
"web-01" trap.queue.depth 1234567890 42
"web-01" trap.cache.hit 1234567890 0.85
"web-01" trap.api.qps 1234567890 1523
EOF
zabbix_sender -z 192.168.1.100 -T -i /tmp/data.txt
HTTP Agent 适用场景:
HTTP Agent 通过 HTTP 拉取数据:
- 监控 Web 业务健康(状态码、响应时间、Body 内容)
- 拉取 RESTful API 数据(JSONPath 提取)
- 与云厂商 API 集成(AWS CloudWatch、阿里云监控)
- 模拟用户访问链路(多步调用、Cookie 处理)
- 自定义数据源(业务系统暴露 /metrics 端点)
HTTP Agent 监控项配置:
Item Type: HTTP agent
URL: https://api.example.com/v1/health
Request method: GET
Request headers: Authorization: Bearer xxxxx
Timeout: 5s
Status codes: 200
Response body:
Type: JSON
JSONPath: $.data.health
Required status codes: 200
多步 HTTP 场景:
Scenario(场景):
Steps:
Step 1: POST /api/login → 提取 Token(Variables: token=$.data.token)
Step 2: GET /api/orders → 携带 Token + Headers
Step 3: 提取订单数(JSONPath: $.total)
适用: 复杂 Web 业务可用性监控、登录后业务流断言
Trapper vs HTTP Agent vs Pushgateway 对比:
| 维度 | Zabbix Trapper | Zabbix HTTP Agent | Prometheus Pushgateway |
|---|---|---|---|
| 方向 | 业务主动推送 | Zabbix 主动拉取 | 业务主动推送 |
| 协议 | Zabbix 私有协议 | HTTP/HTTPS | HTTP 协议 |
| 数据格式 | 键值对 | HTTP 响应(JSON/XML/Text) | Prometheus 文本格式 |
| 典型场景 | 业务自定义指标、批处理 | Web/API 监控 | 短生命周期任务、批处理 |
| 权限 | 需配置 Host 允许推送 | 需访问目标 URL | 需配置 Pushgateway ACL |
| 扩展性 | zabbix_sender 任何语言 | 依赖 HTTP 客户端 | prometheus_client 各语言 SDK |
11 Zabbix 模板(Template)如何设计?模板继承与链接机制是怎样的?
答案:
模板是 Zabbix 的核心抽象单元,把"监控项、触发器、图形、LLD、宏"打包为可复用单元。设计良好的模板应具备单一职责、可继承、可扩展、低耦合特性,是企业级 Zabbix 监控体系的基石。
模板结构:
graph TD
A["Template App MySQL
(主模板)"] --> B["Template App MySQL Processes
(子模板)"]
A --> C["Template App MySQL Connections
(子模板)"]
A --> D["Template App MySQL Replication
(子模板)"]
A --> E["Template App MySQL LLD
(LLD 子模板)"]
F["Host: db-master-01"] -->|Link| A
G["Host: db-slave-02"] -->|Link| A
A -->|含| H["Items: 50"]
A -->|含| I["Triggers: 20"]
A -->|含| J["Graphs: 5"]
A -->|含| K["LLD Rules: 3"]
A -->|含| L["Macros: 5"]
A -->|继承| M["Template Module Linux
(OS 基础)"]
模板设计原则:
| 原则 | 说明 |
|---|---|
| 单一职责 | 一个模板只负责一个应用(如 Template App MySQL、Template App Nginx) |
| 主模板 + 子模板 | 主模板只放公共宏、子模板链接,子模板按功能拆分 |
| 复用优先 | 跨应用的监控(如端口、进程)放独立模板 |
| 可覆盖 | 关键阈值用宏 {$...},主机级可覆盖 |
| 避免硬编码 | 端口、IP、路径都需宏化 |
| LLD 友好 | 监控项原型使用 LLD 宏 |
模板继承关系:
Template App MySQL (主模板)
├─ Template App MySQL Processes (子模板)
├─ Template App MySQL Connections (子模板)
├─ Template App MySQL InnoDB (子模板)
└─ Template App MySQL Replication (子模板)
应用主模板只做:
- 链接所有子模板
- 定义通用宏 (如 {$MYSQL.HOST}, {$MYSQL.PORT}, {$MYSQL.USER})
- 创建 Dashboard
链接与继承的区别:
链接(Link):
- 主机/模板添加其他模板的完整内容
- 可链接多个
模板继承(Template nesting):
- 模板 A "Includes other templates"
- 实质是子模板机制
- 方便拆分主模板
实际模板示例:
主机 db-master-01 配置:
Linked templates:
1. Template App MySQL (主模板)
2. Template Module Linux (OS 基础)
Macros:
{$MYSQL.HOST} = localhost
{$MYSQL.PORT} = 3306
{$MYSQL.USER} = zbx_monitor
→ 自动应用所有子模板的 Items/Triggers/Graphs/LLD
企业级模板组织建议:
命名规范:
Template Module <OS> # OS 基础(CPU/Mem/Disk/Net)
Template App <AppName> # 应用层
Template App <AppName> <Feature># 应用子功能
Template Service <Service> # 业务服务
Template Custom <Team> # 团队自定义
目录:
Templates/
OS/
Databases/
Middleware/
WebServers/
Network/
Business/
模板版本管理:
- 模板导出为 XML,便于 Git 追踪变更
- 模板升级时注意宏的兼容性(旧主机可能缺少新宏)
- 使用
Template mass update批量更新已链接主机
12 Zabbix 宏(Macro)的类型和优先级是怎样的?
答案:
Zabbix 宏({$...})是模板与主机间"参数化"的关键机制,从全局到主机共 7 级优先级,缺省值机制让模板可独立运行,覆盖时仅在主机层修改即可。
宏类型与优先级(从低到高):
| 优先级 | 宏类型 | 作用范围 | 示例 |
|---|---|---|---|
| 1(最低) | 内建宏 | 固定名称的系统宏 | {HOST.ID}、{HOST.NAME}、{DATE}、{TIME} |
| 2 | 正则表达式宏 | 全局正则宏(web) | 正则告警匹配用 |
| 3 | 用户宏(默认) | 全局 | {$SNMP_COMMUNITY} |
| 4 | 用户宏(模板) | 模板级 | {$THRESHOLD.CPU} |
| 5 | 主机宏 | 主机级 | {$DB_PORT} |
| 6 | 触发器/Item 上下文宏 | 仅在该 Item/Trigger 内有效 | 自动上下文宏 |
| 7(最高) | 函数/Action 上下文宏 | 表达式内联 | {?func(/host/key)} |
内建常用宏:
{HOST.NAME} 主机名
{HOST.ID} 主机 ID
{HOST.IP} 主机 IP
{HOST.PORT} 端口
{HOST.CONN} 连接 IP:Port
{HOST.DNS} DNS 名称
{HOST.GROUP} 主机所属组
{ITEM.LASTVALUE} 当前值
{ITEM.VALUE} 历史值
{TRIGGER.SEVERITY} 严重等级
{TRIGGER.STATUS} 状态
{EVENT.SEVERITY} 事件等级
{EVENT.TIME} 事件时间
{DATE} 当前日期
{TIME} 当前时间
{INVENTORY.<FIELD>} 资产清单字段
用户宏示例:
# 模板级宏
{$CPU.WARN} = 70
{$CPU.CRIT} = 90
{$MEM.WARN} = 80
{$DISK.WARN} = 85
{$IF.HIGHER} = 1000000000 # 1Gbps 阈值
# Item 中使用
vfs.fs.size[/,pfree] # 触发器
{Template App Linux: vfs.fs.size[/,pfree].last()} < {$DISK.WARN:20}
# 主机级覆盖
{$MYSQL.PORT} = 13306 # 覆盖模板默认 3306
宏的解析时机:
sequenceDiagram
participant T as Trigger 表达式
participant S as Server
participant DB as 数据库
Note over S,DB: 配置同步
S->>DB: 读取 Host Macro 配置
S->>DB: 读取 Template Macro 配置
S->>S: 合并到内存缓存
Note over T,S: 触发器评估
T->>S: {Template App Linux: vfs.fs.size[/,pfree].last()} < {$DISK.WARN}
S->>S: 解析宏:{$DISK.WARN} = 85
S->>S: 代入:actual_value < 85
S->>S: 评估结果(PROBLEM/OK)
宏的特殊用法:
# 宏的上下文:内建宏引用用户宏
{HOST.NAME} on {HOST.IP} failed: {ITEM.LASTVALUE} > {$THRESHOLD}
# 宏内嵌宏
{$ALERT.URL} = http://alertmanager/{HOST.ID}?p={$ENV}
# 主机宏覆盖模板宏
主机级别: {$MYSQL.PORT} = 13306
模板级别: {$MYSQL.PORT} = 3306
实际生效: 13306(主机级覆盖)
# 缺省值
{$MYSQL.PORT:3306} # 未定义时用 3306
# 用户宏在 Script/Command 中
{$SNMP_COMMUNITY} 替换到外部脚本
最佳实践:
- 所有阈值都用宏({$DISK.WARN}、{$CPU.CRIT}),不要硬编码数字
- 敏感信息(密码、Token)放主机宏 + 加密宏存储
- 团队共享宏 通过全局宏,避免重复定义
- 缺省值兜底
{$VAR:default}防止漏配置
13 Zabbix LLD(Low-Level Discovery)的工作原理是什么?
答案:
LLD(Low-Level Discovery)是 Zabbix 自动发现机制的核心,通过预定义的发现规则(Discovery Rule)自动探测实体(网卡、磁盘、文件系统、数据库、服务),结合 Item/Trigger/Graph 原型批量创建监控项,无需手工逐一配置。
LLD 工作流程:
flowchart TD
A["配置 LLD Rule
(key: vfs.fs.discovery)"] -->|1. 周期执行| B["Agent/Server 返回 JSON"]
B --> C["JSON 解析: {#FSNAME}, {#FSTYPE}"]
C --> D["匹配 Item 原型
(vfs.fs.size[{#FSNAME},pfree])"]
C --> E["匹配 Trigger 原型
(... < 20 on {#FSNAME})"]
C --> F["匹配 Graph 原型"]
D -->|批量创建| G["实际 Item 1: vfs.fs.size[/,pfree]"]
D -->|批量创建| H["实际 Item 2: vfs.fs.size[/home,pfree]"]
D -->|批量创建| I["实际 Item 3: vfs.fs.size[/var,pfree]"]
E --> J["实际 Trigger 1, 2, 3..."]
LLD 关键概念:
| 概念 | 作用 |
|---|---|
| Discovery Rule | LLD 规则,定义发现逻辑,类型同 Item(Agent/SNMP/DB Monitor) |
| Item Prototype | 监控项原型,使用 LLD 宏 {#XXX},LLD 发现时实例化 |
| Trigger Prototype | 触发器原型,可引用 LLD 宏 |
| Graph Prototype | 图形原型,组合多个 Item 原型 |
| Host Prototype | 主机原型(用于主机 LLD) |
| LLD Macro | 形如 {#FSNAME}、{#IFNAME} 的动态变量 |
内置 LLD 规则:
# 操作系统
vfs.fs.discovery # 文件系统
net.if.discovery # 网卡
cpu.discovery # CPU 核心
memory.discovery # 内存
system.sw.packages.discovery # 软件包
system.disk.discovery # 磁盘(SMART)
# 数据库(Agent 2 插件)
postgresql.discovery # PostgreSQL 数据库/表
mysql.discovery # MySQL 数据库/表
redis.discovery # Redis 节点
# 中间件
docker.container.discovery # Docker 容器
LLD 自定义发现规则:
# 自定义发现脚本(返回 JSON)
cat > /etc/zabbix/scripts/discover_services.sh <<'EOF'
#!/bin/bash
systemctl list-units --type=service --state=running --no-legend | \
awk '{print "{\"{#SERVICE}\": \"" $1 "\"}"}' | \
jq -s .
EOF
# 配置文件: UserParameter=service.discovery,/etc/zabbix/scripts/discover_services.sh
返回 JSON 格式:
{
"data": [
{"{#SERVICE}": "nginx.service", "{#PID}": "1234"},
{"{#SERVICE}": "mysql.service", "{#PID}": "5678"},
{"{#SERVICE}": "redis.service", "{#PID}": "9012"}
]
}
Item 原型示例:
Item Prototype:
Name: Free disk space on {#FSNAME}
Key: vfs.fs.size[{#FSNAME},free]
Type: Zabbix agent (active)
Update interval: 60s
Trigger Prototype:
Expression: {Template: vfs.fs.size[{#FSNAME},pfree].last()} < {$DISK.WARN:20}
Name: Free disk space on {#FSNAME} is low
LLD 宏过滤:
# 发现时过滤:只发现特定类型的文件系统
LLD Rule → Filters:
{#FSTYPE} matches (ext4|xfs|btrfs)
{#FSNAME} does not match (/boot|^/sys|^/proc)
LLD 生命周期:
T+0s LLD Rule 周期执行
T+0s 返回 JSON
T+0s 解析 + 过滤
T+0s 实例化所有原型
T+0s 创建实际 Item/Trigger/Graph
T+300s 下次执行(默认 1h 一次)
- 新发现:创建新 Item
- 已存在:跳过
- 消失:删除旧 Item(或保留,配置项控制)
Item 不消失的设置:
LLD Rule → "Lost resources period":
None # 立即删除
1h # 1h 后未发现则删除
Forever # 永保留(已发现的不删除)
14 LLD 宏在监控项原型中如何高级使用?有哪些最佳实践?
答案:
LLD 宏({#MACRO})是原型实例化时的占位符。掌握宏的嵌套、组合、过滤、自定义正则等高级用法,能让模板从"够用"进化到"优雅"。
LLD 宏的来源:
| 来源 | 示例 | 说明 |
|---|---|---|
| 内建 LLD | {#FSNAME}、{#IFNAME} | Agent/Server 内置 |
| 自定义 LLD 脚本 | {#DBNAME}、{#TABLENAME} | 自行构造 JSON |
| 多级嵌套 | {#FSNAME}/{#FSTYPE} | JSON 返回多字段 |
| 正则提取 | {#IF.ALIAS} = {#IFNAME} regex | 二级提取 |
高级用法 1:多 LLD 宏组合
# 自定义发现脚本返回
{
"data": [
{
"{#DB}": "users",
"{#TABLE}": "user_profile",
"{#ENGINE}": "InnoDB"
}
]
}
# Item 原型
mysql.table.size[{#DB},{#TABLE}]
# Trigger 原型
{Template: mysql.table.size[{#DB},{#TABLE}].last()} > 1073741824
高级用法 2:LLD 宏 + 用户宏
# Item 原型中使用宏混合
vfs.fs.size[{#FSNAME},pfree]
# Trigger 阈值用用户宏
{Template: vfs.fs.size[{#FSNAME},pfree].last()} < {$DISK.WARN:20}
# 用户宏可针对 {#FSNAME} 不同设置不同阈值
# 通过主机宏 + 上下文宏
高级用法 3:自定义 LLD 宏与正则提取
# SNMP ifXTable 返回
{
"data": [
{
"{#IFNAME}": "GigabitEthernet0/0/1",
"{#IFALIAS}": "uplink-to-core",
"{#IFSPEED}": "10000000000"
}
]
}
# LLD Rule Filter: 提取 alias 中的 VLAN 信息
Filters:
{#IFALIAS} matches .*VLAN(\d+).*
→ 新宏 {#VLANID} = \1(正则捕获)
高级用法 4:LLD 跨模板引用
# 模板 A: Template Module Linux
LLD Rule: vfs.fs.discovery
→ Item 原型: vfs.fs.size[{#FSNAME},pfree]
→ Trigger 原型: ... < {$DISK.WARN}
# 模板 B: Template App MySQL(继承 A)
LLD Rule: mysql.databases.discovery(自定义)
→ Item 原型: mysql.db.size[{#DBNAME}]
→ Trigger 原型: ... < {$DB.SIZE.WARN}
→ 依赖 Trigger: A 模板的 vfs.fs.size[/,pfree](防止根盘满时反复告警)
高级用法 5:宏预处理与计算
# Item 原型(计算型)
Item Prototype:
Type: Calculated
Key: if.util[{#IFNAME}]
Formula: (last("net.if.in[{#IFNAME}]") + last("net.if.out[{#IFNAME}]")) * 8 / last("net.if.speed[{#IFNAME}]") * 100
# Preprocessing 步骤
Item Prototype → Preprocessing:
1. JavaScript: return Math.round(value / 1024 / 1024) // B → MB
2. Regular expression: \d+
LLD 常见陷阱与最佳实践:
陷阱:
1. LLD 周期太短(< 5min)导致 Server 压力大
2. 过滤规则过宽,产生大量无用 Item
3. 触发器原型硬编码阈值,未用宏
4. Item 原型未启用 Host Inventory 资产
5. 主机 LLD 创建的主机未关联模板
最佳实践:
1. LLD 周期建议 1h-12h(变更不频繁的实体)
2. 必须配置 Filter,过滤 tmpfs、/proc、/sys 等
3. 阈值全部用用户宏,团队/主机可覆盖
4. 命名规范: "Service: <name> on {#HOST.NAME}"
5. Trigger 原型配合 LLD 宏 + 用户宏 + 触发器依赖
6. 主机 LLD 自动发现主机时关联完整模板
7. 大量 LLD 监控项时启用 "Delete lost resources"
LLD 性能影响:
LLD 创建的 Item 数 = SUM(每个 LLD Rule 发现的实体数 × 原型数)
例: 5000 主机 × 每机 5 磁盘 × 3 Item/磁盘 = 75,000 Item
5000 主机 × 每机 3 网卡 × 5 Item/网卡 = 75,000 Item
合计 150,000 Item
→ NVPS 估算: 150000 / 60 = 2,500 NVPS(仅 1 分钟间隔)
→ 需相应调高 StartPreprocessors、HistorySyncer
15 Zabbix 触发器表达式是怎么写的?常用函数有哪些?
答案:
触发器(Trigger)通过"表达式 + 函数 + 常量"对 Item 当前值或历史值进行评估,决定是否产生告警事件(PROBLEM/OK)。表达式语法是 Zabbix 设计的核心,灵活但有一定学习曲线。
触发器表达式语法:
{<server>:<key>.<func>(<params>)} <operator> <constant>
{host:item.key.func(params)} <op> <value>
表达式组成元素:
| 元素 | 说明 |
|---|---|
<server> | 模板/主机名(“Template App X” 或具体主机) |
<key> | 监控项 Key |
<func> | 评估函数(last/avg/min/max/sum/change/diff/nodata) |
<params> | 函数参数(时间秒数) |
<operator> | 比较运算符(>, <, >=, <=, =, <>) |
<constant> | 数字、字符串、宏 |
常用函数:
| 函数 | 作用 | 典型用法 |
|---|---|---|
last() | 最近一次采集值 | {vfs.fs.size[/,pfree].last()}<20 |
avg(N) | N 秒内平均值 | cpu.util.avg(300)}>80 |
max(N) | N 秒内最大值 | max(60)}>90 |
min(N) | N 秒内最小值 | min(300)}<10 |
sum(N) | N 秒内求和 | sum(60)}>1000 |
change() | 与上一次值差(差量) | net.if.in.change(60)}>1000000000 |
diff() | 变化标记(0→1, 1→0) | diff()}=1 |
nodata(N) | N 秒内无数据 | nodata(300)}=1 |
time() | 当前时间(秒) | time()}>080000(早 8 点) |
date() | 当前日期 | date()}=20260101 |
now() | 当前时间(Unix 时间戳) | now()-last()}>3600 |
regexp() | 正则匹配 | `regexp(^(ERROR |
strlen() | 字符串长度 | strlen()}>1000 |
count(N,op,val) | N 秒内满足条件的次数 | count(300,ge,80)}>3 |
forecast() | 预测未来值 | forecast(3600,1h,avg)}<10 |
trendavg() | 历史趋势平均 | trendavg(86400,7d)}>80 |
典型触发器表达式:
# 1. CPU 5 分钟内平均值 > 80%
{Template App Linux: cpu.util.avg(300)}>80
# 2. 磁盘空间小于 20% 持续 5 分钟
{Template App Linux: vfs.fs.size[/,pfree].last()}<{$DISK.WARN:20}
# 3. 端口流量突变(变化量)
{Template SNMP Interfaces: net.if.in[{#IFNAME}].change(300)}>1000000000
# 4. 5 分钟内连续 3 次超标
{Template App Linux: cpu.util.last()}>80 and
{Template App Linux: cpu.util.count(300,gt,80)}>=3
# 5. 服务宕机(无数据)
{Template App Linux: agent.ping.nodata(300)}=1
# 6. 时间窗口告警(仅工作时间)
{Template App X: queue.depth.last()}>1000 and
{Template App X: time()}>090000 and
{Template App X: time()}<180000
# 7. 多条件组合(AND/OR)
{Template App MySQL: mysql.threads.last()}>200 and
{Template App MySQL: mysql.slow_queries.rate(60)}>5
严重等级:
Not classified → Information → Warning → Average → High → Disaster
(递增严重度)
触发器可读性技巧:
# 使用宏和单位
{Host: temp.last()}>80 # 80 度
{Host: temp.last()}>$TEMP_WARN} # 80
{Host: net.if.in.last()}>10Mbps # 难以比较单位
→ 用宏: {Host: net.if.in.last()}>$BANDWIDTH.WARN:10485760}
# 表达式换行
{Template App Linux: cpu.util.avg(300)} > {$CPU.WARN:80} and
{Template App Linux: cpu.util.avg(300)} < 100
Hysteresis(迟滞)模式:
# Problem: > 80%, Recovery: < 70%(迟滞防抖动)
{Template: cpu.last()}>80 # 进入 PROBLEM
{Template: cpu.last()}<70 # 进入 OK
# 配合两套表达式
PROBLEM Expression: {T: cpu.last()}>80
OK Event Generation: Recovery expression: {T: cpu.last()}<70
16 触发器依赖(Dependency)如何防止告警风暴?
答案:
触发器依赖是 Zabbix 抑制告警风暴的核心机制。当上游触发器处于 PROBLEM 时,下游依赖触发器不会单独发送告警。常见模式:父级 vs 子级、节点 vs 服务、端口 vs 进程。
依赖关系示意:
graph TD
A["HOST DOWN
(Host: agent.ping)"] --> B["Port 80 Unavailable"]
A --> C["HTTP Service Unavailable"]
A --> D["MySQL Connection Failed"]
A --> E["Redis Connection Failed"]
A --> F["Disk / Full"]
F --> G["MySQL Write Failed"]
F --> H["Application Error"]
依赖配置:
Trigger B: HTTP Service Unavailable
Depends on:
1. HOST: agent.ping (Host is unreachable)
2. Trigger: Port 80 Unavailable (网络层)
3. Trigger: Service nginx down (进程层)
当 HOST DOWN 时,HTTP Service 触发器不会告警
只有当 A、B、C 均 OK 时,HTTP Service 仍异常才告警
关键概念:
| 概念 | 作用 |
|---|---|
| 依赖方向 | 子级 trigger depends on 父级 trigger |
| 传递性 | 依赖会传递:A 依赖 B,B 依赖 C → A 隐含依赖 C |
| 多父级 | 一个 trigger 可依赖多个父级 |
| OK 自动联动 | 父级 OK 后,子级重新独立工作 |
| 行为 | 父级 PROBLEM 时,子级不发送 action |
典型依赖模板示例:
# 模板层依赖
Template Module Linux:
Trigger: HOST DOWN(agent.ping)
→ 所有其他 Item 的触发器都依赖它
Template App MySQL(继承 Linux):
Trigger: MySQL Connection Failed
→ depends on: HOST DOWN
Trigger: MySQL Replication Lag
→ depends on: MySQL Connection Failed
Template App Nginx:
Trigger: Nginx port 80 down
→ depends on: HOST DOWN
Trigger: Nginx request 5xx
→ depends on: Nginx port 80 down(端口挂了不报 5xx)
配置方法:
Web UI: Trigger → Dependencies → Add parent trigger
或在 trigger 表达式中用 "Depends on":
Trigger: MySQL Connection Failed
Dependencies:
- Trigger: {HOST.NAME}: agent.ping.nodata(300)=1
- Trigger: {HOST.NAME}: icmppingloss.max(60)=100
依赖 vs Action Conditions:
| 机制 | 作用 | 时机 |
|---|---|---|
| Trigger Dependency | 抑制依赖 trigger 产生事件 | Trigger 评估层 |
| Action Conditions | 过滤 action 是否发送 | Action 执行层 |
| Tag-based filtering | 抑制相同 tag 的 action | Action 发送层 |
最佳实践:
1. 主机层依赖(HOST DOWN)
- 主机不在线时,所有服务级 trigger 都不告警
- 在模板中配置:所有应用 trigger depends on HOST
2. 服务层依赖(Service: 端口 → 进程 → 业务)
- 端口挂了不报业务异常
- 进程挂了不报 HTTP 5xx
3. 节点依赖(Node)
- 数据库主从:主库挂了从库告警升级
- K8s 节点:节点 NotReady → Pod 异常
4. 避免循环依赖
- A → B → A 会导致评估异常
告警风暴的真实场景:
场景: 网络交换机故障
1. 交换机挂 → 50 台服务器网络不通
2. 每台服务器触发:agent.ping fail、service down、磁盘读不到、连接超时...
3. 每台机器发 30+ 告警 × 50 台 = 1500 条告警轰炸
4. 值班人员崩溃
→ 依赖配置后:仅 1 条 "交换机 X 不可达" 告警
17 Zabbix 告警升级(Escalation)流程如何设计?
答案:
告警升级(Escalation)是 Action 引擎的核心能力,按照"步骤(Step)“和"条件"在指定时间窗内逐级发送告警、通知更高级别的人、执行远程命令。设计良好的升级流程能在告警处理的"早期"和"晚期"采取不同动作。
告警升级原理:
sequenceDiagram
participant T as Trigger
participant A as Action 引擎
participant S1 as 一线运维
participant S2 as 二线/DBA
participant S3 as 主管/CTO
participant RC as 远程命令
T->>A: PROBLEM 事件
A->>S1: Step 1: 邮件 (立即)
Note over A: 等待 10 分钟
A->>S1: Step 2: 短信 (持续 PROBLEM)
Note over A: 等待 10 分钟
A->>S2: Step 3: 电话 (持续 PROBLEM)
Note over A: 等待 20 分钟
A->>S3: Step 4: 升级到主管 (持续 PROBLEM)
Note over A: 等待 30 分钟
A->>RC: Step 5: 自动重启服务 (持续 PROBLEM)
T->>A: 恢复 OK
A->>S1: 恢复通知(邮件)
Action 关键概念:
| 概念 | 说明 |
|---|---|
| Action | 告警动作主体,绑定 trigger/host/discovery 等 |
| Operations | 操作步骤(发送/远程命令),可多个 |
| Steps | 步骤(1-10),可分批/分时 |
| Step duration | 每步持续时间 |
| Conditions | 触发条件(trigger severity/host group/tag) |
| Send to user group | 收件人(用户组) |
| Send via | 媒介类型(Email/SMS/Webhook/Script) |
| Default subject/message | 告警标题与内容模板 |
Action 步骤设计:
Operations:
Step 1: 立即执行
- Send message: Email to group "ops-l1" (message: ${TRIGGER.NAME} on {HOST.NAME})
Step 2: 10 分钟后(PROBLEM 持续)
- Send message: SMS to group "ops-l1" (短信模板)
- Delay between operations: 600s
Step 3: 30 分钟后(仍 PROBLEM)
- Send message: Email to group "ops-l2-dba" (CC 二线)
- Delay: 1200s
Step 4: 1 小时后
- Run remote command: /usr/local/bin/restart.sh on {HOST.IP}
- Send message: WeChat webhook to channel #sre-alert
Step 5: 4 小时后
- Send message: Email to group "ops-leader"
- Run script: 自动化恢复流程
Action 步骤设置:
Step from / Step to: 步骤范围
1 → 1: 仅步骤 1(独立执行)
1 → 9: 步骤 1-9(连续执行)
Step duration: 单步持续时间(默认 0 = 立即执行)
Step 1: 0 (立即)
Step 2: 600 (10min 后)
Step 3: 1800 (30min 后)
...
Operation type:
- Send message
- Run remote command
- Add host to group
- Remove host from group
- Add to maintenance
- Notify all involved
消息模板示例:
# 告警标题
[Zabbix] {TRIGGER.SEVERITY}: {TRIGGER.NAME} on {HOST.NAME}
# 告警内容
Trigger: {TRIGGER.NAME}
Host: {HOST.NAME} ({HOST.IP})
Severity: {TRIGGER.SEVERITY}
Time: {EVENT.DATE} {EVENT.TIME}
Value: {ITEM.LASTVALUE}
Threshold: {TRIGGER.EXPRESSION}
Status: {TRIGGER.STATUS}
Event ID: {EVENT.ID}
Ack URL: http://zabbix.example.com/tr_events.php?triggerid={TRIGGER.ID}
远程命令(Remote Command):
Operation: Run remote command on {HOST.IP}
Type: Custom script
Execute on: Zabbix agent
Commands:
sudo /usr/local/bin/restart_service.sh {HOST.NAME}
# Zabbix Server 配置
EnableRemoteCommands=1
# Zabbix Agent 端允许远程命令
AllowKey=system.run[*]
# 危险命令禁用
DenyKey=system.run[*]
DenyKey=system.run[*]
告警升级的常见设计模式:
| 模式 | 步骤 |
|---|---|
| 一线+二线升级 | Step 1-2: 一线;Step 3-4: 二线 |
| 分时段升级 | Step 1-2: 工作时间;Step 3+: 非工作时间直接升级 |
| 按严重度分流 | Disaster → 5 分钟升级;Warning → 30 分钟升级 |
| 自动恢复 | Step 5: 自动重启 + 人工跟进 |
| PagerDuty 集成 | Step 4: 集成外部 on-call 系统 |
Action 条件过滤:
Conditions(Action 触发条件):
- Trigger severity >= High
- Host group = "Production"
- Trigger name matches "MySQL"
- Time period: weekday 09:00-18:00
- Tag: Service = "payment"
18 标签(Tag)在告警管理中如何应用?Tag-based filtering 与抑制机制是什么?
答案:
Tag 是 Zabbix 5.0+ 引入的关键能力,给 Trigger/Host/Template/Item 打标签,结合 Action Conditions 实现"按业务、按服务、按团队"的精细化告警路由和抑制。
Tag 体系架构:
graph LR
A["Trigger
tag: Service=payment
tag: Severity=critical"] -->|1. 事件携带 tags| B["Event"]
B -->|2. Action Conditions 匹配| C["Action 1: 支付团队"]
B -->|2. Action Conditions 匹配| D["Action 2: DBA 团队"]
B -->|2. Action Conditions 匹配| E["Action 3: 基础设施"]
F["Inheritance:
Template tag → Host tag
Host tag → Item/Trigger tag"] -.继承.-> A
Tag 关键能力:
| 能力 | 作用 |
|---|---|
| Tag 分类 | Trigger/Host/Template/Item 可独立打 tag |
| Tag 继承 | Template tag 继承到 Host,Host tag 继承到 Item/Trigger |
| Action 过滤 | 按 tag 值路由到不同用户组/媒介 |
| Tag 抑制 | 同 tag 已告警时不再重复发送 |
| Event 携带 | 告警事件携带 tag,便于溯源 |
| 宏中使用 | {EVENT.SERVICE} 等 tag 宏在通知中可用 |
Tag 类型与作用范围:
Tag 作用域:
Template tag # 模板层,所有链接主机继承
Host tag # 主机层,可覆盖模板
Trigger tag # 触发器层,最具体
Item tag # 监控项层(与 LLD 配合)
Tag 命名建议:
Service: payment, user, order
Env: prod, staging, dev
Owner: team-a, team-b
Component: db, cache, queue
Severity: critical, warning, info
Action 条件:Tag 路由:
Action: 支付业务告警
Conditions:
A: Trigger severity >= High
B: Tag "Service" matches "payment"
C: Host group = "Production"
Operations:
Step 1: Send Email to group "payment-team"
Step 2: SMS to "payment-oncall"
Step 3: Phone to "payment-lead"
Action: 数据库告警
Conditions:
A: Trigger severity >= Warning
B: Tag "Component" matches "db"
Operations:
Step 1: Send to "dba-team"
Action: 基础设施告警
Conditions:
A: Tag "Component" matches "infra|network|storage"
Operations:
Step 1: Send to "infra-team"
Tag-based 抑制:
场景: 主机宕机后,MySQL、Nginx、Redis 都会告警
Action: MySQL Down
Conditions:
B: Tag "Service" = "mysql"
Operations:
Step 1: Send to dba-team
Action: 抑制规则
Conditions:
A: Tag "Host" = "{HOST.NAME}" AND Tag "Service" matches ".*"
B: Trigger severity <= Average
Operations:
None (匹配此规则的 trigger 不发送)
→ 当 MySQL 主机已发送 PROBLEM 告警,
同主机的其他子项告警被抑制,避免风暴
实际业务标签设计:
# 模板层
Template App MySQL:
Host tag: Service=mysql, Component=database
Trigger tag: Severity=critical, Type=availability
# 主机层覆盖
Host: order-db-master-01:
Tag: Env=prod, Owner=order-team, Business=order-service
Tag: SLA=critical # 覆盖
# Trigger 层细化
Trigger: MySQL Replication Lag
Tag: SLA=critical, Impact=write-failover
在通知中引用 Tag:
# 告警内容模板
Host: {HOST.NAME} (IP: {HOST.IP})
Service: {EVENT.SERVICE} # Tag "Service"
Environment: {EVENT.ENV} # Tag "Env"
Owner: {EVENT.OWNER} # Tag "Owner"
Component: {EVENT.COMPONENT} # Tag "Component"
# 告警 URL
https://alert.example.com/ack?event={EVENT.ID}&service={EVENT.SERVICE}
Tag vs User Macro 的区别:
| 维度 | Tag | User Macro |
|---|---|---|
| 用途 | 标识与路由 | 参数化阈值/配置 |
| 作用 | Action 条件过滤 | Item/Trigger 内部引用 |
| 继承 | 可继承可覆盖 | 可继承可覆盖 |
| 运行时 | 事件携带,可被表达式/通知使用 | 仅在配置中替换 |
| 典型场景 | “Service=payment 路由到支付团队” | “{$DISK.WARN:20} 阈值可调” |
19 Zabbix Proxy 的工作原理和适用场景是什么?
答案:
Zabbix Proxy 是 Server 的"区域代理",是分布式监控的基石。Proxy 部署在被监控区域,独立完成本区域内采集、触发器评估、数据缓冲,然后周期性批量上报给 Server,缓解 Server 采集压力和网络隔离限制。
Proxy 架构:
graph TD
subgraph "IDC 北京"
A["Zabbix Proxy 北京"]
B["区域设备
Agent/SNMP/IPMI"]
C["网络设备
SNMP"]
A -->|采集| B
A -->|采集| C
end
subgraph "IDC 上海"
D["Zabbix Proxy 上海"]
E["区域设备"]
D -->|采集| E
end
subgraph "核心机房"
F["Zabbix Server"]
G[("数据库")]
F -->|读/写| G
end
A -->|Proxy 数据上报| F
D -->|Proxy 数据上报| F
Proxy 核心能力:
| 能力 | 说明 |
|---|---|
| 本地采集 | Proxy 负责该区域所有 Item 的采集(Agent/SNMP/IPMI/Trapper) |
| 本地触发器评估 | Proxy 本地评估触发器,Buffer 超限才上报 Server |
| 数据缓冲 | 网络中断时本地缓存数据(DB 文件),恢复后批量上传 |
| 配置同步 | 与 Server 同步模板、Item 配置(定期拉取) |
| 自动发现 | Proxy 支持所有发现类型(LLD、网络发现) |
| 告警冗余 | Proxy 异常时本地数据不丢失(最多保留 proxy Buffer 时间) |
Proxy 两种工作模式:
| 模式 | 连接方向 | 数据上报 | 防火墙要求 |
|---|---|---|---|
| 主动模式(推荐) | Proxy 主动连接 Server 10051 | 周期上报缓冲数据 | 仅 Proxy 出站可达 Server |
| 被动模式 | Server 主动连接 Proxy 10051 | Server 拉取数据 | Server 需可达 Proxy |
# Proxy 配置(主动模式,推荐)
ProxyMode=0 # 0: 主动, 1: 被动
Server=<Server IP> # Server 地址(主动模式用)
Port=10051
Hostname=proxy-beijing
BufferSize=4096 # 4MB 数据缓冲(越大越抗网络抖动)
ProxyLocalBuffer=0 # 本地缓冲 0=disable
ProxyOfflineBuffer=1 # 离线缓冲 1=enable(断网时保留数据)
# Proxy 配置(被动模式)
ProxyMode=1
Server=<Server IP>
Port=10051
Hostname=proxy-beijing
Proxy 数据缓冲机制:
正常状态:
Proxy 实时采集 → 写入本地 Buffer → 批量发送 Server
网络中断:
Proxy 实时采集 → 写入本地 Buffer → Buffer 满 → 覆盖旧的历史(可配置)
网络恢复:
Proxy 检测到 Server 可达 → 批量发送缓冲数据 → 触发 Server 处理
→ 历史数据补写(趋势趋势图不受影响)
→ 告警评估由 Server 同步后触发
→ BufferSize 越大,可承受的网络中断时间越长
→ Proxy 内存缓冲不影响 Agent 端的实时采集
Proxy 持久化数据:
Proxy 存储文件:
/tmp/zabbix_proxy.db # SQLite
存储: 配置缓存、历史缓冲、值缓存、队列、趋势
重要:
- Proxy 本身的元数据文件(SQLite)不是最终数据
- Proxy 重启后重置 SQLite,不影响 Server 端已同步数据
- Proxy 离线超过保留期后,Server 触发 Trigger "Zabbix proxy is not available"
Proxy vs Agent 对比:
| 维度 | Proxy | Agent |
|---|---|---|
| 职能 | 数据汇聚 + 代理采集 | 单机指标采集 |
| 规模 | 数百到数千 Host | 单机到数十 Host(被 Proxy/Server 管理) |
| 触发器 | 本地评估 | 不负责评估 |
| 部署 | 独立服务器 | 每台被监控机 |
| 配置 | 从 Server 同步 | Server/Proxy 下发配置 |
| 数据流 | Proxy → Server → DB | Proxy/Server → 值缓存 → DB |
| OS 要求 | 同 Server(支持 Linux/Unix) | 支持 Linux/Windows |
最佳实践:
Proxy 部署场景:
✔ 跨机房/跨 IDC(WAN 环境)
✔ 大规模环境(单 Server > 10k Host 时拆分)
✔ 网络隔离区域(DMZ、办公网)
✔ 远程分支(站点/门店)
✔ 需要本地触发器响应的场景
Proxy 配置建议:
1. 每 Proxy 管理 ≤ 2000 Host(经验值)
2. Proxy 与 Server 间带宽 ≥ 10 Mbps(批量上报)
3. 主动模式优先(防火墙友好)
4. BufferSize ≥ 4MB(容忍网络抖动)
5. Proxy 配置一致性(与 Server 同版本优先)
20 Proxy 主动模式与被动模式有什么区别?各适用于什么场景?
答案:
Proxy 主动/被动模式的区分点在于"谁发起连接":主动模式由 Proxy 发起,适合网络隔离区域(仅 Proxy 出站可达 Server);被动模式由 Server 主动轮询 Proxy,适合局域网场景(Server 可直连 Proxy)。
连接方向对比:
sequenceDiagram
participant S as Zabbix Server
participant P as Zabbix Proxy
participant A as Agent
rect rgb(240, 255, 240)
Note over S,P: 主动模式(推荐)
S->>S: 启动
P->>S: Proxy 注册 (hello)
S-->>P: 返回配置(host/template/item)
loop 周期上报
P->>S: 批量数据(values)
S-->>P: ACK
end
end
rect rgb(255, 240, 240)
Note over S,P: 被动模式
S->>P: 拉取数据
P-->>S: 返回缓冲数据
loop
S->>P: configuration sync
P-->>S: 确认
end
end
P->>A: 本地采集
A-->>P: 返回数据
对比表:
| 维度 | 主动模式 | 被动模式 |
|---|---|---|
| 连接方向 | Proxy 主动连接 Server | Server 主动连接 Proxy |
| Server 端口 | Proxy 出站 10051 | Proxy 监听 10051 |
| 防火墙 | 代理端无需入站 | Server 需入站 Proxy |
| 配置 | ProxyMode=0 + Server 字段 | ProxyMode=1 |
| 中断恢复 | Proxy 感知中断,本地缓冲 | Server 感知 Proxy 不可达 |
| 可观测性 | Proxy 内部监控项更完整 | 依赖 Server 侧队列监控 |
| 流量控制 | Proxy 控制上传速率 | Server 控制拉取频率 |
| 推荐 | 跨 IDC / 临域网 / 远程站点 | 同机房 / 同 VPC |
| 数据延迟 | 受上报周期控制 | 取决于 Server 拉取频率 |
Proxy 主动模式优势:
1. 网络隔离友好:仅 Proxy 出站发起连接,Server 不需要反向可达
2. 本地缓冲:Proxy 主导数据流,断网缓冲数据不丢失
3. 自我监控:Proxy 提供内部监控项(zbx_proxy[queue,pending])
4. 批量策略:Proxy 按批次发送,Server 端负载可控
5. 自动重连:Proxy 持续重试,Server 恢复后自动续传
选择策略:
Proxy 强制主动模式:
✔ 跨防火墙(Proxy 在 DMZ,Server 在内网)
✔ 分支机构(Proxy 在外地,Server 在公司)
✔ Server 无法直接访问 Proxy(NAT、VPN)
✔ 需要 Proxy 独立处理网络中断
Proxy 被动模式:
✔ Proxy 与 Server 同局域网
✔ 需要 Server 主动控制采集周期
✔ 需要 Server 侧精准监控 Proxy 状态
✔ 低延迟要求(Server 高频率拉取)
Proxy 三种角色对比:
| 角色 | 主要用途 | 数据上报 |
|---|---|---|
| Zabbix Proxy | 通用场景,区域代理 + 数据缓冲 | 周期性批量上报 Server |
| Zabbix Server + Proxy | HA 场景,failover | 双节点互备 |
| Zabbix Satelline | 多级 Proxy 级联(很少用) | 级联上报 |
配置调优:
# Proxy 块参数
StartPollers=40
StartTrappers=10
HeartbeatFrequency=60 # 心跳周期(秒)
ConfigFrequency=180 # 配置同步周期(秒)
DataSenderFrequency=10 # 数据发送周期(秒)
# 数据缓冲
BufferSize=4096
TrapperTimeout=30
# 主动模式专属
Port=10051 # 监听端口(日常用不上)
21 Zabbix 6.0+ 原生 HA 集群(High Availability Cluster)的主要机制是什么?
答案:
Zabbix 6.0 LTS 引入原生 HA(High Availability Cluster)支持,多个 Server 节点组成集群,Active-Passive 工作模式,心跳检测 + 数据库级选主,切换时间可达秒级,比传统的 DRBD/Keepalived 方案更简洁可靠。
HA 集群架构:
graph TD
subgraph "Zabbix HA Cluster"
A["Server Node 1 (Active)
主节点"] -->|读写| C[(数据库)]
B["Server Node 2 (Standby)
备用节点"] -->|Standby 不处理业务/不写| C
D["Server Node 3 (Standby)
备用节点"] -->|Standby 不处理业务/不写| C
end
C --> E["Web 前端
PHP (可多实例)"]
F["Agent / Proxy"] -->|连接 Active 节点| A
F -.->|掉线重连| B
HA 核心机制:
| 机制 | 说明 |
|---|---|
| 集群成员 | 每个 Server 节点有 name 和 address,注册到数据库 ha_node 表 |
| 选主 | 数据库级(MySQL/PostgreSQL),基于 ha_node 表的心跳时间戳 |
| 心跳 | 每节点周期写入 ha_node.lastaccess(默认 5s) |
| Active 切换 | Standby 节点检测到 Active 心跳超时 → 自己升级为 Active |
| 故障检测窗口 | HAFailoverDelay(默认 5s,连续 3 个心跳缺失) |
| Proxy/Agent 重连 | 自动检测新的 Active 节点并重连(无需配置) |
| Web 前端 | 可同时连接集群,自动路由到当前 Active(api.ha_nodename) |
| 无 Load Balancer | Server 端完成选主,无需外部 LB(但 LB 可优化前端) |
HA 节点状态:
ACTIVE # 当前主节点,正在处理业务(采集/评估/告警)
STANDBY # 备用节点,实时同步心跳,随时准备接管
STOPPED # 节点已停止(手动维护/故障)
ERROR # 节点异常(配置错误、数据库连接失败)
HA 配置步骤:
# 1. 所有 Server 节点配置相同的数据库连接
DBHost=192.168.1.10
DBName=zabbix
DBUser=zabbix
DBPassword=xxxx
# 2. 配置 HA 节点名称和地址
HANodeName=server-01.example.com
HANodeAddress=192.168.1.101:10051
# 3. 启动多个 Server 实例
systemctl start zabbix-server@server-01
systemctl start zabbix-server@server-02
systemctl start zabbix-server@server-03
HA 节点数据流:
Active 节点:
- 采集(poller/trapper/snmp/ipmi/jmx)
- 预处理(preprocessor)
- 触发器评估(trigger engine)
- 告警动作(alerter/escalator)
- 数据库同步(configuration syncer / history syncer)
- 管理 LLD、Housekeeper
Standby 节点:
- 不做任何采集/评估/告警
- 仅做心跳检测 + 数据库连接保活
- 可选开启 Web 前端但不处理采集业务
- 所有进程无负载(除心跳进程外基本空闲)
故障切换流程:
T+0s Active 节点宕机(进程 crash / 服务器断电)
T+5s Standby 节点检测到 lastaccess 超时(HAFailoverDelay=5)
T+5s Standby 节点检查其他节点
T+5s Standby 节点升为 Active
T+5s 开始接收 Agent/Proxy 连接
T+5~10s Agent/Proxy 重连到新 Active 节点
→ 切换时间: 5-15s(取决于 HAFailoverDelay 和网络延迟)
HA 监控与运维:
# 查看 HA 集群状态(数据库级)
mysql -e "SELECT nodeid, name, address, status, lastaccess, ha_nodename FROM ha_node;"
# 内部监控项
zabbix_get -s 127.0.0.1 -k zabbix[ha,status]
# → 'active' | 'standby'
zabbix_get -s 127.0.0.1 -k zabbix[ha,lastaccess]
# → 当前时间戳
zabbix_get -s 127.0.0.1 -k zabbix[ha,nodename]
# → server-01.example.com
HA 与 Proxy 的配合:
场景: HA + Proxy 混合架构
Proxy 连接 Server HA 集群时,无需配置多个 Server IP
Proxy 配置:
Server=<active-server-ip> # 推荐配置单个 Active 地址
或用: Proxy 检测到连接的 Server 为 Standby → 自动重试
更好的做法:
Proxy 配置同时指定两个 Server 地址:
Server=192.168.1.101,192.168.1.102
但注意 Proxy 优先连接第一个可达的(不智能)
原生 HA vs 传统方案的对比:
| 维度 | 原生 HA(6.0+) | DRBD + Keepalived |
|---|---|---|
| 复杂度 | 低(配置 3 个参数) | 高(DRBD 同步 + VIP 切换 + 共享存储) |
| 切换时间 | 5-15s | 30-60s(DRBD promotion) |
| 数据一致性 | 数据库本身容灾 | DRBD 同步延迟可能丢数据 |
| 存储 | 无共享存储要求 | 需要 DRBD 共享块设备 |
| 运维 | Server/Web 单体化 | 存储/Server/Web 三层分离 |
| 失败点 | 少了存储层(数据库本身) | 存储层单点引入更多故障场景 |
| 回退 | 简单(停止备用节点) | 复杂(DRBD 同步状态需修复) |
22 Zabbix 高可用的传统方案和非原生方案还有哪些?
答案:
在 Zabbix 6.0 原生 HA 出现之前(及 6.0 之后仍有遗留场景),业界使用 DRBD、Keepalived、数据库主从、多 Proxy 等传统方式实现高可用。部分方案仍适用于已有基础设施或补全原生 HA 未覆盖的层。
传统 HA 方案对比:
| 方案 | 组件 | 切换时间 | 复杂度 | 适用版本 |
|---|---|---|---|---|
| DRBD + Keepalived | 共享存储 + VIP | 30-60s | 高 | 4.x-6.x 通用 |
| Active-Standby + 共享存储 | NFS/GFS2 | 60-120s | 高 | 所有版本 |
| 多 Proxy 并行 | 数据叠加 | - | 低 | 所有版本 |
| 数据库 HA + Server 双机 | MySQL MGR + Keepalived | 10-30s | 中 | 所有版本 |
| 6.0+ 原生 HA | Server 集群 | 5-15s | 低 | 6.0+ |
方案 1:DRBD + Keepalived(传统方案)
架构:
Server_Active ← VIP: 192.168.1.10 → Agent/Proxy
│ │
│ DRBD sync │
Server_Standby ← VIP 漂移 │
│ │
[DRBD Primary/Secondary]
│
[MySQL (独立节点)]
流程:
1. 两台 Server 共享一个 DRBD 块设备(/dev/drbd0)
2. DRBD Primary 挂载后启动 zabbix_server
3. Keepalived 维护 VIP(192.168.1.10)
4. 主节点故障 → DRBD Secondary→Primary → Keepalived VIP 漂移 → 启动 Server
缺点:
- DRBD 同步延迟(async vs sync 模式)
- 存储层单点故障(DRBD 本身)
- 切换期间数据丢失(同步模式下仍可能)
方案 2:MS SQL Server AG / MySQL InnoDB Cluster
架构:
Zabbix Server A → MySQL MGR Primary
Zabbix Server B → MySQL MGR Secondary(Read-Only)
VIP / DNS:
Server A 关联 VIP
VIP 切换时 B 接管
流程:
1. MySQL MGR 提供高可用数据库
2. Server A 正常连接数据库 Primary
3. Server A 故障 → VIP 漂移到 B
4. Server B 连接 MySQL MGR Primary(自动切换读/写)
优势:
- 数据库自动容灾(MGR 自动选主)
- Server 层轻量(无共享存储)
- MySQL MGR 本身是 Zabbix 推荐的方案之一
方案 3:Zabbix Proxy + 多 Proxy 分担
架构:
多 Proxy 并行(非 HA,而是负载分担):
Proxy_A (Beijing) — 10,000 Host
Proxy_B (Shanghai) — 8,000 Host
Proxy_C (Guangzhou) — 5,000 Host
Proxy_D (Hangzhou) — 3,000 Host
HA Proxy:
双 Proxy 同区域:
Proxy_A1 (Active) — Agent/SNMP 采集
Proxy_A2 (Standby) — 本地区域备用
→ Agent 配置同时指定两个 Proxy
此方案不是 Server HA,而是 Proxy 层级的高可用
可降低 Server 单点故障风险
方案 4:6.0 原生 HA + 数据库 HA(推荐)
推荐架构:
Zabbix HA Cluster (3 节点)
├─ Server-A (Active)
├─ Server-B (Standby)
└─ Server-C (Standby)
MySQL InnoDB Cluster / PostgreSQL Patroni
├─ DB-Primary (Read/Write)
├─ DB-Replica1 (Read-Only)
└─ DB-Replica2 (Read-Only)
Web Frontend × N (可多实例)
Proxy × N (按区域)
优势:
- Server 层 5-15s 自动切换
- 数据库层自动故障转移
- Web 层无状态,前端可任意分布
- 无共享存储、无 DRBD 引入的单点
HA 设计决策树:
是否需要 Server HA?
├─ Zabbix 6.0+ → 原生 HA(推荐)
└─ Zabbix < 6.0
├─ 已有 DRBD 基础设施 → DRBD + Keepalived
└─ 无 DRBD
├─ 可升级 → 升级 6.0+ 原生 HA
└─ 不可升级
├─ 数据库已 HA → 双 Server + VIP + 数据库切换
└─ 数据库无 HA → Proxy 分担 + 单 Server 容错
23 Zabbix 数据库选型:MySQL、PostgreSQL 与 TimescaleDB 各自优缺点?
答案:
Zabbix 从 1.x 开始支持 MySQL,5.0+ 正式支持 TimescaleDB(PostgreSQL 扩展),6.0 LTS 推荐使用 TimescaleDB。三种数据库在架构、性能、运维复杂度上有明显差异。
数据库对比:
| 维度 | MySQL | PostgreSQL | TimescaleDB |
|---|---|---|---|
| 架构 | 传统关系型 | 传统关系型 | PostgreSQL + 时序表扩展 |
| 历史数据存储 | history 表行式 | 行式,支持分区 | 超表(Hypertable)自动分区 |
| 自动分区 | 需手动(Partitioning by RANGE) | 需 pg_partman 插件 | 内置 Chunk 自动分区 |
| 压缩率 | 无原生存放压缩 | TOAST 压缩 | 列式原生压缩(5x-10x) |
| 趋势/历史保留 | 需手工清理(Housekeeper) | 同 MySQL | Interval 自定义 + 自动压缩 |
| 查询性能(历史) | 行式,分页查询慢 | 好(支持并行查询) | 极好(Chunk 裁剪 + 压缩) |
| NVPS(推荐) | ≤ 3,000(经验值) | ≤ 5,000 | 10,000-100,000+ |
| 部署复杂度 | 低 | 中 | 中高(需配置超表 + 压缩策略) |
| 运维成本 | 低 | 中 | 中(压缩管理) |
| 社区/文档 | 最广泛 | 成熟 | Zabbix 官方推荐 6.0+ |
TimescaleDB 优势(Zabbix 6.0+ 推荐):
TimescaleDB 关键能力:
1. 自动分区(Chunk)
CREATE TABLE history (…) → SELECT create_hypertable('history','clock')
→ 按天/小时/分钟自动分 Chunk,不需要手工维护分区
2. 原生压缩
空间压缩: 5-15x(housekeeping 前)
时间压缩: 自动(job 定时运行)
再分区 + 按时间聚合 → 查询仍高效
3. 连续聚合
类似物化视图 + 自动刷新
大幅提升长周期趋势图/报表性能
4. 列式存储(超表)
Chunk 内部按列存储(压缩友好)
历史查询只需扫描相关列
TimescaleDB 配置示例:
-- Zabbix 数据库初始化(PostgreSQL + TimescaleDB)
-- create database
CREATE DATABASE zabbix WITH TEMPLATE template0;
-- 启用 TimescaleDB 扩展
CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;
-- 历史表转为超表
SELECT create_hypertable('history', 'clock',
chunk_time_interval => 86400); -- 1 天一个 Chunk
SELECT create_hypertable('history_uint', 'clock',
chunk_time_interval => 86400);
SELECT create_hypertable('history_str', 'clock',
chunk_time_interval => 86400);
SELECT create_hypertable('history_log', 'clock',
chunk_time_interval => 86400);
SELECT create_hypertable('history_text', 'clock',
chunk_time_interval => 86400);
SELECT create_hypertable('trends', 'clock',
chunk_time_interval => 86400);
SELECT create_hypertable('trends_uint', 'clock',
chunk_time_interval => 86400);
-- 压缩策略(存储优化)
SELECT add_compression_policy('history', INTERVAL '7 days');
SELECT add_compression_policy('history_uint', INTERVAL '7 days');
SELECT add_compression_policy('history_str', INTERVAL '7 days');
SELECT add_compression_policy('history_log', INTERVAL '7 days');
SELECT add_compression_policy('history_text', INTERVAL '7 days');
MySQL 分区配置(手动维护):
-- MySQL 分区(Zabbix 4.x-5.x 常用)
ALTER TABLE `history`
PARTITION BY RANGE (clock) (
PARTITION p202601 VALUES LESS THAN (UNIX_TIMESTAMP('2026-02-01 00:00:00')),
PARTITION p202602 VALUES LESS THAN (UNIX_TIMESTAMP('2026-03-01 00:00:00')),
PARTITION p202603 VALUES LESS THAN (UNIX_TIMESTAMP('2026-04-01 00:00:00')),
PARTITION p202604 VALUES LESS THAN (UNIX_TIMESTAMP('2026-05-01 00:00:00')),
PARTITION p202605 VALUES LESS THAN (UNIX_TIMESTAMP('2026-06-01 00:00:00')),
PARTITION p202606 VALUES LESS THAN (UNIX_TIMESTAMP('2026-07-01 00:00:00')),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
数据库选型建议:
场景 → 推荐
← 3,000 NVPS → MySQL(够用且运维最轻)
3k-10k NVPS → PostgreSQL(性能强于 MySQL)
≥ 10k NVPS → TimescaleDB(压缩 + Chunk 自动分区)
NVPS 极高 → TimescaleDB + 多 Proxy 分担采集
增量迁移:
MySQL 可在线迁移到 TimescaleDB(pgloader 工具有支持)
迁移后 Housekeeper 策略改为压缩策略,磁盘节省 5-10x
24 Housekeeper(数据清理)的工作原理是什么?如何调优?
答案:
Housekeeper 是 Zabbix Server 的内置进程,负责删除过期的历史数据、事件、审计日志、Action 日志等,防止数据库无限膨胀。不调优的 Housekeeper 在大规模场景下可能成为瓶颈,甚至拖垮数据库写入性能。
Housekeeper 工作流程:
flowchart LR
A["定时任务
(每小时)"] --> B["检查 Item History 保留期"]
A --> C["检查 Event 保留期"]
A --> D["检查 Audit/Action 保留期"]
B --> E["DELETE FROM history WHERE clock < :time"]
C --> F["DELETE FROM events WHERE eventid < :id"]
D --> G["DELETE FROM audit WHERE clock < :time"]
E --> H[(数据库: history 空间释放)]
F --> I[(events 表收缩)]
G --> J[(audit 表压缩)]
保留期配置:
# Web UI → Administration → General → Housekeeper
Housekeeping frequency: 1 (小时)
Trigger data storage period: 365
Internal events: 365
Network discovery events: 30
Auto-registration events: 30
# Item 级保留期(每个 Item 可单独设置)
Item:
History storage period: 7d-90d
Trends storage period: 365d
# 全局保留期(Item 未设置时使用)
History retention: 14d
Trends retention: 365d
Housekeeper 性能影响:
问题: Housekeeper 在大表上执行 DELETE 大量数据时:
- 表锁定/行锁定(MySQL InnoDB 需小心死锁)
- INSERT 被阻塞(写入 history 表会锁等待)
- 触发器评估延迟(历史数据被锁定)
- Event 表 DELETE 影响 event 处理
建议:
- MySQL: 禁用内置 Housekeeper,改用外部 Cron 分区 Drop/Truncate
- PostgreSQL: 可启用内置(并行 DELETE 较友好)
- TimescaleDB: 内置压缩 + Chunk drop(压缩后数据自动过期)
优化方案 1:MySQL 分区 Drop(推荐)
-- 每月 1 日凌晨 将过期分区直接 DROP(极快)
-- 代替 DELETE,秒级完成(DROP TABLE 是 DDL,无锁)
ALTER TABLE `history` DROP PARTITION p20260401;
ALTER TABLE `history` DROP PARTITION p20260402;
-- ...
-- Zabbix 配置:禁用内置 Housekeeper 的历史表删除
HousekeepingFrequency=0 # 关闭内置 Housekeeper
优化方案 2:TimescaleDB 压缩 + 过期策略
-- TimescaleDB 策略:保留 30 天后自动删除 Chunk
SELECT add_retention_policy('history', INTERVAL '30 days');
SELECT add_retention_policy('history_uint', INTERVAL '30 days');
-- 配合压缩:7 天后自动压缩
SELECT add_compression_policy('history', INTERVAL '7 days');
-- 最佳实践:压缩 7d + 保留 30d → 磁盘节省 80%
优化方案 3:外部脚本(通用)
#!/bin/bash
# /usr/local/bin/zbx_housekeeper.sh
# cron: 0 2 * * * /usr/local/bin/zbx_housekeeper.sh
DB_USER=zabbix
DB_PASS=xxxx
DB_NAME=zabbix
# 删除 90 天前的 history_uint
echo "DELETE FROM history_uint WHERE clock < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 90 DAY)) LIMIT 100000;" | \
mysql -u$DB_USER -p$DB_PASS $DB_NAME &
Housekeeper 监控项:
# 内部监控项检查 Housekeeper 状态
zabbix_get -s 127.0.0.1 -k zabbix[housekeeping,start_time] # 上次清理时间
zabbix_get -s 127.0.0.1 -k zabbix[housekeeping,count] # 本次清理行数
zabbix_get -s 127.0.0.1 -k zabbix[housekeeping,duration] # 清理耗时(ms)
zabbix_get -s 127.0.0.1 -k zabbix[process,housekeeper,avg,busy] # Housekeeper 负载
25 Zabbix 性能瓶颈如何定位?NVPS/TPS 估算与配置调优方法?
答案:
Zabbix 性能瓶颈最常用的指标是 NVPS(New Values Per Second,每秒新值数),也称为 TPS(Transactions Per Second)。定位瓶颈需遵循"Cache → DB → Poller → Preprocessor"的顺序排查。
NVPS 估算:
NVPS = SUM( 所有 Item 数 / 采集间隔)
例:
Item 类型 Item 数 采集间隔(s) NVPS
Internet/Agent 800 60 13.3
SNMP 200 300 0.7
Trapper 50 - 10
Active Agent 1200 60 20.0
LLD 5 3600 0.0
Web Scenario 10 120 0.08
------
总计: 2265 Item ~44 NVPS
→ 一台 Server 可承载数千 NVPS(经验值 2,000-10,000)
→ >10,000 NVPS 需 Proxy 分发和 TimescaleDB
瓶颈排查流程:
flowchart TD
A["发现延迟/队列堆积"] --> B["检查 zabbix[queue]"]
B --> C{"队列值 > 10?"}
C -- No --> K["检查其他进程
db_syncer/housekeeper"]
C -- Yes --> D{"poller busy > 75%?"}
D -- Yes --> E["增加 StartPollers"]
D -- No --> F{"trapper busy > 75%?"}
F -- Yes --> G["增加 StartTrappers"]
F -- No --> H{"history_syncer busy > 75%?"}
H -- Yes --> L["检查 DB I/O:
磁盘 iowait、慢查询"]
H -- No --> I{"preprocessor busy > 75%?"}
I -- Yes --> J["增加 StartPreprocessors"]
I -- No --> M["Cache size 不足
检查 Cache miss"]
内部监控项定位瓶颈:
# 队列深度(主要指标)
zabbix_get -s 127.0.0.1 -k zabbix[queue] # 总队列
zabbix_get -s 127.0.0.1 -k zabbix[queue,5m] # 5 分钟以上延迟
zabbix_get -s 127.0.0.1 -k 'zabbix[queue,proxy,5m,beijing]' # 特指 Proxy
# 进程负载
zabbix_get -s 127.0.0.1 -k zabbix[process,poller,avg,busy] # poller 忙率
zabbix_get -s 127.0.0.1 -k zabbix[process,trapper,avg,busy]
zabbix_get -s 127.0.0.1 -k zabbix[process,historysyncer,avg,busy]
zabbix_get -s 127.0.0.1 -k zabbix[process,preprocessor,avg,busy]
# Cache 命中
zabbix_get -s 127.0.0.1 -k zabbix[cache,buffer,history] # 历史缓存使用率
zabbix_get -s 127.0.0.1 -k zabbix[cache,buffer,value] # 值缓存
zabbix_get -s 127.0.0.1 -k zabbix[cache,buffer,historyindex] # 索引缓存
# 数据库相关
zabbix_get -s 127.0.0.1 -k zabbix[db,wait_time] # DB 等待时间
zabbix_get -s 127.0.0.1 -k zabbix[db,query,insert,history] # 插入次数
典型瓶颈与调优:
| 现象 | 瓶颈点 | 调优措施 |
|---|---|---|
| 队列堆积 > 10 | Poller 不足 | 增加 StartPollers |
| Preprocessor 忙 > 75 | 预处理瓶颈 | 增加 StartPreprocessors |
| history syncer 忙 | DB 写入 I/O | 检查 DB 配置; 启用批量插入; 使用 TimescaleDB |
| Cache miss 上升 | 缓存不足 | 增大 HistoryCacheSize 等 |
| DB wait_time 高 | DB 慢查询 | 检查分区、压缩;分析慢查询日志 |
| SNMP 采集慢 | SNMP 设备超时 | Timeout 调低;增加 StartSNMPPollers |
| Agent 连接超时 | Agent 端口 | Agent 端同时启用 ListenPort + ServerActive |
| Bulk 写入延迟 | 磁盘 I/O | 分离数据文件至 SSD; commit 调优 |
Server 配置调优模版:
# 高性能配置(假设 10,000 NVPS)
StartPollers=80
StartTrappers=40
StartPingers=5
StartHTTPPollers=20
StartSNMPPollers=20
StartIPMIPollers=5
StartJMXPollers=10
StartLLD=10
StartPreprocessors=20
StartAlerters=10
StartEscalators=10
# Cache 调大
HistoryCacheSize=512M
HistoryIndexCacheSize=128M
TrendCacheSize=256M
ValueCacheSize=512M
# 数据库相关
CacheUpdateFrequency=60
MaxHousekeeperDelete=50000
HistorySyncer=10
TrendFunctionCacheSize=8M
HistoryCacheSetSize=128M
# 超时
Timeout=3
SNMPTimeout=1
TrapperTimeout=30
OS 层调优:
# 系统参数
kernel.shmmax = 68719476736 # 64GB 共享内存
kernel.sem = 250 32000 100 256 # 信号量(Zabbix 多进程要求)
# 数据库(MySQL)
innodb_buffer_pool_size = 16G # 总内存 50-70%
innodb_io_capacity = 2000 # SSD
innodb_log_file_size = 2G
innodb_flush_log_at_trx_commit = 2 # 允许 1s 数据丢失提升写入性能
26 Zabbix 7.x 在性能和扩展性方面有哪些重要改进?
答案:
Zabbix 7.x(2024 年发布)在性能和扩展性上带来多项底层改进,包括 Native Agent 2 持久连接、数据库连接池、监控项预处理完全异步化、Server 内部项缓存重构。
Zabbix 7.x 关键改进:
| 改进 | 影响 |
|---|---|
| 持久连接 | Agent 2 原生长连接,减少连接建立开销,主动模式下批量传递效率倍增 |
| 预处理异步化 | 预处理步骤完全异步执行,不再阻塞 poller 进程,单台 Server 可承载更高 NVPS |
| 数据库连接池 | Server 和 Proxy 支持数据库连接池(DBCacheSize),减少连接建立/关闭开销 |
| 双重历史写入 | history 和 trend 同批入库,减少 I/O 次数 |
| LLD 异步化 | LLD 发现和处理不再阻塞 Server 主流程,多 LLD 并发 |
| Web 前端 PHP 8.2+ | 仅支持 PHP 8.2/8.3,性能提升 20%+ (vs PHP 7.x) |
| 宏引擎优化 | 宏解析在配置同步时完成,运行时不再解析,大幅降低内存使用 |
| 事件处理并发 | 告警事件处理支持多线程并发,避免单个事件队列阻塞 |
持久连接对比:
Zabbix 6.0:
Agent 主动模式:每次采集周期 (60s) 建立新连接 → 断开
Agent A(5000 host)→ Server: 5000次连接建立/60s ≈ 83次/秒 TCP
Zabbix 7.x:
Agent 2 主动模式:建立长连接,复用
Agent A(5000 host)→ Server: 2-5个持久 TCP 连接 → 多路复用
→ 减少 Server 端 TCP 状态表压力
→ 减少 Agent 端 fork/exec 开销(Agent 2)
预处理完全异步化:
Zabbix 6.0: 预处理 → poller → 同步等待(polling + preprocessing 串行)
Zabbix 7.x: 预处理 → 异步队列 → preprocessor 空闲进程独立执行
↓ 影响:
NVPS: +30-80%(预处理密集场景提升最明显)
CPU 利用率:preprocessor 进程不再与 poller 绑定,可独立控制
数据库连接池:
# Zabbix 7.x Server 配置
DBCacheSize=32M # 数据库连接池大小(共用的连接状态缓存)
DBMaxPoolSize=100 # 连接池最大连接数
DBPoolIdleSize=64 # 连接池空闲保持数
DBPoolCheckTimeout=300 # 空闲连接回收时间
↓ 影响:
高并发: 连接池降低建连开销
慢查询: 池化连接减少等待
Proxy: 受益尤甚(频繁连接/断开历史模式)
性能对比数据(官方参考):
场景: 10,000 Host × 200 Item = 2,000,000 Item × 60s ≈ 33,333 NVPS
Zabbix 6.0 LTS:
Server 进程: 100 (poller) + 50 (trapper) + 30 (preprocessor) + ...
Server 内存: 16-24 GB
DB: TimescaleDB, 4 核 32G
Zabbix 7.x:
Server 进程: 60 (poller) + 40 (trapper) + 10 (preprocessor) + ...
Server 内存: 12-16 GB
DB: TimescaleDB, 4 核 32G
↓ 提升:
同 NVPS 下减少 30-50% 进程数
内存减少 20-40%
Agent 连接数减少 80%+(持久连接)
升级注意事项:
重要:
- Agent 2 需升级到 7.x 版本才能使用持久连接
- PHP 版本必须 ≥ 8.2
- 数据库 schema 需要迁移(Zabbix 7.0 有额外表结构变更)
- 旧版 C-Agent 仍可用,但无法享受持久连接优化
- Proxy 需与 Server 同版本(向下兼容到 6.0 有限)
27 Zabbix API 如何用于批量自动化?常见场景有哪些?
答案:
Zabbix API 基于 JSON-RPC 2.0 协议,HTTP POST 请求到 api_jsonrpc.php,支持对所有 Zabbix 管理对象(主机、模板、Host Group、Item、Trigger、Action、User、Media)的 CRUD 操作,是实现批量自动化、CMDB 同步、CI/CD 集成的关键接口。
API 基础:
# 认证
curl -X POST http://zabbix.example.com/api_jsonrpc.php \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "user.login",
"params": {"user": "Admin", "password": "zabbix"},
"id": 1
}'
# 返回: {"result":"auth_token_xxxx","id":1}
# 后续所有请求携带 auth
AUTH="auth_token_xxxx"
常见自动化场景:
# 场景 1: 批量创建主机
curl -X POST http://zabbix.example.com/api_jsonrpc.php \
-H "Content-Type: application/json" \
-d "{
\"jsonrpc\": \"2.0\",
\"method\": \"host.create\",
\"params\": {
\"host\": \"web-01\",
\"interfaces\": [
{\"type\": 1, \"main\": 1, \"useip\": 1, \"ip\": \"10.0.0.1\", \"dns\": \"\", \"port\": \"10050\"}
],
\"groups\": [{\"groupid\": \"5\"}],
\"templates\": [{\"templateid\": \"10001\"},{\"templateid\": \"10234\"}],
\"macros\": [
{\"macro\": \"{$SSH_PORT}\", \"value\": \"22\"}
]
},
\"auth\": \"$AUTH\",
\"id\": 2
}"
# 场景 2: 获取主机 ID 和状态
curl -X POST http://zabbix.example.com/api_jsonrpc.php \
-H "Content-Type: application/json" \
-d "{
\"jsonrpc\": \"2.0\",
\"method\": \"host.get\",
\"params\": {
\"output\": [\"hostid\",\"host\",\"status\"],
\"filter\": {\"host\": [\"web-01\",\"web-02\"],\"status\": [0]}
},
\"auth\": \"$AUTH\",
\"id\": 3
}"
# 场景 3: 批量更新主机宏
curl -X POST http://zabbix.example.com/api_jsonrpc.php \
-H "Content-Type: application/json" \
-d "{
\"jsonrpc\": \"2.0\",
\"method\": \"host.update\",
\"params\": {
\"hostid\": \"10234\",
\"macros\": [
{\"macro\": \"{$DISK.WARN}\", \"value\": \"85\"}
]
},
\"auth\": \"$AUTH\",
\"id\": 4
}"
# 场景 4: 获取告警事件并确认
curl -X POST http://zabbix.example.com/api_jsonrpc.php \
-H "Content-Type: application/json" \
-d "{
\"jsonrpc\": \"2.0\",
\"method\": \"event.get\",
\"params\": {
\"output\": \"extend\",
\"severities\": [4,5],
\"time_from\": \"$(date -d '1 hour ago' +%s)\",
\"acknowledged\": false
},
\"auth\": \"$AUTH\",
\"id\": 5
}"
常用 API 方法:
| 方法 | 操作 | 场景 |
|---|---|---|
host.create / host.update / host.delete | 主机增删改 | CMDB 同步、自动注册 |
hostgroup.get / hostgroup.create | 主机组管理 | 业务分组 |
template.create / template.export | 模板 CRUD | 版本控制 |
trigger.create / trigger.get | 触发器管理 | 批量配置 |
action.create / action.update | 动作管理 | 告警路由 |
event.get / event.acknowledge | 事件查询与确认 | 值班系统集成 |
history.get / trend.get | 历史/趋势查询 | 外部报表 |
dashboard.export / dashboard.import | Dashboard 导入导出 | 监控看板 |
maintenance.create / maintenance.delete | 维护期管理 | 变更窗口 |
usermacro.get / usermacro.create | 宏 CRUD | 参数化 |
configuration.export / configuration.import | 配置导入导出 | Git 备份 |
Python 自动化示例:
# pip install py-zabbix
from pyzabbix import ZabbixAPI
zapi = ZabbixAPI('http://zabbix.example.com')
zapi.login('Admin', 'zabbix')
# 查询所有激活的主机
hosts = zapi.host.get(output=['hostid', 'host'],
filter={'status': 0})
print(f"总激活主机数:{len(hosts)}")
# 批量创建主机
for ip, hostname in cmdb_hosts.items():
zapi.host.create(
host=hostname,
interfaces=[
{'type': 1, 'main': 1, 'useip': 1, 'ip': ip, 'port': '10050'}
],
groups=[{'groupid': group_id}],
templates=[{'templateid': tmpl_id}],
macros=[{'macro': '{$ENV}', 'value': 'prod'}]
)
print(f"创建主机 {hostname} ({ip})")
# 批量创建维护期
zapi.maintenance.create(
name=f"升级维护 {date}",
hostids=[host_id],
timeperiods=[
{'timeperiod_type': 0,
'start_date': start_ts,
'period': 3600} # 1 hour
],
tags_evaltype=0,
tags=[{'tag': 'source', 'value': 'deploy'}]
)
API 自动化最佳实践:
1. 认证复用: 只 login 一次,auth token 有效期内复用
2. 批量操作: 每次 API 调用可包含多个对象,减少 HTTP 开销
3. 幂等性: host.create → host.get 先检查再 create(防止重复)
4. 错误处理: JSON-RPC 返回 error 时捕获并重试
5. 限速: 单脚本每秒 < 10-20 次 API 调用(Server 端有保护)
6. 配置备份: 定期 configuration.export → Git 仓库(Zabbix 模板版本管理)
7. 与 CMDB 集成: Ansible/Terraform 调用 Zabbix API 自动化主机创建
28 Zabbix 安全加固有哪些关键措施?
答案:
Zabbix 部署在生产环境时需从网络层、传输层、认证层、数据层、API 层五个维度进行安全加固。默认配置以可用性优先,生产部署必须有对应安全策略覆盖。
安全加固全面清单:
| 层次 | 加固措施 | 配置 |
|---|---|---|
| 传输加密 | Agent ↔ Server/Proxy:TLS/PSK | TLSConnect=psk; TLSAccept=psk |
| 数据库加密 | DB 连接 TLS | DBHost TLS 连接 |
| Web 前端 | HTTPS only | Nginx/Apache 反向代理 TLS |
| Web 认证 | LDAP/SAML/OAuth2 | Authentication type: LDAP |
| API | API 访问限制 + Token | API.access_token 限制 |
| Agent 安全 | 限制 System.Run | DenyKey=system.run[*] |
| Web 前端 IP 限制 | 仅允许内网/IP | Nginx allow/deny |
| 时区/日志 | 统一时区,日志输出 | LogFileSize=10, DebugLevel=3 |
| Proxy 加密 | Proxy ↔ Server TLS | TLSConnect=psk |
| Web 前端密码 | 密码策略(长度、过期) | User authentication policy |
| XSS/SQL 注入 | PHP 安全配置 | session.cookie_httponly, csp |
TLS/PSK 配置示例:
# 1. 生成 PSK Key
openssl rand -hex 32 > /etc/zabbix/psk.key
# 2. Server 配置
# /etc/zabbix/zabbix_server.conf
TLSConnect=psk
TLSAccept=psk
TLSPSKIdentity=Server1
TLSPSKFile=/etc/zabbix/psk.key
# 3. Agent 配置
# /etc/zabbix/zabbix_agentd.conf
TLSConnect=psk
TLSAccept=psk
TLSPSKIdentity=Agent1
TLSPSKFile=/etc/zabbix/agent_psk.key
# 4. Web UI → Host → Encryption
# 每个主机配置 PSK Identity 和 PSK key
# 5. 验证
zabbix_get -s 127.0.0.1 -k agent.ping --tls-connect psk \
--tls-psk-identity "Server1" --tls-psk-file /etc/zabbix/psk.key
Agent 最小权限:
# /etc/zabbix/zabbix_agentd.conf
# 关键:拒绝危险 Key
DenyKey=system.run[*]
AllowKey=system.run[uptime]
# 或者只允许指定 Key(白名单模式推荐)
# AllowKey 优先于 DenyKey
AllowKey=system.run[*] # 默认禁止
AllowKey=agent.ping
AllowKey=system.hostname
AllowKey=system.cpu.util[*]
AllowKey=system.uname
AllowKey=net.if.discovery
AllowKey=vfs.fs.discovery
# UserParameter 沙箱化
# 不要在 UserParameter 中调用未验证的输入
# 使用 sudo 限制执行用户
AllowRoot=0 # 禁止 root 执行远程命令
EnableRemoteCommands=0 # 禁止远程命令(默认)
数据库安全:
-- Zabbix 数据库用户最小权限
CREATE USER 'zabbix'@'%' IDENTIFIED BY 'strong_password_xxxx';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX, REFERENCES
ON zabbix.* TO 'zabbix'@'%';
-- 注意:Zabbix DBSchema 迁移需要额外权限(如 ALTER TABLE)
-- 但日常运行时不需要 CREATE/DROP/ALTER→可去掉
-- 只读报表用户
CREATE USER 'zabbix_read'@'%' IDENTIFIED BY 'report_password';
GRANT SELECT ON zabbix.* TO 'zabbix_read'@'%';
Web 前端安全:
# Nginx 反向代理
server {
listen 443 ssl http2;
server_name zabbix.example.com;
ssl_certificate /etc/ssl/zabbix.crt;
ssl_certificate_key /etc/ssl/zabbix.key;
# 仅允许内网 IP
allow 10.0.0.0/8;
allow 192.168.0.0/16;
deny all;
# CSP 增强
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;";
# 禁用目录列表
autoindex off;
location / {
proxy_pass http://127.0.0.1:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
# PHP 安全配置
session.cookie_httponly = 1
session.cookie_secure = 1
session.use_strict_mode = 1
API 安全:
# Web UI → Administration → API Tokens
# 优点:API Token 比密码更安全(可设置过期、权限范围)
# API Token 使用:
curl -X POST http://zabbix.example.com/api_jsonrpc.php \
-H "Content-Type: application/json" \
-H "Authorization: Bearer api_token_xxxx" \ ← Bearer token
-d '{...}'
# API Rate Limiting
# Zabbix 默认没有速率限制,可 Nginx 层实现
limit_req_zone $binary_remote_addr zone=zabbix_api:10m rate=10r/s;
维护期(Maintenance)用于变更安全:
Maintenance: 云环境变更窗口
- 变更期间自动关闭告警(不产生事件)
- 维护期过后自动恢复
- 支持周期性维护期(如每月补丁维护)
创建方式:
- API: maintenance.create
- 脚本: zabbix_maintenance.py
- Web UI: Configuration → Maintenance
29 Zabbix 与 Prometheus + Grafana 在监控体系中的选型对比?
答案:
Zabbix 和 Prometheus 并非非此即彼,现代观测性架构中两者长期共存:Zabbix 负责传统基础设施(物理机、网络设备、数据库中间件),Prometheus 负责云原生(K8s、微服务、容器)。Grafana 作为统一可视化层可以整合两者数据源。
多维度对比:
| 维度 | Zabbix | Prometheus | Prometheus+Grafana |
|---|---|---|---|
| 定位 | 中心化多协议监控平台 | 时序数据库 + 告警引擎 | 生态(LGTM 堆栈) |
| 采集模型 | Agent/SNMP/IPMI/Trapper 多协议 | 主要 Pull + Pushgateway | 同 Prometheus |
| 数据模型 | 主机-Item 对象模型 | 指标名 + 多维 Label | 同 Prometheus |
| 告警引擎 | 内置触发器 + Action 升级 | 规则评估 + Alertmanager | Alertmanager 路由 |
| 可视化 | 自带 Dashboard + Grafana | 无(依赖 Grafana) | Grafana 为主 |
| 模板库 | 内置丰富官方模板 | 社区 Exporter 丰富 | 社区 Exporter + 仪表盘 |
| 协议适配 | SNMP/IPMI/JMX/HTTP Agent 原生 | 需额外 Exporter | 同 Prometheus |
| 扩展性 | Proxy 分发 + Server HA | 联邦 / Thanos / Cortex | Mimir / VictoriaMetrics |
| 运维认知 | PHP + MySQL/PostgreSQL | Go + TSDB | 多组件运维 |
| K8s 适配 | 需手动配置 | 天然支持 | 完全适配 |
| 多语言 SDK | C/Go/其他(zabbix_sender) | 所有主流语言 | 同 Prometheus |
| 数据保留 | MySQL 行 + Housekeeper | 块压缩 + 过期策略 | 可配置 |
| 告警升级 | 内置(escalation) | 无(Alertmanager 不提供升级) | 需外部系统 |
| 资产/CMDB | 内置资产管理(Inventory) | 无 | 无 |
选型决策树:
是否需要监控以下设备:
├─ 物理服务器(温度/IPMI/传感器) → Zabbix(最成熟)
├─ 网络设备(SNMP) → Zabbix(原生支持)
├─ 数据库/中间件 → Zabbix 或 Prometheus Exporter
├─ Kubernetes/容器 → Prometheus(标准方案)
├─ 云原生微服务/Service Mesh → Prometheus + Grafana Tempo
└─ 业务自定义指标 → Prometheus Client 库
是否已有 Zabbix 基础设施:
├─ 已有 5000+ 监控项 → 扩展 Zabbix 部署
├─ 全面 K8s 化 → 逐步引入 Prometheus
└─ 混合架构 → Zabbix(传统层)+ Prometheus(云原生)
团队技能:
├─ 熟悉 PHP/MySQL → Zabbix 运维友好
├─ 熟悉 Go/Linux → Prometheus 运维友好
└─ 两者兼备 → 混合架构:统一 Grafana 前端
Grafana 统一可视化:
Grafana → 统一仪表盘入口
数据源一: Zabbix (Zabbix Data Source Plugin)
- 接入 Zabbix 历史/趋势数据
- 查询 Zabbix 对象模型(host/group/template)
- 通过 Zabbix API 获取告警事件
数据源二: Prometheus / Thanos
- 用 PromQL 查询多维指标
- Service 级指标聚合展示
数据源三: Loki
- 日志搜索与面板关联
架构示例:
Grafana Dashboard:
├─ Panel 1: 物理服务器 → Zabbix
├─ Panel 2: K8s → Prometheus
├─ Panel 3: 日志 → Loki
└─ Panel 4: 告警 → Alertmanager
混合部署推荐架构:
推荐架构(中大规模):
传统层(Zabbix):
Zabbix Server HA (3 节点)
Zabbix Proxy × N (按区域)
Agent 2 (Linux/Windows)
SNMP 轮询 (网络设备)
IPMI (硬件健康)
云原生层(Prometheus + VictoriaMetrics):
Prometheus Operator (K8s 监控)
VictoriaMetrics (长期存储)
Prometheus AlertManager (告警)
观测性层(Grafana + Loki + Tempo):
Grafana (统一仪表盘)
Zabbix Datasource Plugin
Prometheus Datasource
Loki (日志)
Tempo (分布式追踪)
统一告警:
PagerDuty / Opsgenie
Zabbix Action → Webhook → PagerDuty
Alertmanager → Webhook → PagerDuty
30 Zabbix 常见故障场景与排查思路?
答案:
Zabbix 生产环境中最常见的故障集中在四个层面:Server 进程挂死、数据库写入瓶颈、采集延迟/队列堆积、Agent 连接问题。以下是主流故障场景的排查流程。
故障 1:Server 进程挂死(高负载)
现象:
- zabbix_server 运行但无响应
- 队列堆积(zabbix[queue] > 1000)
- Agent 连接超时
排查:
# 1. 检查进程负载
zabbix_get -s 127.0.0.1 -k zabbix[process,poller,avg,busy]
zabbix_get -s 127.0.0.1 -k zabbix[process,trapper,avg,busy]
# 2. 检查 Server 日志
tail -100 /var/log/zabbix/zabbix_server.log | grep -i error
# 3. 检查 DB 连接
zabbix_get -s 127.0.0.1 -k zabbix[db,wait_time]
# 4. 检查 Cache 使用率
zabbix_get -s 127.0.0.1 -k zabbix[cache,buffer,history]
修复:
- 调大 HistoryCacheSize / ValueCacheSize
- 增加 HistorySyncer 数量
- 检查慢查询(DB 层)
- 如果是 Housekeeper 阻塞:停止 Housekeeper + 手动分区 Drop
故障 2:数据库写入瓶颈
现象:
- history_syncer 进程繁忙 > 75%
- DB wait_time 高
- history/trends 插入延迟(INSERT backlog)
- Server 日志出现 "lost X values"
排查:
# 1. 检查慢查询
# MySQL
SHOW FULL PROCESSLIST;
SHOW GLOBAL STATUS LIKE 'Innodb_row_lock%';
# 2. 检查数据库 I/O
iostat -x 1 | grep -E 'sda|nvme'
iotop -oP
# 3. 检查 history 表大小
SELECT table_name, table_rows, ROUND(data_length/1024/1024,2) size_mb
FROM information_schema.tables
WHERE table_schema = 'zabbix';
修复:
- 增大 HistorySyncer / HistoryCacheSize
- 切换到 TimescaleDB(原生分区 + 压缩)
- 关闭内置 Housekeeper(用分区 Drop 代替)
- 增加 DB 并发写入(innodb_io_capacity)
故障 3:Agent 连接失败
现象:
- Trigger: agent.ping.nodata(300)=1
- Item 显示 No value
- zabbix_get 连接超时
排查:
# Server 端
zabbix_get -s 192.168.1.10 -k agent.ping -p 10050
# 返回: ZBX_TCP_READ() timed out
# Agent 端
systemctl status zabbix-agent
zabbix_agentd -t agent.ping
# 网络检查
tcpdump -i eth0 port 10050 -c 5
常见原因:
1. Agent 配置错误(Server IP 不对)
2. 防火墙阻挡(iptables/nftables/安全组)
3. Agent 端口被占用(多个 Agent 进程冲突)
4. 超时太短(Timeout < Agent 响应时间)
5. TLS/PSK 配置不匹配
6. 主机名不匹配(Hostname / HostnameItem)
修复:
- 检查 /etc/zabbix/zabbix_agentd.conf
- 检查防火墙: nc -zv 192.168.1.10 10050
- 增加 Timeout = 5 (Server 和 Agent 都改)
- 验证 TLS 配置:tls-connect / tls-accept 匹配
故障 4:Proxy 离线
现象:
- Proxy 状态显示 Not available
- 该区域监控数据全部停止
- Trigger: "Zabbix proxy is not available"
排查:
# 1. 检查 Proxy 进程
systemctl status zabbix-proxy
tail -100 /var/log/zabbix/zabbix_proxy.log
# 2. 检查网络
telnet <Server IP> 10051
# 3. Proxy 配置
grep -E '^(Server|Hostname|BufferSize|ConfigFrequency|DataSenderFrequency)' \
/etc/zabbix/zabbix_proxy.conf
# 4. 检查 Proxy 缓冲文件
ls -lh /tmp/zabbix_proxy.db
修复:
- 重启 Proxy: systemctl restart zabbix-proxy
- 检查 Proxy 与 Server 版本兼容性
- 增大 BufferSize(网络不稳定场景)
- 调整 DataSenderFrequency(减小 = 更频繁上报)
故障 5:时间不同步
现象:
- 历史数据时间错位
- 触发器评估异常(某些函数依赖 clock 排序)
- 趋势图显示异常
排查:
# 所有机器(Server/Agent/Proxy/DB)
timedatectl status
ntpq -pn
chronyc tracking
常见原因:
- NTP 服务未安装或未配置
- 虚拟机时钟漂移(尤其是 VMotion 后)
- 硬件 RTC 与系统时间偏差
修复:
- 配置统一的 NTP 源
- 启用 chrony / ntpd
- VM 场景启用 KVM clock=kvm
- 验证: ntpdate -q pool.ntp.org
故障 6:Web UI 慢/报错
现象:
- Dashboard 页面加载 > 10s
- PHP 报错(`PHP Fatal error: Allowed memory size exhausted`)
- PHP/DB 连接超时
排查:
# PHP 配置
php -i | grep memory_limit # 应 ≥ 256M
php -i | grep max_execution_time # 应 ≥ 300
# 慢查询
tail -100 /var/log/mysql/slow-query.log
修复:
- PHP memory_limit = 256M-512M
- PHP max_execution_time = 300
- PHP post_max_size = 32M
- 开启 PHP OPcache
- 检查 Web 前端与 Server 版本一致
- Dashboard 减少历史数据量(增加时间范围限制)
Zabbix 维护常用命令总结:
# Server 状态
systemctl status zabbix-server
# 获取内部指标
zabbix_get -s 127.0.0.1 -k zabbix[queue]
zabbix_get -s 127.0.0.1 -k 'zabbix[queue,5m]'
# 进程负载
zabbix_get -s 127.0.0.1 -k 'zabbix[process,poller,avg,busy]'
# 主动模式测试
zabbix_sender -z 127.0.0.1 -s "test-host" -k test.key -o 1
# 日志
journalctl -u zabbix-server -n 200 --no-pager
tail -f /var/log/zabbix/zabbix_server.log
# 数据库检查
mysql -e "SELECT COUNT(*) FROM proxy_history;"
mysql -e "SHOW ENGINE INNODB STATUS\G" | grep -A5 "HISTORY LIST"
# Housekeeper 监控
zabbix_get -s 127.0.0.1 -k zabbix[housekeeping,start_time]
zabbix_get -s 127.0.0.1 -k zabbix[housekeeping,count]