PPTV的Zabbix监控体系
编者按:InfoQ开设新栏目“品味书香”,精选技术书籍的精彩章节,以及分享看完书留下的思考和收获,欢迎大家关注。本文节选自姚仁捷著《Zabbix监控系统深度实践》中的第23章“PPTV的Zabbix监控体系”,以PPTV的监控体系为例,给大家一个完整的实战说明。前半部分主要介绍PPTV基于Zabbix进行的二次开发,后半部分介绍Zabbix在整个监控体系中的角色和作用。
1 Python Zabbix API
在PPTV的运维开发团队,主要的开发语言是Python,因为Python入门简单,开发快速,而且是一个“电池都包括”的语言(表示Python的各种库应有尽有)。Zabbix虽然用起来不算困难,但都需要鼠标操作,没办法集成到命令行中。Zabbix本身提供了API接口,但是封装的不是很好,不是面向对象的建模,要记忆这么多方法也不容易。因此,笔者参照其他人开发的Zabbix API,用Python写了一个模块——ZabbixPythonApi。它的作用是在Zabbix API上根据Zabbix对象封装了一层,让我们在使用API的时候是基于对象的。Zabbix Python Api已经开源在Github上了,地址为:https://github.com/baniuyao/ZabbixPythonApi。这个API是基于Zabbix 1.8.8开发的,在Zabbix 2.2也可以运行。
使用起来很简单,首先需要引入我们的API模块:
from zapi import ZabbixAPI
接着是登录Zabbix:
zapi = ZabbixAPI(url='http://your.zabbix.address', user='admin', password='zabbix') zapi.login()
然后就是针对资源的操作,比如查找名字为“HostABC”的host:
zapi.Host.find({‘hostname’:’HostABCr’})
返回值如下:
[{ 'available': '1', 'disable_until': '0', 'error': u'', 'errors_from': '0', 'flags': '0', 'host': 'HostABC', 'hostid': '10108', 'ipmi_authtype': '-1', 'ipmi_available': '0', 'ipmi_disable_until': '0', 'ipmi_error': u'', 'ipmi_errors_from': '0', 'ipmi_password': u'', 'ipmi_privilege': '2', 'ipmi_username': u'', 'jmx_available': '0', 'jmx_disable_until': '0', 'jmx_error': u'', 'jmx_errors_from': '0', 'lastaccess': '0', 'maintenance_from': '0', 'maintenance_status': '0', 'maintenance_type': '0', 'maintenanceid': '0', 'maintenances': [], 'name': 'HostABC', 'proxy_hostid': '0', 'snmp_available': '0', 'snmp_disable_until': '0', 'snmp_error': u'', 'snmp_errors_from': '0', 'status': '1', 'templates': [{'hostid': '0', 'templateid': '0'}] }]
是不是返回的属性特别多?Zabbix API会返回这个搜索到的Host的所有属性。可以在find方法中加入一个参数,使得find方法只会得到一个指定的属性,如:
zapi.Host.find({'name':'HostABC'}, attr_name='hostid')
这样返回的就仅仅是搜索到的Host的“hostid”这个属性的值了:
['10108']
通过这个例子,大家应该能举一反三了吧。使用API时传递的参数(比如上面例子中的name),可以参考Zabbix的官方文档。
2 Spider——服务器添加Zabbix监控
使用监控系统最大的问题,就是添加监控。在PPTV使用Zabbix的初期,添加监控非常麻烦。需要根据服务器上面运行的应用程序,去添加对应的监控。比如运行了Reids则要增加对Redis的监控,运行了Nginx需要添加对Nginx的监控。一台服务器还可以手动操作,如果100台、1000台呢?而且,只要是人进行的操作,就是可能会出错的地方。
除了需要人力工作,容易出错外,手动添加服务器监控最大的问题就是无法和自动化运维的其他系统集成。理想的状态是一台服务器上线后,应该能自动添加监控;一台服务器下线,应该自动取消监控。很多公司应该使用的是类似“工单”的东西来进行流程上的控制,当服务器上线时,一张“添加监控工单”会发送给对应的运维工程师,然后运维工程师去进行操作。这一环,会变成整个自动化运维的瓶颈。
面对这种问题,Zabbix推出了auto discovery功能,它设计的初衷就是解决上面提到的自动添加监控的问题。它的设计非常好,但有一些局限,比如它不支持从进程去判断服务器上存活了什么应用,只能从Zabbix Server去侦测Zabbix Agent上运行了哪些端口,从而去判断运行了哪些程序。而且,自动侦测使用IP范围去探测服务器,这个粒度太粗了,很有可能会造成误操作。比如服务器下线这个动作,如果使用了自动侦测,它会一直侦测这个网段,那么这里就隐含了一个限制:删除监控会发生在服务器关机之后(我们使用Action来控制超过多久的服务器自动移除监控),这样就会产生误报警。假设监控了一台Nginx服务器,现在要下线了,那么确定流量切走以后,会关闭Nginx进程,然后关机。而Zabbix要在关机后才能删除监控,那么在关闭Nginx进程到关机的这段时间,Zabbix会认为Nginx进程已经消失了,这是个问题,会报警。而实际上,这个根本不需要报警。
基于这些需求,笔者开发了Spider,它的作用简单来说就是根据服务器的hostname,对运行的应用加入对应的监控,而需要的只是一个IP。Spider界面如图所示。
3 Event Console
在查看报警时,Zabbix做得不是很好。一是每一个报警的维度很少,只能看某个服务器的某个报警,顶多加上一个报警的等级。另外展示报警的方式也不好,不能让人很好地发现问题。而且,虽然Zabbix有ACK功能,但太过简陋,它只能知道某个人在什么时候ACK了这个请求。
在PPTV时,除了上海的兄弟们,武汉还有24小时值班的工程师,他们一般是第一个接收到Zabbix报警的人,他们希望在接收到报警后,对于简单的问题可以直接远程执行命令,或者自动恢复,比如重启PHP进程之类。
基于这些需求,我们开发了EventConsole平台。它可以展示报警,处理报警。在上面运维工程师可以很方便地看到目前发生了什么问题,以及紧急程度有多高。界面如图所示。
4 Rule Engine
Rule Engine是PPTV报警系统的核心部分。它的作用是根据Zabbix中Action的信息,组织报警数据,进行发送邮件给对应负责人,将报警推送到EventConsole,自动执行一些命令,收集出问题时刻的服务器数据等操作。
为什么要开发Rule Engine?使用Action来发送邮件不是挺好的吗?Zabbix支持很多宏,可以在报警邮件中发送很多东西。我们先撇开Zabbix,想象一下,如果你收到一封报警,你最希望里面有些什么内容。以我个人来说,我想看到出问题时这台服务器的一些基本系统数据,比如CPU负载、内存、哪些进程在跑等。我还想知道出问题的这个监控点的历史数据是怎样的。如果能根据报警内容的不同,事先做一些分析,那是更好的。
Rule Engine就是为了满足这些需求而设计的。Zabbix的Action不再发送邮件,而是将必要的信息,比如itemid、triggerid等传递到后端的rule_engine_agent,rule_engine_agent将这条消息发送到ActiveMQ,然后rule_engine从ActiveMQ拿到消息,根据报警的类型,去组合不同的报警信息。比如报警内容为Linux服务器内存不够了,那么就需要内存使用的排行;如果报警是磁盘I/O高,那么就需要消耗I/O的排行。当组合好这个报警信息后,一是要发送邮件给对应的运维和研发,二是将消息发送到Event Console。
在这个处理过程中,在发送报警邮件和发送消息给Event Console之前,会访问一个叫做Snooze Console的系统,来确定这个报警是否需要发送。“Snooze”操作的作用就是停止某一类报警一段时间。
5 报警系统架构
图示是整个报警系统的架构。报警的消息从触发Action开始,将需要的信息(比如itemid,triggerid等)发送给Rule Agent,Rule Agent将消息转发到ActiveMQ。Rule Engine会从ActiveMQ中抓取消息,从Snooze Console中查询这个报警是否需要处理,再根据报警的类型进
行不同的处理,组合不同的邮件内容,发送邮件或者短信。然后把这个报警消息发给ActiveMQ。之后,Event Console会从ActiveMQ获取消息,显示在Event Console的前端界面中。