Хабрахабр

[Перевод] Как приоритеты pod’ов в Kubernetes стали причиной простоя в Grafana Labs

Прим. перев.: Представляем вашему вниманию технические подробности о причинах недавнего простоя в работе облачного сервиса, обслуживаемого создателями Grafana. Это классический пример того, как новая и, казалось бы, исключительно полезная возможность, призванная улучшить качество инфраструктуры… может навредить, если не предусмотреть многочисленные нюансы её применения в реалиях production. Замечательно, когда появляются такие материалы, позволяющие учиться не только на своих ошибках. Подробности — в переводе этого текста от вице-президента по продукту из Grafana Labs.

Приношу извинения всем клиентам, пострадавшим от сбоя. В пятницу, 19 июля, сервис Hosted Prometheus в Grafana Cloud перестал функционировать примерно на 30 минут. Мы крайне серьезно относимся к этому инциденту. Наша задача — предоставлять нужные инструменты для мониторинга, и мы понимаем, что их недоступность усложняет вашу жизнь. В этой заметке объясняется, что произошло, как мы на это отреагировали и что делаем для того, чтобы подобное больше не повторялось.

Предыстория

Сервис Grafana Cloud Hosted Prometheus основан на Cortex — проекте CNCF по созданию горизонтально масштабируемого, высокодоступного, мультитенантного (multi-tenant) сервиса Prometheus. Архитектура Cortex состоит из набора отдельных микросервисов, каждый из которых выполняет свою функцию: репликацию, хранение, запросы и т.д. Cortex активно разрабатывается, у него постоянно появляются новые возможности и повышается производительность. Мы регулярно деплоим новые релизы Cortex в кластеры, чтобы клиенты могли воспользоваться этими возможностями — благо, Cortex умеет обновляться без простоев.

(Прим. Для беспростойных обновлений сервис Ingester Cortex'а требует дополнительную реплику Ingester'а во время процесса обновления. Его задача — собирать постоянный поток sample'ов, группировать их в chunk'и Prometheus и сохранять в базе данных вроде DynamoDB, BigTable или Cassandra.) Это позволяет старым Ingester'ам пересылать текущие данные новым Ingester'ам. перев.: Ingester — базовый компонент Cortex'а. Для их работы необходимо иметь по 4 ядра и 15 Гб памяти на pod, т.е. Стоит отметить, что Ingester'ы требовательны к ресурсам. В целом у нас обычно гораздо больше неиспользованных ресурсов в кластере, нежели 4 ядра и 15 Гб памяти, поэтому мы можем легко запускать эти дополнительные Ingester'ы во время обновлений. 25 % процессорной мощности и памяти базовой машины в случае наших кластерах Kubernetes.

Да мы и не стремимся: CPU и память всегда пригодятся для других процессов. Однако часто бывает так, что во время нормальной работы ни на одной из машин нет этих 25% невостребованных ресурсов. Идея в том, чтобы присваивать Ingester'ам более высокий приоритет, чем другим (stateless) микросервисам. Для решения этой проблемы мы решили воспользоваться Kubernetes Pod Priorities. Эти pod'ы переносятся в свободные ресурсы на других машинах, оставляя достаточно большую «дыру» для запуска дополнительного Ingester'а. Когда нам нужно запустить дополнительный (N+1) Ingester, мы временно вытесняем другие, меньшие pod'ы.

Они тестировались на внутреннем кластере без клиентского трафика примерно одну неделю. В четверг, 18 июля, мы развернули четыре новых уровня приоритетов в своих кластерах: критический, высокий, средний и низкий. Критический был зарезервирован для мониторинга (Prometheus, Alertmanager, node-exporter, kube-state-metrics и т.д.). По умолчанию pod'ы без заданного приоритета получали средний приоритет, для Ingester'ов был установлен класс с высоким приоритетом. Наш конфиг — открытый, и посмотреть PR можно здесь.

Авария

В пятницу, 19 июля, один из инженеров запустил новый выделенный кластер Cortex для крупного клиента. Конфиг для этого кластера не включал новые приоритеты pod'ов, поэтому всем новым pod'ам присваивался приоритет по умолчанию — средний.

Поскольку Ingester'ы нового кластера по умолчанию имели средний приоритет, а существующие в production pod'ы работали вообще без приоритета, Ingester'ы нового кластера вытеснили Ingester из существующего production-кластера Cortex. В кластере Kubernetes не хватило ресурсов для нового кластера Cortex, а существующий production-кластер Cortex не был обновлен (Ingester'ы остались без высокого приоритета).

Новому pod'у по умолчанию был присвоен средний приоритет, и очередной «старый» Ingester в production лишился ресурсов. ReplicaSet для вытесненного Ingester'а в production-кластере обнаружил вытесненный pod и создал новый для поддержания заданного количества копий. Результатом стал лавинообразный процесс, который привел к вытеснению всех pod'ов с Ingester для production-кластеров Cortex'а.

Это позволяет нам более эффективно сжимать их перед записью в долгосрочное хранилище. Ingester'ы сохраняют состояние (stateful) и хранят данные за предыдущие 12 часов. Cortex не пишет данные в Ingester'ы, которые отключаются. Для этого Cortex проводит шардинг данных по сериям, используя распределенную хэш-таблицу (Distributed Hash Table, DHT), и реплицирует каждую серию на три Ingester'а с помощью кворумной согласованности в стиле Dynamo. Таким образом, когда большое число Ingester'ов покидают DHT, Cortex не может обеспечить достаточную репликацию записей, и они «падают».

Обнаружение и устранение

Новые уведомления Prometheus на основе «бюджетных ошибок» (error-budget-based — подробности появятся в будущей статье) стали бить тревогу через 4 минуты с момента начала отключения. В течение следующих примерно пяти минут мы провели диагностику и нарастили нижележащий кластер Kubernetes для размещения как нового, так и существующих production-кластеров.

Еще через пять минут старые Ingester'ы успешно записали свои данные, а новые — запустились, и кластеры Cortex снова стали доступны.

ООМ-ошибки были вызваны десятикратным ростом QPS (как мы полагаем, из-за чрезмерно агрессивных запросов с серверов Prometheus клиента). Еще 10 минут ушло на диагностику и исправление out-of-memory (OOM) ошибок от обратных прокси-серверов аутентификации, расположенных перед Cortex.

Последствия

Общая продолжительность простоя составила 26 минут. Данные не были потеряны. Ingester'ы успешно загрузили все in-memory-данные в долговременное хранилище. Во время отключения Prometheus-серверы клиентов сохраняли в буфер удаленные (remote) записи с помощью нового API remote_write на основе WAL (за авторством Callum Styan из Grafana Labs) и повторили неудачные записи после сбоя.


Операции записи production-кластера

Выводы

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

Кроме того, следовало заранее позаботиться об их высоком приоритете. Оглядываясь назад, следует признать, что нам не следовало задавать по умолчанию средний приоритет, пока все Ingester'ы в production не получили высокий приоритет. Надеемся, что наш опыт поможет другим организациям, рассматривающим возможность использования приоритетов pod’ов в Kubernetes. Теперь все исправлено.

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

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

Мы также получили ценный опыт работы с Grafana Loki — нашей новой системой агрегации логов, — которая помогла убедиться, что все Ingester'ы должным образом повели себя во время и после сбоя. Пережитый сбой имел и некоторые позитивные последствия: получив в распоряжение необходимые ресурсы, Cortex автоматически восстановился без дополнительного вмешательства.

P.S. от переводчика

Читайте также в нашем блоге:

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть