2.1 主机和服务范例
Nagios是一个优雅的程序,简洁易懂。它能够以用户期望的方式完成用户期望的工作,而且还能够进行扩展来做一些惊人的事情。在读者掌握一些基础内容之后,就有能力构建一套监控系统并深入研究了,对于那些扛着OpenView 重担的朋友而言,这才是一套梦寐以求的监控系统。
2.1.1 从头开始
如果读者想要了解Nagios本身及其用途,最简单的方式就是返回第1章中寻找讲述“治标不治本的系统监控方式”的段落。治标不治本的方式常常会出现,尤其是当系统管理员刚刚经历过一次重要服务或应用的故障之后。服务出现故障不可用时,管理员没有及时发现,直到客户或经理告诉他后才知道,这时管理员还没有意识到他所管理的系统已经出现了问题。系统管理员其实是非常主动的,所以在很久以前,我们的系统管理员就已经有一组脚本运行在他所管理的服务器上了。这些脚本能够检测很多对象的可用性。至少其中有一个看起来应该是这样的:
Ping -qc 5 server1 || (echo "server1 is down" | mail dude@domain.org)
上述Shell脚本将会向服务器1发送5个ICMP回显包,如果服务器1没有响应,脚本将会发送邮件通知系统管理员。这个脚本不错,清晰易懂,可以在某台服务器集中运行,并回答了一个重要的问题—服务器是否正常可用。但是,很快,就会有糟糕的事情发生。
某天,一台路由器出现故障,它位于系统管理员的工作站和服务器1到服务器40之间,忽然负责进行运行脚本的服务器无法连通这个网段了。这导致有40封不必要的邮件发送到了系统管理员的邮箱里,每一封的内容都是服务器无法Ping通。不久之后,其他的管理员以及一些经理也想得到一部分的通知,于是这位系统管理员建立了多个邮件列表组。但是其中一些人很快发现得到了重复的邮件—因为他们属于多个邮件列表,每个邮件列表都会收到相同的通知。几周之后,系统管理员在凌晨3点时收到了一封非关键的通知,但他决定早上起来后再进行修复工作,于是又继续睡觉了。但是当早上上班时,他完全忘记了这件事,所以在某位用户注意到并打电话之前,服务持续不可用。
这位系统管理员的想法是正确的,他在自己的能力范围内编写了一个脚本,以便有效地检测故障。他只是需要一种更智能的方式来运行脚本,而不是更好的脚本。他需要一套高效的调度和通知系统:能够对一堆小监控脚本的执行状况和结果进行跟踪,能够管理被监控对象组的依赖关系,提供通知升级功能,并确保无论人们的身份如何都不会收到重复的告警。简而言之,这些功能,就是Nagios。
Nagios是一个框架,无论用户的小监控程序是使用何种语言编写,都可以将它们完全托管到Nagios中。用户只需要配置很少的参数,Nagios就能够帮你调度那些小的监控程序(或插件),收集它们返回的状态,确保通知发送给正确的人,并根据规则按需升级。Nagios同时能够对所有插件的状态情况进行跟踪,记录状态改变的日期和时间,并内置了历史报告的功能。Nagios提供了很多挂钩(Hook),使数据的输入和输出都很方便,所以它能够向图形程序(比如RRDTool和MRTG)提供实时数据,并且能够很方便地与其他监控系统协作,无论是向上集成(输出数据)或是向下集成(接收数据)。
对我来说,Nagios最讨人喜欢的一点是它能够充分利用用户所擅长的技能(不论个人还是组织),并且不会将用户的努力付诸东流。如果你是一位TCL 的绝地武士,组织因为能力才会重视你,那么他们不应该忽视你的努力——你为了更好地集中化他们的监控工具而花了五个月时间研究一款基于TCL的监控平台。因为Nagios无意控制用户的监控方式,所以它不会驱使用户组织使用某些工具集,也不会强迫用户推倒重来。
2.1.2 主机和服务
我在本章前面提到过Nagios对用户想要监控的对象以及监控方式进行的一些假设。它允许你定义所有的对象,定义是Nagios工作机制赖以为生的东西。Nagios操作的所有元素都需要用户明确定义。比如,Nagios知道,当插件返回一个严重状态时,意味着事件发生,它应该发送一个通知,但是Nagios不知道“发送给某人”是什么意思。用户应当定义Nagios用于通知联系人的文本命令语法,而用户在进行这些定义时,应当以联系人、服务为基础逐个定义,或者同时定义。很多人使用邮件通知,但是用户将会发现Nagios已经预定义好了,可以直接通过它完成大多数的工作,所以用户无须定义所有对象,至少无须定义Nagios工作的机制。
Nagios对用户环境进行的大多数重要假设是关于主机和服务的,这是Nagios中两个最基础的对象类型。读者可能认为主机是一个物理实体,因为服务器和网络设备确实是最常见的主机类型,但是实际上,主机对象可以是任何通过TCP协议通信的东西:特定类型的环境传感器、我朋友Chris的冰箱等都属于主机类型。服务则是由主机提供的逻辑实体,对于平躺在机架中的Web服务器来说,运行于其上的守护进程就是一个服务。
通常,一台独立的主机会运行多个应用—至少有多个元素应当被监视,但是主机自身只会处于启动或是宕机状态,或者说是不是可用。因此,Nagios允许用户对每台主机定义唯一的主机检测机制以及多个服务检测。Nagios通过这些主机和服务检测的定义,对插件进行调用以获得主机或服务的状态。比如,服务器1的配置文件中,可能定义了插件check_ping作为主机检测。如果主机检测失败,意味着主机是不可用的。如果主机宕机,在这台主机上的所有服务也同样不可用,因此如果为主机上所有的服务都分别发送一条短信通知,听起来一定很傻。就算不通知,在主机恢复前对主机上所有的服务进行检测,也一样很傻。
对于主机/服务的假设使Nagios能够很容易地搞清楚服务与主机的依赖关系。当Nagios运行插件对某台主机上的某个服务进行检测时,如果插件返回了一个错误状态,Nagios首先就会对该主机进行检测。如果主机检测也返回了错误状态,则表示主机不可用,此时,Nagios只会通知用户主机宕机,同时推迟所有服务检测,直到主机可用为止。
2.1.3 相互依赖
其实,相互依赖的概念遍及Nagios。Nagios趋向于智能,不会浪费资源进行无意义的检测,比如明显不可用的主机和服务,在通知方面也一样。Nagios对于检查不同主机上服务之间的依赖关系,采取两种方式。
第一种是父子关系,只在主机定义中有效。每一个主机定义都可定义父节点,只需要设置parents参数。这种方式对于网络设备后的主机,如防火墙甚至虚拟化服务器,都会十分有效。如果主机1的父节点宕机,Nagios会认为主机1不可达,而非宕机,这对于力求高标准SLA的人来说,是个非常重要的区别。如果某台主机处于不可达状态,Nagios就不会操心这台主机的主机和服务检测了。然而,如果你希望在主机不可达的情况下发送通知,也是可以通过配置实现的。
第二种方式,是依赖关系的定义,通过此方式,Nagios可以跟踪主机之间依赖关系。这种定义对于主机和服务都有效,用于检查不同主机或运行于不同主机的服务之间更加细微的依赖关系。这种类型的依赖跟踪比较好的示例就是Web代理。在图2-1中,防火墙是预先配置的,所以只有安全网络中的一台主机允许访问Web服务器的80端口。而其他服务器必须通过这台主机的代理服务发送Web请求。Nagios也不例外,如果它想检测Web服务器80端口的状态,也必须同样通过代理服务器。因为Nagios对于其他类型的网络访问不依赖于Web代理服务器,所以父子关系并不适用,而需要建立的依赖关系是:Web服务器80端口的检测服务依赖于代理服务器的8080端口的检测服务。如果Web代理服务挂了,Nagios就不应该检测或通知Web服务的状态了,这才是依赖关系应该做的事情。
图2-1 Nagios使用依赖关系定义来检查相互依赖的服务
2.1.4 主机和服务的消极面
我认为,Nagios自身在对主机和服务范例的处理方式方面是个天才。这种方式简单易懂,不仅执行过程符合用户预期,而且管理方便。但是,主机和服务假设,在某种程度上限制了Nagios的功能。
为了说明这个问题,我以某大型企业或大学的邮件系统为例。这样一套系统由MX记录、边界邮件系统、内部中继服务器以及面向用户的群件(Groupware)组成。邮件系统内部的任一服务和主机的故障都会对整体产生影响,但是不一定导致完全不可用。如果某个MX记录出现问题,完全不会对邮件流程 产生任何影响,又如群件系统出现故障,系统依然能够通过MX记录发送邮件,但是可能用户无法进行邮件交互。
作为业务流程以及高层实体,诸如邮件,往往是由多台主机上的多个服务聚合而成,很难见到单台主机或服务的规模。Nagios为包含不同主机上独立的服务,提供了主机组和服务组。这样用户就能够创建一个名为邮件的服务组,其中汇总了企业邮件所依赖的每个服务的状态。但是,如果服务器1上的POP(邮局协议)协议不可用,对于外行而言该故障对整个邮件实体产生的影响不是很明显。
假设Nagios插件是用户定义的,并且在很多情况下,是由用户创建的—某位上进的管理员能够写出专用插件来逐个检测邮件系统的整体状态。但是在主机和服务范例中,插件所检测的服务应当属于那台主机呢?主机和服务的假设导致对大型实体建模有些困难,但只是有些困难,对于那些希望这样做的人而言,还是可以做到的。在后面的章节中,我会介绍一些结合业务流程使用已有检测插件的方法,其中包括Check_MK插件,Nagios XI中内置的业务流程视图以及其他可视化的选项。