Наша команда из трёх человек управляет Kubernetes в продакшене — поэтому мы создали ИИ-SRE
Мы создаём децентрализованную платформу данных. Данные клиентов никогда не покидают их инфраструктуру — это наше обещание. Чтобы его выполнить, мы эксплуатируем пять кластеров Kubernetes в нескольких регионах Scaleway, в каждом из которых работают PostgreSQL, MinIO, Qdrant, Argo Workflows и сервис данных на FastAPI. Межкластерная коммуникация идёт по mTLS через Skupper. Деплои проходят через GitOps-пайплайны ArgoCD.
Звучит как инфраструктура компании, у которой есть команда платформенной инженерии (platform engineering). У нас её нет. Нас трое.
Когда под падает в три часа ночи, телефон звонит у CTO. Когда синхронизация ArgoCD ломается прямо во время демо для клиента, дежурной ротации нет — есть только тот, кто первым это заметит. Мы обслуживаем продакшен-инфраструктуру для реальных клиентов с реальными данными, и честно признаём: на протяжении многих месяцев наш процесс реагирования на инциденты выглядел так — «проверить Slack, надеяться, что ничего серьёзного, разобраться и починить».
Нам нужна была помощь. Не дашборд и не ещё одно правило алертинга. Настоящая пара рук, способная посмотреть на оповещение, понять, реальное ли оно, разобраться в причине и либо самостоятельно исправить, либо подсказать, куда смотреть.
Мы это и построили.
Ловушка усталости от алертов
Для наблюдаемости (observability) мы используем SigNoz — трейсы, логи, метрики, полный стек OpenTelemetry. Мы потратили немало времени на настройку правил алертинга: высокий процент ошибок, циклические перезапуски подов (crash loops), сбои синхронизации ArgoCD, предупреждения о заполнении PVC, аномалии задержек, ошибки баз данных и так далее.
Алерты работают. В этом и проблема.
Большинство из них — шум. Heartbeat тестового тенанта возвращает несколько 401 из-за неверного API-ключа? Скорее всего, безобидно, но стоит проверить, не атака ли это. MCP-сервис формирует корневой спан длительностью 30 секунд из-за таймаута Istio — это не проблема с задержкой, просто так работает Streamable HTTP. Под на дев-кластере перезапустился один раз, превысив лимит памяти при крупном импорте, — и самостоятельно восстановился.
Но часть алертов — настоящие. И по одному только Slack-уведомлению не поймёшь, какие именно. Каждый требует одних и тех же первых пяти минут: зайти в нужный контекст по SSH, выполнить kubectl get pods, проверить логи, посмотреть трейсы, выяснить, не мерджили ли что-нибудь недавно. Расследование однообразное, механическое и при этом совершенно необходимое.
Мы тратили часы каждую неделю на разбор алертов. В большинстве случаев итог был один: «всё в порядке, игнорируем». Немногочисленные реальные инциденты получали такой же замедленный отклик, как и шум, — потому что мы уже были измотаны.
Что если бы рунбук мог выполнять сам себя?
В каждой ops-команде есть рунбуки. Наш теперь живёт в файле CLAUDE.md — структурированный документ, описывающий действия для каждого типа алерта. Проверь поды. Проверь логи. Проверь свежие MR. Если падает один под — перезапусти его. Если проблема связана с базой данных — немедленно эскалируй. Никогда, ни при каких обстоятельствах не удаляй приложение ArgoCD (этот урок мы усвоили на собственном горьком опыте — каскадное удаление всех управляемых ресурсов, мгновенный продакшен-аутаж).
Рунбук складывался месяцами отладки и был хорошим. Проблема в том, что его нужно читать и исполнять живому человеку в три ночи с затуманенной головой.
У Anthropic есть ответ на это: Claude Code только что получил новую функцию под названием каналы (channels) — возможность отправлять внешние события в работающую сессию Claude. Не поллинг. Не чат-бот, которому задают вопросы. Живая сессия, принимающая вебхуки, алерты и сообщения и самостоятельно на них реагирующая.
Мы поняли: если направить алерт SigNoz в сессию Claude, и эта сессия имеет доступ к kubectl, к git для проверки кода, а в качестве системного промпта использует наш рунбук — получается агент SRE.
Мы собрали его за один день.
Архитектура
Конфигурация намеренно простая:
Два кастомных сервера каналов обеспечивают ввод и вывод данных:
-
Канал вебхуков слушает порт 8788, принимая вебхуки в формате Alertmanager от SigNoz. Когда срабатывает алерт, SigNoz отправляет POST с данными, канал разбирает их в структурированное событие, которое поступает в сессию Claude с метаданными: имя алерта, серьёзность, сервис и кластер.
-
Канал Slack подключается через Socket Mode (WebSocket, без публичного URL) и обеспечивает связь агента с личными сообщениями CTO. Агент может отправлять сообщения, CTO — отвечать. Полноценный двусторонний диалог. Также встроен таймер эскалации: если агент пометил что-то как критическое, а CTO не ответил в течение 10 минут, агент напоминает. Снова. И снова.
Вся инфраструктура — одна виртуальная машина у нашего облачного провайдера. Два ядра процессора, два гигабайта оперативной памяти, 6 евро в месяц.
Паттерн делегирования
Вот техническая идея, которая сделала всё это практичным.
У сессии Claude Code есть контекстное окно (context window). Каждый вызов инструмента, каждый вывод kubectl, каждый дамп логов потребляет токены. Если агент расследует каждый алерт напрямую, контекст заполнится за несколько часов, и сессия станет бесполезной.
Решение: главный агент никогда не расследует сам. Он делегирует.
Когда приходит алерт, главный агент читает метаданные — имя алерта, серьёзность, сервис, кластер — и быстро принимает фильтрующее решение. Resolved-алерты записываются в лог и игнорируются. Известный шум (heartbeat тестовых тенантов) отклоняется. Всё остальное порождает субагента.
Субагент — это свежий экземпляр Claude с собственным контекстным окном. Он получает детальный промпт: «Расследуй алерт High Error Rate на сервисе backend в кластере platform-dev. Проверь поды, проверь логи, проверь, не мерджили ли MR в последний час. Доложи: реальный алерт или ложноположительный, корневая причина, рекомендуемое действие».
Субагент выполняет всю тяжёлую работу — запускает команды kubectl, запрашивает трейсы из SigNoz, обращается к GitLab API за свежими мерджами, читает git log. Он возвращает краткое резюме. Затем завершает работу. Его контекст удаляется.
Главный агент читает резюме и принимает решение: автоматически исправить, эскалировать или проигнорировать. Его контекст остаётся чистым. Он может работать днями.
Учим его, что безопасно
Автономность без ограничений — это риск. Мы провели чёткие границы.
Безопасные операции — агент выполняет их без согласования:
-
Перезапустить деплоймент (
kubectl rollout restart) -
Удалить зависший под (Kubernetes пересоздаст его)
-
Очистить зависший Argo Workflow
-
Принудительно обновить приложение ArgoCD
Запрещённые операции — зафиксированы в рунбуке и ограничены RBAC ServiceAccount для kubectl, не подлежат пересмотру:
-
Никогда не удалять ArgoCD Application (каскадно удаляет все управляемые ресурсы)
-
Никогда не удалять неймспейс, PVC или секрет
-
Никогда не трогать операции с базами данных
-
Никогда не масштабировать что-либо до нуля
-
Никогда не пушить в git
Всегда эскалировать — требует суждения человека:
-
Ошибки баз данных
-
Проблемы с сертификатами или mTLS
-
Одновременное затрагивание нескольких сервисов
-
Всё, что агент не понимает до конца
-
Всё, что требует вмешательства
Агент также адаптирует поведение под среду. На дев-кластерах он либерален — свободно перезапускает компоненты, отправляет одно непринуждённое сообщение в Slack, если что-то странное. В продакшене он параноидален — проверяет дважды, агрессивно эскалирует и напоминает каждые 10 минут при отсутствии ответа.
RBAC принудительно соблюдает эти границы на уровне Kubernetes. ServiceAccount агента может читать всё, но писать — только в деплойменты (для перезапусков) и удалять поды и воркфлоу. Физически удалить приложение ArgoCD он не может, даже если инструкции рунбука каким-то образом будут обойдены.
Память об инцидентах
Агент перезапускается каждый день в 4 утра с чистым контекстным окном. Наивный подход: он забывает всё. Наш подход: нет.
Каждое расследование — закончилось ли оно «шумом», «автоматическим исправлением» или «эскалацией» — записывается в SQLite-базу на виртуальной машине. Прежде чем субагент начнёт что-либо расследовать, его первый шаг — проверить историю: «Этот алерт срабатывал раньше? Сколько раз? Каков был вердикт?»
При запуске агент получает сводку, сгенерированную из базы данных:
=== Сводка SRE — последние 7 дней === Всего: 47 алертов | 38 шум | 6 реальных | 3 исправлено автоматически | 3 эскалировано Повторяющийся шум (рекомендуется настройка): - High Latency на openaire-test | 12x - Tenant Inactive на tenant-test-* | 8x Недавние реальные инциденты: - [17 апр] Под CrashLooping на backend — исправлено автоматически: OOMKilled, восстановился - [16 апр] ArgoCD Out-of-Sync на data-cluster — эскалировано: некорректные helm values Необработанные эскалации: - [16 апр] PVC на 87% на data-cluster-biorxiv — продолжает расти
Это меняет поведение агента. Алерт, который двенадцать раз за неделю оказывался шумом, мгновенно отклоняется вместо полноценного расследования. Алерт, который во вторник оказался реальным, эскалируется быстрее.
И вот обратная связь, которая делает сам алертинг лучше: когда агент обнаруживает повторяющийся шум, он пишет CTO конкретное предложение по настройке. «High Latency на openaire-test срабатывал 12 раз за 7 дней и каждый раз оказывался шумом. Предложение: увеличить окно оценки с 10 до 20 минут или перейти на детекцию аномалий». Конфигурация алертинга улучшается со временем автоматически.
Первый день
Агент запустился в боевом режиме в среду во второй половине дня. Буквально через несколько минут он уже обрабатывал реальные алерты.
Первым делом он корректно отклонил пачку алертов «High Latency» на тестовых сервисах как временный шум. Никакого расследования — просто распознавание паттерна по рунбуку. Именно то, что мы сделали бы вручную, только вручную мы добрались бы до этого спустя час.
Затем он поймал ArgoCD App Out-of-Sync на дата-кластере. Запустил субагента для расследования, определил, что автоматически исправить нельзя (сбои синхронизации требуют ревью git diff человеком), и эскалировал в Slack — с полным контекстом: что проверил, что нашёл и что рекомендует.
CTO был на встрече. Агент напоминал. Десять раз за следующие два часа. «Всё ещё не подтверждено. Напоминание №7». «CTO недоступен уже 90 минут». Он неустанен. Не отвлекается, не забывает, не решает, что всё, наверное, нормально.
Когда CTO наконец ответил в Slack — с телефона, прямо во время встречи — разговор продолжился в треде. «Что изменилось в последнем деплое?» Агент проверил. Двусторонняя асинхронная работа с инцидентом прямо с экрана телефона.
Больше всего нас удивило другое: агент правильно понял, что неймспейсы tenant-test-* — это тестовые окружения с известными проблемами heartbeat, хотя мы упомянули об этом в рунбуке одной строкой. Он никогда не расследовал эти алерты. Просто записывал «известная проблема, игнорирую» и шёл дальше.
Цифры
Виртуальная машина стоит €6,50 в месяц. Агент работает на нашей существующей подписке Claude Team — никаких расходов за каждый вызов API, никаких тарифов по счётчику, никаких неожиданных счетов. Предельная стоимость агента SRE — буквально стоимость виртуальной машины.
Для сравнения: AI-расследования Watchdog у Datadog стоят $800 за 20 штук, то есть $40 каждое — и в результате вы получаете сводку о том, что, возможно, не так. SSH-подключиться и починить нужно самостоятельно. При нашем объёме алертов мы бы потратили пакет за пару дней.
Но само сравнение упускает суть. Мы выбирали не между нашим агентом и Datadog. Мы выбирали между нашим агентом и «никем». Реальная альтернатива для стартапа нашего размера — не корпоративный продукт за $40 за расследование. Это «никто не смотрит на алерты, пока что-то не сломается настолько серьёзно, что придётся кого-то разбудить».
Настоящая ценность не в цене. Она в инцидентах, которые обнаруживаются в 3 ночи, а не тлеют до утра. В том, что CTO не нужно переключать контекст в середине встречи с клиентом, чтобы разобраться с шумом. В спокойствии и нормальном сне.
Собери своё
Паттерн универсальный. Нужны три вещи:
-
Инструмент мониторинга, совместимый с Alertmanager (SigNoz, Prometheus, Grafana — всё, что умеет отправлять вебхуки)
-
Claude Code с каналами (отправка событий в работающую сессию)
-
Небольшая виртуальная машина (любая, способная запустить Node.js и kubectl)
Канал вебхуков занимает около 80 строк TypeScript. Он принимает POST, разбирает payload Alertmanager и отправляет его в сессию Claude как событие канала. Вот и всё.
Канал Slack сложнее — подключение через Socket Mode, инструменты для ответов, передача разрешений, таймер эскалации — но ядро то же самое: принимать события извне, отправлять их в Claude, давать Claude вызывать инструменты в ответ.
Ключевая идея — рунбук как код. Если у вас есть рунбук — даже неформальный, существующий только у кого-то в голове — его можно записать как CLAUDE.md. Формат не важен. Важно явно зафиксировать:
-
Что проверять для каждого типа алерта
-
Что безопасно исправлять автоматически
-
Что требует участия человека
-
Насколько срочно эскалировать
Рунбук нашего агента — около 350 строк основных правил плюс дюжина playbook-файлов для конкретных алертов, которые субагенты загружают по требованию. Playbook-файлы хранятся отдельно — в контексте главного агента находится только логика диспетчеризации, а не все возможные команды kubectl для всех типов алертов. На написание ушёл один день. Теперь он выполняется круглосуточно.
Весь исходный код открыт: github.com/the-alien-club/ai-sre
Что дальше
Мы думаем над тем, чтобы агент создавал задачи в Jira для повторяющихся паттернов. Не просто эскалировал в Slack, а реально документировал проблему, прикладывал ссылки на релевантные MR и назначал задачу на проработку.
В перспективе мечта — проактивное обнаружение. Агент уже имеет доступ к метрикам, трейсам и логам. Теоретически он мог бы заметить медленный рост потребления памяти или постепенно увеличивающийся процент ошибок ещё до достижения порога алерта. До этого пока далеко, но инфраструктура уже готова.
Пока у нас есть то, чего не существовало ещё на прошлой неделе: SRE, который никогда не спит, не устаёт от алертов и обходится дешевле обеда для всей команды. Для трёхчеловеческого стартапа, управляющего продакшен-Kubernetes, это не приятный бонус. Это выживание.