Почему мониторинг – это не набор графиков, а основа управления ИТ-системой

Изображение: Magnific.com
В распределенной ИТ-системе все компоненты могут оставаться доступными, а пользовательский сценарий при этом перестает выполняться. Логи в такой ситуации показывают отдельные события, но не позволяют быстро понять, где возникла деградация и что стало ее причиной. В результате инженерное расследование превращается в последовательную проверку десятков гипотез, а команда нередко вынуждена откатывать изменения, не успев разобраться в поведении новой архитектуры. Почему мониторинг должен закладываться в систему до запуска и как одна метрика помогла найти ошибку, которую не показывали ни тесты, ни логи, рассказывает Богдан Евстратенко, разработчик компании ITKey.

В ИТ мониторинг часто воспринимают как вспомогательную задачу. Сначала нужно разработать продукт, запустить сервис, перенести данные, закрыть релиз, а графики, алерты и дашборды можно настроить потом, когда появится время. На практике время на мониторинг редко появляется само. Зато время на расследование инцидента без мониторинга находится всегда: обычно ночью, перед важной демонстрацией или в момент пиковой нагрузки.

Один из показательных случаев произошел в 2017 году во время миграции критичного компонента системы распознавания документов с Redis на Aerospike. Снаружи продукт выглядел просто: пользователь загружал документ и получал структурированные данные. Внутри работал распределенный пайплайн: микросервисы на FastAPI обменивались сообщениями через RabbitMQ, воркеры параллельно обрабатывали страницы, а промежуточные статусы и метаданные хранились в Redis.

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

На тестах всё выглядело корректно. Документы на 200–300 страниц проходили обработку, end-to-end-сценарии завершались, очевидных ошибок в логах не было. Но накануне демонстрации менеджер по продажам попросил проверить реальный документ потенциального клиента: счет на несколько тысяч страниц. Именно этот сценарий показал, что система работает только на ограниченном наборе тестовых данных.

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

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

Команда начала проверять стандартные гипотезы: зависание воркеров, изменение семантики записи и чтения метаданных, ограничения Aerospike, ошибки в логике миграции. Постепенно появилась закономерность: документы на 100–300 страниц обрабатывались нормально, после 500–600 страниц система начинала деградировать, а около тысячи страниц сценарий уже не доходил до результата.

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

В результате расследование превратилось в перебор версий. Каждую гипотезу нужно было воспроизвести, дождаться деградации, сравнить логи, внести изменение и повторить проверку. В распределенной системе без наблюдаемости это уже не инженерная диагностика, а попытка восстановить картину по косвенным признакам.

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

Позже версию с Aerospike развернули повторно, но уже с мониторингом: Prometheus, Grafana, экспортеры, инфраструктурные и прикладные метрики. Команда начала смотреть не только на состояние воркеров и очередей, но и на сеть, базу данных, объемы передаваемых данных и характеристики операций.

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

График сразу сузил область поиска. Вместо десятков версий остался небольшой набор мест, где сервисы записывали и читали метаданные из Aerospike. Причина оказалась почти простой: в SDK Aerospike был параметр, который определял, какие данные возвращать после сохранения записи. Из-за его значения система после записи получала обратно не минимальный ответ и не нужные поля, а все сохраненные метаданные документа.

На небольших файлах это почти не проявлялось. Поэтому тесты на 200–300 страницах проходили. Но в документах на 500–1000 страниц метаданных становилось значительно больше, особенно если в счете было много строк и детализации по биллингу. Каждый лишний возврат данных увеличивал сетевую нагрузку, а при росте размера документа эффект становился лавинообразным. В какой-то момент инфраструктура переставала успевать обрабатывать этот объем, и пайплайн деградировал.

Исправление заняло минуты: нужно было изменить один параметр. После этого большие документы начали проходить обработку стабильно, а ограничением снова стали вычислительные мощности воркеров, а не непредвиденная нагрузка между сервисами и хранилищем.

Что на самом деле показала эта история

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

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

В нашем случае метрики не «магически» нашли баг. Они резко сузили область поиска. До графика с исходящим трафиком Aerospike у команды было несколько равноправных версий: очередь, воркеры, таймауты, база, сеть, логика пайплайна. После графика стало понятно, что нужно смотреть на операции записи и чтения метаданных. Это и есть практическая ценность наблюдаемости: она не отменяет инженерное расследование, а делает его короче и точнее.

Важно развести два понятия. Мониторинг отвечает на заранее известные вопросы: доступен ли сервис, растет ли latency, сколько ошибок, сколько ресурсов занято, сработал ли алерт. Наблюдаемость шире: она позволяет задавать системе новые вопросы, когда заранее неизвестно, где искать причину. Тихая деградация живой распределенной системы —  как раз такой случай. Логи показывали отдельные события, но не давали картины. Метрики трафика показали направление расследования.

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

Почему это важно для облачной инфраструктуры

На уровне одного OCR-пайплайна такая история заканчивается ночным откатом и разбором причины. В облачной платформе цена той же ошибки выше. Если деградация возникает не в одном прикладном сервисе, а в инфраструктурном слое, она может затронуть виртуальные машины, хранилище, сеть, API, порталы администрирования и команды эксплуатации сразу у нескольких внутренних заказчиков.

Именно поэтому для платформ вроде KeyStack мониторинг не может быть внешней надстройкой, которую подключают «когда-нибудь потом». В облачной инфраструктуре он должен быть частью эксплуатационной модели. Администратору нужно видеть не только состояние отдельных узлов, но и поведение OpenStack-сервисов, гипервизоров, очередей, хранилищ, сетевых компонентов, алертов и пользовательских операций в портале.

Здесь важен не сам набор инструментов, а то, какие вопросы они позволяют закрывать. Команде эксплуатации нужно быстро понять, где начинается деградация: на уровне вычислений, сети, хранилища, очередей, API или пользовательского сценария. В KeyStack для этого используется отдельный контур мониторинга и логирования, который помогает собирать метрики, строить дашборды, настраивать оповещения и анализировать события в распределенной инфраструктуре. Для платформы, рассчитанной на enterprise-контуры, это не дополнительная опция, а условие нормальной промышленной эксплуатации.

Когда инфраструктура растет до тысяч гипервизоров и десятков тысяч виртуальных машин, команде уже недостаточно понимать, что «сервис доступен». Нужно видеть, что именно происходит внутри платформы и как техническое состояние компонентов связано с пользовательскими операциями. Иначе инцидент снова превращается в перебор гипотез, только уже не в одном продукте, а в большом облачном контуре.

В этом смысле история 2017 года остается актуальной не как рассказ про Redis, Aerospike или один параметр SDK. Она показывает общий инженерный принцип: чем сложнее система, тем дороже управлять ею по логам и ощущениям. На малом масштабе это может закончиться бессонной ночью. На масштабе корпоративной облачной платформы – может затронуть работу десятков сервисов и команд.

Именно здесь проходит граница между «система работает» и «системой можно управлять». Для небольшого сервиса эта разница может быть незаметной. Для облачной платформы, на которой живут критичные нагрузки заказчика, она становится принципиальной.

Тематики: Интеграция

Ключевые слова: автоматизация бизнеса, облачные технологии, ИТ инфраструктура