(原文地址:https://blog.goquxiao.com/posts/2015/02/17/ji-yu-zabbix-dockerkai-fa-de-jian-kong-xi-tong/)php
团队所开发的持续监测网站/APP的产品,须要有一项监控功能,具体来讲就是,对URL/域名进行周期性(小于1分钟)监测,而且能对异常事件进行实时告警。在最近这几个月,我一直将大部分时间和精力花在了设计开发这套系统上面,一共经历了两个大版本。下文就对这套监控系统进行介绍,分享给你们。前端
本身以前没有这类系统的开发设计经验,因而问了下周围同事。和同事讨论的结果是:既然如今人手不够(就我一我的),我以前也没开发过这类系统,时间又比较紧迫(领导给的排期是“越快越好”……),那么找一个已有的开源监控系统进行二次开发,应该是一个不错的选择。那么,选择哪一种开源监控系统呢?根据同事以往的经验,能够考虑zabbix,本身也调研过一段时间zabbix,它的优势有以下几条:docker
架构简单、清晰数据库
文档丰富,代码注释十分详细express
agent/server部署方便编程
包含整套监控流程:包括采集、触发、告警后端
agent支持用户自定义监控项服务器
触发器表达式丰富网络
暴露了一套HTTP + JSON的接口架构
另外,除了以上这样,还有一个比较重要的一个缘由:团队中的同事以前也调研过zabbix。在人手不足、时间又紧的状况下,这一个因素的权重就显得相对较高。因此,最终选择了在zabbix基础上进行二次开发。
至于使用docker,是考虑到监控的对象,会由于用户的增加、以及用户的操做,有动态的变化。做为设计者,天然但愿有一种机制,可以可编程地、动态地控制zabbix agent的数量。咱们既不让某一个agent(具体应该是agent的端口)有过多的监控项,致使监控项没法在一个周期内完成数据采集;又不想有生成过多的agent,形成系统资源的浪费。目前势头正劲的docker,怎能不进入个人视野?社区活跃、文档完善、相对其余虚拟化技术又很轻,都成为了我选择docker的缘由。
这个监控系统的设计目标是:但愿可以提供秒级时间粒度的监控服务,实时监控用户网页的可用性指标,作到快速反馈。
具体的需求为:当用户在咱们的产品中建立持续监测任务,对于用户输入的URL进行两种类型的监控,即HTTP返回码以及PING返回时间。当某一类监控的采样数据异常时——例如HTTP返回500、PING超时——就会在用户界面上返回告警事件,用以提醒用户;采样数据正常时,再返回告警事件的状态。
第一个版本中,系统的设计特色为:
一台物理服务器对应一个zabbix的host
监控项使用被动采集方式
每一个zabbix agent处于一个docker container内,每生成一个container,就在物理机上面开放一个端口,并生成一个对应的zabbix agent interface
对于上游的每一个监控任务,会在每一个IDC节点各生成了一组zabbix采集监控任务,具体对应关系为:(groupid, hostid, interfaceid, itemid, triggerid)
告警事件的生成,采用了轮询trigger状态的方式,当上游监控任务对应的处于PROBLEM状态的节点数大于总节点数时,产生告警事件;当全部节点均为OK状态时,产生告警恢复事件
第一个版本的架构,以下图所示:
Monitor Web
模块,做为后端的接口供前端来调用,主要提供监测任务添加、修改、删除,告警事件列表返回、告警事件删除等功能。Monitor Syncer
模块,用于按期检查每一个监测任务对应的zabbix trigger的状态,根据trigger的状态,来生成告警事件以及告警恢复事件。Zabbix Server
和Zabbix Agent
就构成了监控系统的核心服务。其中,一台物理机器中,包含了多个Docker container,每一个container中运行这一个zabbix agent。
以建立监控任务为例,当前端发出建立监测任务时,Monitor Web
模块接收到该请求,进行以下操做:
在每个IDC(对于zabbix中的group)中,各建立一个container,在container中启动zabbix agent,记录其对外开放的端口
根据获得的端口,在zabbix host中,建立zabbix interface(和agent的端口一一对应)
根据获得的interface,建立HTTP和PING两种类型的zabbix item和trigger,分别监控URL的HTTP返回码,以及host的PING返回值。zabbix server开始进行数据采集和监控
在业务数据库表中添加该条监测任务记录
Monitor Syncer
每隔一个周期(30s),扫描一遍目前全部监测任务,再从zabbix数据库中查找到对应trigger的状态。若是trigger状态为PROBLEM的超过了半数,那么该监控任务就处于了告警状态,最后再根据该任务目前是否处于告警状态,来决定是否须要添加告警事件;那么对应的,若是trigger状态均为OK,而且目前任务处于告警状态,那么则须要为告警事件添加对应的恢复状态。
这样,就完成了添加任务 -> 告警 -> 恢复的整个监控系统的典型流程。
对第一个版本进行了性能测试,获得了如下性能指标:
(3台服务器,1台部署Zabbix Server,2台部署Docker + Zabbix Agent。服务器配置:Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz X 24,128G 内存,千兆网卡)
样本采集项:1111 item
样本采集频率:60s
最大入口流量: 68 kbps
最大出口流量: 270 kbps
每秒下发采集请求: ~19 qps
由于开发时间所限,以及对于新技术的调研不够深刻,第一个版本有很多不足,主要体现以下:
zabbix agent采用的是被动模式,每次采集数据zabbix server都须要向zabbix agent查询监控项,网络出口数据量较大
因为数据采集都是进行须要发起网络操做,而每一个采集数据的频率又较高,所以会出现数据采集不完整、没法连续采集的现象
采用轮询方式探测故障事件,效率较低,实时性不高,同时也有单点问题
任务请求没有进行持久化,若是由于模块问题而丢失或操做失败,没法回滚
针对初版本发现的问题,在设计上作了一些升级,具体升级点和设计上面的特色以下:
再也不采用物理机器和Zabbix Host一一对应的关系,而是采用Docker container和Zabbix Host一一对应(这里的Zabbix Host就是一个虚拟Host的概念)
采用etcd进行分布式状态管理,动态自主注册Zabbix Host
采集项使用Agent自主上传方式
Zabbix Host和监控项之间的比例可配置,即配置每一个Zabbix Host上最多进行的监控项数量
监控项自动转移,若是一个Zabbix Host出现异常,系统能够将上面的监控项迁移至其余健康的Zabbix Host
借助Zabbix Action,将异常状态的改变实时传递给系统,而不是由系统进行轮询
任何请求将进行持久化,方便查看以及请求的回滚
第二版的架构变成了这样:
上图中,Monitor Web
一方面接收前端的请求,它收到请求作的惟一的事情就是将请求数据写入数据库进行持久化;另外一方面,它还会接收来自Zabbix Server
的事件请求,这里的事件表示trigger状态的改变。
Monitor Admin
有两个职责:1)按期检测未完成的请求(添加/删除监控任务),拿到请求以后经过Zabbix API在对应的Zabbix Agent中添加/删除监控项(item + trigger);2)侦听ETCD中的key状态变化,进行相应地Zabbix Host建立/删除,以及监控项的迁移。
每当启动一个Docker container,就会将物理机的IDC、ETCD Server地址、Zabbix Server地址等参数传递至container,而后在内部启动zabbix_agentd
,而且按期检查zabbix_agentd
是否存活,若是存活的话,则生成一个惟一的key,向ETCD发起key建立/更新请求;若是不存活,则key会天然的过时。这样,Monitor Admin
就经过ETCD得知了各个zabbix_agentd
的健康情况,而且在内存中存储一份agent的拓扑结构。
启动了多个container,在Zabbix Server中就对应了多个Zabbix Host,以下图所示:
除了总体架构的升级,还在了许多方面(主要是Zabbix)进行了调优,好比:
尽可能增长agent的超时时间
由于咱们的监控采集项,都是须要对URL或者域名进行网络操做,这些操做每每都会比较耗时,并且这是正常的现象。所以,咱们须要增长在Zabbix agent的采集超时,避免正常的网络操做还没完成,就被判断为超时,影响Server的数据获取。
### Option: Timeout # Spend no more than Timeout seconds on processing # # Mandatory: no # Range: 1-30 # Default: # Timeout=3 Timeout=30
不要在采集脚本中加上超时
既然Zabbix agent中已经配置了采集超时时间,就不须要在采集脚本中添加超时了。一方面增长了维护成本,另外一方面若是配置不当,还会形成Zabbix agent中的超时配置失效。(以前在脚本中使用了timeout
命令,因为设置不正确,致使采集项老是不连续,调试了很久才查明缘由。)
增长Zabbix Server的Poller实例
默认状况,用于接收Zabbix agent采集数据的Poller实例只有5个。对于周期在1分钟内、数量会达到千级别的采集项来讲,Poller实例显然是不够的,须要增大实例数,充分利用好服务器资源。例如:
### Option: StartPollers # Number of pre-forked instances of pollers. # # Mandatory: no # Range: 0-1000 # Default: # StartPollers=5 StartPollers=100
利用好Zabbix trigger expression
若是只把trigger expression理解为“判断某个item value大于/小于某个阈值”,那就过低估Zabbix的trigger expression了,它其实能够支持不少复杂的逻辑。好比,为了防止网络抖动,须要当最近的连续两个采集项异常时,才改变trigger的状态,表达式能够写成:(假设item_key<0
为异常)
{host:item_key.last(#1)}<0&{host:item_key.last(#2)}<0
再举个例子,一样是为了防止采集的服务不稳定,咱们能够规定,当目前trigger的状态为PROBLEM,而且最近5分钟的采集数据均正常的时候,才能够将trigger状态改成OK,表达式能够这样写:
({TRIGGER.VALUE}=0&{host:item_key.last(#1)}<0&{host:item_key.last(#2)}<0) | ({TRIGGER.VALUE}=1&{host:item_key.min(5m)}<0)
具体能够参考Trigger expression
测试环境:
3台服务器,硬件参数与以前保持一致
Zabbix Server * 1
监控服务器 * 1
ETCD Server * 1
Docker container * 500 (在1台物理机中)
性能指标:
样本采集项:7100
样本采集频率:60s
Zabbix Server每秒处理监控项: 130 个监控项 / 秒 (初版为~19 qps)
平均入口流量:454.25 kbps
最大入口流量:916.12 kbps (初版为68 kbps)
平均出口流量:366.65 kbps
最大出口流量:1.68 Mbps (初版为270 kbps)
部分性能指标的监测图以下:
Zabbix Server每秒处理监控项数目
Zabbix Server网卡入口流量
Zabbix Server网卡出口流量
能够看出,跟初版相比,最大可采集的数据量是原来的近7倍,Zabbix Server的进出口流量有明显的提高,监控项的处理吞吐率也和采集项数量有了一致的提升,是原来的6.8倍,而且没有出现监控项在一个周期内没法采集到的状况(若是再增长监控项,则会不按期出现采样不连续的状况),性能提高仍是比较明显的。
本文从架构上介绍了若是基于Zabbix以及Docker,构建一个监控系统。
(广告时间,感兴趣的朋友能够登陆咱们的官网进行注册,使用咱们的评测/监测/加速等服务,而且经过添加PC持续监测任务来对网站进行实时监控。)
固然,目前的版本仍然不够完美,目前“抗住”了,而后须要考虑“优化”,年后预计会有较大改动,架构上以及技术上,本身已经在考量中。
(又是广告时间,团队急需后端小伙伴,能够经过咱们的官网了解到咱们的产品,也过年了,年终奖也发了,感兴趣的、有想法的朋友,欢迎将简历发送至hr@mmtrix.com
,谢谢!)
-- EOF --