SNMP
Примечание
Для корректного отображения устройств на дашбоарде в Grafana следует использовать значение тега component
как IP-адрес или имя устройства, которое мониторится с помощью snmp-exporter
SNMP поллинг
Для SNMP мониторинга удаленных устройств применяется snmp-exporter.
Для генерации конфигурационного файла используется специальная утилита generator. В архив с snmp-exporter
добавлен каталог стандартных MIB-файлов для генерации конфигураций.
Эта утилита обрабатывает необходимые MIB-файлы и преобразует их в список OID-цепочек и названий метрик.
SNMP exporter
опрашивает удаленные устройства на основе этих данных и выводит метрики в формате Prometheus для дальнейшего анализа другими системами.
Запуск snmp-exporter с помощью агента мониторинга
Для установки экспортера как сервиса см. руководство.
Для корректного запуска экспортера необходимо выполнить следующие настройки агента:
Настройка раздела exporters
В конфигурационном файле агента в разделе exporters
укажите имя запускаемого экспортера и параметр is_custom
:
exporters:
- name: snmp_exporter
is_custom: true
args: "--config.file=/opt/astramon-agent/exporters/config/snmp.yml"
health_address: 127.0.0.1:9116/metrics
Поле
name
должно совпадать с названием бинарного файла с учетом дополнительных условий именования сторонних экспортеров (например:astramon-snmp_exporter-custom
).Параметр
is_custom
указывает агенту, что это сторонний экспортер, но агент может управлять им (запускать, выполнятьhealth check
, останавливать и сообщать статус работы экспортера в Config API). Также это предотвращает использование функциональности, доступной только для экспортеров, специально разработанных для агента мониторинга.Параметр
args
содержит параметры запуска экспортера, включая путь к файлу конфигурации.
Настройка раздела metrics
Выполните настройку в разделе metrics
:
custom_targets:
- name: snmp_exporter1
component: 10.177.248.228
target: 127.0.0.1:9116
metrics_path: /snmp?module=apcups&target=10.177.248.228
- name: snmp_exporter2
component: 10.177.248.234
target: 127.0.0.1:9116
metrics_path: /snmp?module=linux&target=10.177.248.234
Поле
name
должно быть уникальным (это особенность работыvmagent
). В примере показан сбор данных с двух целевых устройств.Параметр
component
добавляет лейблcomponent
для различения метрик разных устройств.Параметр
target
указывает адрес и порт, с которого будут считываться метрики.Параметр
metrics_path
позволяет обратиться к конкретному эндпоинту для получения метрик. По умолчанию используется/metrics
, но в данном случае эндпоинт выводит метрики для разных устройств. При необходимости можно добавить запись для сбора метрик напрямую из/metrics
.
В текущей реализации поддерживаются версии SNMP v1 и v2c.
Файл правил состоит из пяти основных частей:
Header - Документация с определением переменных
Lookup - Таблицы приведения числовых обозначений в человекочитаемый формат
Preparation - Подготовка служебной информации и предварительная обработка трапов
Body - Ветвление правил по SNMP трапам
Footer - Подготовка результата для дальнейшей обработки
Header - подготовка переменных
if (typeof $OID1 == "undefined") $OID1 = "";
if (typeof $OID2 == "undefined") $OID2 = "";
if (typeof $OID3 == "undefined") $OID3 = "";
if (typeof $OID4 == "undefined") $OID4 = "";
if (typeof $OID5 == "undefined") $OID5 = "";
if (typeof $OID6 == "undefined") $OID6 = "";
if (typeof $OID7 == "undefined") $OID7 = "";
if (typeof $OID8 == "undefined") $OID8 = "";
if (typeof $OID9 == "undefined") $OID9 = "";
if (typeof $OID10 == "undefined") $OID10 = "";
if (typeof $OID11 == "undefined") $OID11 = "";
if (typeof $OID12 == "undefined") $OID12 = "";
if (typeof $1 == "undefined") $1 = "";
if (typeof $2 == "undefined") $2 = "";
if (typeof $3 == "undefined") $3 = "";
if (typeof $4 == "undefined") $4 = "";
if (typeof $5 == "undefined") $5 = "";
if (typeof $6 == "undefined") $6 = "";
if (typeof $7 == "undefined") $7 = "";
if (typeof $8 == "undefined") $8 = "";
if (typeof $9 == "undefined") $9 = "";
if (typeof $10 == "undefined") $10 = "";
if (typeof $11 == "undefined") $11 = "";
if (typeof $12 == "undefined") $12 = "";
_Manager = "";
_Agent = "";
_Class = "";
_Node = "";
_NodeAlias = "";
_AlertKey = "";
_AlertGroup = "";
_Summary = "";
_Severity = "";
_Type = "";
_Identifier = "";
_ExpireTime = 0;
_FirstOccurrence = new Date($ReceivedTime * 1000);
_LastOccurrence = _FirstOccurrence;
_Alert = false;
Lookup - таблицы приведения
IIANAifType = {
"1": "Other", // other - none of the following
"2": "Regular 1822", // regular1822
"3": "HDH 1822", // hdh1822
"4": "DDN X.25", // ddnX25
"5": "RFC-877 X.25", // rfc877x25
"6": "Ethernet CSMA-CD", // ethernetCsmacd
"7": "ISO 8802.3 CSMA-CD", // iso88023Csmacd
"8": "ISO 8802.4 Token Bus", // iso88024TokenBus
...
"212": "Voice FGD Exchange Access North American", // voiceFGDEANA - voice FGD Exchange Access North American
"213": "Voice Direct Inward Dialing" // voiceDID - voice Direct Inward Dialing
}
ifAdminStatus = {
"1": "Up", // up - ready to pass packets
"2": "Down", // down
"3": "Testing" // testing - in some test mode
}
ifOperStatus = {
"1": "Up", // up - ready to pass packets
"2": "Down", // down
"3": "Testing", // testing - in some test mode
"4": "Unknown", // unknown - status can not be determined for some reason.
"5": "Dormant", // dormant
"6": "Not Present", // notPresent - some component is missing
"7": "Lower Layer Down" // lowerLayerDown - down due to state of lower-layer interface(s)
}
Preparation - подготовка данных
// Устанавливаем стандартный Agent, Manager и Class
_Manager = "SNMP Trap adapter on " + hostname()
_Agent = "SNMPagent"
_Class = "300"
// Проверяем если получили SNMPv2 трап и ковертируем его в SNMPv1 стиль
if (typeof $notify !== "undefined") // Если $notify существует то это SNMPv2 трап
{
_Node = $PeerAddress
_NodeAlias = $PeerIPaddress
if (regmatch($notify, "\.iso\.")) {
$notify = ".1." + extract($notify, "\.iso\.(.*)")
}
if (nmatch($notify, ".1.3.6.1.6.3.1.1.5")) // SNMPv2 Generic трап
{
$Enterprise = extract($notify, "(.*)\.[0-9]+$")
$specific_trap = "0"
$generic_trap = (int(extract($notify, ".*\.([0-9]+)$")) - 1).toString()
} else // Enterprise Specific трап
{
if (match(extract($notify, "\.([0-9]+)\.[0-9]+$"), "0")) {
$Enterprise = extract($notify, "(.*)\.[0-9]+\.[0-9]+$")
} else {
$Enterprise = extract($notify, "(.*)\.[0-9]+$")
}
$specific_trap = extract($notify, ".*\.([0-9]+)$")
$generic_trap = "6"
}
} else // Это SNMPv1 трап
{
_Node = $Node
if (typeof $IPAddress !== "undefined")
{
_NodeAlias = $IPAddress
} else {
_NodeAlias = $IPaddress
}
}
Body - определение трапов
Пример конфигурации для Cisco Generic трапов:
if (match($generic_trap, "6")) // Проверяем если Enterprise Specific трап
{
switch ($Enterprise) {
case "dummy case statement": // Это позволит ибежать синтаксических ошибок при отсутствующих кейсай
break
// В этом сегменте определяем Enterprise Specific трапы не относящиеся к Generic, как в следующем примере
case ".1.3.6.1.4.1.9.9.43.2": // Если $Enterpries соответствует Cisco и трапу ciscoConfigManMIBNotificationPrefix
switch ($specific_trap) {
case "1": // - ciscoConfigManEvent
// ...
break
case "2": // - ccmCLIRunningConfigChanged
// ...
break
case "3": // Если $specific_trap соответсвует ccmCTIDRolledOver
_AlertGroup = "cisco"
_Agent = "cisco"
_Summary = "ccmCTIDRolledOver: This notification indicates that the Config Change Tracking ID has rolled over and will be reset."
_Severity = 3
_Type = 1
_ExpireTime = 10
_Identifier = _Node + _Summary
break
default:
_Summary = "Unknown specific trap number (" + $specific_trap + ") received for enterprise " + $Enterprise
_Identifier = _Node + $Enterprise + $generic_trap + $specific_trap + _Agent + _Manager
_Severity = 3
_Type = 1
}
break
default:
$EventID = $Enterprise + "|" + $generic_trap + "|" + $specific_trap
switch ($EventID) {
case "dummy case statement": // Это позволит ибежать синтаксических ошибок при отсутствующих кейсай
break
default:
_Summary = "Enterprise ID Not Found (see details): " + $Enterprise + " " + $generic_trap + " " + $specific_trap
_Severity = 2
_Type = 1
}
_Identifier = _Node + " " + $Enterprise + " " + $generic_trap + " " + $specific_trap + " " + _AlertGroup + " " + _AlertKey + " " + _Agent + " " + _Manager
}
} else // Проверяем если Generic трап
{
// Стантартно для Generic
_Agent = "Generic"
switch ($generic_trap) {
// В этом сегменте определяем только SNMP Generic трапы
case "0": // coldStart
_AlertGroup = "Generic"
_AlertKey = ""
_Summary = "Cold Start"
_Severity = 2
_Type = 1
_Identifier = _Node + " " + _AlertGroup + " " + _Agent + " " + _Manager + " " + $generic_trap
break
case "1": // warmStart
// ...
break
case "2": // linkDown
// ...
break
// ...
default:
_Summary = "Invalid Generic Trap Number: " + $Enterprise + " " + $generic_trap + " " + $specific_trap
_Severity = 2
_Type = 0
_Identifier = _Node + " " + $Enterprise + " " + $generic_trap + " " + $specific_trap + " " + _Agent + " " + _Manager
}
switch ($Enterprise) {
// В этом сегменте определяем SNMP Generic трапы которые относятся к другим MIB или к Enterprise (Generic трапы имеющие дополнительную Enterprise информацию)
case ".1.3.6.1.6.3.1.1.5": // RFC1907 - SNMPv2-MIB
if (nmatch($OID1, ".1.3.6.1.4.1.9") || nmatch($OID2, ".1.3.6.1.4.1.9") || nmatch($OID4, ".1.3.6.1.4.1.9")) { // Если трап содержит один из данных OID, значит это Enterprise Generic трап принадлежащий Cisco
_Agent = "Generic-Cisco SNMPv2"
_Class = "40057"
switch ($generic_trap) {
case "0": // При попадании в этот кейс, выполняем следующий что бы не дублировать код
case "1": // Для трапов coldStart и warmStart одинаковая ветка, так что можно их обрабатывать одинаково
$sysUptime = $1
$whyReload = $2
details($sysUptime, $whyReload)
_Summary = _Summary + ": " + $2
_Identifier = _Identifier + " " + $2
break
case "2":
case "3": // Так же как и для предыдущих, linkDown и linkUp обрабатываем одинаково
// ...
break
// ...
default:
}
} if (nmatch($OID6, ".1.3.6.1.4.1.9")) { // Если Generic трап содержит данный OID, значит это Generic-Cisco трап
_Agent = "Generic-Cisco SNMPv2"
_Class = "40057"
switch ($generic_trap) {
case "2":
case "3": // linkDown, linkUp
$ifIndex = $1
$ifAdminStatus = ifAdminStatus[$2] + " ( " + $2 + " )"
$ifOperStatus = ifOperStatus[$3] + " ( " + $3 + " )"
$ifDescr = $4
$ifType = IANAifType[$5] + " ( " + $5 + " )" // Берем описание из Lookup таблицы
$locIfReason = $6
details($ifIndex, $ifAdminStatus, $ifOperStatus, $ifDescr, $ifType, $locIfReason)
switch ($2) {
case "2": // Down
_Summary = _Summary + ", Administratively: " + $6 + " ( " + $4 + " )"
_Severity = 2
break
case "3": // Testing - in some test mode
_Summary = _Summary + ", Testing: " + $6 + " ( " + $4 + " )"
_Severity = 2
break
default:
_Summary = _Summary + ": " + $6 + " ( " + $4 + " )"
}
_Identifier = _Identifier + " "
break
default:
// ...
}
} else { // Если не подходит не под онид из перечисленнх вариантов, значит это Generic IETF SNMPv2 Трап
_Agent = "Generic-IETF-SNMPv2-MIB"
switch ($generic_trap) {
case "2":
case "3": // linkDown, linkUp
// ...
break
// ...
default:
// ...
}
}
break
// ...
default:
if (match($Enterprise, "")) {
_Summary = "Dummy Enterprise! If you matched here you have problems! (see details)"
}
else // Обрабатываем неизвестный Enterprise как SNMPv1 Generic трап
{
_Agent = "Generic-Unknown"
switch ($generic_trap) {
case "2":
case "3": // linkDown, linkUp
//...
break
default:
_Summary = _Summary + " ( Enterprise = " + $Enterprise + " )"
}
}
}
}
Полный файл правил для Cisco Generic можно найти в репозитории .
set("Manager", _Manager);
set("Agent", _Agent);
set("Class", _Class);
set("Node", _Node);
set("NodeAlias", _NodeAlias);
set("AlertKey", _AlertKey);
set("AlertGroup", _AlertGroup);
set("Summary", _Summary);
set("Severity", _Severity);
set("Type", _Type);
set("Identifier", _Identifier);
set("ExpireTime", _ExpireTime);
set("FirstOccurrence", _FirstOccurrence.getTime() / 1000);
set("LastOccurrence", _LastOccurrence.getTime() / 1000);
set("Alert", _Alert);
Алерты
Для отправки алертов необходимо установить параметр _Alert = true в соответствующих ветках файла правил:
// ...
case "2": // linkDown
_AlertGroup = "Generic Link Status"
_AlertKey = "ifEntry." + $1
_Summary = "Link Down"
_Severity = 5
_Type = 1
_Identifier = _Node + " " + _AlertKey + " " + _AlertGroup + " " + _Agent + " " + _Manager
_Alert = true // При установке данного параметра в true будет создан алерт на текущий трап
break
// ...
Доступные параметры в файле правил
Параметр |
Поддерживаемые версии |
Описание |
---|---|---|
|
V1, V2c |
Строка community SNMP |
|
V3 |
Context Engine ID |
|
V1 |
Строка enterprise SNMP |
|
V1 |
Целочисленное значение Generic SNMP-трапа |
|
V1, V2c, V3 |
IP-адрес источника трапа |
|
V1, V2c, V3 |
Имя узла источника (или IP-адрес, если имя не разрешено) |
|
V2c, V3 |
Специфическое поле notify для V2c |
|
V1, V2c, V3 |
Имя хоста/IP-адрес отправителя трапа |
|
V1, V2c, V3 |
IP-адрес отправителя трапа |
|
V1, V2c, V3 |
Протокол получения (UDP/TCP) |
|
V1, V2c, V3 |
Номер порта источника |
|
V1, V2c, V3 |
Время получения пакета |
|
V1 |
Идентификатор SNMP-запроса |
|
V3 |
Security Engine ID авторитетного SNMP-субъекта (для трапов - ID источника) |
|
V3 |
Уровень безопасности: |
|
V3 |
Security Name для аутентификации |
|
V1, V2c, V3 |
Версия SNMP (1 для V1, 2 для V2c) |
|
V1 |
Целочисленное значение Specific SNMP-трапа |
|
V1, V2c |
Аптайм системы в тиках |
|
- |
Шестнадцатеричное представление переменных varbind |
Примечание
В текущей реализации нет генератора файла правил из MIB файлов, поэтому для новых устройств файл правил необходимо создавать/дополнять вручную.
В файле правил используется синтаксис JavaScript.