一、迁移前的核心痛点拆解

很多运维同学都有过换监控系统的经历,从Zabbix换到Nagios不是简单换个工具,这里面藏着不少容易踩的坑。我去年帮一家做电商代运营的公司做过迁移,踩过的坑整理成了三个核心痛点,先给大家拆明白。

1.1 监控逻辑的底层差异

Zabbix是偏主动拉取+被动推送结合的,它自带的模板能批量套,比如给10台服务器加CPU监控,改个模板就能全生效;但Nagios的逻辑完全反过来,它是被动接收,所有监控规则都是基于“检查项”来的,得自己写检查脚本,没有批量套模板的原生能力。举个最常见的例子,Zabbix里给10台服务器加内存监控,只需要把“内存使用率”的触发器设成“超过80%报警”,再把这个模板关联给10台机器就行;但Nagios得先写一个检查内存的脚本,再给每台机器单独加这个检查项,哪怕10台机器的检查规则完全一样,也得重复操作10次。

1.2 历史数据的兼容难题

Zabbix的历史数据存在自己的数据库里,比如MySQL,存的是带时间戳的数值,格式是固定的;但Nagios的历史数据是存在它自己的“状态数据库”里,而且默认只存7天,还不支持直接导入Zabbix的格式。我当时帮那家电商公司迁移时,他们有近2年的服务器历史数据,要用来做年度性能分析,要是直接丢了,年度报告根本没法写,这也是最头疼的痛点。

1.3 业务场景的映射混乱

Zabbix能把不同的监控项组合成“主机组”“应用集”,比如把“订单服务器”“支付服务器”归成“核心业务组”,能直接看这个组的整体状态;但Nagios没有原生的“业务组”概念,它的“主机组”只是机器的分类,不能把不同机器的监控项组合起来看整体状态。比如那家电商公司原来用Zabbix的业务组看“核心业务可用性”,迁移到Nagios后,这个功能直接没了,得自己想办法补。

二、历史数据保留的适配方案

解决了痛点,先解决最核心的历史数据问题,我当时用的是“数据转换+双系统并行”的方案,具体步骤很细,给大家拆成两步。

2.1 数据格式转换的具体实现

首先得把Zabbix的历史数据转成Nagios能识别的格式,这里要用到两个工具:一个是Zabbix自带的“历史数据导出脚本”,另一个是自己写的转换脚本。先给大家放具体的脚本,这里用的是Shell脚本,因为运维同学对Shell最熟。

# 第一步:从Zabbix的MySQL数据库导出历史数据
# 先进入Zabbix的容器或者服务器,导出指定时间范围的历史数据,比如2022年1月到2023年12月的CPU使用率数据
mysql -u zabbix -pZabbix@2024 -D zabbix -e "
SELECT itemid, clock, value 
FROM history_uint 
WHERE itemid = 10012 -- 这个是Zabbix里CPU使用率监控项的ID,要提前查好
AND clock BETWEEN UNIX_TIMESTAMP('2022-01-01 00:00:00') AND UNIX_TIMESTAMP('2023-12-31 23:59:59')
INTO OUTFILE '/tmp/zabbix_cpu_history.csv' 
FIELDS TERMINATED BY ',' 
LINES TERMINATED BY '\n';
"

# 第二步:转换格式,把Zabbix的itemid转成Nagios的检查项名称,把UNIX时间戳转成可读时间
# 这里是自己写的转换脚本,保存成zabbix2nagios.sh
#!/bin/bash
# 读取Zabbix导出的CSV文件
while IFS=',' read -r itemid clock value; do
  # 把itemid替换成Nagios的检查项名称,比如原来的itemid=10012对应Nagios的check_cpu_usage
  check_name="check_cpu_usage"
  # 把UNIX时间戳转成YYYY-MM-DD HH:MM:SS格式
  date_str=$(date -d "@$clock" "+%Y-%m-%d %H:%M:%S")
  # 输出Nagios能识别的格式:检查项名称,时间,数值
  echo "$check_name,$date_str,$value" >> /tmp/nagios_history.csv
done < /tmp/zabbix_cpu_history.csv

这里要注意一个细节:Zabbix的itemid是唯一的,每台机器的同一个监控项的itemid不一样,所以转换的时候要提前把每台机器的itemid和Nagios的检查项对应好,比如“订单服务器1的CPU监控项”对应的Nagios检查项是“check_cpu_usage_order1”,不能搞混。

2.2 数据导入的验证

转换完的CSV文件,怎么导入Nagios?其实Nagios没有原生的导入历史数据的功能,所以我们用的是“扩展插件”的方式,把转换后的数据存到Nagios的状态数据库里。这里要用到Nagios的“状态历史表”的结构,先给大家看Nagios状态历史表的结构:

CREATE TABLE statehistory (
  statehistory_id INT NOT NULL AUTO_INCREMENT,
  host_name VARCHAR(255) NOT NULL,
  service_description VARCHAR(255) NOT NULL,
  state INT NOT NULL,
  state_time DATETIME NOT NULL,
  PRIMARY KEY (statehistory_id)
);

然后我们写一个导入脚本,把转换后的CSV数据插入到这个表里:

# 把转换后的Nagios历史数据导入到Nagios的状态数据库
mysql -u nagios -pNagios@2024 -D nagios -e "
LOAD DATA INFILE '/tmp/nagios_history.csv'
INTO TABLE statehistory
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
(host_name, service_description, state, state_time)
SET state = value; -- 这里把value赋值给state,因为CPU使用率的数值对应state的数值
"

导入完之后,要验证数据对不对,比如查一下2022年1月1日的CPU数据是不是和Zabbix里的一致,避免出现时间戳转换错的问题。

三、业务场景映射的适配方案

解决了历史数据,接下来是业务场景的映射,这部分要结合具体的业务需求来做,不能一概而论。

3.1 核心业务可用性的映射

那家电商公司原来用Zabbix的业务组看“核心业务可用性”,这个业务组包含了订单服务器、支付服务器、商品服务器的所有监控项,整体可用性低于99.9%就报警。迁移到Nagios后,我们用的是“Nagios插件+自定义业务检查”的方案,具体来说,就是写一个自定义的检查脚本,把核心业务的所有检查项的状态汇总起来,计算整体可用性。 给大家看这个自定义脚本的代码,用的是Shell脚本:

#!/bin/bash
# 自定义核心业务可用性检查脚本,保存成check_business_availability.sh
# 检查订单服务器的CPU、内存、磁盘状态
order1_cpu=$(nagios_status_query --host order1 --service check_cpu_usage_order1)
order1_mem=$(nagios_status_query --host order1 --service check_mem_usage_order1)
order1_disk=$(nagios_status_query --host order1 --service check_disk_usage_order1)

# 检查支付服务器的CPU、内存、磁盘状态
pay1_cpu=$(nagios_status_query --host pay1 --service check_cpu_usage_pay1)
pay1_mem=$(nagios_status_query --host pay1 --service check_mem_usage_pay1)
pay1_disk=$(nagios_status_query --host pay1 --service check_disk_usage_pay1)

# 检查商品服务器的CPU、内存、磁盘状态
goods1_cpu=$(nagios_status_query --host goods1 --service check_cpu_usage_goods1)
goods1_mem=$(nagios_status_query --host goods1 --service check_mem_usage_goods1)
goods1_disk=$(nagios_status_query --host goods1 --service check_disk_usage_goods1)

# 计算整体可用性:所有检查项正常的数量 / 总检查项数量
total_checks=9
normal_checks=0

# 统计正常的检查项数量
for status in $order1_cpu $order1_mem $order1_disk $pay1_cpu $pay1_mem $pay1_disk $goods1_cpu $goods1_mem $goods1_disk; do
  if [ $status -eq 0 ]; then # 0代表正常,1代表警告,2代表严重
    normal_checks=$((normal_checks + 1))
  fi
done

# 计算可用性百分比
availability=$(echo "scale=2; $normal_checks / $total_checks * 100" | bc)

# 输出结果,符合Nagios的检查结果格式:状态码 输出信息
if (( $(echo "$availability < 99.9" | bc -l) )); then
  echo "CRITICAL: 核心业务可用性为 $availability%,低于99.9%"
  exit 2
elif (( $(echo "$availability < 99.95" | bc -l) )); then
  echo "WARNING: 核心业务可用性为 $availability%,低于99.95%"
  exit 1
else
  echo "OK: 核心业务可用性为 $availability%,正常"
  exit 0
fi

这个脚本的逻辑很简单:先获取所有核心业务的检查项状态,然后统计正常的数量,计算整体可用性,最后输出符合Nagios要求的结果。写完之后,把这个脚本加到Nagios的检查项里,就能实现原来的“核心业务可用性”的功能了。

3.2 批量监控的映射

原来Zabbix能批量给服务器加监控项,Nagios没有原生的批量功能,我们用的是“配置文件模板+变量替换”的方案。具体来说,就是先写一个通用的配置模板,然后用变量替换的方式,给每台服务器生成对应的配置文件。 给大家看配置模板的代码,用的是Nagios的配置格式:

# 通用服务器监控配置模板,保存成server_template.cfg
define host {
  use                     linux-server
  host_name               $HOST_NAME$
  alias                   $HOST_ALIAS$
  address                 $HOST_IP$
}

define service {
  use                     generic-service
  host_name               $HOST_NAME$
  service_description     CPU Usage
  check_command           check_cpu_usage!80!90
}

define service {
  use                     generic-service
  host_name               $HOST_NAME$
  service_description     Memory Usage
  check_command           check_mem_usage!80!90
}

然后写一个变量替换的脚本,把模板里的变量替换成每台服务器的具体信息,生成对应的配置文件:

#!/bin/bash
# 变量替换脚本,保存成generate_config.sh
# 服务器列表,每一行是“主机名,别名,IP”
servers=(
  "order1,订单服务器1,192.168.1.10"
  "pay1,支付服务器1,192.168.1.11"
  "goods1,商品服务器1,192.168.1.12"
)

# 遍历服务器列表,生成配置文件
for server in "${servers[@]}"; do
  IFS=',' read -r host_name host_alias host_ip <<< "$server"
  # 替换模板里的变量
  sed -e "s/\$HOST_NAME\$/$host_name/g" \
      -e "s/\$HOST_ALIAS\$/$host_alias/g" \
      -e "s/\$HOST_IP\$/$host_ip/g" \
      server_template.cfg > /tmp/${host_name}_config.cfg
done

这个脚本的逻辑很简单:先把所有服务器的信息存在一个数组里,然后遍历数组,用sed命令把模板里的变量替换成每台服务器的具体信息,生成对应的配置文件。生成完之后,把这些配置文件加到Nagios的配置目录里,就能实现批量监控的功能了。

四、迁移的应用场景、优缺点、注意事项

4.1 应用场景

不是所有公司都适合从Zabbix换到Nagios,我总结了几个适合的场景: 第一个是“需要深度定制监控逻辑的场景”,比如有些公司的业务逻辑很特殊,需要自己写很多复杂的检查脚本,Nagios的灵活性比Zabbix高,能满足这种需求;第二个是“对监控性能要求极高的场景”,比如有些公司有几千台甚至几万台服务器,Zabbix的主动拉取逻辑会占用很多带宽,Nagios的被动接收逻辑占用的带宽少,性能更好;第三个是“已经有成熟的Nagios生态的场景”,比如有些公司已经用Nagios插件、Nagios的告警系统很久了,换成Zabbix反而要重新适配,成本更高。

4.2 技术优缺点

先说说从Zabbix换到Nagios的优点:第一是灵活性高,能自己写复杂的检查脚本,定制监控逻辑;第二是性能好,被动接收的逻辑占用的带宽和资源少,适合大规模监控;第三是配置简单,Nagios的配置文件是纯文本的,容易修改和管理。 再说说缺点:第一是没有原生的批量监控功能,需要自己写脚本实现;第二是历史数据管理麻烦,默认只存7天,导入和维护历史数据的成本高;第三是没有原生的业务组功能,需要自己写脚本实现业务场景的映射。

4.3 注意事项

迁移的时候有几个细节要注意:第一是“双系统并行验证”,迁移前要把Zabbix和Nagios同时运行至少1个月,对比两个系统的监控数据,确保Nagios的监控逻辑是对的,避免出现漏报警或者误报警的情况;第二是“监控项的阈值对齐”,迁移的时候要把Zabbix里的监控项阈值(比如CPU使用率超过80%报警)同步到Nagios里,不能改,避免出现报警逻辑不一致的情况;第三是“历史数据的备份”,迁移前要把Zabbix的历史数据备份好,避免转换的时候出现数据丢失的情况。

五、迁移总结

从Zabbix迁移到Nagios,核心是解决三个问题:监控逻辑的差异、历史数据的兼容、业务场景的映射。历史数据的保留可以用“数据转换+双系统并行”的方案,业务场景的映射可以用“自定义检查脚本+配置模板”的方案。迁移的时候要根据自己公司的实际情况,选择适合的方案,不要盲目照搬别人的经验。 最后要提醒大家,迁移不是为了换工具而换工具,而是为了满足业务的需求,比如如果你的公司对监控性能要求不高,Zabbix已经能满足需求,就没必要换Nagios;如果你的公司需要深度定制监控逻辑,Nagios的灵活性能满足需求,再考虑迁移。