Как приоритетите на подовете в Kubernetes доведоха до прекъсване в Grafana Labs

Прим. прев.: Представяме ви техническите подробности за причините за неотдавнашния престой в работата на облачната услуга, осигурявана от създателите на Grafana. Това е класически пример за това как нова и, изглеждаща изключително полезна функция, предназначена да подобри качеството на инфраструктурата… може да навреди, ако не се предвидят многобройните нюанси на нейното прилагане в реалностите на продукцията. Преводът на този текст от вицепрезидента по продукта от Grafana Labs предоставя ценни материали, които ни помагат да учим не само от нашите грешки.

Как приоритетите на pod-овете в Kubernetes доведоха до престой в Grafana Labs

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

Предистория

Услугата Grafana Cloud Hosted Prometheus се базира на Cortex — проекта CNCF за създаване на хоризонтално мащабируема, високо достъпна, мултидентантна (multi-tenant) услуга Prometheus. Архитектурата на Cortex се състои от набор от отделни микросервизи, всеки от които изпълнява своя функция: репликация, съхранение, запитвания и т.н. Cortex активно се разработва, постоянно се добавят нови функции и се повишава производителността. Редовно разгръщаме нови версии на Cortex в клъстери, за да позволим на клиентите да се възползват от тези възможности — за щастие, Cortex може да бъде обновяван без престой.

За обновления без престой услугата Ingester на Cortex изисква допълнителна реплика на Ingester по време на процеса на обновление. (Прим. прев.: Приемник — основният компонент на Cortex. Неговата задача е да събира постоянен поток от примери, да ги групира в chunk’ове за Prometheus и да ги съхранява в база данни като DynamoDB, BigTable или Cassandra.) Това позволява на старите Ingester-и да предават текущите данни на новите Ingester-и. Струва си да се отбележи, че Ingester-ите изискват значителни ресурси. За тяхното функциониране е необходимо да имате по 4 ядра и 15 Гб памет на pod, т.е. 25 % от процесорната мощност и паметта на основната машина в нашите Kubernetes клъстери. Обикновено имаме много повече неизползваеми ресурси в клъстера, отколкото 4 ядра и 15 Гб памет, така че можем лесно да стартираме тези допълнителни Ingester-и по време на актуализации.

Обаче често се случва, че по време на нормална работа на нито една от машините няма тези 25% неизползвани ресурси. И не се стремим: CPU и памет винаги ще са необходими за други процеси. За да решим този проблем, решихме да се възползваме от приоритетите на Kubernetes pod-овете. Идеята е да присвоим на Ingester-ите по-висок приоритет от този на другите (stateless) микросервизи. Когато трябва да стартираме допълнителен (N+1) Ingester, временно изместваме други, по-малки pod-ове. Тези pod-ове се преместят в свободните ресурси на други машини, оставяйки достатъчно голяма „дупка“ за стартиране на допълнителен Ingester.

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

Авария

В петък, 19 юли, един от инженерите стартира нов специализиран клъстер Cortex за голям клиент. Конфигурацията за този клъстер не включваше новите приоритети на pod-овете, затова на всичките нови pod-ове беше присвоен приоритет по подразбиране — среден.

В Kubernetes клъстера нямаше достатъчно ресурси за новия кластер Cortex, а съществуващият production кластер Cortex не беше обновен (Ingester-ите останаха без висок приоритет). Тъй като Ingester-ите на новия клъстер по подразбиране имаха среден приоритет, а съществуващите в production pod-ове работеха изобщо без приоритет, Ingester-ите на новия клъстер изместиха Ingester-ите от съществуващия production кластер Cortex.

ReplicaSet за изключения Ingester в продукционния кластер откри изключен pod и създаде нов за поддържане на зададеното количество копия. На новия pod по подразбиране беше присвоен среден приоритет, а следващият "стар" Ingester в продукцията загуби ресурси. Результатът беше лавинообразен процес, който доведе до изключването на всички pod-ове с Ingester за продукционни клъстери на Cortex.

Ingester-ите запазват състояние (stateful) и съхраняват данни през последните 12 часа. Това ни позволява по-ефективно да компресираме данните преди записването им в дългосрочно хранилище. За целта Cortex извършва шардинг на данните по серии, използвайки разпределена хеш-таблица (Distributed Hash Table, DHT), и репликира всяка серия на три Ingester-а с помощта на кворумна съгласуваност в стил Dynamo. Cortex не записва данни в Ingester-и, които са изключени. Така, когато голям брой Ingester-и напуснат DHT, Cortex не може да осигури достатъчна репликация на записите и те "падат."

Откритие и отстраняване на

Новите известия на Prometheus, базирани на "бюджет за грешки" (error-budget-based — подробности ще последват в бъдеща статия) сигнализираха тревога след 4 минути от началото на изключването. През следващите около пет минути проведохме диагностика и увеличихме подлежащия кластер Kubernetes за разполагане както на нови, така и на съществуващи продукционни клъстери.

Още след пет минути старите Ingester-и успешно записаха данните си, а новите — стартираха, и клъстерите Cortex отново стана достъпни.

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

Последици

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

Как приоритетите на pod-овете в Kubernetes доведоха до престой в Grafana Labs
Операциите по запис на продукционния кластер

Изводи

Е важно да извлечем уроците от този инцидент и да предприемем необходимите мерки, за да избегнем повторението му.

Оглядавайки се назад, трябва да признаем, че не трябваше да задаваме приоритет по подразбиране среден докато всички Ingester’и в продукция не получиха високо приоритет. Освен това, трябваше предварително да се погрижим за техния висок приоритет. Сега всичко е оправено. Надяваме се, че нашият опит ще помогне на други организации, които обмислят използването на приоритети на pod-овете в Kubernetes.

Ще добавим допълнителен контрол върху разгръщането на каквито и да било допълнителни обекти, чиито конфигурации са глобални за кластера. Отсега нататък подобни промени ще бъдат оценявани отопо-голямо количество хора. Освен това, модификация, която доведе до срив, беше считана за твърде незначителна за отделен проектен документ — тя бе обсъждана само в GitHub issue. От този момент нататък всички подобни промени в конфигурацията ще бъдат придружавани от съответна проектна документация.

Накрая, автоматизираме увеличаването на размера на обратния прокси сървър за удостоверяване, за да предотвратим OOM при натоварване, свидетели на което станахме, и ще анализираме параметрите по подразбиране на Prometheus, свързани с откат и мащабиране, за да предупредим бъдещи подобни проблеми.

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

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

Прочетете също в нашия блог:

Източник: habr.com

Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри 🔥 Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри | ProHoster