Мониторинг сетевого оборудования через SNMP
Введение
Данная документация описывает процесс настройки системы мониторинга сетевого оборудования (коммутаторы SNR, маршрутизаторы MikroTik) с использованием стека технологий:
- SNMP — протокол для сбора метрик с устройств
- Telegraf — агент для сбора и отправки метрик
- InfluxDB — база данных для хранения временных рядов
- Grafana — платформа для визуализации и алертинга
Что такое метрики и SNMP
Метрики
Метрики — это числовые показатели, характеризующие состояние системы в определённый момент времени. Примеры метрик сетевого оборудования:
| Метрика | Описание | Пример значения |
|---|---|---|
| Uptime | Время работы устройства | 25 days, 9:12:47 |
| ifInOctets | Входящий трафик (байты) | 29153382 |
| ifOutOctets | Исходящий трафик (байты) | 1110677606 |
| ifOperStatus | Статус интерфейса | 1 (up) / 2 (down) |
| CPU Load | Загрузка процессора | 15% |
SNMP (Simple Network Management Protocol)
SNMP — стандартный протокол для мониторинга и управления сетевыми устройствами. Работает по модели "запрос-ответ" через UDP порт 161.
Ключевые понятия SNMP
OID (Object Identifier) — уникальный идентификатор метрики в виде числовой последовательности:
1.3.6.1.2.1.1.3.0 = sysUptime (время работы системы)
│ │ │ │ │ │ │ │ └── индекс
│ │ │ │ │ │ │ └──── system (1)
│ │ │ │ │ │ └────── mib-2 (1)
│ │ │ │ │ └──────── mgmt (2)
│ │ │ │ └────────── internet (1)
│ │ │ └──────────── dod (6)
│ │ └────────────── org (3)
│ └──────────────── iso (1)
└────────────────── root
MIB (Management Information Base) — база данных, описывающая доступные OID'ы на устройстве. Бывают:
- Стандартные (RFC) — одинаковые для всех вендоров
- Приватные — специфичные для производителя (например, 1.3.6.1.4.1.14988 для MikroTik)
Community String — строка аутентификации (по сути пароль) для доступа к SNMP. По умолчанию часто public для чтения.
Стандартные OID'ы для интерфейсов
1.3.6.1.2.1.2.2.1.1 — ifIndex (индекс интерфейса)
1.3.6.1.2.1.2.2.1.2 — ifDescr (имя интерфейса)
1.3.6.1.2.1.2.2.1.3 — ifType (тип: 6=ethernet, 23=ppp)
1.3.6.1.2.1.2.2.1.4 — ifMtu (MTU)
1.3.6.1.2.1.2.2.1.5 — ifSpeed (скорость)
1.3.6.1.2.1.2.2.1.7 — ifAdminStatus (админ статус)
1.3.6.1.2.1.2.2.1.8 — ifOperStatus (операционный статус)
1.3.6.1.2.1.2.2.1.9 — ifLastChange (время последнего изменения)
1.3.6.1.2.1.2.2.1.10 — ifInOctets (входящие байты)
1.3.6.1.2.1.2.2.1.16 — ifOutOctets (исходящие байты)
Извлечение метрик через SNMP
Для работы с SNMP из командной строки используется пакет snmp:
# Установка
sudo apt install snmp
# Получить одно значение
snmpget -v2c -c public 192.168.1.1 1.3.6.1.2.1.1.3.0
# Обход дерева OID'ов
snmpwalk -v2c -c public 192.168.1.1 1.3.6.1.2.1.2.2.1.2
# Параметры:
# -v2c — версия SNMP (1, 2c или 3)
# -c — community string
# IP — адрес устройства
# OID — идентификатор метрики
Пример вывода snmpwalk для интерфейсов:
iso.3.6.1.2.1.2.2.1.2.1 = STRING: "Ethernet1/0/1"
iso.3.6.1.2.1.2.2.1.2.2 = STRING: "Ethernet1/0/2"
iso.3.6.1.2.1.2.2.1.2.15729389 = STRING: "<l2tp-Tashkent_Oazis>"
Число после последней точки (1, 2, 15729389) — это ifIndex, уникальный идентификатор интерфейса.
Архитектура системы мониторинга
┌─────────────────┐ SNMP (UDP 161) ┌─────────────┐
│ SNR Switch │◄──────────────────────►│ │
│ 172.20.104.253 │ │ │
└─────────────────┘ │ │
│ Telegraf │
┌─────────────────┐ SNMP (UDP 161) │ (сборщик) │
│ MikroTik CCR │◄──────────────────────►│ │
│ 172.20.107.254 │ │ │
└─────────────────┘ └──────┬──────┘
│
│ HTTP (8086)
▼
┌─────────────┐
│ InfluxDB │
│ (хранение) │
└──────┬──────┘
│
│ Flux queries
▼
┌─────────────┐
│ Grafana │
│ (визуализа- │
│ ция) │
└─────────────┘
Поток данных
- Устройства (свитчи, роутеры) хранят метрики и отвечают на SNMP-запросы
- Telegraf периодически опрашивает устройства по SNMP и отправляет данные в InfluxDB
- InfluxDB хранит временные ряды метрик
- Grafana запрашивает данные из InfluxDB и отображает дашборды
Telegraf — сборщик метрик
Что такое Telegraf
Telegraf — агент для сбора, обработки и отправки метрик. Поддерживает более 200 входных плагинов (inputs) и 50+ выходных (outputs).
Структура конфигурации
# Глобальные настройки агента
[agent]
interval = "60s" # Как часто собирать метрики
flush_interval = "60s" # Как часто отправлять в БД
hostname = "telegraf-server" # Имя хоста для тегов
# Куда отправлять данные
[[outputs.influxdb_v2]]
urls = ["http://influxdb:8086"]
token = "your-token"
organization = "myorg"
bucket = "network"
# Откуда собирать данные
[[inputs.snmp]]
agents = ["udp://192.168.1.1:161"]
version = 2
community = "public"
# Одиночные значения (scalars)
[[inputs.snmp.field]]
oid = "1.3.6.1.2.1.1.3.0"
name = "uptime"
# Таблицы (несколько значений с индексами)
[[inputs.snmp.table]]
name = "interface"
[[inputs.snmp.table.field]]
oid = "1.3.6.1.2.1.2.2.1.2"
name = "ifDescr"
is_tag = true # Сохранить как тег, не как значение
Ключевые концепции
Measurement — логическая группа метрик (аналог таблицы в SQL):
snmp— системные метрики устройстваinterface— метрики интерфейсов
Fields — числовые значения метрик:
uptime = 219316700ifInOctets = 29153382
Tags — строковые метки для фильтрации:
agent_host = "172.20.107.254"ifDescr = "<l2tp-Tashkent_Oazis>"hostname = "ccr-office"
Timestamp — время сбора метрики (наносекунды Unix epoch)
Формат данных (Line Protocol)
interface,agent_host=172.20.107.254,ifDescr=<l2tp-Tashkent_Oazis> ifInOctets=29153382,ifOperStatus=1 1770232095000000000
└───┬───┘ └────────────────────┬────────────────────────────────┘ └─────────────┬─────────────────┘ └────────┬────────┘
measurement tags fields timestamp
Тестирование конфигурации
# Проверить что Telegraf собирает
docker exec -it telegraf telegraf --config /etc/telegraf/telegraf.conf --test
# Вывод покажет собранные метрики:
> snmp,agent_host=172.20.104.253,hostname=ID-SW1 uptime=217262000u
> interface,agent_host=172.20.104.253,ifDescr=Ethernet1/0/1 ifInOctets=1755198811u,ifOperStatus=1i
InfluxDB — база данных временных рядов
Что такое InfluxDB
InfluxDB — специализированная база данных для хранения временных рядов (time series). Оптимизирована для:
- Высокой скорости записи
- Эффективного сжатия данных
- Быстрых запросов по временным диапазонам
Основные понятия
Organization — логическая группировка ресурсов (как namespace)
Bucket — контейнер для данных с политикой хранения (retention policy)
Token — ключ доступа к API
Flux — язык запросов
Flux — функциональный язык запросов для InfluxDB 2.x. Использует pipe-forward оператор |> для построения цепочки преобразований.
Базовая структура запроса
from(bucket: "network") // 1. Источник данных
|> range(start: -1h) // 2. Временной диапазон
|> filter(fn: (r) => r._measurement == "interface") // 3. Фильтрация
|> filter(fn: (r) => r._field == "ifInOctets")
|> last() // 4. Агрегация
Основные функции Flux
Источник и диапазон:
from(bucket: "network")
|> range(start: -1h) // Последний час
|> range(start: -1h, stop: -30m) // От часа до 30 минут назад
|> range(start: v.timeRangeStart, stop: v.timeRangeStop) // Из Grafana
Фильтрация:
|> filter(fn: (r) => r._measurement == "interface")
|> filter(fn: (r) => r.ifDescr =~ /l2tp/) // Regex
|> filter(fn: (r) => r._field == "ifInOctets" or r._field == "ifOutOctets")
Агрегация:
|> last() // Последнее значение
|> first() // Первое значение
|> mean() // Среднее
|> sum() // Сумма
|> count() // Количество
|> min() / max() // Минимум / максимум
Группировка:
|> group(columns: ["ifDescr"]) // Группировать по интерфейсу
|> group() // Убрать группировку (объединить всё)
Преобразование:
|> pivot(rowKey: ["ifDescr"], columnKey: ["_field"], valueColumn: "_value")
// Превращает строки в столбцы (из длинного формата в широкий)
|> map(fn: (r) => ({ r with newField: r._value * 8 }))
// Создать новое поле
|> rename(columns: {oldName: "newName"})
// Переименовать столбец
|> keep(columns: ["ifDescr", "Status", "_value"])
// Оставить только указанные столбцы
|> drop(columns: ["_start", "_stop"])
// Удалить столбцы
Вычисление производных (для трафика):
|> derivative(unit: 1s, nonNegative: true)
// Скорость изменения в секунду (байты/сек)
|> map(fn: (r) => ({ r with _value: r._value * 8.0 }))
// Конвертация в биты/сек
Работа со временем:
|> map(fn: (r) => ({
r with
isStale: int(v: now()) - int(v: r._time) > 120000000000
// 120000000000 наносекунд = 2 минуты
}))
Примеры запросов
Получить статус всех L2TP туннелей:
from(bucket: "ideabuck")
|> range(start: -5m)
|> filter(fn: (r) => r._measurement == "interface")
|> filter(fn: (r) => r.ifDescr =~ /l2tp/)
|> filter(fn: (r) => r._field == "ifOperStatus")
|> last()
Подсчитать активные порты:
from(bucket: "ideabuck")
|> range(start: -5m)
|> filter(fn: (r) => r._measurement == "interface")
|> filter(fn: (r) => r._field == "ifOperStatus")
|> filter(fn: (r) => r.ifDescr =~ /Ethernet/)
|> last()
|> filter(fn: (r) => r._value == 1)
|> group()
|> count()
Трафик по портам в bits/sec:
from(bucket: "ideabuck")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "interface")
|> filter(fn: (r) => r._field == "ifInOctets")
|> derivative(unit: 1s, nonNegative: true)
|> map(fn: (r) => ({ r with _value: r._value * 8.0 }))
Таблица с несколькими полями (pivot):
from(bucket: "ideabuck")
|> range(start: -5m)
|> filter(fn: (r) => r._measurement == "interface")
|> filter(fn: (r) => r._field == "ifOperStatus" or r._field == "ifInOctets" or r._field == "ifOutOctets")
|> last()
|> pivot(rowKey: ["ifDescr"], columnKey: ["_field"], valueColumn: "_value")
Grafana — визуализация
Структура дашборда
Дашборд в Grafana — JSON-документ, содержащий:
{
"title": "SNR Switch Monitoring",
"uid": "unique-id",
"panels": [...], // Массив панелей
"templating": {...}, // Переменные дашборда
"time": { // Временной диапазон по умолчанию
"from": "now-1h",
"to": "now"
},
"refresh": "30s" // Автообновление
}
Типы панелей
Stat — одно большое число:
{
"type": "stat",
"title": "Active Ports",
"options": {
"colorMode": "value",
"graphMode": "none"
}
}
Time Series — график временного ряда:
{
"type": "timeseries",
"title": "Traffic",
"fieldConfig": {
"defaults": {
"unit": "bps" // bits per second
}
}
}
Table — таблица:
{
"type": "table",
"title": "Port Status",
"transformations": [
{ "id": "merge" } // Объединить фреймы
]
}
Структура панели
{
"type": "stat",
"title": "Switch Uptime",
"gridPos": { "h": 4, "w": 6, "x": 0, "y": 0 }, // Позиция и размер
"datasource": {
"type": "influxdb",
"uid": "datasource-uid"
},
"targets": [ // Запросы к данным
{
"query": "from(bucket: \"network\") |> ...",
"refId": "A"
}
],
"fieldConfig": { // Настройки отображения
"defaults": {
"unit": "dtdurations", // Формат: duration
"thresholds": {...}
},
"overrides": [...] // Переопределения для конкретных полей
},
"options": { // Специфичные настройки типа панели
"colorMode": "value"
}
}
Единицы измерения (units)
| Unit | Описание | Пример |
|---|---|---|
bps | bits per second | 1.5 Mbps |
Bps | bytes per second | 150 KB/s |
decbytes | bytes (decimal) | 1.5 GB |
bytes | bytes (binary) | 1.4 GiB |
dtdurations | duration | 3 weeks |
percent | процент | 85% |
none | без единиц | 42 |
Value Mappings
Преобразование значений в текст/цвета:
{
"id": "mappings",
"value": [
{
"type": "value",
"options": {
"Up": {
"color": "green",
"text": "🟢 Up"
}
}
},
{
"type": "value",
"options": {
"Down": {
"color": "red",
"text": "🔴 Down"
}
}
}
]
}
Transformations
Преобразования данных на стороне Grafana:
- Merge — объединить несколько фреймов в один
- Organize fields — переупорядочить/переименовать столбцы
- Filter by name — скрыть столбцы
- Add field from calculation — вычисляемые поля
Практическое развёртывание
Docker Compose
version: '3.8'
services:
influxdb:
image: influxdb:2.7
container_name: influxdb
restart: unless-stopped
ports:
- "8086:8086"
volumes:
- influxdb_data:/var/lib/influxdb2
telegraf:
image: telegraf:latest
container_name: telegraf
restart: unless-stopped
volumes:
- ./telegraf/telegraf.conf:/etc/telegraf/telegraf.conf:ro
depends_on:
- influxdb
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
depends_on:
- influxdb
volumes:
influxdb_data:
grafana_data:
Порядок настройки
-
Запустить стек:
docker compose up -d -
Настроить InfluxDB:
- Открыть http://localhost:8086
- Создать пользователя, организацию, bucket
- Сгенерировать API token
-
Настроить Telegraf:
- Создать
telegraf/telegraf.conf - Указать token и bucket
- Добавить SNMP agents
- Перезапустить:
docker compose restart telegraf
- Создать
-
Настроить Grafana:
- Открыть http://localhost:3000 (admin/admin)
- Добавить InfluxDB data source (Flux)
- Импортировать или создать дашборд
Настройка SNMP на устройствах
SNR Switch:
- SNMP Configuration → SNMP management → SNMP Agent state: Open
- Community managers → добавить community string (например
monitoring) - Security IP state → Open (или добавить IP сервера мониторинга)
MikroTik:
/ip snmp set enabled=yes
/ip snmp community set 0 name=monitoring
Примеры конфигураций
Полный telegraf.conf
[agent]
interval = "60s"
flush_interval = "60s"
[[outputs.influxdb_v2]]
urls = ["http://influxdb:8086"]
token = "your-api-token"
organization = "idea"
bucket = "ideabuck"
# SNR Switch
[[inputs.snmp]]
agents = ["udp://172.20.104.253:161"]
version = 2
community = "monitoring"
[[inputs.snmp.field]]
oid = "1.3.6.1.2.1.1.3.0"
name = "uptime"
[[inputs.snmp.field]]
oid = "1.3.6.1.2.1.1.5.0"
name = "hostname"
is_tag = true
[[inputs.snmp.table]]
name = "interface"
[[inputs.snmp.table.field]]
oid = "1.3.6.1.2.1.2.2.1.2"
name = "ifDescr"
is_tag = true
[[inputs.snmp.table.field]]
oid = "1.3.6.1.2.1.2.2.1.8"
name = "ifOperStatus"
[[inputs.snmp.table.field]]
oid = "1.3.6.1.2.1.2.2.1.9"
name = "ifLastChange"
[[inputs.snmp.table.field]]
oid = "1.3.6.1.2.1.2.2.1.10"
name = "ifInOctets"
[[inputs.snmp.table.field]]
oid = "1.3.6.1.2.1.2.2.1.16"
name = "ifOutOctets"
# MikroTik Router
[[inputs.snmp]]
agents = ["udp://172.20.107.254:161"]
version = 2
community = "public"
[[inputs.snmp.field]]
oid = "1.3.6.1.2.1.1.3.0"
name = "uptime"
[[inputs.snmp.field]]
oid = "1.3.6.1.2.1.1.5.0"
name = "hostname"
is_tag = true
[[inputs.snmp.table]]
name = "interface"
[[inputs.snmp.table.field]]
oid = "1.3.6.1.2.1.2.2.1.2"
name = "ifDescr"
is_tag = true
[[inputs.snmp.table.field]]
oid = "1.3.6.1.2.1.2.2.1.8"
name = "ifOperStatus"
[[inputs.snmp.table.field]]
oid = "1.3.6.1.2.1.2.2.1.9"
name = "ifLastChange"
[[inputs.snmp.table.field]]
oid = "1.3.6.1.2.1.2.2.1.10"
name = "ifInOctets"
[[inputs.snmp.table.field]]
oid = "1.3.6.1.2.1.2.2.1.16"
name = "ifOutOctets"
Troubleshooting
SNMP не отвечает
# Проверить ping
ping 172.20.104.253
# Проверить SNMP
snmpwalk -v2c -c monitoring 172.20.104.253 1.3.6.1.2.1.1.1.0
# Если timeout — проблемы:
# 1. SNMP не включен на устройстве
# 2. Неправильный community string
# 3. Фильтрация по IP (Security IP state)
# 4. Firewall блокирует UDP 161
Telegraf не собирает метрики
# Тест конфигурации
docker exec -it telegraf telegraf --config /etc/telegraf/telegraf.conf --test
# Логи
docker logs telegraf
# Частые ошибки:
# "no such host" — неправильный IP или DNS
# "timeout" — нет сетевого доступа
# "authentication failure" — неправильный community
Данные не появляются в InfluxDB
# Проверить что bucket существует
# В InfluxDB UI: Data Explorer → выбрать bucket
# Проверить token
# Должен иметь права на запись в bucket
# Проверить логи Telegraf на ошибки записи
docker logs telegraf | grep -i error
Grafana не показывает данные
- Проверить Data Source → Test connection
- Проверить organization и bucket в настройках
- В панели → Query Inspector → посмотреть ошибки запроса
- Проверить временной диапазон (данные могут быть за другой период)
Панель показывает "No data"
- Расширить временной диапазон
- Проверить фильтры в запросе
- Убедиться что measurement и field names совпадают с тем что присылает Telegraf
Таблица показывает один элемент вместо списка
- Добавить transformation "Merge"
- Проверить
|> group()в конце Flux запроса