Розбий моноліт! Kuberton — конференція для DevOps-ів & Python, Java, Ruby, GO розробників. 2-3 March, 2019
×Закрыть

Мониторинг микросервисов: разделяй и властвуй

Когда продукт — это сеть взаимосвязанных сервисов с большим количеством внешних зависимостей, то ответ на простой вопрос «Наш продукт работает или что-то сломалось?» и далее поиск неисправностей и узких мест превращается в нетривиальную задачу.

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

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

Photo by Krists Luhaers

Основные принципы

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

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

Учитывая размеры системы и все ограничения, а также применение правила «разделяй и властвуй» к решению подобных задач, мы определили 3 основных принципа мониторинга:

  1. Каждый сервис имеет Service Level Agreement (SLA — соглашение о качестве сервиса).
  2. Каждый экземпляр каждого сервиса отслеживает поток входящих запросов и параметры реакции на них.
  3. Каждый экземпляр каждого сервиса отслеживает поток исходящих запросов к другим сервисам и параметры их реакции на эти запросы.

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

SLA — соглашение о качестве сервиса

Давайте сфокусируем внимание на одном сервисе, а все остальные будем рассматривать как внешние зависимости, даже если они разрабатываются теми же людьми.

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

Эти параметры называются Service Level Indicators (SLI — параметры качества сервиса). Wikipedia приводит достаточно хорошее описание SLI. Существует несколько популярных комбинаций этих параметров, они собраны на этом слайде.

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

Имея допустимые интервалы для параметров производительности и доступности, мы определяем Service Level Objective (SLO — измеримые характеристика сервиса). Больше про SLO можно прочитать на Wikipedia. Примеры SLO: сервис должен быть доступен 99,9% времени в течение года, в 95% случаев время ответа должно быть не более 300 миллисекунд. Сохраняя запас между декларируемыми SLO и реальными характеристиками системы, мы оставляем себе возможность заранее определить негативные тренды в поведении системы и отреагировать на них.

Следующий шаг — это определение Service Level Agreement (SLA — соглашение о качестве сервиса). Wikipedia содержит неплохую статью о SLA.

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

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

Мониторинг входящего потока

Система мониторинга постоянно следит за тем, как используется сервис и как он реагирует на нагрузку.

SLA — это двустороннее соглашение, и обе стороны должны соблюдать свои обязанности. Мы доверяем пользователям нашего сервиса в том, что они будут придерживаться параметров соглашения, но всякое случается. Так что некоторая защита нашему сервису не помешает.

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

Мы называем это «мониторингом входящего потока», потому что метрики описывают входящие запросы и реакцию на них.

Мониторинг исходящего потока

Другой важный поток запросов, который мы отслеживаем, — исходящий поток: запросы, генерируемые экземплярами нашего сервиса ко внешним сервисам и параметры их реакции на эти запросы.

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

Когда экземпляр нашего сервиса отправляет запрос к внешнему сервису, мы записываем метрики, определенные как SLI этого внешнего сервиса. Так как метрики описывают поток исходящих запросов, генерируемых нашим сервисом — мы называем это «мониторинг исходящего потока».

Мониторинг исходящего потока может показаться чрезмерным усложнением, однако он позволяет нам решить несколько важнейших задач:

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

Выводы

Комбинация из SLA, мониторинга входящих и исходящих потоков дает нам:

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

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

Кстати, эту статью вы также можете прочитать на английском.

LinkedIn

47 комментариев

Подписаться на комментарииОтписаться от комментариев Комментарии могут оставлять только пользователи с подтвержденными аккаунтами.

Стаття рівня Капітана Очевидності.

Думаю, что статья получилась бы лучше, если бы вы описали как работаете с системами мониторинга (Prometheus, Graphite), какие косяки могут вылезти, best practices и т.д.

Провокационный вопрос
Ваш микросеовис зависит от внешних сервисов и по sla должен дать ответ не дольше чем за минуту

Внешний сервис начинает тормозить

Вам или надо возвращать ошибку чтоб не нарушать sla или отдавать ответ дольше и нарушать

Что хуже?

Ну есть варианты: пнуть владельцев того сервиса который начал тормозить, пока проблема решается наш сервис может или возвращать ошибку или какие-то закешированные значения/значения по умолчанию. Circuit breaker как раз о такой ситуации. Еще вариант: когда время ответа доходит превышает 90ую персентиль — перепослать запрос еще раз.

Все зависит от конкретного сервиса.

Хуже когда хозяева сервиса на знают о проблеме, или когда они не готовы к этому

В таком случае у вас должен быть SLA с внешним сервисом или как минимум условие в своём SLA «если тот сервис отвечает не дольше Х». Если такого нет, то лучше вернуть ошибку из которой явно следует что она вызвана той зависимостью.

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

писать в логи можно, но кто-то должен отслеживать логи.

Метрики, алёртинг.

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

Делать метрики из логов достаточно сложно технологически при больших объемах логов.

А в чём технические сложности? Интересно именно исходя из вашего опыта ваше мнение.

Есть несколько причин.

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

Просто парсить логи может быть ресурсоемкой задачей на много серверов при большом объеме.

Есть вариант парсить их прямо не сервере где они записаны. Я делал такое при помощи collectd для httpd. Если они отправляются сразу в сеть через rsyslog или что-то подобное можно сделать разбор на транзитных узлах — я помню какие-то агенты умеют выкидывать email, SSN и прочее из сообщений, может они и метрики могут вытаскивать.

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

Это имеет смысл делать для, того что называется «off the shelf», продуктов с плохими метриками. Если это наш сервис, то добавить метрики сильно проще чем поддерживать регулярки для логов и всей инфраструктуры для их разбора.

Ага общий смысл ясен спасибо!

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

ЗЫ: к.м.к. вопрос формата логов решается достаточно просто так же ж как сетевыми уровнями есть некая общая инфа скажем время события есть инфа скажем адрес источника есть какой-то общий сет типов источника сооств. его значение в каждой записи и далее по типу уже определяется следующий уровень (его формат) и т.д. Т.е. можно сагрегировать вообще всё в одну большую кучу но уже изначально упорядоченную по тому кто кому когда посылал и видно к какому типу это относится а далее уже анализ фильтр сильно упрощается ну скажем мы смотрим только на TCP который в свою очередь только IP а кроме них ещё куча всего остального которую уже можно отбросить и из этого например вычленить только HTTP сессии или скажем только SSL или другие уровня конкретного приложения это всё как иллюстрация просто такое разделение реализовать на уровне и в терминах вашей системы к.м.к. должно получиться.

ЗЫ: ну либо вы и так это уже сделали а я просто статью не читал ))

Прочитайте статью — там есть пара интересный идей ;) Лучше конечно читать на английском — не все получилось хорошо перевести.

Вам или надо возвращать ошибку чтоб не нарушать sla или отдавать ответ дольше и нарушать

Что хуже?

Это должно быть описано в SLA

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

Собираем кучу данных, алертим то что важно. А самое главное мы можем быстро понять, что проблемы не у нас, пнуть виновных и отправиться спать дальше.

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

Просто невозможно построить модель описывающую этот муравейник, а очень нужно. Вот и придумываем как упростить мир и таки решить проблему.

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

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

к.м.к. мысль в том что проверять «асинхронные процессы внутри» при условии что снаружи с точки зрения всё работает в допустимых рамках это несколько «избыточная оптимизация» точнее же ж некоторые работы над тем чего вероятно вообще нет.

Из своего опыта я могу полагать у сервиса либо системы конкретно известные слабые места например «потенциальный предел при достижении 10к 50% шифрованного трафика» и наблюдать за ними проставляя известные и конкретные метрики и наблюдая конкретные пути исполнения и сесвисы-участники но скажем если системы обработки данных чисто потенциально и по всей логике в «потенциальных пределах» принимают одинаковое участие независимо от условий самого «предела» то и следить за ними особого смысла нет при условии общей работоспособности системы с точки зрения пользователя.

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

Плюс хорошо бы б возможность прогона специальных тестовых сессий уже на реальных инстансах системы включая тесты производительности (проверка тех самых «потенциальных пределов») но при этом различая логгирование инфы сессий «реальных» и «тестовых». Но здесь другой момент который мне пока неизвестен о стоимости таких прогонов в условиях арендуемой облачной инфраструктуры iaas/paas ведь по сути за них придётся платить реальные деньги.

ЗЫ: кстати если подумать то же ж самое относится к «облачно сервисной» стоимости того же ж избыточного логгирования которое соотв. занимает ресурсы которые соотв. стоят денег.

Мой проект занимается обработкой сообщений от IoT: железки шлют нам по HTTP какие-то сообщения, а дальше внутри к этим сообщениям подмешивается контекст и все это переводит state machines в новые статусы. Переходы в какие-то статусы могут заканчиваться какими-то действиями.

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

Динамическую глубин логирования уже реализовали — я читал где-то несколько постов. Плюс где-то была интересная идея включить DEBUG логгинг для какого-то подмножества запросов — просто так.

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

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

Никакой практической ценности. Зачем такое вообще постить и как это пользовать? Не понятно.

сервис должен быть доступен 99,9% времени в течение года

И как Вы это обеспечиваете? Учитывая, что даже топ игроки (например, Амазон) давно уже поменяли свои SLA на что-то вроде «мы делаем все лучшее чтобы обеспечить 99.99%, но вот если у нас не получилось и uptime упадет до 99%, то вот вам скидка».

99.99%, но вот если у нас не получилось и uptime упадет до 99%, то вот вам скидка

в этом как бы и суть SLA — финансовая компенсация за непредоставление заявленного уровня сервиса
а уровень этой компенсации — это уже отдельный вопрос и все большие компании именно так перекрывают собственные риски за счет клиентов, ограничивая максимальную сумму компенсации — суммой контракта с клиентом (без какой-либо дополнительной компенсации финансовых потерь, вызванных простоем сервиса)

Это IaaS и такие показатели доступности это нормально.

Учитывая, что даже топ игроки (например, Амазон)

а, понял — это был коментарий к Амазону

Отож. IaaS типа Амазона или Гугла может иметь Service Availablity Target 99% — их клиенты всегда могут построить высокодоступное решение используя стандартные подходы. А вот SaaS уже себе такого позволить не может и кол-во девяток долдно быть больше. Но опять таки в разумных пределах.

99.9% обеспечить вполне возможно: DR + полная автоматизация любых процессов + проактивный мониторинг. Чаще всего проблемы не возникают мгновенно, а накапливаются со временем. Соответственно рецепт — это надежный и продуманный мониторинг с ранней диагностикой. Самолеты летают и мосты стоят со значительно более высокой надежностью.

99.9% обеспечить вполне возможно

Конечно можно. Но обычно это дорого. Поэтому я и спросил.

Чаще всего проблемы не возникают мгновенно

Ну не знаю. Вот мы юзаем почту, пуш нотификейшены. Юзеры через вебхуки юзают пачку сторонних сервисов. Так вот — все они постоянно отваливаются. При чем — мгновенно. Ну и не по нашей вине.

Дорого, но это бизнесу решать, что им лучше: прилечь или потратиться.

Любео дублирование дорого. Но тут начинается оценка рисков.

И при этом никаких технических деталей. Что за микросервисы, какое облако, есть ли kubernetes, какие тулы для мониторинга, и тп все осталось за кадром. В результате статья ни о чем.

дык

Salesforce.com

классический черный ящик

Обычно это Prometheus и обработка данных через Elastic/Graphite/COrtex + Graphana. Для богатых — Dynatrace

Для совсем богатых — appdynamics

мало ли в Бразилии педров ©
IBM Application Performance Management

Ну или для совсем отбитых — Zabbix

и в чем их отбитость?
и он все же не ориентирован на мониторинг приложений

мы держали Graphite до 20М метрик/минуту. Дальше уже не имело смысла. Там хранилище очень неэффективное + при выпадении одного из серверов появляются случайные провалы при запросах данных.

Prometheus вот прямо хорош, особенно с новым хранилищем. Но нужно сильно постараться, чтобы построить правильную систему перекачки метрик между инстансами. А еще очень хотелось бы писать данных на ceph или hdfs вместо локального диска.

Elastic совсем не может держать нашу нагрузку — мы пытались.

Статья о том как выжить в мире хаоса и при этом хорошо спать ночью.

Сервисы, в большинстве своем, это Java
для сбора данных с хостов используется CollectD
сами сервисы чаще всего используют Dropwizard-metrics,
мы используем push-модель для передачи метрик, т.е. дальше метрики пишутся по REST в Kafka, переправляются в другой датацентр, а там записываются в Argus (наша доморощенная система — github.com/salesforceeng/Argus).
Есть и kubernetes — именно от сюда растут ноги требования, что мы хотим делать RCA без доступа к хостам.
В общем система мониторинга прокачивает 100М+ метрик в минуту и продолжает расти экспоненциально. 3 года назад было 3М в минуту.

Вот это другое дело. Кстати, вы используете kubernetes autoscaler? Какая у вас утилизация CPU/RAM?

Мы не используем kubernetes autoscaler, обычно нагрузка заранее известных пределах. Я делал проект когда автоскуйлинг работал через prometheus — метрики сливались в prometheus, а от туда через алерты уже вызывались API для scale up/down. стандартный автоскейлер очень простой для реальной жизни — не все измеряется в CPU.

Про утилизацию CPU/RAM прямо не знаю что написать. Где-то больше, где-то меньше.. На хостах с apache zookeeper все практически в 0, но там другие ограничения.

Не обязательно расти от CPU. Если pod автоскейлинг работает от числа запросов(RPS), а пределом подов является 100 на ноду, то можно получить nodes автоскейлинг в зависимости от числа запросов на ingress контроллере. Правда размер ноды должен быть подобран, чтобы выдерживать 100 подов. Или по той же памяти. Но в целом согласен, автоскейлер довольно деревянный до сих пор.

Подписаться на комментарии