В AWS рассказали, как устроили самовосстановление GPU-узлов в Kubernetes: в их тестах полный цикл от обнаружения критического сбоя до запуска нагрузки на новой ноде укладывается меньше чем в 12 минут. Для команд, которые гоняют ML-нагрузки на Amazon EKS, это не красивая автоматизация, а способ не держать инженера на ночном дежурстве из-за «отвалившейся» видеокарты или умершего runtime.
Как пишет The New Stack, в AWS исходили из довольно приземленной реальности: на масштабе в десятки тысяч кластеров даже редкие аппаратные сбои происходят по нескольку раз в день. У GPU пропадает устройство на шине PCIe, у контейнерного runtime случаются зависания, у сетевых интерфейсов бывают странные исчезновения. Раньше типичный сценарий выглядел так: оператор замечает проблему на дашборде, заходит на узел, cordon, drain, удаление инстанса, ожидание замены. Каждое действие ручное, каждое съедает время, а ночью и в выходные деградация спокойно может висеть часами.
Чтобы убрать человека из этого цикла, AWS собрала EKS Node Monitoring Agent. Агент отслеживает проблемы на ноде и публикует их в Kubernetes через NodeCondition, а дальше решение о ремонте и замене подхватывает Karpenter. В EKS Auto Mode эта схема встроена по умолчанию: сама платформа управляет выделением вычислений, масштабированием, патчингом ОС и безопасностью, а для GPU-нагрузок умеет подбирать семейства инстансов вроде P5, P6 и G6. Для обычных managed node groups и самостоятельных установок Karpenter агент доступен как add-on. Отдельно AWS уточняет, что код агента в 2026 году стал open source, так что логику можно разбирать и дорабатывать без гадания по черному ящику.
Что именно AWS считает «здоровьем» ноды
Один из самых полезных выводов в этой истории: проблемы ноды и проблемы приложения нельзя складывать в одну корзину. Kubelet и так публикует стандартные состояния вроде DiskPressure, MemoryPressure и PIDPressure, но AWS принципиально не использует их как триггер на замену узла. Логика простая: если приложение само сожрало память или забило PID, пересоздание ноды просто перевезет ту же проблему на другую машину. Поэтому агент следит за тем, что kubelet обычно не покрывает: сбои ядра, контейнерного runtime, сети, хранилища и ускорителей. Для каждой аномалии есть только две категории: terminal condition, после которой нода идет на ремонт, и informational event, который лишь сигнализирует оператору.
Среди терминальных случаев для GPU AWS перечисляет весьма конкретные вещи: несовпадение числа доступных GPU, критические XID-ошибки, double-bit ECC, проблемы NVLink и NVSwitch, отсутствие Fabric Manager, а также некоторые неустранимые ошибки в Neuron-ускорителях. В событийную, но не фатальную группу попадают перегрев, power warnings, деградация PCIe-линка, пороги page retirement и ряд сетевых или дисковых аномалий. Здесь важен не сам список, а дисциплина классификации. В AWS прямо пишут, что однажды изменили серьезность причины NvidiaDeviceCountMismatch с warning на fatal и тут же получили побочные эффекты: сломались дашборды, у клиентов поехала автоматизация ремонта, а поведение кластера стало иным просто из-за смены severity. Вывод у них жесткий: reason code в NodeCondition нужно воспринимать как API-контракт, где переименование или смена уровня серьезности уже тянет на breaking change.
Второй нетривиальный момент касается статусов Absent и Unknown. Для оператора они звучат почти одинаково, но для автоматики разница критична. Если монитор отключен, агент не должен писать Unknown: кто-нибудь downstream однажды решит, что это повод к ремонту. Поэтому в AWS выбрали третью опцию: если монитор не работает или выключен, condition просто не публикуется. На бумаге это выглядит мелочью, а на практике именно такие «мелочи» потом отправляют здоровые узлы в drain.
Почему в GPU-кластерах опасен даже полезный агент
Самый показательный фрагмент материала связан не с аппаратными сбоями, а с тем, как агент сам начал мешать training-нагрузкам. На одном из крупных распределенных GPU-тренингов клиент заметил периодические просадки производительности и в итоге выяснил, что их создает сам Node Monitoring Agent. Причина была неприятно банальной: независимые goroutine у разных мониторинговых задач просыпались синхронно, давали резкий CPU burst и в обычном веб-сервисе остались бы незаметны, но в тесно синхронизированном distributed training даже микрозадержка на одной ноде тормозит весь коллектив NCCL. Клиент просто отключил агент, и производительность сразу выросла. Для команды, которая строит систему защиты ноды, это, мягко говоря, плохой сигнал.
Исправление тоже оказалось показательным своей приземленностью. В AWS добавили стартовый jitter к интервалам опроса, чтобы goroutine не выстреливали одновременно; закешировали системные вызовы к /proc; а обработчики с одинаковым интервалом перевели на более предсказуемую последовательную очередь. Это не меняет громкий маркетинговый слоган про self-healing, но меняет то, насколько инструмент годится для реального production. Урок здесь полезен далеко за пределами EKS: для чувствительных GPU-кластеров важен не только средний расход CPU агентом, но и форма этого расхода во времени. Ровные 0,5% процессора почти никто не заметит; те же 0,5%, собранные в короткие пики, могут обернуться потерянными часами тренировки.
Еще один практический вывод касается задержек детекта. AWS отдельно пишет, что измерять нужно не скорость самого агента, а всю цепочку сигнала. Для kernel panic бутылочным горлышком может оказаться journald и его flush cadence, а не poll interval агента. Для критических GPU-событий картина лучше: нарушения по линии DCGM policy violations, включая часть XID и ECC-ошибок, прилетают почти мгновенно, без polling, фактически в субсекундном режиме. Но другие проверки, например состояние NVSwitch fabric health или clock throttle, идут через окно поллинга с нижней границей в пять минут. Отсюда следствие для SLO: нельзя обещать «30 секунд на детект» вообще для всего подряд, если часть источников физически живет по другим таймингам.
Сама цепочка ремонта у AWS выглядит так: агент фиксирует терминальную проблему и переводит condition в False, Karpenter стартует таймер терпимости, затем проверяет защитные ограничения и только после этого taint, drain, termination и запуск замены. Для ускорителей окно ожидания составляет 10 минут, для остальных категорий, включая kernel, runtime, storage и networking, 30 минут. Дополнительно действует safety gate: одновременно нельзя ремонтировать больше 20% нод в одном NodePool, чтобы массовый сбой из-за неудачного AMI или зональной аварии не превратился в самоуничтожение кластера. Если fault transient и condition успевает очиститься до конца окна, таймер просто сбрасывается. Если нет, нода уходит на замену.
От диагностики AWS тоже не стала требовать чудес в реальном времени. Компания отделила быстрый detection от тяжелого diagnosis: агент не таскает подробные логи в горячем пути, а собирает их по запросу через NodeDiagnostic CRD и команду kubectl ekslogs <node-name>. В их тестах сборка лог-бандла занимает около семи секунд, хранится он 10 минут, а доставка идет через Node Log Query API, который в Kubernetes 1.36 получил статус GA. Для закрытых managed-окружений без SSH это, пожалуй, даже важнее самой авто-замены: broken node исчезнет, но без артефактов вы так и не поймете, был ли это единичный вылет драйвера или системная проблема образа.
Для рынка это еще один сигнал, что Kubernetes все меньше терпит ручной «героизм» и все больше требует инженерии вокруг инфраструктурных контрактов: reason codes, safety breakers, latency budget, границы ответственности между kubelet и внешней автоматикой. Особенно это касается дорогих GPU-кластеров, где ошибка в классификации сбоя стоит не только нервов SRE-команды, но и очень конкретных GPU-часов. Подробности разбора собраны в материале .