感谢本文作者田川,Zabbix中级认证专家。
Zabbix proxy的一个特性是如果与Zabbix服务器的连接丢失时可以缓存收集的监控数据。在这篇文章中,将使用数据包捕获和数据包分析来展示它如何发生。
01
Zabbix设置和捕获Zabbix代理流量
这是本次演示中的设置:
· 中心站点的一个Zabbix服务器(IPv6地址是2001:db8:1234::bebe,DNS名称是zabbixtest.lein.io)
· 远程站点中的一个Zabbix代理“proxy-1”(IPv6地址是2001:db8:9876::fafa,IPv4地址是10.0.41.65)
· 远程站点中的一个Zabbix客户端“Testhost“,通过代理发送数据
简单起见,代理只监视一个项目:系统运行时间(监控项键值system.uptime,采用Zabbix主动模式),查询间隔时间为20秒。
这个代理是一个使用SQLite数据库的主动类型代理,配置文件中有以下非默认配置参数:
Server=zabbixtest.lein.io
Hostname=Proxy-1
DBName=/var/lib/zabbix/zabbix_proxy
Zabbix服务器前端中添加此代理,名称是“proxy-1”。
这里使用Zabbix服务器和代理的版本是6.4.0beta5,客户端通常与新版本的服务器和代理兼容,所以这里使用了4.0.44版本的现有客户端。
成功运行这些设置后,在Zabbix服务器上启动数据包捕获,仅捕获用于代理通信的数据包:
sudo tcpdump host 2001:db8:9876::fafa -v -w proxybuffer.pcap
在运行几分钟后,将数据包从代理中丢弃,从而产生了“网络中断”:
sudo ip6tables -A INPUT -s 2001:db8:9876::fafa -j DROP
让这个drop规则保持几分钟,然后用一个合适的ip6tables命令删除它(在本次演示中是sudo ip6tables-D INPUT 1),并在此之后停止网络数据捕获。
02
使用Wireshark分析捕获的Zabbix流量
将捕获文件(proxybuffer.pcap)下载到本地电脑。本地电脑中需要安装Wireshark,还需要安装Wireshark的Zabbix解析器(https://github.com/markkuleinio/wireshark-zabbix-dissectors)。如果没有这个特定的解析器,Zabbix数据包内容只是不可读的二进制数据,因为从Zabbix 4.0版本开始,代理通信被压缩了。
可以在此处下载相同的捕获文件:
https://github.com/markkuleinio/wireshark-zabbix-dissectors/raw/master/samples/proxybuffer.pcap
在Wireshark中打开捕获文件后,首先在显示过滤中输入zabbix,在协议树中扩展zabbix字段,得到的是:
由于这是一个与服务器通信的主动类型代理,因此总是首先有来自代理的数据包(要发送的配置请求或数据),然后是来自服务器的响应。
让我们只看来自代理的数据包,可以通过在过滤中添加代理IP地址来获得(将IP地址从source列拖动到显示过滤中):
基本上显示两种类型的数据包:
· 代理数据
· 请求代理配置
配置请求更容易解释:在Zabbix proxy 6.4中有一个配置参数ProxyConfigFrequency(在早期的Zabbix版本中,该参数为ConfigFrequency):
默认值是10秒。每次配置请求中都会发生的流程是代理会说“我当前的配置修订版是1234”,然后服务器对此做出响应。
注意:Zabbix 6.4中的配置请求概念已更改为尽可能使用incremental configurations(增量配置),因此与Zabbix 6.2及更早版本中3600秒或一小时的早期默认值相比,代理可以更快地获得更新的配置。有关更多信息,请参阅Zabbix 6.4.0中的新增内容。
上面显示的另一种数据包类型是代理数据包。它实际上也用于数据以外的其它方面。在代理配置中,有一个参数DataSenderFrequency:
它的默认值是1秒。但正如上文引用的那样,即使增加了配置值(实际上是降低了同步频率),主动类型代理也会每隔1秒连接服务器。
上面显示的第一个数据包(为了更好的可读性,重新格式化了JSON):
{
"request": "proxy data",
"host": "Proxy-1",
"session": "38cca0391f7427d0ad487f75755e7166",
"version": "6.4.0beta5",
"clock": 1673190378,
"ns": 360076308
}
数据包中没有“数据”,只是代理对服务器说“嘿,我还在这里!”这样,如果服务器有话要说,比如在代理或代理监控的任何主机上运行远程命令,它就有机会与代理进行对话。
如前所述,测试设置仅由一个监控项组成,并且每20秒收集一次,因此并非所有数据包都包含监控数据是很自然的。
通过在显示过滤中添加zabbix.proxy.data(将“Proxy Data:True”字段拖动进显示过滤中)来进一步过滤数据包,以仅显示代理数据包:
现在,显示了大约20秒的数据包,所以应该有了一个实际的数据包,数据包编号176:它比其他数据包大了大约50个字节,所以一定有一些东西。以下是该数据包的Data字段内容:
{
"request": "proxy data",
"host": "Proxy-1",
"session": "38cca0391f7427d0ad487f75755e7166",
"history data": [
{
"id": 31,
"itemid": 44592,
"clock": 1673190392,
"ns": 299338333,
"value": "1686"
}
],
"version": "6.4.0beta5",
"clock": 1673190393,
"ns": 429562969
}
除了前面的字段外,现在还有一个名为history data的列表包含着一个对象。该对象含有itemid和value等字段。itemid字段含有监控项的实际标识(item ID),当在Zabbix前端编辑监控项时,可以在浏览器的URL地址中看到。1686这个值是监视项的实际值(系统正常运行时间以秒为单位,主机大约在28分钟前重新启动过)。
既然非常确信TCP长度约为136-138字节的数据包只是没有项目数据的空数据包,那么可以通过在显示过滤器添加TCP.len>140来获得有趣的数据包:
当查看网络数据包的时间戳时,可以看到17:08:30为止一直存在间隔20秒一次的数据传输。然后是大约3.5分钟的间隙,下一次发送时间是17:11:53,然后数据以20秒一次的间隔再次开始传输。3.5分钟的间隙对应于上文中通过命令手动造成的网络中断。停机后的数据包比其它数据包大:
{
"request": "proxy data",
"host": "Proxy-1",
"session": "38cca0391f7427d0ad487f75755e7166",
"history data": [
{
"id": 37,
"itemid": 44592,
"clock": 1673190512,
"ns": 316923947,
"value": "1806"
},
{
"id": 38,
"itemid": 44592,
"clock": 1673190532,
"ns": 319597379,
"value": "1826"
},
--- JSON truncated ---
{
"id": 45,
"itemid": 44592,
"clock": 1673190672,
"ns": 345132325,
"value": "1966"
},
{
"id": 46,
"itemid": 44592,
"clock": 1673190692,
"ns": 348345312,
"value": "1986"
}
],
"auto registration": [
{
"clock": 1673190592,
"host": "Testhost",
"ip": "10.0.41.66",
"port": "10050",
"tls_accepted": 1
}
],
"version": "6.4.0beta5",
"clock": 1673190708,
"ns": 108126335
}
可以看到来自代理的同一数据包中有几个历史数据对象。itemid字段仍然与前面(44592)相同,value字段以20秒为单位递增。此外,时间戳(clock和nanoseconds)也在相应地增加,因此可以看到这些值是什么时间被实际收集的,尽管它们被代理缓存并在几分钟后就会被发送到服务器。
也可以通过查看Zabbix前端页面中该监控项的最新数据得到证实:
一个很好的递增图,没有间隙或锯齿状边缘。
再展开说明一下,下面的信息是Zabbix代理日志中的停机情况(代理服务器上的/var/log/zabbix/zabbi_proxy.log):
738:20230108:170835.557 Unable to connect to [zabbixtest.lein.io]:10051 [cannot connect to [[zabbixtest.lein.io]:10051]: [4] Interrupted system call]
738:20230108:170835.558 Will try to reconnect every 120 second(s)
748:20230108:170835.970 Unable to connect to [zabbixtest.lein.io]:10051 [cannot connect to [[zabbixtest.lein.io]:10051]: [4] Interrupted system call]
748:20230108:170835.970 Will try to reconnect every 1 second(s)
748:20230108:170939.993 Still unable to connect...
748:20230108:171040.015 Still unable to connect...
738:20230108:171043.561 Still unable to connect...
748:20230108:171140.068 Still unable to connect...
748:20230108:171147.105 Connection restored.
738:20230108:171243.563 Connection restored.
日志一开始看起来很混乱,因为它显示了两次消息。此外,正如前面的数据包列表所证明的那样,第二条“连接已恢复”消息在数据发送已恢复近一分钟后到达。对此的解释是(据我所知)configuration syncer和data sender是代理中的独立进程,如以下链接所述:https://www.zabbix.com/documentation/current/en/manual/concepts/proxy#proxy-process-types。
当查看数据包时,可以看到在17:12:43(即第二条“连接恢复”消息到达时),代理向服务器发送了一个代理配置请求,因此显然data sender每秒都会尝试重新连接(以便于快速恢复监控数据),而config syncer仅2两分钟尝试一次(基于“将尝试每120秒重新连接一次”消息,这对应于停机开始时间17:08:35加上2 x 2分钟,再加上一些额外的秒,可能是因为TCP超时)。
Zabbix服务器日志(/var/log/zabbix/zabbix _server.log)中没有关于此次中断的消息,因为中断不是在TCP会话期间发生的,并且代理处于主动模式(即连接始终由代理启动,而不是由服务器启动),所以在Zabbix服务器进程日志中没有什么特别的记录。
03
代理数据缓存的配置
在Zabbix proxy 6.4的配置文件中,有两个控制缓存的配置参数:
ProxyLocalBuffer
ProxyOfflineBuffer
Proxy Offline Buffer是一个重要参数。如果需要容忍代理服务器和Zabbix服务器之间超过1小时的停机时间(并且代理上有足够的磁盘存储空间),则可以增加该值。因为代理使用单独的数据库(安装代理时进行配置)来存储缓存数据,所以没有单独的文件名或路径可供配置。
Proxy Local Buffer对大多数人来说是无需关注的(默认情况下此参数也是禁用的),因为只有计划将收集的数据直接从代理数据库中提取到其它外部应用程序时,该参数才有用处,并且需要通过一定的灵活性来合理安排从数据库中检索数据以避免影响数据库效能。
扫一扫|加入技术交流群
微信号|17502189550
备注“使用Zabbix年限+企业+姓名”
5000+用户已加入!
一个人走得快,一群人走得远!