一、为什么要做Nagios配置自动化

很多运维朋友刚接触Nagios的时候,都会被它的配置搞到头大。Nagios是用来监控服务器、服务状态的工具,比如你要监控10台服务器的CPU、内存,还要监控3台数据库的端口、进程,就得手动在Nagios的配置文件里写对应的主机定义、服务定义,还要把主机分到不同的组里,比如分成“生产服务器组”“测试服务器组”。要是服务器少还好,几十上百台的话,手动写配置不仅慢,还容易写错——比如IP地址输错、服务名拼错,最后监控不生效不说,排查问题还得花半天。

更麻烦的是,公司的服务器是动态变化的:今天加了2台测试服务器,明天有3台生产服务器下线,后天要给某个业务线加新的监控服务,每次都要改配置,改完还得重启Nagios才能生效,效率低得要命。所以,把Nagios的配置做成自动化,是很多运维团队的刚需。而Ansible作为常用的自动化工具,能帮我们实现“动态生成配置”的需求,不用再手动敲代码。

二、核心思路:Ansible如何实现Nagios配置自动化

要实现自动化,核心是把“静态的配置”变成“动态生成的配置”。简单来说,我们可以把所有需要监控的主机信息(比如IP、所属分组、监控的服务)存到一个固定的地方,比如Ansible的清单文件(Inventory)或者一个配置表,然后用Ansible的模板功能,把这些信息自动填充到Nagios的配置文件里,最后推送到Nagios服务器上,重启服务生效。

举个例子,原来我们手动写Nagios的主机配置,是这样的:

define host {
    use                     linux-server
    host_name               test-server-01
    alias                   测试服务器01
    address                 192.168.1.10
    hostgroups              test-servers
}

如果有10台服务器,就得写10遍这样的代码,改来改去很麻烦。而用Ansible的话,我们只需要写一个模板,把主机的IP、名称、分组这些变量留出来,Ansible会自动把所有主机的信息填进去,生成10段对应的配置,不用我们手动写。

2.1 用到的核心Ansible功能

这里先给大家介绍两个Ansible里最核心的功能,也是实现这个自动化工作流的基础: 第一个是Ansible清单(Inventory),它是用来管理所有主机信息的地方,我们可以把主机的IP、所属分组、自定义变量(比如要监控的服务列表)都写在这里,相当于一个主机信息的数据库。 第二个是Ansible模板(Template),它是一个带变量的文本文件,后缀是.j2,Ansible会读取模板里的变量,替换成实际的值,生成最终的配置文件。

三、完整工作流搭建(含详细示例)

接下来我们就一步步搭建这个自动化工作流,所有示例统一使用技术栈:Ansible + Nagios Core,全程用生活化的语言讲,大家跟着做就能实现。

3.1 准备工作

首先要确保你的环境里已经装好了两个东西:一个是Ansible(装在你用来做自动化的控制机上,比如你的笔记本或者一台专门的运维服务器),另一个是Nagios Core(装在你的监控服务器上,用来接收配置、执行监控)。安装方法很简单,Ansible可以用pip install ansible或者系统包管理工具装,Nagios Core可以从官网下载安装包,或者用yum/apt装。

装完之后,我们先确认一下:控制机能通过SSH连接到Nagios服务器,权限足够(比如能修改Nagios的配置文件、重启Nagios服务)。

3.2 步骤1:编写Ansible清单(Inventory)

清单是我们所有主机信息的来源,我们可以把需要监控的主机分成不同的组,比如生产服务器组、测试服务器组,每个组里的主机有自己的IP、名称、要监控的服务。

我们新建一个inventory.ini文件,内容如下,这里的注释都标清楚了:

# 清单文件:所有需要监控的主机信息
# 测试服务器组
[test-servers]
test-server-01 ansible_host=192.168.1.10 host_name=test-server-01 alias=测试服务器01
test-server-02 ansible_host=192.168.1.11 host_name=test-server-02 alias=测试服务器02

# 生产服务器组
[prod-servers]
prod-server-01 ansible_host=192.168.1.20 host_name=prod-server-01 alias=生产服务器01
prod-server-02 ansible_host=192.168.1.21 host_name=prod-server-02 alias=生产服务器02
prod-server-03 ansible_host=192.168.1.22 host_name=prod-server-03 alias=生产服务器03

# 组变量:每个组要监控的服务,这里用数组存服务列表
[test-servers:vars]
# 测试服务器要监控的服务:CPU、内存、磁盘、SSH端口
services=[{"service_name":"check_cpu","description":"CPU使用率","check_command":"check_nrpe!check_cpu"},
          {"service_name":"check_memory","description":"内存使用率","check_command":"check_nrpe!check_memory"},
          {"service_name":"check_disk","description":"磁盘使用率","check_command":"check_nrpe!check_disk"},
          {"service_name":"check_ssh","description":"SSH端口","check_command":"check_ssh"}]

[prod-servers:vars]
# 生产服务器要监控的服务:比测试多了数据库端口、进程
services=[{"service_name":"check_cpu","description":"CPU使用率","check_command":"check_nrpe!check_cpu"},
          {"service_name":"check_memory","description":"内存使用率","check_command":"check_nrpe!check_memory"},
          {"service_name":"check_disk","description":"磁盘使用率","check_command":"check_nrpe!check_disk"},
          {"service_name":"check_ssh","description":"SSH端口","check_command":"check_ssh"},
          {"service_name":"check_mysql_port","description":"MySQL端口","check_command":"check_tcp!3306"},
          {"service_name":"check_mysql_process","description":"MySQL进程","check_command":"check_nrpe!check_mysql_process"}]

这个清单里,我们把主机分成了test-servers和prod-servers两个组,每个主机都有IP(ansible_host)、主机名(host_name)、别名(alias),组变量里定义了每个组要监控的服务,服务的名称、描述、检查命令都写清楚了,这样Ansible就能知道每个组的主机要监控什么。

3.3 步骤2:编写Ansible模板(Template)

模板是用来生成Nagios配置文件的核心,我们要写两个模板:一个是主机组配置模板,用来生成所有主机的定义;另一个是服务配置模板,用来生成所有服务的定义。

首先新建主机模板文件hosts.cfg.j2,内容如下:

# Ansible自动生成的主机配置,请勿手动修改
# 测试服务器组主机定义
{% for host in groups['test-servers'] %}
define host {
    use                     linux-server  # 继承Nagios自带的linux模板
    host_name               {{ hostvars[host].host_name }}  # 主机名,从清单读取
    alias                   {{ hostvars[host].alias }}  # 别名,从清单读取
    address                 {{ hostvars[host].ansible_host }}  # IP地址,从清单读取
    hostgroups              test-servers  # 所属主机组
}
{% endfor %}

# 生产服务器组主机定义
{% for host in groups['prod-servers'] %}
define host {
    use                     linux-server
    host_name               {{ hostvars[host].host_name }}
    alias                   {{ hostvars[host].alias }}
    address                 {{ hostvars[host].ansible_host }}
    hostgroups              prod-servers
}
{% endfor %}

这个模板里,用{% for ... %}循环把test-servers和prod-servers组里的所有主机都遍历一遍,把每个主机的host_name、alias、ansible_host这些变量替换成实际的值,生成对应的主机定义。

然后新建服务模板文件services.cfg.j2,内容如下:

# Ansible自动生成的服务配置,请勿手动修改
# 测试服务器组服务定义
{% for host in groups['test-servers'] %}
{% for service in hostvars[host].services %}
define service {
    use                     generic-service  # 继承Nagios自带的服务模板
    host_name               {{ hostvars[host].host_name }}  # 所属主机
    service_description     {{ service.description }}  # 服务描述
    check_command           {{ service.check_command }}  # 检查命令
}
{% endfor %}
{% endfor %}

# 生产服务器组服务定义
{% for host in groups['prod-servers'] %}
{% for service in hostvars[host].services %}
define service {
    use                     generic-service
    host_name               {{ hostvars[host].host_name }}
    service_description     {{ service.description }}
    check_command           {{ service.check_command }}
}
{% endfor %}
{% endfor %}

这个模板里,先循环每个组的主机,再循环每个主机的services数组,把每个服务的描述、检查命令替换成实际的值,生成对应的服务定义。

3.4 步骤3:编写Ansible Playbook

Playbook是Ansible的执行脚本,用来告诉Ansible要做什么:先把模板生成的配置文件推送到Nagios服务器,然后重启Nagios服务生效。

新建playbook.yml文件,内容如下:

# Ansible Playbook:自动生成并推送Nagios配置
- name: 生成Nagios主机和服务配置
  hosts: nagios_server  # 目标主机是Nagios服务器
  become: yes  # 用root权限执行
  vars:
    # Nagios配置文件的路径,根据自己的安装路径修改
    nagios_config_path: /usr/local/nagios/etc/objects

  tasks:
    # 任务1:生成主机配置文件
    - name: 生成主机配置文件
      template:
        src: hosts.cfg.j2  # 模板文件路径
        dest: "{{ nagios_config_path }}/hosts.cfg"  # 生成后的配置文件路径
        mode: 0644  # 配置文件的权限

    # 任务2:生成服务配置文件
    - name: 生成服务配置文件
      template:
        src: services.cfg.j2
        dest: "{{ nagios_config_path }}/services.cfg"
        mode: 0644

    # 任务3:重启Nagios服务,让配置生效
    - name: 重启Nagios服务
      systemd:
        name: nagios
        state: restarted
        enabled: yes

这个Playbook的逻辑很简单:先连接到Nagios服务器,然后用template模块把两个模板生成对应的配置文件,推送到Nagios的配置目录,最后重启Nagios服务。

3.5 步骤4:执行自动化流程

所有文件都写好之后,我们只需要在控制机上执行一条命令,就能完成整个自动化流程:

# 执行Playbook,指定清单文件
ansible-playbook -i inventory.ini playbook.yml

执行完之后,我们可以登录到Nagios服务器,查看/usr/local/nagios/etc/objects/目录下的hosts.cfg和services.cfg文件,就能看到所有自动生成的配置了,Nagios也会自动开始监控这些主机和服务。

如果后续要加新的主机或者服务,只需要修改inventory.ini文件,再加一条主机信息或者修改services数组,然后重新执行一遍上面的命令,新的配置就会自动生成并生效,不用再手动改任何配置文件。

四、应用场景分析

这个自动化工作流的应用场景非常广,只要是需要用Nagios做监控的团队,都可以用:

  1. 多环境监控:比如公司有测试、开发、生产多个环境,每个环境有几十上百台服务器,用这个工作流可以快速给每个环境生成对应的监控配置,不用手动区分。
  2. 动态扩容场景:比如电商公司大促前要加一批临时的服务器,大促后下线,用这个工作流可以快速把新服务器加进监控,下线后从监控里移除,不用手动改配置。
  3. 多业务线监控:比如公司有多个业务线,每个业务线有自己的服务器和监控需求,用这个工作流可以给每个业务线单独定义主机组和服务,生成对应的配置。

五、技术优缺点分析

5.1 优点

  1. 效率高:原来手动写配置可能要花几个小时,现在改完清单执行一条命令就搞定,大大节省了时间。
  2. 不容易出错:所有配置都是从清单自动生成的,避免了手动输错IP、服务名的问题。
  3. 可维护性强:所有主机和服务的信息都集中在清单文件里,改起来很方便,配置文件是自动生成的,不用怕手动改乱。
  4. 扩展性好:如果要加新的主机组、新的服务,只需要修改清单和模板,不用改核心流程。

5.2 缺点

  1. 初期学习成本:需要先了解Ansible的基本用法,比如清单、模板、Playbook,对完全没接触过Ansible的人来说,要花点时间学习。
  2. 依赖清单的准确性:如果清单里的主机信息写错了,生成的配置也会错,所以要确保清单的正确性。
  3. 复杂场景的适配:如果监控的服务非常复杂,比如需要自定义很多参数,模板可能会写得比较复杂,需要花时间调整。

六、注意事项

  1. 权限问题:Ansible连接Nagios服务器的用户,要有修改Nagios配置文件和重启Nagios服务的权限,最好用root用户,或者给普通用户加sudo权限。
  2. 配置路径:不同的Nagios安装方式,配置文件的路径可能不一样,比如用yum装的Nagios,路径可能是/etc/nagios/,要根据自己的实际情况修改Playbook里的nagios_config_path变量。
  3. 服务名称和命令:清单里的服务名称和检查命令,要和Nagios里定义的一致,比如check_cpu、check_memory这些命令,要在Nagios的commands.cfg里已经定义好,不然监控会不生效。
  4. 模板的维护:如果要加新的服务或者新的参数,要修改模板,改完之后要测试一下,确保生成的配置是正确的。
  5. 版本兼容:要确保Ansible的版本和Nagios的版本兼容,一般来说,新版本的Ansible和Nagios Core都能兼容,不用太担心,但如果是很老的版本,可能会有问题。

七、文章总结

Nagios配置自动化,本质上是把原来的“手动写配置”变成“自动生成配置”,用Ansible的清单管理主机信息,用模板生成配置文件,用Playbook完成推送和重启,整个流程简单易上手,能大大提高运维的效率,减少出错的概率。

这个工作流的核心是“分离配置和模板”,把所有变化的信息(比如主机IP、服务列表)放在清单里,把不变的配置结构放在模板里,这样不管主机和服务怎么变,只需要改清单,就能自动生成正确的配置。

对于中小团队来说,这个工作流完全能满足日常的监控需求,不用复杂的工具,只用Ansible就能实现;对于大团队来说,还可以在这个基础上扩展,比如把清单和CMDB(配置管理数据库)对接,实现更复杂的动态配置。