Мониторинг скорости интернет каналов в Zabbix

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Всем привет!

Я работаю в крупной компании федеральной компании, у которой более 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

Шаблон Inernet 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}'

Теперь добавляем шаблон к необходимым хостам и можно проверить работоспособность. Также в хостах необходимо переопределить макрос, при котором будет срабатывать триггер низкой скорости интернета.

Нажимаем на нужный хост и выбираем Скорость интернета. Получаем ответ:

Результат замера скорости
Результат замера скорости

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

Статистика замеров скорости интернета
Статистика замеров скорости интернета

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

Источник: https://habr.com/ru/post/590775/


Интересные статьи

Интересные статьи

Привет, Хабр. Меня зовут Александр Альперн, я CEO и основатель компании Webinar Group. Сегодня хотелось бы обсудить такие вопросы, как использование технологий машинного обучения и ис...
Это — подборка материалов о перспективных сетевых протоколах Roughtime и Dat, методах построения радиорелейной Wi-Fi-сети и способах обнаружения брутфорса в сети провайдера. Читать д...
Раньше, для того чтобы стать клиентом Почты, нужно было обладать специальными знаниями о её устройстве: разбираться в тарифах и правилах, пробираться сквозь ограничения, о которых знали только со...
Как нацеленный на профессионалов формат MIDI на короткое, но примечательное время стал основным способом распространения музыки в интернете Почему-то каждый год, когда на горизонте начинает ...
Итак, я продолжу статью, посвященную мониторингу безопасности облачных провайдеров. В первой части я рассказывал об опыте Cisco в работе с внешними облачными сервисами, а также о наблюдениях Cisc...