感谢作者方傅皓敏、傅皓樑供稿!欢迎投稿分享你的使用经验。
Zabbix5.0、6.0中文手册译者
就职于某知名金融公司,从事于运维架构领域相关工作,负责公司AIOPS架构方面工作。
对于开源监控、数据库、分部署存储等方面有丰富的实践经验。
由于公司业务平台的网络环境苛刻,以Zabbixserver为核心开发设计一套适应性强的监控运维境更强的方案,不仅能满足当下的需求还能方便后续扩展。写这篇文档的初衷希望遇到类似环境的同学有一个参考,在碰到严格、复杂的网络环境,数量庞大机器管理,如何能够利用Zabbix的特性做到深度监控。
需要面对的挑战
(1)端口受限,我们的网络环境非常苛刻,节点系统对外只开放访问22、80(部分),服务端有80、端口。
(2)带宽受限,服务端、节点系统分布在不同区域,连接靠一根多个系统公用千M光纤,在保证监控完整的同时不能影响业务。
(3)数量庞大,目前近万台节点,还在不断在增加,监控项30W+。
(4)如何统一管理,如何批量部署客户端、更新监控项配置。
(5)监控数据如何写入Zabbix,zabbixserver是否扛得住。
(6)什么数据库才能抗住这么大数据量,后面如何扩展。
终版配置环境
(1)Zabbix5.4server*1。
(2)TiDB分布式数据库,TiDB采用TiDB3、tikv3、pd*3。
(3)RabbitMQ*1。
(4)Jenkinsserver1,Jenkinsnode3。
脚本和客户端采用python和go编写。
终版监控架构图
架构说明
(1)监控模块,数据从右往左,agent-server-rabbitmq-脚本处理-ZabbixServer(ZabbixApi)-Zabbix数据库(Tidb)。
(2)Agent部署模块,从server提取当前agent注册清单-并入agent总清单-对比agent和总清单的差异,对于那些没有安装agent主机通过ssh协议远程连接上进行执行署脚本。
解决问题
第一阻力:端口受限,只能用22、80,那么如何部署zabbixagent和zabbixserver,为什么不用的zabbix分布式让zabbixagent主动上报,而采用当前的架构?
解决方案:
目前用的最多zabbix分布式如下图,那为什么我们不用呢?zabbixagent上报数据需要访问zabbixproxy端口,通常整个环境也是在一个局域网内亦或者整个网络环境可以调控。
而我们的网络环境如下,环境限制问题有:
(1)客户端只能和网关进行相连,中心开放的端口只有80,客户端只开放80,,22。
(2)因为中心机房网关是单线光前通往agent所在地,同时网关也用于其他业务,对于带宽的要求也要进一步压缩。
(3)Zabbixagent包都比较大,远程下发包的流量也会影响带宽的使用。
(4)从这几方面考虑无法通过zabbixagent进行上报数据方式。
通过go编写wsagent主动上报,这样只要wsserver端开80端口就能解决此问题,go的agent压缩后只有3M,可以解决包过大传输的问题和3、4问题,演变的数据上报架构如下。
(1)Server是使用go写的websocket服务端简称ws,agent上部署了2个服务(webscoket客户端和监控服务都是用go自己写的)。
(2)客户端上的监控服务通过本地的配置文件会不断异步执行监控项存储至内存中,客户端上的wsagent也可以执行wsserver下发的命令。
(3)通过jenkins定时任务发送给wsserver让其转发送给所有wsagent,上报自身监控数据给wsserver,后者将数据存放至rabbitmq的监控项数据队列中,这里要说明一下,rabbitmq队列要设置TTL,不然一旦消费者挂了数据囤积后会把mq内存给打满了,这里我们对wsserver、消费者都通过脚本进行监测使其能够自愈。
第二阻力:数据在mq中如何消费到zabbix中的近万台主机的监控项中呢,采用什么方式?
解决方案:
(1)RabbitMQ和zabbixserver都在都在同一网络中,这样网络限制就会小很多,这当中第一个要解决的是如何创建监控项,因为监控项都是不定式的,例如多个磁盘,多个服务等,这样只能采用自动发现,常用的自动发现2种:一种通过自制脚本创建自动发现监控项,这种一般都是定式的,已经知道有哪些监控项,如知道目前主机上有3个磁盘,通过自动发现就可以节省每个主机上手动创建3个监控项,还有一种通过在zabbixagent主机执行脚本获取待创建监控项队列,
(2)我们使用的是第三种通过zabbixsender发送给zabbixserver数据的方式创建监控项例如:
zbx_sender-zzabbix_server的ip-shostip-key自动发现的key-o{“data”:[“#{ITEM_NAME}”:“监控项名字”,”#{ITEM_KEY}”:“监控项key”]}
这个是zabbix自带的命令,可以使用python、go、java等语言自己写一个,我们是用python写的。第一个问题解决了,下面就是第二个自动发现的监控项都有存活周期,这个周期如何更新,例如:自动发现设置7天后删除,那7天后失效了怎么办,经过测试上面创建监控项命令对存在的监控项再次创建就会更新监控项存活时间,例如昨天创建的监控项到今天还有6天就要被删除了,那今天再次创建监控项就会从今天开始计时往后延长7天。最后一个问题就是插入数据了,这个比较容易解决,命令提供在下面,在这里我们发现一个坑不知道大家有没有注意,使用zbx_sender时发送的数据时间是执行命令时的,而监控项数据在客户端采集到执行命令会有时间差,这个问题在自制zab_sender中已经解决,里面有个参数是value_clock,脚本网上可以找到,看似问题都解决了其实不然。插入监控项数据命令。
zbx_sender-zzabbix_server的ip-shostip-key监控项key-o监控项值
我们的监控项数量有30W+,相信大家的数量也不会少,我们agent完成后大约有W+的监控项,那如果监控项间隔为5分钟,相当于每次创建监控项任务要5分钟发送W次,zabbixserver的lld进程最多只能开启个,发送命令可以分布式多线程、多进程来发送,但是接收只有1个zabbixserver,我们运行到后面zabbixserver就出现不会执行队列(创建监控项、更新监控项、插入数据)了,队列全部溢出。
对于这个问题我们尝试了以下2种方式,虽然全部失败但是也积累了经验。
1.双zabbixserver模式
这个模式查了相关文档没人用过,使用后会产生2个告警,查了源码和相关文档后找出原因,监控项数据发送给zabbixserver后,zabbixserver会匹配对应监控项的触发器规则,如果匹配后发送给数据库,这样就不难理解会出现2个告警了,几个zabbixserver就会有几个zabbixserver,这样问题还难不倒我们,一个zabbixserver接收监控项数据,一个zabbixserver接收创建监控项及更新监控项,但是就是这样对于大量更新监控项也扛不住,通过分析lld大部分工作在于更新监控项存活时间,从日志跟踪中找到下面的sql,而创建监控项通常就创建一次,所以只要解决了这个问题就完美了。
updateitem_discoverysetlastcheck=whereitemid=
通过分析zabbixserverlog每一个触发更新监控项会输出行日志,至少有50个以上的动作,那W监控项的工作量可想而知了,如果采用批量update直接对数据库进行操作就可以解决这个问题了。解决方法如下,在消费监控项数据时把对应节点监控项输出一份到监控项需更新队列中,通过脚本汇聚这些监控项与zabbix数据库items表进行关联取差集得到需要更新的监控项id,然后使用update批量更新,sql如下,item_free表为关联后取得itemid写入表中,不然不好操作:
Updateitem_discoverysetlastcheck=UNIX_TIMESTAMP(NOW()),ts_delete=UNIX_TIMESTAMP(NOW())+(7*24*)whereitemidin(selectitemidfromitem_free)
2.zabbixproxy模式
zabbixproxy不支持lld,所以发送创建监控项数据后,不会创建监控项,查看配置文件就没有lld的进程,查了下原理也释然,zabbixproxy是定时读取zabbixserver的配置数据保存在zabbixproxy数据库中,如果能够创建监控项信息,那多个zabbixproxy数据上传时会产生数据冲突。
第三阻力:什么数据库才能抗住这么大数据量,后面如何扩展?
我们数据库从mysql-postgresql-tidb不断进行迭代,从mysql说起吧,现在还在mysql的通常都是分表分库的方式,单标0W已经影响性能了,当初mysql优化到极限单标W数据,查询3秒,面对现在动不动几亿的数据量实在扛不住,postgresql是我们上一代的zabbixserver数据库,单表性能没得说,目前各个zabbix场景下用的最多的就属他了,但是pg是单点的不能用于扩展,看着每天增加的指标量,数据阶梯式增长,在这种情况下分布式数据库是必选的方案,tidb是开源的分布式数据库,想要扩展性能可以通过横向扩节点的方式,简单容易上手、社区活跃、官方解答问题非常积极,对于我们运维人员是一个福音,再更新数据库后虽然问题很多,但是大势所趋目的办法。
碰到的问题
问题1:zabbixserver日志排查问题?
我们的架构核心是通过zabbix_sender发送zabbix_server创建监控项、更新监控项、更新监控项值,在更新自动发现监控项存活和创建监控项时遇到zabbix_server处理不过来,具体的排查通过查看zabbixserver的lld日志来判断,这里如果直接打开debug日志满屏刷无法定位问题,通过设置日志文档来打开lld日志输出,具体参考: