Привет, Хабр! На связи Даниил Понизов и Роман Лазовский, руководитель и MLOps‑инженер команды ML‑платформы в RWB. Мы занимаемся разработкой платформы машинного обучения, в том числе — контролируем инфраструктуру и эффективное использование ресурсов.

Недавно проходил Inside AI Meetup, где мы рассказали про внедрение AIOps практик в нашей команде — видеозапись вы найдете тут.

В этой статье мы расскажем, как пришли к внедрению AIOps‑подхода для работы с алертами по утилизации ресурсов, почему стандартные методы перестали работать и как автоматизация помогла нам повысить среднюю месячную утилизацию GPU на отдельных кластерах более чем на 60%.

Стандартный подход к алертам — когда не работает

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

Приходит алерт → инженер анализирует проблему → что-то исправляет → процесс повторяется
Приходит алерт → инженер анализирует проблему → что‑то исправляет → процесс повторяется

Но со временем у такого подхода появляется несколько проблем:

  • что делать, если одинаковые алерты продолжают срабатывать снова и снова? Мы могли исправить проблему, а через день или неделю получить тот же самый сигнал и мучительно вспоминать, что именно сделали.

  • как хранить состояние алерта? Если процесс реакции состоит из нескольких этапов, где хранить контекст? Как передавать информацию между участниками процесса? Как напоминать о смене статуса, если в решении проблемы участвуют несколько команд?

  • и наконец, что делать, когда таких алертов становятся десятки или сотни в день?

Нашей задачей было не просто стандартизировать работу с алертами. Мы решали конкретную проблему распределения ресурсов. С CPU и RAM работать относительно просто: существуют эвристические подходы, которые позволяют динамически перераспределять ресурсы. С GPU ситуация сложнее.

Как понять, что GPU используется эффективно

Для начала нужно определить, что такое хорошая утилизация GPU.

Давайте прикинем, какие метрики вообще можем смотреть. Мы используем GPU в Kubernetes‑кластерах и подключаем видеокарты через GPU Operator, внутри которого работает DCGM Exporter от NVIDIA. Он предоставляет собой набор метрик, связанных с состоянием и использованием видеокарт.

Эти метрики можно разделить на четыре группы. О них ниже ↓

  1. Метрики вычислительной утилизации. Они показывают загрузку графического движка, стриминговых мультипроцессоров и тензорных ядер.

  2. Использование памяти GPU. Метрики, отражающие использование графической памяти GPU. 

  3. Физические показатели видеокарты. Температура, потребляемая мощность, наличие троттлинга из‑за перегрева или недостатка питания.

  4. Ошибки GPU. Из‑за неправильного паттерна использования видеокарт могут возникать ошибки, которые снижают пиковую производительность.

Сохраняйте памятки:

Хорошая утилизация GPU — это не только высокая загрузка вычислительных ресурсов. Нужно также следить за тем, чтобы память использовалась эффективно, карты не ограничивались физическими параметрами, а количество ошибок GPU было минимальным.

Два сценария контроля ресурсов

У нас есть два разных направления со своей спецификой.

Первое — исследовательский кластер (Research Cluster) на базе JupyterHub. Сейчас это уже далеко не коробочное решение: у нас больше 800 пользователей, которые проводят исследования.

Для CPU и RAM у нас работает динамический ресурсный менеджер. Он эвристически перераспределяет ресурсы: у тех, кто оптимально их использует, всё остаётся без изменений; из тех мест, где ресурс утилизируется неэффективно, часть CPU или RAM перераспределяется между другими задачами.

С GPU так сделать невозможно. Мы используем MIG для разделения видеокарт на меньшие логические единицы, но без остановки рабочих процессов динамически перераспределить GPU нельзя. Из‑за этого пользователи могут занимать ресурсы больше необходимого. Например, взять десять видеокарт для обучения небольшой модели, наша автоматика отключит эту машину из‑за низкой утилизации и затем пользователь просто снова может запустить такую же машину. Поэтому нужны другие подходы.

Второй сценарий — наши AI/ML и другие сервисы в проде. Их у нас тысячи, каждый сервис живёт внутри своего namespace, на который установлены ресурсные лимиты.

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

Также это продуктовые сервисы, которые приносят деньги. Мы не можем просто отключать их, как в ресерч‑кластере. Любые действия должны быть согласованы с владельцами сервисов.

Почему ручные методы не помогли

Исторически мы пробовали несколько подходов.

Для ресерч‑кластера мы создавали алерты по пользователям, отправляли их в общий канал, отмечали владельцев и ожидали, что пользователи будут самостоятельно следить за использованием ресурсов. К чему это ведёт? Через некоторое время все перестают обращать внимание на уведомления и продолжают брать максимум доступных ресурсов.

Алерты по пользователям в канале
Алерты по пользователям в канале

Тогда мы ввели своеобразный механизм отслеживания утилизации: начали собирать еженедельные отчёты и формировать список пользователей с низкой эффективностью использования ресурсов. После этого мы вручную разбирали каждый случай: почему так, можно ли что‑то изменить, какие меры применить. При сотнях пользователей такой процесс перестал масштабироваться.

Еженедельные отчёты — ручное разбирательство со злостными нарушителями
Еженедельные отчёты — ручное разбирательство со злостными нарушителями

Для продакшен‑сервисов мы использовали похожий подход: создавали алерты, отмечали ответственных, отправляли сообщения напрямую. Это также почти не повлияло на показатели утилизации.

Алерты по сервисам в личке
Алерты по сервисам в личке

Следующим шагом стали агрегированные таблицы, где мы пытались определить самые проблемные сервисы. Но и такой подход нельзя было масштабировать бесконечно…

Агрегация статистики использования ресурсов по сервисам
Агрегация статистики использования ресурсов по сервисам

Так мы начали искать способы автоматизации.

Как мы выбрали AIOps

На рынке существует подход, который позволяет автоматизировать работу с алертами — AIOps. Его идея состоит в том, чтобы собрать алерты, агрегировать их, обогатить контекстом и автоматизировать процесс реакции, в том числе с помощью AI.

Полноценных open source AIOps‑платформ практически нет. В основном такие решения представлены в виде облачных сервисов, которые нам не подошли из‑за требований к безопасности данных. Из узкого ассортимента тех, кто позиционирует себя как open source, мы выбрали KeepHQ.

Почему KeepHQ? Мы искали решение, которое было бы понятно платформенной команде, легко поддерживалось и позволяло гибко адаптировать систему под существующие процессы.

Архитектура Keep оказалась достаточно простой. Бэкэнд построен на FastAPI, фронтэнд — на Next.js, для взаимодействия используется WebSocket, база данных — PostgreSQL. Это заметно упростило деплой.

Кроме того, у Keep есть документация по Kubernetes и готовый Helm Chart. Мы изменили values‑файл и достаточно быстро развернули платформу внутри своей инфраструктуры.

Основные задачи, которые нам нужно было решить:

  • убрать дубли алертов

  • сохранить контекст

  • не терять историю коммуникаций

  • привести алерты к единой модели

В Keep для этого есть необходимые компоненты: провайдеры интеграций, UI, воркфлоу для автоматизации, обогащения и дедупликации.

Дедупликация и обогащение алертов

Первый важный вопрос: что считать одной проблемой? Конкретный под? Namespace? Кластер? Нам было важно управлять этой сущностью гибко и не хранить всё только в системе мониторинга.

Keep стал агрегирующим слоем после Grafana. Он предоставляет визуальное представление всех алертов, их текущее состояние и полную историю изменений. При этом KeepHQ не заменяет Prometheus и Grafana. Мониторинг по‑прежнему обнаруживает отклонение и формирует технический сигнал, а KeepHQ работает как process‑ и orchestration layer: хранит состояние кейса, связывает повторные события, добавляет владельца и контекст, запускает workflow и контролирует, чем закончилась обработка проблемы.

Отдельная проблема — бесконечный поток сообщений в чатах.

Алерты по утилизации отличаются от классических аварийных алертов. Если сервер упал, нужно срочно реагировать. Но низкая утилизация ресурса часто является долгим процессом: нельзя просто отключить продакшен‑сервис, не понимая его зависимостей.

Здесь помогает механизм дедупликации KeepHQ. Для каждого типа сигнала мы определяем набор полей, идентифицирующих одну проблему. Повторные срабатывания с тем же ключом не создают новые независимые алерты, а обновляют существующий объект, сохраняя его статус, историю и процессные поля. Через систему прошло около 400 тысяч событий, при этом коэффициент дедупликации составил около 99%.

Следующий слой — обогащение.

Технические данные приходят из Grafana: метки утилизации, ресурсы, namespace, сервисы. Но нам также нужна процессная информация: статус проблемы, история коммуникации, связь с конкретными сообщениями. Keep позволяет добавлять эти данные и отслеживать весь жизненный цикл проблемы.

Автоматизация процесса

Просто видеть алерт недостаточно: система должна контролировать его дальнейший жизненный цикл. Workflow в KeepHQ состоит из триггера, условий и последовательности действий. Он может запускаться при поступлении события, вручную или по расписанию, выбирать алерты в нужном статусе, проверять дедлайны, менять enriched‑поля, вызывать внешние API и переводить кейс на следующий этап. YAML‑представление позволяет хранить такую логику как код, версионировать и проводить ревью изменений.

Со временем мы разделили воркфлоу на группы:

  1. основные воркфлоу описывают жизненный цикл кейса: поиск владельца, ожидание ответа, срок на исправление, проверку обоснования и эскалацию

  2. сервисные воркфлоу поддерживают консистентность данных: синхронизируют enriched‑поля, закрывают устаревшие кейсы и возвращают в обработку алерты, у которых закончился период исключения. Такое разделение позволяет менять отдельный этап процесса, не затрагивая весь пайплайн

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

Когда появляется проблема с утилизацией, система сначала пытается определить владельца сервиса и сообщает ему, какой ресурс используется неэффективно. При этом найденный ответственный не всегда оказывается настоящим владельцем. Сервисы могут переходить между командами, зоны ответственности — меняться, а информация о владельцах — устаревать. Поэтому человек может сообщить, что сервис ему не принадлежит. В таком случае проблема не закрывается и не теряется: система продолжает поиск корректного ответственного.

Если владелец найден, он должен выбрать, что делать дальше: подтвердить проблему и взять время на исправление либо объяснить, почему текущий объём ресурсов необходим. Например, сервис может держать резерв под пиковую нагрузку, обеспечивать требуемое время ответа или не иметь возможности быстро масштабироваться. Само обещание исправить проблему не считается результатом. Система запоминает договоренность и спустя установленное время проверяет, изменилась ли утилизация. Если проблема действительно устранена, процесс завершается. Если ресурс продолжает использоваться неэффективно, кейс возвращается в работу и переходит к эскалации.

Как выглядит процесс обработки проблемы

Когда алерт приходит из Grafana, запускается основной воркфлоу утилизации.

Первое действие — поиск владельца сервиса. Если владелец найден, ему отправляется уведомление о проблеме. Если нет — мы повторяем поиск.

Человек может выбрать, что он не ответственный. Это нормально, потому что мы правда можем неправильно связать сервис с пользователем. В большой инфраструктуре всегда есть шанс столкнуться с такой проблемой.

Владелец подтверждает проблему и обещает исправить её в определённый срок. Если проблема решена — процесс завершается. Если нет — начинается эскалация.

Если проблему нельзя исправить сейчас, владелец может запросить временное исключение, указав срок и обоснование. После проверки алерт выводится из активной обработки, но остаётся в KeepHQ вместе с владельцем, причиной, комментарием и датой пересмотра. По окончании срока workflow автоматически возвращает кейс в активный контур. Таким образом, исключение работает как контролируемая отсрочка, а не как бессрочное отключение уведомления.

Главная идея нашей статусной модели — это замкнутый жизненный цикл. Промежуточные статусы не являются финалом. Главное состояние — проблема должна быть решена.

Где здесь AI

Мы не рассматривали AI как инструмент, который полностью заменит человека и самостоятельно будет управлять инфраструктурой, однако, конечно, хотели увидеть пользу от выбора AI‑автоматизации. В open source версии Keep AI‑возможности оказались достаточно ограниченными.

Из полезного мы попробовали несколько сценариев:

  • первый — использование LLM внутри воркфлоу. Через любого провайдера можно вызвать модель и выполнить такие задачи, как нормализация данных, определение проблемы или суммаризация

  • второй — AI Workflow Builder Assistant. Он позволяет описать задачу в чат‑формате, после чего Keep может автоматически создать YAML‑описание воркфлоу. Для нас этот инструмент оказался полезен как генератор первоначальной структуры workflow: он помогал быстрее собрать YAML‑черновик и проверить общую последовательность шагов. Однако условия, интеграции и переходы между статусами мы всё равно адаптировали и проверяли вручную

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

Что пришлось доработать в Keep

Keep — это open source, поэтому мы ожидали, что придётся что‑то менять. Так и получилось.

Первое, что мы доработали — Python step. Изначально Python step был рассчитан фактически на выполнение короткого выражения. Но требовалась полноценная логика: запуск многострочных скриптов, работа с зависимостями и доступ к контексту алерта, enriched‑полям, переменным и результатам предыдущих шагов. Поэтому мы расширили step до script‑based выполнения с передачей полного контекста workflow.

Второе — механизм отмены и подавления алертов. Нужно было сохранять дополнительные поля: причины отмены, сроки и другую информацию. По умолчанию Keep не сохранял эти данные после возвращения алерта в активное состояние.

Третья задача — работа с устаревшими алертами. Мы сознательно принимаем алерты из Grafana через webhook, чтобы контролировать набор сигналов, поступающих в KeepHQ. Но webhook не обеспечивает полную синхронизацию жизненного цикла сущностей. Если правило удалили, переименовали или изменили его labels, старый объект в KeepHQ может больше не получать обновлений и остаться активным. Поэтому было решено добавить сервисный workflow, который обнаруживает такие устаревшие кейсы и переводит их в корректное состояние.

Также мы внесли небольшие изменения в UI и исправили работу LLM‑провайдера (он не подключался просто из коробки).

Результаты

Мы начали внедрение автоматизации на небольшом количестве кластеров и namespace.

На одном из кластеров удалось увеличить среднюю месячную относительную утилизацию на 62%. На других кластерах рост составил около 40%, а в некоторых случаях заметного эффекта не было. Иногда ресурс уже используется максимально эффективно или его нельзя уменьшить из‑за особенностей работы сервисов.

Несколько неожиданно — AI в AIOps‑платформе KeepHQ для наших задач практически не сыграл роли. AI‑функции оказались скорее способом автоматизировать небольшие ручные действия, а не полноценным инструментом управления инфраструктурой.

Основную пользу дал сам подход AIOps: мы смогли выстроить прозрачный процесс работы с алертами, сохранить контекст, автоматизировать коммуникацию и сделать управление ресурсами более системным. Именно это позволило повысить эффективность использования инфраструктуры и лучше понять, где все еще остаются точки роста.

Что планируем внедрять дальше:

  • AI‑валидация обоснований и логики отклонения

  • AI‑агент для рекомендаций по повышению утилизации

  • автоматический поиск ответственного за сервис

  • расширение статистики, метрик и дашбордов

  • улучшение запросов для поиска кейсов недоиспользования ресурсов

  • гибкое управление порогами алертов.

Будем ждать ваших комментариев! Расскажите, как вы справляетесь с похожими проблемами.


Больше про машинное обучение — в telegram‑канале RWB делает ML. Подписывайтесь!