July 9

Вы не готовы к мониторингу Kubernetes, пока не поймете эти концепции

Это перевод оригинальной статьи You’re Not Ready for Kubernetes Observability Until You Understand These Concepts.

Перевод сделан специально для телеграм-канала Мониторим ИТ. Подписывайтесь! Там еще больше полезных постов о мониторинге.

Реальная история обеспечения наблюдаемости в Kubernetes (которая действительно работает в продакшене)

Большинство людей начинают работать с Prometheus и Grafana, не понимая, какие задачи они решают. Вот что вам нужно знать в первую очередь.

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

Это не базовая версия из учебного пособия, а полная боевая архитектура со всеми решениями и компромиссами, которые с ней связаны.

Позвольте мне пошагово объяснить вам основные понятия, закономерности и причины, по которым всё работает именно так.

Две разные проблемы, два разных решения

Когда вы начинаете работать с мониторингом Kubernetes, первое, что вам нужно понять, это то, что вы решаете две совершенно разные задачи.

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

Метрики показывают, насколько хорошо всё работает. Ваша задержка составляет 200 миллисекунд. Загрузка CPU — 75%. За последнюю минуту было обработано 1000 запросов. Эти показатели отражают состояние и производительность системы.

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

Как на самом деле работает сбор логов

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

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

Простая модель для управляемых вычислительных ресурсов

Если вы используете, например, AWS Fargate, где вычислительный уровень управляется автоматически, сбор логов не представляет сложности.

Вы устанавливаете аддон в кластер. Это может быть CloudWatch Observability add-on. Может быть OpenTelemetry или Fluentd. Эти аддоны разворачивают коллекторы, которые автоматически обнаруживают ваши pod’ы и начинают забирать логи.

Ключевое слово — «pull» (запрос). Сборщики подключаются к логам вашего пода и передают их в пункт назначения. Обычно первым делом используется CloudWatch.

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

Паттерн-sidecar для сложных приложений

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

В вашем поде работают два контейнера вместо одного: основной контейнер приложения и контейнер для ведения логов. Оба контейнера монтируют один и тот же том.

Вот как это происходит

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

Мы делаем это таким образом, чтобы обеспечить разделение ответственности. Код вашего приложения остаётся простым. Он просто записывает данные в файл. Вся сложность форматирования, батчинга, повторных попыток при неудачной отправке и маршрутизации в разные назначения находится в sidecar’е.

Если вам нужно изменить место хранения логов или их формат, вы изменяете конфигурацию sidecar-контейнера. Код вашего приложения при этом остаётся неизменным.

Почему одного CloudWatch недостаточно при масштабировании

Большинство начинают с отправки всех данных в CloudWatch. Он интегрирован с AWS. Он надежен. Он хорошо подходит для небольших систем.

Однако при генерации значительного объема логов у CloudWatch есть ограничения.

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

Именно поэтому в production-конфигурациях добавляют дополнительные слои.

Паттерн корпоративного пайплайна логов

В нашей bootcamp-конфигурации логи проходят через несколько этапов. Каждый этап выполняет свою конкретную задачу.

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

Из CloudWatch логи передаются в функцию Lambda. Это необязательный, но полезный механизм. Lambda стандартизирует форматы логов, добавляет метаданные и приводит в порядок временные метки. Разные сервисы логируют по-разному. Этот этап делает всё единообразным.

Далее следует Kinesis Firehose. Это ваш стриминговый буфер. Вместо записи тысяч отдельных лог-записей в конечное хранилище, Kinesis объединяет их в батчи.

Мы настроили буфер на 20 минут. Он собирает логи, а затем сбрасывает всё одним эффективным батчем.

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

Конечная цель — OpenSearch. Именно здесь по-настоящему проявляется возможность мониторинга в масштабах.

Что отличает OpenSearch

OpenSearch создан для одной цели: быстрого полнотекстового поиска по огромным массивам данных.

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

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

В нашей системе мы храним данные за 7 дней в OpenSearch. Это актуальные данные для активного расследования и мониторинга.

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

Таким образом, стратегия хранения данных такова: 7 дней в OpenSearch для быстрых запросов, 30 дней в CloudWatch в качестве промежуточного варианта, и годы в S3 для соответствия требованиям.

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

Чем отличается сбор метрик

Пока логи проходят через этот пайплайн, метрики работают в совершенно другой системе.

Принципиальное различие заключается в структуре данных. Логи — это неструктурированный текст. Метрики — это числа с подписями. Логи рассказывают истории. Метрики измеряют показатели.

Prometheus — это стандарт для метрик Kubernetes. Он использует pull-модель, что выглядит непривычно для большинства людей.

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

Почему используется модель «pull» вместо «push»? Это обеспечивает контроль и надежность. Prometheus контролирует расписание сбора данных. Если ваше приложение аварийно завершает работу, Prometheus узнает об этом немедленно, поскольку сбор данных завершается неудачей. При использовании модели «push» аварийно завершившееся приложение просто перестает отправлять данные, и вы можете этого не заметить.

Что на самом деле делает Prometheus

Люди часто путают, что такое Prometheus. Это не система долгосрочного хранения. Это база данных временных рядов, оптимизированная под свежие данные и быстрые запросы.

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

Prometheus также ничего не визуализирует. Это не его задача. Он собирает, хранит и позволяет запрашивать метрики. Визуализация — это задача Grafana.

Как приложения предоставляют доступ к метрикам

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

Для каждого основного языка программирования существуют клиентские библиотеки Prometheus. В Python есть prometheus_client. В Go есть официальный client_golang. В Java есть несколько вариантов.

Схема всегда одна и та же. Импортируйте библиотеку. Определите свои метрики в виде счетчиков, индикаторов или гистограмм. Увеличивайте или устанавливайте значения в своем коде. Запускайте HTTP-сервер, который отдаёт эти метрики.

В результате у приложения появляется эндпоинт вроде /metrics, который возвращает текущие значения в формате Prometheus. Prometheus опрашивает этот эндпоинт и сохраняет данные.

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

ServiceMonitor сообщает Prometheus, что нужно опрашивать

Prometheus должен знать, какие эндпоинты опрашивать и как часто. В Kubernetes это описывается с помощью ресурсов ServiceMonitor.

В ServiceMonitor указано: «Найти все поды с этими метками, собирать их метрики с порта каждые 30 секунд по этому пути».

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

Это динамический процесс. Когда запускаются новые поды с совпадающими метками, Prometheus автоматически начинает их опрашивать. Когда pod’ы завершают работу, Prometheus перестаёт это делать. Ручная настройка не требуется.

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

Что на самом деле делает Grafana

Grafana — это всего лишь инструмент визуализации. Он ничего не собирает и ничего не хранит. Он подключается к источникам данных и создает красивые графики.

При установке kube-prometheus-stack с помощью Helm, Grafana поставляется в комплекте и предварительно настроена с Prometheus в качестве источника данных. Но вы можете добавить и другие источники данных: CloudWatch для метрик AWS, OpenSearch для визуализации на основе логов, а также любую базу данных, поддерживаемую Grafana.

Главное преимущество Grafana заключается в возможности объединять данные из разных источников в одном дашборде. Вы можете показать метрики приложения из Prometheus, производительность базы данных из CloudWatch и тренды ошибок из логов OpenSearch — всё на одном экране.

Использование готовых дашбордов вместо создания с нуля

Вот что значительно сэкономит время. На сайте grafana.com/grafana/dashboards доступны тысячи готовых панелей мониторинга.

Нужен мониторинг кластера Kubernetes? Найдите подходящий дашборд. Скопируйте его ID. Импортируйте в Grafana. Готово. У вас профессиональный мониторинг без написания ни одного запроса.

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

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

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

Создание кастомных дашбордов по мере необходимости

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

В Grafana есть конструктор запросов, но понимание базового языка запросов сильно помогает. Для источников данных Prometheus это PromQL.

Простой PromQL-запрос http_requests_total может отображать общее количество запросов. Вы можете фильтровать запросы по меткам, например, http_requests_total{service=”catalog”} только для сервиса catalog. Вы можете рассчитать скорость запросов с помощью rate(http_requests_total[5m]), чтобы показать количество запросов в секунду за 5 минут.

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

Концепция соглашений об уровне обслуживания (SLA) и почему они важны

Именно здесь наблюдаемость соприкасается с реальностью бизнеса.

Соглашение об уровне обслуживания (SLA) — это обещание вашим клиентам относительно качества предоставляемых услуг. Возможно, вы обещаете 99,1% времени безотказной работы. Возможно, вы обещаете время ответа менее 500 миллисекунд для 95% запросов.

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

Позвольте мне показать вам, что на самом деле означает 99,1% времени безотказной работы. В одном месяце примерно 2,5 миллиона секунд. 99,1% времени безотказной работы означает, что допустимое время простоя составляет 0,9%. Это примерно 64 часа в месяц.

Это ваш бюджет простоя. Ваша система мониторинга отслеживает, укладываетесь ли вы в бюджет. Если вы расходуете его слишком быстро, вам нужно исправить ситуацию до того, как нарушится соглашение об уровне обслуживания (SLA).

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

Подводя итог

Полная картина наблюдаемости включает в себя поток логов через один конвейер и поток метрик через другой.

Логи передаются из подов к коллекторам, а затем в CloudWatch, опционально проходят через Lambda для форматирования, затем через Kinesis для буферизации, попадают в OpenSearch для анализа и в S3 для резервного хранения.

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

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

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

Подписывайтесь на телеграм-канал Мониторим ИТ, там еще больше полезной информации о мониторинге!