Всем привет!
Я работаю в крупной компании федеральной компании, у которой более 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
group - группа или группы в Zabbix, для которых необходимо делать замер скорости интернета
#!/usr/bin/python
# - *- 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='https://zabbix.megafon-retail.ru', 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
В данном шаблоне необходимо создать следующие элементы данных:
Speed Upload
Speed Download
Триггеры:
Нет данных замеров скорости более 48 часов
Низкая скорость загрузки
Низкая скорость выгрузки
Макросы:
{$LOW_SPEED} - для записи скорости, при которой срабатывает триггер
Также добавляем Скрипт для замера скорости вручную (Администрирование -> Скрипты -> Создать скрипт)
В поле команда вставляем путь к скрипту в следующем виде /usr/lib/zabbix/externalscripts/iperf/iperf3_speed_testing.py {HOST.CONN} '{HOST.HOST}'
Теперь добавляем шаблон к необходимым хостам и можно проверить работоспособность. Также в хостах необходимо переопределить макрос, при котором будет срабатывать триггер низкой скорости интернета.
Нажимаем на нужный хост и выбираем Скорость интернета. Получаем ответ:
Далее проверяем элементы данных обновились. Ждем некоторое время и можем получаем такую статистику для каждого хоста:
На это всё. Спасибо за внимание!