关键词: zabbix 监控 GPU 监控项自动化注册 脚本监控服务
部署具体细节就不详细展开了,我这里有三台机器,其中一台部署docker版的zabbix server
然后在这三台机器都部署zabbix agent2,
整体组成了这个三台机器的zabbix监控集群
在server端的web console配置主机(host),配置监控项(item),我这边的服务器目前数量不多,暂时没有配置模板(template)
具体配置参考其他教程,或者官网用例
这里我具体展开说下。
正常使用官方提供的监控项,可以监控机器的cpu / mem / desk / net 等等,但是没有监控到GPU,所以只能自己加监控项。
官方提供的简单的脚本监控,在zabbix_agent2.d做相关配置就能实现,但是这个一个监控项需要写一个脚本,我需要监控的一个机器就有40+的监控项,不太方便。所有我使用python开发一个脚本来实现所有的监控项的数据监控,然后在服务器起一个系统服务来做gpu的状态监控。
具体就是不经过zabbixagent处理,使用zabbix api实现监控数据的上传,然后在web console进行监控。
相关代码:
def get_nv_info(self):
self.packet = []
pynvml.nvmlInit()
device_count = pynvml.nvmlDeviceGetCount()
self.packet.append(
ZabbixMetric(self.hostname, 'gpu.num', device_count)
)
for i in range(device_count):
handle = pynvml.nvmlDeviceGetHandleByIndex(i)
gpu_name = pynvml.nvmlDeviceGetName(handle)
mem_info = pynvml.nvmlDeviceGetMemoryInfo(handle)
temperature = pynvml.nvmlDeviceGetTemperature(handle, 0)
powerusage = pynvml.nvmlDeviceGetPowerUsage(handle)
self.packet.extend(
[ZabbixMetric(self.hostname, f'gpu.{str(i)}.name', gpu_name.decode('utf-8')),
ZabbixMetric(self.hostname, f'gpu.{str(i)}.powerusage', powerusage / 1000),
ZabbixMetric(self.hostname, f'gpu.{str(i)}.temperature', temperature),
ZabbixMetric(self.hostname, f'gpu.{str(i)}.mem.total', mem_info.total),
ZabbixMetric(self.hostname, f'gpu.{str(i)}.mem.free', mem_info.free),
ZabbixMetric(self.hostname, f'gpu.{str(i)}.mem.used', mem_info.used),
ZabbixMetric(self.hostname, f'gpu.{str(i)}.mem.used.percent', mem_info.used / mem_info.total),
])
pynvml.nvmlShutdown()
self.packet.extend(
[ZabbixMetric(self.hostname, f'gpu.all.powerusage',
sum([float(x.value) for x in self.packet if 'powerusage' in x.key])),
ZabbixMetric(self.hostname, f'gpu.all.temperature.max',
max([float(x.value) for x in self.packet if 'temperature' in x.key])),
ZabbixMetric(self.hostname, f'gpu.all.mem.total',
sum([float(x.value) for x in self.packet if 'mem.total' in x.key])),
ZabbixMetric(self.hostname, f'gpu.all.mem.free',
sum([float(x.value) for x in self.packet if 'mem.free' in x.key])),
ZabbixMetric(self.hostname, f'gpu.all.mem.used',
sum([float(x.value) for x in self.packet if 'mem.used' in x.key])),
ZabbixMetric(self.hostname, f'gpu.all.mem.used.percent',
sum([float(x.value) for x in self.packet if 'mem.used' in x.key]) / sum(
[float(x.value) for x in self.packet if 'mem.total' in x.key])),
])
result = self.zabbix_sender.send(self.packet)
这里有一点,必须先把监控项的key写入到server才能通过api把数据写入到server,类似需要先注册item key,才能在这个item 下记录数据。
所以实现了写数据之前,需要先检查下item key是否已经在server生成了,没有的化先使用item.create进行初始化。
这里有个细节,就是zabbix api需要写 params ,这个需要稍微研究下对应的方法的params写法。
比如 Zabbix采集器 类型的 监控项, 在 item.create方法下需要指定几个参数,
看官方文档并没有明确给出每一种监控项类型的 params 写法,但是在监控项对象中给出params 参数又有很多必填项,我这里卡住导致很多参数不该有而导致的报错。具体信息如下
下面报错就是因为url不该有。
---------------------------------------------------------------------------
ZabbixAPIException Traceback (most recent call last)
Cell In[203], line 11
1 params = {
2 "name": "gpu.0.powerusage",
3 "key_": "gpu.0.powerusage",
(...)
9 "delay": "30s"
10 }
---> 11 zabbixapi.do_request('item.create', params=params)
File /usr/local/lib/python3.8/dist-packages/pyzabbix/api.py:304, in ZabbixAPI.do_request(self, method, params)
302 err = res_json['error'].copy()
303 err.update({'json': str(request_json)})
--> 304 raise ZabbixAPIException(err)
306 return res_json
ZabbixAPIException: {'code': -32602, 'message': 'Invalid params.', 'data': 'Item with key "gpu.0.powerusage" already exists on "aiserver2".', 'json': "{'jsonrpc': '2.0', 'method': 'item.create', 'params': {'name': 'gpu.0.powerusage', 'key_': 'gpu.0.powerusage', 'hostid': '10597', 'type': 2, 'value_type': 3, 'units': 'MB', 'url': '', 'delay': '30s'}, 'id': '1', 'auth': '********'}"}
item创建的可用代码:
def _regist_key(self, key):
params = {
"name": key, #监控项 name 和 key 可以一样
"key_": key,
"hostid": self.zabbix_host_id, #hostid 可以先通过host调用api拿到对于的hostid ,这里host是web console配置的主机名
"type": 2, # 监控项的类型 这里使用的 Zabbix采集器 类型 以及下面几个枚举值都参考官方文档吧
"value_type": self._check_item_value_type(key), # 记录的数据类型,字符串 整型 浮点 等
"units": self._check_item_unit(key), #单位 例如 B / ℃ / W
"delay": "30s"
}
self.zabbix_api.do_request('item.create', params)
整体代码调通之后,再吧代码配置到系统服务中,避免服务器重启后监控丢失
目前经常会因为要更新驱动而重启机器的情况
# cd /etc/systemd/system
# vim gpumoniter.service
[Unit]
Description=gpumoniter
After=network.target
[Service]
ExecStart=python3 /etc/zabbix/read_gpu_status_info.py
[Install]
WantedBy=multi-user.target
# scp 分发到其他服务器
# scp xxx.py host:`pwd`
# scp xxx.service host:`pwd`
# systemctl enable --now gpumoniter.service
# systemctl status gpumoniter.service
# systemctl restart gpumoniter.service
# journalctl -u gpumoniter.service -n 10 -f
在GPU监控逻辑开发中发现,在自己的后端服务监控中也可以埋点到zabbix来做监控,然后在前端配置相关监控图标,感觉这个链路是通的,也挺方便,统计服务都省了。
后续在有相关内容的话,会再回来更新。
[1]:zabbix6 api item object
[2]:zabbix6 api hostgroup
[3]:Python 调用 zabbix api
[4]:最强Linux课程上线 玩转Zabbix监控实战开发