Всем привет!
Я работаю в крупной федеральной компании, у которой более 2000 объектов. Для большинства задач необходим стабильный канал интернета с высокой скоростью. Поэтому нам необходимо было сделать систему, которая позволяет отслеживать скорость работы интернет каналов на этих объектах, и в случае проблем информировала бы нас об этом.
Собрав все инструменты, что у меня есть, я решил сделать мониторинг скорости интернета на базе Zabbix. Для замеров скорости используется утилита iperf3. Весь код сделан на python.
Схема работы мониторинга скорости интернет каналов
На объектах установлены сетевые шлюзы на Linux, на которых поднят iperf3 в режиме сервера. В каждом филиале есть сервер Zabbix Proxy, на котором запускается iperf3 в режиме клиента и замеряет скорость интернета, после он в Zabbix trap записывает данные замера.
/usr/bin/iperf3 -B <IP_address> -Ds
apt install iperf3 python-pip python
pip install py-zabbix
pip install protobix
Далее создаем папку iperf в /usr/lib/zabbix/externalscripts/. В папке создаем два файла iperf3_speed_testing.py и iperf3_task.py (один для замера скорости из Zabbix, второй для периодических замеров всех). И даем им нужные разрешения. Владельцем папки делаем пользователя zabbix.
mkdir /usr/lib/zabbix/externalscripts/iperf
touch /usr/lib/zabbix/externalscripts/iperf/iperf3_speed_testing.py
touch /usr/lib/zabbix/externalscripts/iperf/iperf3_task.py
chown -R zabbix:zabbix /usr/lib/zabbix/externalscripts/iperf
chmod +x /usr/lib/zabbix/externalscripts/iperf/iperf3_speed_testing.py
chmod +x /usr/lib/zabbix/externalscripts/iperf/iperf3_task.py
#!/usr/bin/python
#- *- coding: utf-8 - *-
import protobix
import argparse
import subprocess
import sys
import json
import time
proxy = subprocess.Popen(['hostname'], stdout=subprocess.PIPE)
proxy = proxy.communicate()[0]
def showResult(_upload, _download):
print "Отправка: " + str(round(_upload/1000000,2)) + " Мбит/с"
print "Получение: " + str(round(_download/1000000,2)) + " Мбит/с"
def sendData(_upload, _download):
host_moria = sys.argv[2]
host_status = {}
host_status['speed_upload'] = _upload
host_status['speed_download'] = _download
zbx_datacontainer = protobix.DataContainer()
zbx_datacontainer.server_active = proxy.split('\n')[0]
zbx_datacontainer.server_port = 10051
zbx_datacontainer.data_type = "items"
zbx_datacontainer.add({host_moria: host_status})
# print json.dumps({host_moria: host_status}, indent=4)
zbx_datacontainer.send()
showResult(_upload, _download)
start_time = time.time()
result = subprocess.Popen(['/usr/bin/iperf3', '-c', sys.argv[1], '-J', '-P', '5'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
wait = time.time()-start_time
while wait < 45 and result.poll() == None:
wait = time.time()-start_time
if wait > 40 and wait < 45 :
result.kill()
stdout_value = {"error":"Timeout error"}
stdout_json = stdout_value
stdout_value = str(stdout_value)
break
else:
stdout_value, stderr_value = result.communicate()
stdout_json = json.loads(stdout_value)
while stdout_value.find('error') != -1 and stdout_json['error'] == 'error - unable to receive results: Resource temporarily unavailable':
result = subprocess.Popen(['/usr/bin/iperf3', '-c', sys.argv[1], '-J', '-P', '5'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout_value, stderr_value = result.communicate()
stdout_json = json.loads(stdout_value)
if stdout_value.find('error') == -1:
sendData(stdout_json['end']['sum_sent']['bits_per_second'],stdout_json['end']['sum_received']['bits_per_second'])
else:
print stdout_json['error']
Скрипт /usr/lib/zabbix/externalscripts/iperf/iperf3_task.py необходим для запуска задачи на замер скорости в выбранных группах хостов Zabbix. Для работы данного скрипта также необходимо создать пользователя с доступом к Zabbix API. В данном скрипте используются следующие переменные:
# - *- coding: utf- 8 - *-
from pyzabbix.api import ZabbixAPI
import protobix
import argparse
import subprocess
import sys
import json
import time
zabbix_user = <zabbix_api_user>
zabbix_password = <zabbix_api_password>
group = ('Gateway_branch_1','Gateway_branch_2')
start_time_script = time.time()
proxy = subprocess.Popen(['hostname'], stdout=subprocess.PIPE)
proxy = proxy.communicate()[0]
def sendData(host, upload, download):
host_moria = host
host_status = {}
host_status['speed_upload'] = upload
host_status['speed_download'] = download
zbx_datacontainer = protobix.DataContainer()
zbx_datacontainer.server_active = proxy.split('\n')[0]
zbx_datacontainer.server_port = 10051
zbx_datacontainer.data_type = "items"
zbx_datacontainer.add({host_moria: host_status})
# print json.dumps({host_moria: host_status}, indent=4)
zbx_datacontainer.send()
def getZabbixGroupID(groupName):
groups = zapi.hostgroup.get(filter={'name':groupName})
for group in groups:
return group['groupid']
zapi = ZabbixAPI(url=zabbix_server, user=zabbix_user, password=zabbix_password)
hosts = zapi.host.get(groupids=[getZabbixGroupID(group[0]),getZabbixGroupID(group[1])], selectInterfaces=['ip'])
for host in hosts:
# print (host['host'])
start_time = time.time()
result = subprocess.Popen(['/usr/bin/iperf3', '-c', host['interfaces'][0]['ip'], '-J', '-P', '5'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
wait = time.time()-start_time
while wait < 45 and result.poll() == None:
wait = time.time()-start_time
if wait > 40 and wait < 45 :
result.kill()
stdout_value = {"error":"Timeout error"}
stdout_json = stdout_value
stdout_value = str(stdout_value)
break
else:
stdout_value, stderr_value = result.communicate()
stdout_json = json.loads(stdout_value)
while stdout_value.find('error') != -1 and stdout_json['error'] == 'error - unable to receive results: Resource temporarily unavailable':
result = subprocess.Popen(['/usr/bin/iperf3', '-c', host['interfaces'][0]['ip'], '-J', '-P', '5'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout_value, stderr_value = result.communicate()
stdout_json = json.loads(stdout_value)
if stdout_value.find('error') == -1:
sendData(host['host'], stdout_json['end']['sum_sent']['bits_per_second'], stdout_json['end']['sum_received']['bits_per_second'])
zapi.user.logout()
related_time = time.time() - start_time_script
host_moria = proxy.split('\n')[0]
host_status = {}
host_status['iperf_task_time'] = float(round(related_time,2))
zbx_datacontainer = protobix.DataContainer()
zbx_datacontainer.server_active = 'hqpv-zbxcl1.megafon-retail.ru'
zbx_datacontainer.server_port = 10051
zbx_datacontainer.data_type = "items"
zbx_datacontainer.add({host_moria: host_status})
zbx_datacontainer.send()
Создаем задачу в crontab
0 2,6,10,14,18,22 * * * /usr/lib/zabbix/externalscripts/iperf/iperf3_task.py
Мы делаем замер раз в 4 часа. Нам этого хватает.
Если у вас используется просто Zabbix сервер, то на нем нужно сделать то же самое.
Шаблон Inernet speed testing
В данном шаблоне необходимо создать следующие элементы данных:
Триггеры:
Триггеры
Макросы:
Также добавляем Скрипт для замера скорости вручную (Администрирование -> Скрипты -> Создать скрипт)
Данные для настройки скрипта ручного замера
В поле команда вставляем путь к скрипту в следующем виде /usr/lib/zabbix/externalscripts/iperf/iperf3_speed_testing.py {HOST.CONN} '{HOST.HOST}'
Теперь добавляем шаблон к необходимым хостам и можно проверить работоспособность. Также в хостах необходимо переопределить макрос, при котором будет срабатывать триггер низкой скорости интернета.
Нажимаем на нужный хост и выбираем Скорость интернета. Получаем ответ:
Результат замера скорости
Далее проверяем элементы данных обновились. Ждем некоторое время и можем получаем такую статистику для каждого хоста:
Статистика замеров скорости интернета
На этом всё. Спасибо за внимание!
habr.com
Я работаю в крупной федеральной компании, у которой более 2000 объектов. Для большинства задач необходим стабильный канал интернета с высокой скоростью. Поэтому нам необходимо было сделать систему, которая позволяет отслеживать скорость работы интернет каналов на этих объектах, и в случае проблем информировала бы нас об этом.
Собрав все инструменты, что у меня есть, я решил сделать мониторинг скорости интернета на базе Zabbix. Для замеров скорости используется утилита iperf3. Весь код сделан на python.
Схема работы
В общем случае, схема мониторинга выглядит следующим образом:
На объектах установлены сетевые шлюзы на Linux, на которых поднят iperf3 в режиме сервера. В каждом филиале есть сервер Zabbix Proxy, на котором запускается iperf3 в режиме клиента и замеряет скорость интернета, после он в Zabbix trap записывает данные замера.
Настройка и запуск iperf3 на удаленном объекте
Как уже писал выше, на объектах установлены сетевые шлюзы на Linux. На них был установлен iperf3 и создана задача на запуск iperf3 при старте шлюза. Запуск осуществляется следующей командой, где <IP_address> интерфейса, через который осуществляется замер скорости:/usr/bin/iperf3 -B <IP_address> -Ds
Настройка iperf3 на Zabbix Proxy сервере
Для начала необходимо установить следующие пакеты: iperf3, python-pip, python. Из pip нам необходимо установить py-zabbix и protobix.apt install iperf3 python-pip python
pip install py-zabbix
pip install protobix
Далее создаем папку iperf в /usr/lib/zabbix/externalscripts/. В папке создаем два файла iperf3_speed_testing.py и iperf3_task.py (один для замера скорости из Zabbix, второй для периодических замеров всех). И даем им нужные разрешения. Владельцем папки делаем пользователя zabbix.
mkdir /usr/lib/zabbix/externalscripts/iperf
touch /usr/lib/zabbix/externalscripts/iperf/iperf3_speed_testing.py
touch /usr/lib/zabbix/externalscripts/iperf/iperf3_task.py
chown -R zabbix:zabbix /usr/lib/zabbix/externalscripts/iperf
chmod +x /usr/lib/zabbix/externalscripts/iperf/iperf3_speed_testing.py
chmod +x /usr/lib/zabbix/externalscripts/iperf/iperf3_task.py
Описание и содержимое скриптов
Скрипт /usr/lib/zabbix/externalscripts/iperf/iperf3_speed_testing.py необходим для выполнения запуска замера скорости на текущий момент. Он запускает запуск замеров на выбранном хосте в Zabbix.#!/usr/bin/python
#- *- coding: utf-8 - *-
import protobix
import argparse
import subprocess
import sys
import json
import time
proxy = subprocess.Popen(['hostname'], stdout=subprocess.PIPE)
proxy = proxy.communicate()[0]
def showResult(_upload, _download):
print "Отправка: " + str(round(_upload/1000000,2)) + " Мбит/с"
print "Получение: " + str(round(_download/1000000,2)) + " Мбит/с"
def sendData(_upload, _download):
host_moria = sys.argv[2]
host_status = {}
host_status['speed_upload'] = _upload
host_status['speed_download'] = _download
zbx_datacontainer = protobix.DataContainer()
zbx_datacontainer.server_active = proxy.split('\n')[0]
zbx_datacontainer.server_port = 10051
zbx_datacontainer.data_type = "items"
zbx_datacontainer.add({host_moria: host_status})
# print json.dumps({host_moria: host_status}, indent=4)
zbx_datacontainer.send()
showResult(_upload, _download)
start_time = time.time()
result = subprocess.Popen(['/usr/bin/iperf3', '-c', sys.argv[1], '-J', '-P', '5'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
wait = time.time()-start_time
while wait < 45 and result.poll() == None:
wait = time.time()-start_time
if wait > 40 and wait < 45 :
result.kill()
stdout_value = {"error":"Timeout error"}
stdout_json = stdout_value
stdout_value = str(stdout_value)
break
else:
stdout_value, stderr_value = result.communicate()
stdout_json = json.loads(stdout_value)
while stdout_value.find('error') != -1 and stdout_json['error'] == 'error - unable to receive results: Resource temporarily unavailable':
result = subprocess.Popen(['/usr/bin/iperf3', '-c', sys.argv[1], '-J', '-P', '5'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout_value, stderr_value = result.communicate()
stdout_json = json.loads(stdout_value)
if stdout_value.find('error') == -1:
sendData(stdout_json['end']['sum_sent']['bits_per_second'],stdout_json['end']['sum_received']['bits_per_second'])
else:
print stdout_json['error']
Скрипт /usr/lib/zabbix/externalscripts/iperf/iperf3_task.py необходим для запуска задачи на замер скорости в выбранных группах хостов Zabbix. Для работы данного скрипта также необходимо создать пользователя с доступом к Zabbix API. В данном скрипте используются следующие переменные:
- zabbix_user - пользователь с доступом к API
- zabbix_password - пароль пользователя API
- zabbix_server - адрес сервера zabbix
- group - группа или группы в Zabbix, для которых необходимо делать замер скорости интернета
# - *- coding: utf- 8 - *-
from pyzabbix.api import ZabbixAPI
import protobix
import argparse
import subprocess
import sys
import json
import time
zabbix_user = <zabbix_api_user>
zabbix_password = <zabbix_api_password>
group = ('Gateway_branch_1','Gateway_branch_2')
start_time_script = time.time()
proxy = subprocess.Popen(['hostname'], stdout=subprocess.PIPE)
proxy = proxy.communicate()[0]
def sendData(host, upload, download):
host_moria = host
host_status = {}
host_status['speed_upload'] = upload
host_status['speed_download'] = download
zbx_datacontainer = protobix.DataContainer()
zbx_datacontainer.server_active = proxy.split('\n')[0]
zbx_datacontainer.server_port = 10051
zbx_datacontainer.data_type = "items"
zbx_datacontainer.add({host_moria: host_status})
# print json.dumps({host_moria: host_status}, indent=4)
zbx_datacontainer.send()
def getZabbixGroupID(groupName):
groups = zapi.hostgroup.get(filter={'name':groupName})
for group in groups:
return group['groupid']
zapi = ZabbixAPI(url=zabbix_server, user=zabbix_user, password=zabbix_password)
hosts = zapi.host.get(groupids=[getZabbixGroupID(group[0]),getZabbixGroupID(group[1])], selectInterfaces=['ip'])
for host in hosts:
# print (host['host'])
start_time = time.time()
result = subprocess.Popen(['/usr/bin/iperf3', '-c', host['interfaces'][0]['ip'], '-J', '-P', '5'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
wait = time.time()-start_time
while wait < 45 and result.poll() == None:
wait = time.time()-start_time
if wait > 40 and wait < 45 :
result.kill()
stdout_value = {"error":"Timeout error"}
stdout_json = stdout_value
stdout_value = str(stdout_value)
break
else:
stdout_value, stderr_value = result.communicate()
stdout_json = json.loads(stdout_value)
while stdout_value.find('error') != -1 and stdout_json['error'] == 'error - unable to receive results: Resource temporarily unavailable':
result = subprocess.Popen(['/usr/bin/iperf3', '-c', host['interfaces'][0]['ip'], '-J', '-P', '5'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout_value, stderr_value = result.communicate()
stdout_json = json.loads(stdout_value)
if stdout_value.find('error') == -1:
sendData(host['host'], stdout_json['end']['sum_sent']['bits_per_second'], stdout_json['end']['sum_received']['bits_per_second'])
zapi.user.logout()
related_time = time.time() - start_time_script
host_moria = proxy.split('\n')[0]
host_status = {}
host_status['iperf_task_time'] = float(round(related_time,2))
zbx_datacontainer = protobix.DataContainer()
zbx_datacontainer.server_active = 'hqpv-zbxcl1.megafon-retail.ru'
zbx_datacontainer.server_port = 10051
zbx_datacontainer.data_type = "items"
zbx_datacontainer.add({host_moria: host_status})
zbx_datacontainer.send()
Создаем задачу в crontab
0 2,6,10,14,18,22 * * * /usr/lib/zabbix/externalscripts/iperf/iperf3_task.py
Мы делаем замер раз в 4 часа. Нам этого хватает.
Если у вас используется просто Zabbix сервер, то на нем нужно сделать то же самое.
Настройка шаблонов и скриптов в Zabbix
Для начала необходимо создать шаблон с элементами данных замеров скорости интернета. Я назвал шаблон Internet Speed Testing
Шаблон Inernet speed testing
В данном шаблоне необходимо создать следующие элементы данных:
- Speed Upload

- Speed Download

Триггеры:
- Нет данных замеров скорости более 48 часов
- Низкая скорость загрузки
- Низкая скорость выгрузки

Макросы:
- {$LOW_SPEED} - для записи скорости, при которой срабатывает триггер

Также добавляем Скрипт для замера скорости вручную (Администрирование -> Скрипты -> Создать скрипт)

Данные для настройки скрипта ручного замера
В поле команда вставляем путь к скрипту в следующем виде /usr/lib/zabbix/externalscripts/iperf/iperf3_speed_testing.py {HOST.CONN} '{HOST.HOST}'
Теперь добавляем шаблон к необходимым хостам и можно проверить работоспособность. Также в хостах необходимо переопределить макрос, при котором будет срабатывать триггер низкой скорости интернета.
Нажимаем на нужный хост и выбираем Скорость интернета. Получаем ответ:

Результат замера скорости
Далее проверяем элементы данных обновились. Ждем некоторое время и можем получаем такую статистику для каждого хоста:

Статистика замеров скорости интернета
На этом всё. Спасибо за внимание!


Мониторинг скорости интернет каналов в Zabbix
Всем привет! Я работаю в крупной федеральной компании, у которой более 2000 объектов. Для большинства задач необходим стабильный канал интернета с высокой скоростью. Поэтому нам необходимо было...
