一、Bind配置
Bind是目前使用最广泛的DNS服务器软件,安装完Bind后,可以使用其自带的zone-statistics
统计功能接口进行服务监控。
- 在Bind配置文件
/etc/named.conf
中,先在options段中关闭全局统计功能,只针对我们需要统计的zone进行统计。options { ... zone-statistics no; //关闭全局统计功能 ... }
- 打开Bind的统计接口,在options {} 段外加入下面配置,开启http统计接口http://127.0.0.1:8653
options { ... } statistics-channels { inet 127.0.0.1 port 8653 allow { 127.0.0.1; }; };
- 对需要监控的zone加入
zone-statistics yes
打开统计功能zone "example.com" IN { type slave; masters { 10.33.83.243; }; file "/var/named/slaves/example.com.zone"; zone-statistics yes; };
二、Zabbix监控脚本和配置
- Zabbix Agent增加配置
/etc/zabbix/zabbix_agentd.d/bind.conf
UserParameter=bind.check,/usr/local/zabbix-ztc/bin/bind.py -c /etc/zabbix/zabbix_agentd.conf --update-items UserParameter=bind.discovery,/usr/local/zabbix-ztc/bin/bind.py -c /etc/zabbix/zabbix_agentd.conf --discovery
- 监控脚本
/usr/local/zabbix-ztc/bin/bind.py
,使用python库protobix
,方法参考Hadoop集群监控#!/usr/bin/python # -*- coding: utf-8 -*- import re import sys import protobix import requests from lxml import etree class BIND(protobix.SampleProbe): __version__ = '1.0.0' def _parse_probe_args(self, parser): pass return parser def _init_probe(self): j = { 'zones': {}, 'counter': {}, 'zonemaintenancecounter': {}, 'resolvercounter': {}, 'socketcounter': {}, 'incounter': {}, 'outcounter': {}, 'cache': {}, 'memory': {} } url = 'http://127.0.0.1:8653/' with requests.get(url, timeout=2) as r: if r.status_code == 200: data = r.text else: raise RuntimeError root = etree.fromstring(data.encode('utf8')) # get the statistics version if root.tag == 'isc': version = root.find('./bind/statistics').attrib['version'] elif root.tag == 'statistics': version = root.attrib['version'] else: raise ValueError # check the statistics version if version.startswith('2.'): for view in root.iterfind('./bind/statistics/views/view'): if view.findtext('./name') in ('_default',): for zone in view.iterfind('./zones/zone'): if zone.find('./counters') is not None: counters = {} for counter in zone.iterfind('./counters/*'): counters[counter.tag] = counter.text j['zones'][zone.findtext('./name')] = counters for stat in root.iterfind('./bind/statistics/server/nsstat'): j['counter'][stat.findtext('./name')] = stat.findtext('./counter') for stat in root.iterfind('./bind/statistics/server/zonestat'): j['zonemaintenancecounter'][stat.findtext('./name')] = stat.findtext('./counter') for view in root.iterfind('./bind/statistics/views/view'): if view.findtext('./name') in ('_default',): for stat in view.iterfind('./resstat'): j['resolvercounter'][stat.findtext('./name')] = stat.findtext('./counter') for stat in root.iterfind('./bind/statistics/server/sockstat'): j['socketcounter'][stat.findtext('./name')] = stat.findtext('./counter') for stat in root.iterfind('./bind/statistics/server/queries-in/rdtype'): j['incounter'][stat.findtext('./name')] = stat.findtext('./counter') for stat in root.iterfind('./bind/statistics/views/view/rdtype'): j['outcounter'][stat.findtext('./name')] = stat.findtext('./counter') # Memory for child in root.iterfind('./bind/statistics/memory/summary/*'): j['memory'][child.tag] = child.text # Cache for local for child in root.iterfind('./bind/statistics/views/view/cache'): if child.attrib['name'] == 'localhost_resolver': for stat in child.iterfind('./rrset'): j['cache'][stat.findtext('./name')] = stat.findtext('./counter') elif version.startswith('3.'): for child in root.iterfind('./server/counters'): # V2 ./bind/statistics/server/nsstat if child.attrib['type'] == 'nsstat': for stat in child.iterfind('./counter'): j['counter'][stat.attrib['name']] = stat.text # V2 ./bind/statistics/server/sockstat if child.attrib['type'] == 'sockstat': for stat in child.iterfind('./counter'): j['socketcounter'][stat.attrib['name']] = stat.text # V2 ./bind/statistics/server/zonestat if child.attrib['type'] == 'zonestat': for stat in child.iterfind('./counter'): j['zonemaintenancecounter'][stat.attrib['name']] = stat.text # V2 ./bind/statistics/server/queries-in/rdtype if child.attrib['type'] == 'qtype': for stat in child.iterfind('./counter'): j['incounter'][stat.attrib['name']] = stat.text # they are only for block _default for child in root.iterfind('./views/view/counters'): # V2 ./bind/statistics/views/view/rdtype if child.attrib['type'] == 'resqtype': for stat in child.iterfind('./counter'): j['outcounter'][stat.attrib['name']] = stat.text # V2 ./bind/statistics/views/view => _default name only if child.attrib['type'] == 'resstats': for stat in child.iterfind('./counter'): j['resolvercounter'][stat.attrib['name']] = stat.text # V2: no (only in memory detail stats) if child.attrib['type'] == 'cachestats': for stat in child.iterfind('./counter'): j['cache'][stat.attrib['name']] = stat.text # V2 has @name = localhost_resolver, interal, external for child in root.iterfind('./views/view/cache'): if (child.attrib['name'] == '_default'): for stat in child.iterfind('./rrset'): j['cache'][stat.findtext('./name')] = stat.findtext('./counter') # for sets stating with !, we replace that with an _ (! is not allowed in zabbix) if re.match('^!', stat.findtext('./name')): j['cache'][stat.findtext('./name').replace('!', '_')] = stat.findtext('./counter') # for all the Zone stats only for child in root.iterfind('./views/view'): # only for default if (child.attrib['name'] == '_default'): # V2 ./bind/statistics/views/view -> ./zones/zone => _default name only for zone in child.iterfind('./zones/zone'): counters = {} for stat in zone.iterfind('./counters'): if stat.attrib['type'] == 'rcode' or stat.attrib['type'] == 'qtype': for counter in stat.iterfind('./counter'): counters[counter.attrib['name']] = counter.text j['zones'][zone.attrib['name']] = counters # V2 ./bind/statistics/memory/summary/* for child in root.iterfind('./memory/summary/*'): j['memory'][child.tag] = child.text else: raise ValueError self.j = j def _get_discovery(self): data = {} key = 'bind.discoverzones' data[key] = [{'{#ZONE}': zone} for zone in self.j['zones'].keys()] return {self.hostname: data} def _get_metrics(self): data = {} for k, v in self.j.items(): if k == 'zones': for kk, vv in v.items(): for kkk, vvv in vv.items(): data['bind.zonecounter[{0},{1}]'.format(kk, kkk)] = vvv else: for kk, vv in v.items(): data['bind.{0}[{1}]'.format(k, kk)] = vv return {self.hostname: data} if __name__ == '__main__': ret = BIND().run() print(ret) sys.exit(ret)
-
Zabbix(版本3.2)模板下载
下载:zbx_bind_templates.zip