Child pages
  • Performance Management in NOC Microservices

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Описание

Подсистема Performance Management (PM) в ноке отвечает за сбор метрик с оборудования (дискавери) и контроль их значения (пороги, threshold).

...

Следует признать, что PM находится в стадии развития. Заложены широкие возможности, но много требует доработки или реализации. Посмотрим на то, что есть сейчас.

Архитектура и компоненты

Архитектурно PM состоит из источника данных, сборщика (коллектора), транспорта, писателя и хранилища. Туда же, можно добавить интерфейс для отображения графиков и интерфейс для аналитики (отчётов).

...

Пройдёмся по компонентам подробнее:

Активатор

Запускает скрипты для сбора метрик.

  • Generic.get_metrics - реализация сбора метрик по SNMP, поскольку является платформо-независимой. Работа скрипта определяется конфиг-файлами, расположенными в папках snmp_metrics профиля. В ней присутствуют JSON фалйы со специфичными для профиля метрики SNMP (н-р OID’ы для памяти и процессора)  соответствующего профиля. Для добавления своих метрик, необходимо добавить файлик с ними в папку snmp_metrics. Подробнее вопрос будет рассмотрен далее.

  • Profile.get_metrics - реализует различные платформо-зависимые вещи: сбор метрик по CLI и генераторы OID'ов

  • get_capabilities - напрямую в сборе метрик не участвует, но определяет поддержку оборудованием протокола SNMP и различных ньансов работы с ним (поддержку bulk, ). В случае отсутствия поддержки SNMP, сбор метрик запускаться не будет.

  • get_interfaces - сам по себе в сборе метрик не участвует. Но он необходим в случае сбора метрик с интерфейсов, т.к. возвращает ifindex. Если не будет ifindex, то не будет метрик с интрейсов.

Дискавери

За сбор метрик отвечает Periodic дискавери. Его задачи:

...

Центральная штука, в общем.

NSQD aka транспорт

ПО очереди для работы в реальном времени с гарантированной первой доставкой. Занимается передачей сообщений из одного конца очереди в другой. NSQD необходим в одном экземпляре на каждую ноду, NSQLOOKUPD минимум 1 (2 для отказоустойчивости).

Info

Архитектурно NSQD состоит из 3 компонент: 2 обязательных и 1 опционального. 

  • процесс NSQD отвечает за работу очередей: принимает сообщения и передаёт их к месту назначения. Должен присутствовать на каждой НОДе, где есть процесс, пишущий в очередь. В случае невыполнения требования возможны потери сообщений.
  • процесс NSQLOOKUPD отвечает за поиск демонов NSQD с необходимыми топиками (очередями с сообщениями). Необходим по крайней мере в 1 экземпляре.
  • процесс NSQADMIND Это админка, к NSQD не обязательна, но позволяет просматривать различную статистику и управлять очередями (очищать, удалять и т.д.)

CHWRITER

Слушает приходящие сообщения (канал metrics) и, по мере их накопления, записывает в БД. Интервал записи поддаётся настройке. Рекомендуется держать его поближе к БД.

ClikcHouse (CH)

В качестве хранилища для метрик используется БД Clickhouse от Yandex


Сущности

  • Метрика - некоторая изменяющаяся во времени величина, подлежащая фиксации. Формально говоря, метрикой может быть любая величина: скорость интерфейса, число свободной памяти, статус интерфейса и т.д. Достаточно, чтобы она менялась во времени и представляла какой-то интерес.
    Метрики бывают:

    • Скалярные - когда одной метрике соответствует одно значение. Н-р если у устройства 1 датчик температуры, то метрике Температура будет соотв. 1 значение - показатель этого датчика. Если же, датчиков несколько, то необходимо будет создавать метрики Температура датчика 1Температура датчика 2 и т.д.
    • Векторные - когда одной метрике соответствует более одного значения. Н-р метрике Кол-во входящих пакетов соответствует столько значений, сколько интерфейсов на устройстве. Рядом с векторными метриками идёт понятие Path, рассмотрено ниже.

...

  • Генератор - потребен при сборе векторных метрик по SNMP. Реализует интерфейс дискавери метрик, раскладывая базовый SNMP OID на OID’ы по которым пойдёт сбор данных. Самый простой пример - это создание из OID’а кол-ва прошедших байт через интерфейс OID’ов для каждого интерфейса. Н-р базовый OID для входящих пакетов на интерфейс (ifInUcastPkts): 1.3.6.1.2.1.2.2.1.11, чтобы снять эту метрику для конкретного интерфейса к нему необходимо дописать его номер: 1.3.6.1.2.1.2.2.1.11.2, вот этим и занимаются генераторы. Подробнее, рассмотрены в разделе добавления метрик.

Настройка сбора метрик

Прервём поток букв(smile) и попробуем снабдить их картинками. В текущей реализации настройку сбора метрик очень упростили. Фактически, необходимо:

...

Пройдёмся по этим шагам подробнее:


Настрока Managed Object

Необходимо проверить ManagedObject:

...

  • SNMP Capabilities:
    • SNMP - базовая проверка SNMP, проходит путём опроса устройства OID  sysObjectID (.1.3.6.1.2.1.1.2.0)
    • SNMP | Bulk - поддержка устройством пакетных (Bulk) запросов
    • SNMP | IF-MIB - разрешён ли для опроса IF-MIB (если данного капса нет, то опрос метрик интерфейсов проходить не будет)
    • SNMP | IF-MIB | HC - поддержка 64-разрядных счётчиков
    • SNMP | v1, v2c, v3c - поддержка версии SNMP

Настройка Managed Object Profile

Идём в "Service Activation" -> Setup -> "Managed Object Profile". Выбираем существующий или создаём новый профиль. В нём, на вкладке Metrics нажимаем Add и выбираем метрику, которую необходимо собирать. Для этого достаточно заполнить 3 поля:

...

После, переходим на вкладку "Periodic Discovery" и активируем сбор метрик (устанавливаем галочка Enable и Metric). По необходимости, настраиваем интервал обхода.


Настройка сбора метрик с интерфейсов

Метрики для интерфейсов настраиваются в Inventory -> Setup -> "Interface Profiles". В нём необходимо аналогично Managed Object Profile добавить метрики.

...

После этого привязать профиль к интерфейсам. Это можно сделать в меню Inventory -> Interfaces. Необходимо в выпадающем списке выбрать MO и назначить профили. В это же меню можно попасть по кнопке Interfaces из "Service Activation" -> "Managed Object" -> <MO>.

Настройка Interfaces Classification Rules

Делается опционально-обязательно. Предназначены для автоматического назначения профила интерфейса на интерфейс. Конечно, можно вручную устанавливать профили интерфейсов, но это не продуктивно(smile) Поэтому можно расписать правила классификации. Делается это  из меню Inventory -> Setup -> "Interface Classification Rule".

Подробно работа с правилами расписана тут: Классификация интерфейсов.

Настройка Dashboard

Просмотр метрик идёт через Dashboard. Он доступен из интерфейса MO: в этом случае, он, автоматически, настраивается на отображение всех метрик, собираемых с данного MO или по адресу https://<AddressNOCWeb>/ui/grafana:

...

Проверить настройки можно кнопкой "Test Connection". После нажимаем Save. Наслаждаемся эффектом.

Добавление своих метрик
Anchor
add_variable_metric
add_variable_metric

Для добавления метрики необходимо выполнить 2 шага:

...

Info

Если метрика относится к параметру объекта (н-р показатель какого-нибудь датчика) - используем Environment, если метрика для интерфейса (н-р размер входящего буфера) - то scope interface. Имя задаётся через прямую черту: | это позвляет отстраивать иерархию метрик. Рекомендуется пользоваться данным соглашением


Добавлени MetricTypes

После выбора Metric Scope идём в интерфейс создания метрики: PM -> Setup -> Metric Type. И нажимаем на кнопку Добавить, заполняем поля:

...

После нажатия Save (Сохранить) можно назначить метрику в один из профилей, для сбора. Но, для того, чтобы она начала собираться необходимо создать конфигурацию для сборщика.

Настройка метрики на сборщике (активаторе)

В задаче активатору приходит список метрик (в виде имён), в зависимости от способа их получения: SNMP или не SNMP дальнейший путь расходится.

...

Info

Формулы для Scale можно написать в "<noc>/core/script/metrics.py".

Code Block
languagepy
themeEmacs
titleScale functiion
collapsetrue
def percent(value, total):
    """
    Convert absolute and total values to percent
    """
    if total:
        return float(value) * 100.0 / float(total)
    else:
        return 100.0

def percent_one(value, total):
    """
    Convert absolute and total values to percent
    """
    if total:
        return float(value) * 100.0 / (float(total) + float(value))
    else:
        return 100.0


Генераторы

Отвечают за формирование списка SNMP OIDов для сбора устройства на основе файла конфигурации. Указываются в директиве "$type" конфига.

В базовой системы реализованы следующие генераторы:

OID

Считывает OID, заданный в конфиг файле. Доступны параметры type и scale.

...

Info
Сами функции находят в файле core/script/metrics.py
percent_usage(value, total):
percent_invert(value, total):
sum(*args):
subtract(*args):
is1(x):

OIDS

Позволяет перечислять OID’ы списком с указанием path. Полезен, если метрика векторная, но сами значения наперёд известны и неизменны.

...

Здесь появляется дополнительное свойство - path. Его формат можно уточнить в MetricScope. Например, для Environment будут:

  • chassis
  • slot
  • module
  • name




CAPS

Специфичный генератор. Проверяет Capabilities, если присутствует - отрабатывает соответствующее правило
! для платформы и версии

CAPINDEX и CAPLIST

При налачии capabilities в специальном формате, позволяет сгенерировать SNMP OID по шаблону.
Capindex - Caps в виде числа, Caplist в виде чисел, разделённых символом.

MATCHERS

Реализует возможность выбора SNMP OIDов на основании платформы/версии ПО оборудования через конфигурацию. Конфигурация для метрик распологается в файликах из папки snmp_metrics профиля. Теперь в них можно применять генератор match:

...

Code Block
languagejs
{
  "$metric": "CPU | Usage",
  "$type": "match",
  "$matchers": {
    "is_5328": {
      "platform": {
        "$regex": "5328"
            }
        },
    "is_2328": {
      "platform": {
        "$regex": "2328"
            }
        }
    },
  "$match": [{
    "$match": "is_2328",
    "oid": "1.3.6.1.4.1.2011.2.23.1.18.1.3.0",
    "path": ["","","", "Current_Load"],
    "$type": "oid",
    "type": "gauge",
    "scale": 1
  },{
    "$match": "is_5328",
    "$type": "slot",
    "oid": "1.3.6.1.4.1.2011.6.3.4.1.2.{{ hwSlotIndex }}"
   },{
    "$type": "oid",
    "oid": "1.3.6.1.4.1.2011.6.3.4.1.3.0.0.0",
    "type": "gauge",
    "scale": 1
  }]
}

Генератор профиля

Есть возможность написать свой генератор, если не подходит какой-либо из стандартных. Конфиг, при этом выглядит так:

...

Code Block
languagepy
from noc.sa.profiles.Generic.get_metrics import Script as GetMetricsScript
from noc.sa.profiles.Generic.get_metrics import OIDRule
from noc.core.mib import mib

class SlotRule(OIDRule):
    # Имя генератора, должно совпадать с параметром $type в конфиге
    name = "slot"

    def iter_oids(self, script, metric):
        """
        Основной метод, должен вернуть переменные для подстановки в шаблон и путь (path)
        """
        sysSlotIndex = [0]
        i = 1
        r = {}
        # Здесь мы используем значение CAPS для определения правильного числа коммутаторов в стэке
        if script.has_capability("Stack | Member Ids"):
            sysSlotIndex = [int(index) for index in script.capabilities["Stack | Member Ids"].split(" | ")]
        elif script.has_capability("Stack | Members"):
            # Индексы коммутаторов в стеке делаем списком
            sysSlotIndex = range(1, script.capabilities["Stack | Members"] + 1)
        else:
            sysSlotIndex = [1]

        for ms in sysSlotIndex:
            r[str(i)] = "%d" % ms
            # r[str(i)] = {"healthModuleSlot": ms}
            i += 1

        for i in r:
            """
            В цикле обходим индексы и формируем переменную `hwSlotIndex`, для получения нормального OID'a используем метод `self.expand` передавая ему словарь с переменными и шаблон OID (`self.oid`)
            """
            if self.is_complex:
                # Это проверка на наличие нескольких OID (если их необходимо передавать в функцию для расчёта)
                gen = [mib[self.expand(o, {"hwSlotIndex": r[i]})] for o in self.oid]
                path = ["0", "0", i, ""] if "CPU" in metric.metric else ["0", i, "0"]
                if gen:
                    # self.type и self.scale - берутся из конфига. При необходимости, можно задавать другие параметры и получать к ним доступ здесь
                    yield tuple(gen), self.type, self.scale, path
            else:
                oid = mib[self.expand(self.oid, {"hwSlotIndex": r[i]})]
                path = ["0", "0", i, ""] if "CPU" in metric.metric else ["0", i, "0"]
                if oid:
                    yield oid, self.type, self.scale, path


Сбор метрик по CLI

В случае сбора метрик по CLI необходимо писать реализацию полноценного скрипта get_metrics для работы по CLI.

...

Code Block
languagepy
from noc.sa.profiles.Generic.get_metrics import Script as GetMetricsScript
from noc.lib.text import parse_table

class Script(GetMetricsScript):
    name = "Juniper.JUNOSe.get_metrics"

    CLI_METRICS = set(["Subscribers | Summary"])
    # Полезно указывать, какие метрики скрипт может собирать. Это исключит его запуск при сборе других метрик.

    def collect_profile_metrics(self, metrics):
        # Основной метод. При вызывается при старте скрипта 
        if self.has_capability("BRAS | PPTP"):
            self.logger.debug("Merics %s" % metrics)
            # Проверяем, что есть соответствующий CAPS и метрики, которые мы можем собрать
            if self.CLI_METRICS.intersection(set(m.metric for m in metrics)):
                # Запускаем функцию сбора. Делить скрипт на функции необязательно, но полезно для удобочитаемости
                self.collect_subscribers_metrics(metrics)

    def collect_subscribers_metrics(self, metrics):
        # if not (self.ALL_SLA_METRICS & set(metrics)):
        #     return  # NO SLA metrics requested
        ts = self.get_ts()
        # Получаем время (timestamp) и запускаем функцию сбора значений метрик с устройства
        m = self.get_subscribers_metrics()
        for bv in metrics:
            # обходим метрики (в данной переменной содержатся все метрики переданные для сбора)
            if bv.metric not in self.CLI_METRICS:
                # Если мы не можем собирать метрику - то пропускаем
                continue
            for slot in m:
                # set_metrics передаёт собранную метрику для отдачи дискавери.
                self.set_metric(
                    id=bv.id,
                    metric=bv.metric,
                    value=m[slot],
                    ts=ts,
                    path=["0", slot, ""]
                )

    def get_subscribers_metrics(self):
        """
        Returns collected subscribers metric in form
        slot id -> {
            rtt: RTT in seconds
        }
        :return:
        """
        v = self.cli("show subscribers summary slot")
        v = v.splitlines()[:-2]
        v = "\n".join(v)
        r_v = parse_table(v)
        if len(r_v) < 3:
            return {}
        # r = defaultdict(dict)
        r = dict(r_v)
        return r


Что-то пошло не так (Отладка)

Возможно разное. Если после выполненных настроек красивые графики не появились, или, внезапно, канули в болото - необходимо разобраться в причинах и починить.

Для выяснение причин отсутствия графиков имеет смысл повторно пройти все этапы настройки и проверить, не пропущена ли где запятая. Если таковую найти не удалось - идём проверять по порядку участия в PM:

Проверка выполненных настроек и дискавери.

Для начала, необходимо заглянуть в лог периодик дискавери. Проверить дату последнего запуска и заглянуть в лог. При нормальной работе там можно увидеть:

...

  • Interface metrics are not configured. Skipping - необходимо проверить назначены ли метрики на профили интерфейсов и профили интерфейсов на интерфейсы
  • SLA not configured, skipping SLA metrics - проверить профили SLA

Проверка реквизитов доступа.

Необходимо проверить, что устройство доступно с активатора по SNMP. Это делается путём запуска скрипта

...

Мы всё сделали, а данных таки нет. Попробуем выяснить - в каком месте может возникнуть проблема.

Проверка работы дискавери

Проверка работы дискавери осуществляется командой: 

...

Если есть какие-то проблемы с записью в БД в логе будут ругательные сообщения.

Проверка CH

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

...


Посмотреть отображаются ли данные и время последних записей. Если в данных пусто, а лог писателя говорит что они записаны… То необходимо подсмотреть в логе сервера ClickHouse

Отладка скрипта сбора метрик

Чтобы проверить, нет ли ошибки в скриптах, можно воспользоваться механизмом отладки, только, дополнительно передать в скрипт парметры. Делается это так:

Code Block
languagebash
# ./noc script --debug Cisco.IOS.get_metrics "xxx-sw61" metrics:='[{"metric": "Environment | Voltage", "id": 0}]'
.....
 Result: [{'scale': 1.0, 'name': 'Memory | Usage', 'tags': {'object': None}, 'ts': 1469865495320386816, 'value': 49.583421519590374, 'type': 'gauge'}]


Уточнения