#kubernetes #databases #azure #longread
Часть 2 из 4
Берём пример.
У нас есть AKS-кластер, инстансы
Заливаешь одну среднюю БД, смотришь нагрузочное тестирование - в простое совсем мелкий CPU/memory usage.
Включаешь арифметику с умножением и думаешь "Отлично, сейчас закину кучу баз на пару нод".
Вынужден расстроить, но так у тебя не получится сделать, давай разберёмся почему.
1. Количество дисков
Читаешь доки Azure - максимум 16 диска на наш инстанс. Patroni для HA просит 3 реплики, то есть 3 PV на базу. Считаем: 16 дисков - это 5 изолированных кластеров БД (комплаенс, привет), 1 в запасе или под мелочи.
Поднял 3 кластера по 3 реплики - и всё, приехали, больше некуда.
https://learn.microsoft.com/en-us/azure/virtual-machines/sizes/general-purpose/dasv5-series?tabs=sizestorageremote
Думаешь ладно. Денег много, возьму в этом же семействе инстанс дороже и мощнее, но и там ограничение 32 диска(10 кластеров + 2 диска под другие нужны).
2а. Максимальное количество подов на ноде (параметр
В Azure CNI дают до 250 подов на ноду, но по умолчанию нашего инстанса 80.
Считаем: апп с HPA (1 апп + 2 min HPA реплики) + Patroni (3 пода) = 6 подов на микросервис. Минус системные штуки (CNI, CSI, экспортёры, filebeat и так далее) - остаётся где-то 65.
То есть при привычных всем системным ресурсам и 3 репликам на бизнес микросервис апп + 3 реплики кластера БД, мы не сможем поднять больше 10 кластеров(да и не смогли бы, диски раньше нас тормознули бы).
https://learn.microsoft.com/en-us/azure/aks/azure-cni-overlay?tabs=kubectl#maximum-pods-per-node
2б. Резервирование памяти (параметр MAX_PODS)
Временно забудем про первый пункт с дисками и пофантазируем "Сейчас увеличу до 200 макс подс, в конфиге же легко и нам не будет мешать этот параметр".
AKS забирает память под ОС и kubelet: примерно 20 МБ на под + запас + операционная система +hard eviction.
Формула примерно такая, тут не буду топить за точность вычислений, на память пишу
(20 MB × 200(max_pods)) + 50 MB + 100 MB
Из ожидаемых тобой 32 гигабайт на ноде ты получаешь доступным для аллокации будет меньше.
С учётом hard eviction 100mb цифры примерно такие для нашего инстанса:
При
При
При
В попытке уместить не умещаемое ты теряешь драгоценную память на ноде.
Часть 2 из 4
Берём пример.
У нас есть AKS-кластер, инстансы
Standard_D8as_v5 - 8 ядер, 32 ГБ RAM. Заливаешь одну среднюю БД, смотришь нагрузочное тестирование - в простое совсем мелкий CPU/memory usage.
Включаешь арифметику с умножением и думаешь "Отлично, сейчас закину кучу баз на пару нод".
Вынужден расстроить, но так у тебя не получится сделать, давай разберёмся почему.
1. Количество дисков
Читаешь доки Azure - максимум 16 диска на наш инстанс. Patroni для HA просит 3 реплики, то есть 3 PV на базу. Считаем: 16 дисков - это 5 изолированных кластеров БД (комплаенс, привет), 1 в запасе или под мелочи.
Поднял 3 кластера по 3 реплики - и всё, приехали, больше некуда.
https://learn.microsoft.com/en-us/azure/virtual-machines/sizes/general-purpose/dasv5-series?tabs=sizestorageremote
Думаешь ладно. Денег много, возьму в этом же семействе инстанс дороже и мощнее, но и там ограничение 32 диска(10 кластеров + 2 диска под другие нужны).
2а. Максимальное количество подов на ноде (параметр
MAX_PODS)В Azure CNI дают до 250 подов на ноду, но по умолчанию нашего инстанса 80.
Считаем: апп с HPA (1 апп + 2 min HPA реплики) + Patroni (3 пода) = 6 подов на микросервис. Минус системные штуки (CNI, CSI, экспортёры, filebeat и так далее) - остаётся где-то 65.
То есть при привычных всем системным ресурсам и 3 репликам на бизнес микросервис апп + 3 реплики кластера БД, мы не сможем поднять больше 10 кластеров(да и не смогли бы, диски раньше нас тормознули бы).
https://learn.microsoft.com/en-us/azure/aks/azure-cni-overlay?tabs=kubectl#maximum-pods-per-node
2б. Резервирование памяти (параметр MAX_PODS)
Временно забудем про первый пункт с дисками и пофантазируем "Сейчас увеличу до 200 макс подс, в конфиге же легко и нам не будет мешать этот параметр".
AKS забирает память под ОС и kubelet: примерно 20 МБ на под + запас + операционная система +hard eviction.
Формула примерно такая, тут не буду топить за точность вычислений, на память пишу
(20 MB × 200(max_pods)) + 50 MB + 100 MB
Из ожидаемых тобой 32 гигабайт на ноде ты получаешь доступным для аллокации будет меньше.
С учётом hard eviction 100mb цифры примерно такие для нашего инстанса:
При
--max-pods=80: ~28.7 GB (28714 MB)При
--max-pods=200: ~26.3 GB (26314 MB)При
--max-pods=250: ~25.3 GB (25314 MB)В попытке уместить не умещаемое ты теряешь драгоценную память на ноде.
👍5
#kubernetes #databases #azure #longread
Часть 3 из 4
3. Сетевой стек
Azure CNI 250 IP на ноду, звучит неплохо. Но неявные проблемы - это отдельная песня. Первое: задержки между репликами. Думаешь, раз в одном кластере, сеть летает, а на деле CNI overlay добавляет 1-5 мс, и для синхронной репликации (типа Patroni) это уже ощутимо. Второе: подсеть кластера. Сотни баз, поды плодятся, и твоя дефолт /24 (256 IP) заканчивается на раз-два, а расширить - рестарт кластера и нервы. Третье: пропускная способность. NIC на ноде (12500 Mb/s) делится на всех, и 200 подов с трафиком - это бутылочное горлышко.
4. Бекапы
Мы разобрались(нет) с первыми болями и дошли до масштабирования.
Подняли dev кластер, развесили taints/toleration, скейлинг нод и подов, задеплоили оператора, на аппы повесили клеймы кластеров/БД, рассчитали, что вам надо, допустим по 4 кластера на ноду. Везде всё умещается.
Время учится делать бекапы. Допустим вы решили пойти путем через velero(а оно чертовски удобное).
Поставили расписание снепшотов, радостно проверили пару баз и ушли домой.
Утром приходите и видите - все запланированные бекапы не сработали. Копаясь в ивентах и логах вы поняли, что не хватило дисков.
с Azure Disk и VolumeSnapshot нюанс: для восстановления из снапшота нужен новый PVC, а дисков и так не хватает. Сами снапшоты PVC не требуют, но при развёртывании - да.
А если расписания в Velero, то без костылей никак: все снепшоты штатно запускаются разом - и по всему кластеру дисков не найти. Пока новые ноды в нужных зонах/регионах запустятся, джоба велеро просто упадёт по таймауту.
Разносишь по времени, ограничиваешь параллельность - выкручиваешься.
Уже на этих аргументах, подкрепленных моей болью, поеданием полной ложки коричневой субстанции я предлагаю завершить монолог "почему много баз в кубере это плохо", но мы идём дальше.
Часть 3 из 4
3. Сетевой стек
Azure CNI 250 IP на ноду, звучит неплохо. Но неявные проблемы - это отдельная песня. Первое: задержки между репликами. Думаешь, раз в одном кластере, сеть летает, а на деле CNI overlay добавляет 1-5 мс, и для синхронной репликации (типа Patroni) это уже ощутимо. Второе: подсеть кластера. Сотни баз, поды плодятся, и твоя дефолт /24 (256 IP) заканчивается на раз-два, а расширить - рестарт кластера и нервы. Третье: пропускная способность. NIC на ноде (12500 Mb/s) делится на всех, и 200 подов с трафиком - это бутылочное горлышко.
4. Бекапы
Мы разобрались(нет) с первыми болями и дошли до масштабирования.
Подняли dev кластер, развесили taints/toleration, скейлинг нод и подов, задеплоили оператора, на аппы повесили клеймы кластеров/БД, рассчитали, что вам надо, допустим по 4 кластера на ноду. Везде всё умещается.
Время учится делать бекапы. Допустим вы решили пойти путем через velero(а оно чертовски удобное).
Поставили расписание снепшотов, радостно проверили пару баз и ушли домой.
Утром приходите и видите - все запланированные бекапы не сработали. Копаясь в ивентах и логах вы поняли, что не хватило дисков.
с Azure Disk и VolumeSnapshot нюанс: для восстановления из снапшота нужен новый PVC, а дисков и так не хватает. Сами снапшоты PVC не требуют, но при развёртывании - да.
А если расписания в Velero, то без костылей никак: все снепшоты штатно запускаются разом - и по всему кластеру дисков не найти. Пока новые ноды в нужных зонах/регионах запустятся, джоба велеро просто упадёт по таймауту.
Разносишь по времени, ограничиваешь параллельность - выкручиваешься.
Уже на этих аргументах, подкрепленных моей болью, поеданием полной ложки коричневой субстанции я предлагаю завершить монолог "почему много баз в кубере это плохо", но мы идём дальше.
😁6👍3
#kubernetes #databases #azure #longread
Часть 4 из 4
5. Операторы и типы баз данных.
"ой, а ты же даже ничего не сказал про типы базы данных(MySQL, PostgreSQL, MongoDB etc), ты ничего не сказал про операторы и разницу между ними, как же так?".
Каждый из операторов, которые я трогал в 2024-2025 годах обладал своими минусами.
Пожалуй отдельно могу отметить только https://cloudnative-pg.io/. Он невероятно чертовски хорош и очень быстро развивается.
Остальные почти все не годятся вам с дефолтными параметрами.
Например zalando оператор по дефолту с выключенной фичей DCS.
https://github.com/zalando/postgres-operator/blob/master/charts/postgres-operator/values.yaml#L454
Это гарантирует вам регулярную проблему с
Почитать вам https://patroni.readthedocs.io/en/master/dcs_failsafe_mode.html
Другой дефолтный параметр вообще превратит ваш кластер в постоянно расползающийся лаг, который будет течь как красотки на концерте Энрике Иглесиаса.
6. IOPS
Потом в процессе эксплуатуации доходит, что IOPS в Azure (и в AWS EKS) от размера диска зависит.
Мелкий диск (допустим 128 ГБ) - 500 IOPS, и для активных баз это ни о чём.
Хочешь больше - бери 512 ГБ (2300 IOPS) или 1 ТБ (5000 IOPS).
База мелкая, а из-за трёх реплик платишь за объём втридорога.
То есть в том случае, если ваш тип базы данных потребляет много IOPS, то вам придётся брать большие скоростные диски, а это уже не так весело и совсем не так дёшево.
"Так каков итог?" - спросите вы. Можно или нельзя пихать БД в managed кубер AKS/EKS?
Мой ответ такой:
- когда много баз - нельзя. Аргументы выше.
- когда базы очень большие(размер, большое потребление ресурсов CPU/Memory) - совершенно нельзя. Аргумент мне не хватило времени написать, может позже накатаю пост. не обещаю, много работы.
- когда OPS команда неквалифицированная. При ресторах будут большие проблемы, а DRP вам не всегда сможет помочь.
Это основные тезисы и рекомендации.
Мы можем сделать фактор репликации 2 или даже 1 реплику, но это уже не про HA.
Мы можем сделать 1 кластер на все базы, но это уже не про изоляцию и безопасность.
Выбор за каждым.
Update:
Апдейтнул пост, добавив, что рекомендации только для AKS/EKS.
Ничего не смогу сказать за других облачных провайдеров, у меня нет этого опыта.
Там могут не быть этих корнер кейсов(но могут быть другие).
Ничего не могу сказать за managed k8s, меня вселенная бережёт от работы с ними.
Часть 4 из 4
5. Операторы и типы баз данных.
"ой, а ты же даже ничего не сказал про типы базы данных(MySQL, PostgreSQL, MongoDB etc), ты ничего не сказал про операторы и разницу между ними, как же так?".
Каждый из операторов, которые я трогал в 2024-2025 годах обладал своими минусами.
Пожалуй отдельно могу отметить только https://cloudnative-pg.io/. Он невероятно чертовски хорош и очень быстро развивается.
Остальные почти все не годятся вам с дефолтными параметрами.
Например zalando оператор по дефолту с выключенной фичей DCS.
https://github.com/zalando/postgres-operator/blob/master/charts/postgres-operator/values.yaml#L454
Это гарантирует вам регулярную проблему с
demoting self because DCS is not accessible and I was a leader и тем, что аппликейшны не смогут подключаться к кластеру (помогает рестарт аппликейшна, как ни странно).Почитать вам https://patroni.readthedocs.io/en/master/dcs_failsafe_mode.html
Другой дефолтный параметр вообще превратит ваш кластер в постоянно расползающийся лаг, который будет течь как красотки на концерте Энрике Иглесиаса.
6. IOPS
Потом в процессе эксплуатуации доходит, что IOPS в Azure (и в AWS EKS) от размера диска зависит.
Мелкий диск (допустим 128 ГБ) - 500 IOPS, и для активных баз это ни о чём.
Хочешь больше - бери 512 ГБ (2300 IOPS) или 1 ТБ (5000 IOPS).
База мелкая, а из-за трёх реплик платишь за объём втридорога.
То есть в том случае, если ваш тип базы данных потребляет много IOPS, то вам придётся брать большие скоростные диски, а это уже не так весело и совсем не так дёшево.
"Так каков итог?" - спросите вы. Можно или нельзя пихать БД в managed кубер AKS/EKS?
Мой ответ такой:
- когда много баз - нельзя. Аргументы выше.
- когда базы очень большие(размер, большое потребление ресурсов CPU/Memory) - совершенно нельзя. Аргумент мне не хватило времени написать, может позже накатаю пост. не обещаю, много работы.
- когда OPS команда неквалифицированная. При ресторах будут большие проблемы, а DRP вам не всегда сможет помочь.
Это основные тезисы и рекомендации.
Мы можем сделать фактор репликации 2 или даже 1 реплику, но это уже не про HA.
Мы можем сделать 1 кластер на все базы, но это уже не про изоляцию и безопасность.
Выбор за каждым.
Update:
Апдейтнул пост, добавив, что рекомендации только для AKS/EKS.
Ничего не смогу сказать за других облачных провайдеров, у меня нет этого опыта.
Там могут не быть этих корнер кейсов(но могут быть другие).
Ничего не могу сказать за managed k8s, меня вселенная бережёт от работы с ними.
👍11
Forwarded from Alexandr Kruchkov
Коллеги со связкой Azure AKS/ AWS EKS + ArgoCD.
У кого-то после последних апдейтов(просмто смена версии, автосесурити апдейт) поломал ли чего в кластере при взаимодействии ArgoCD -> k8s API?
Дикий бурст насилия.
Если кто сталкивался и решил - напишите плиз.
Всем любопытным: я искал на гитхабе, писал в саппорт, гуглил, смотрел на реддите, читал ивенты, смотрел логи и контроллера и аппликейшнсета, менял конфиги и джиттер и реконселейшн, и многое другое.
Или киданите киворд, если где-то рядом нашли решение.
У кого-то после последних апдейтов(просмто смена версии, автосесурити апдейт) поломал ли чего в кластере при взаимодействии ArgoCD -> k8s API?
Дикий бурст насилия.
Если кто сталкивался и решил - напишите плиз.
Всем любопытным: я искал на гитхабе, писал в саппорт, гуглил, смотрел на реддите, читал ивенты, смотрел логи и контроллера и аппликейшнсета, менял конфиги и джиттер и реконселейшн, и многое другое.
Или киданите киворд, если где-то рядом нашли решение.
👍2
Forwarded from Alexandr Kruchkov
Alexandr Kruchkov
Коллеги со связкой Azure AKS/ AWS EKS + ArgoCD. У кого-то после последних апдейтов(просмто смена версии, автосесурити апдейт) поломал ли чего в кластере при взаимодействии ArgoCD -> k8s API? Дикий бурст насилия. Если кто сталкивался и решил - напишите плиз.…
ТЛДР: ажур конченные спидораковые ублюдки свинособачьих шлюх.
После автоматического и не отключаемого обновления AKS в API-сервере появился строгий рейт-лимит, которого раньше либо не было, либо он был мягче. Это вызвало неожиданный эффект: ArgoCD стал чаще дёргать апи и это вызвало нагрузку на API до 40-80 тысяч RPS на каждом из кластеров, увеличив латентность и количество запросов.
Отключение контроллеров Argo не сразу спасло ситуацию - нагрузка держалась из-за накопившейся очереди.
Даже базовые операции (GET, PUT, PATCH) застревали, уходя в retry, а метрики показывали код 409 (Conflict) из-за одновременных попыток обновить ресурсы.
Admission-контроллеры тоже вставали в очередь, усугубляя хаос.
воркэраундсолюшн: отключить ArgoCD/Kyverno, вебхуки и другие активные компоненты, пока нагрузка не упадёт до 30–50 RPS. После этого можно постепенно включать их обратно - ArgoCD зальёт кучу watch-запросов, GET-ов и патчей для синхронизации(чего он там сперва пушит в апиху) и кластер стабилизируется.
Если же Argo и/или киверно не выключать, он уходит в бесконечный retry storm, перегрузка API сохраняется, а метрики с пикамиточёными ошибок 409.
Дольше всего ушло времени на трублшутинг, из-за моей тупости не было сразу понимания, что при вырубании просто арго/киверно и других говн, ещё и хуки ж насильничают апи и надо ещёёёёё время, чтобы всё рассосалось.
После автоматического и не отключаемого обновления AKS в API-сервере появился строгий рейт-лимит, которого раньше либо не было, либо он был мягче. Это вызвало неожиданный эффект: ArgoCD стал чаще дёргать апи и это вызвало нагрузку на API до 40-80 тысяч RPS на каждом из кластеров, увеличив латентность и количество запросов.
Отключение контроллеров Argo не сразу спасло ситуацию - нагрузка держалась из-за накопившейся очереди.
Даже базовые операции (GET, PUT, PATCH) застревали, уходя в retry, а метрики показывали код 409 (Conflict) из-за одновременных попыток обновить ресурсы.
Admission-контроллеры тоже вставали в очередь, усугубляя хаос.
воркэраундсолюшн: отключить ArgoCD/Kyverno, вебхуки и другие активные компоненты, пока нагрузка не упадёт до 30–50 RPS. После этого можно постепенно включать их обратно - ArgoCD зальёт кучу watch-запросов, GET-ов и патчей для синхронизации(чего он там сперва пушит в апиху) и кластер стабилизируется.
Если же Argo и/или киверно не выключать, он уходит в бесконечный retry storm, перегрузка API сохраняется, а метрики с пиками
Дольше всего ушло времени на трублшутинг, из-за моей тупости не было сразу понимания, что при вырубании просто арго/киверно и других говн, ещё и хуки ж насильничают апи и надо ещёёёёё время, чтобы всё рассосалось.
😁9🤯5👏1🌚1😎1
#aws #eks #kubernetes
Задача уровня
Ну вот подключил ты Karpenter/Cluster Autoscaler + SPOT инстансы через разные node group.
Всё даже работает, ты проверяешь в EKS web консоли.
Задача: как быстро и удобно понять когда/сколько у тебя
Для аналитики использования и вообще для удобства.
Перебираешь все метрики и не видишь ничего сходу.
А сходу их и нет. (а, ну или мне сейчас накидают горелых пирожков с гусятками в мою печурку в комментариях)
Прометей/VM не знает ничего про споты или не споты.
А давайте мы сделаем всё сами.
Сперва в наших существующих нод группах вешаем лейблы
Задеплоили, проверяем, есть ли лейблы
Видим свои лейблы:
-
- - spot
- - on-demand
Ок, лейбл повесили, теперь ноды с разных нод-групп имеют лейбл, по которому мы определяем кто есть кто.
А что же дальше?
Дальше нам нужно научить "какой-то" компонент обсервабилити кубернетиса собирать его.
У нас есть метрика с именем
Компонент
Смотрим в прометиусе/ВМ - метрика есть, но наших новых лейблов нет.
Как бы вы его не ставили, добавьте в его конфиг такой параметр
Тем самым, мы разрешаем обогащать метрику новыми лейблами из списка.
* Звездочку писать не рекомендую - этим вы лишь будете занимать сильно больше лишнего места в хранилище прометиуса/викиторииметрикс.
Применяем, смотрим в графане - красота(скриншот).
Результат: пару простых движений и у нас есть график в графане сколько каких нод у нас было в нужный момент времени.
Видим график и понимаем "ага, нам есть над чем работать, надо сделать тюнинг спот инстансов больше, чем он деманд, чтобы платить меньше", но об этом мы поговорим в следующий раз.
* параметр extraArgs может отличаться синтаксисом вашего чарта, читайте документацию по тому способу, как вы ставили куб стейт метрикс.
Задача уровня
junior+/middle-
Ну вот подключил ты Karpenter/Cluster Autoscaler + SPOT инстансы через разные node group.
Всё даже работает, ты проверяешь в EKS web консоли.
Задача: как быстро и удобно понять когда/сколько у тебя
on-demand нод, а когда spot нод?Для аналитики использования и вообще для удобства.
Перебираешь все метрики и не видишь ничего сходу.
А сходу их и нет.
Прометей/VM не знает ничего про споты или не споты.
А давайте мы сделаем всё сами.
Сперва в наших существующих нод группах вешаем лейблы
resource "aws_eks_node_group" "on-demand-group" {
...
labels = {
"node-type" = "on-demand"
...
}
...
}
resource "aws_eks_node_group" "spot-group" {
...
labels = {
"node-type" = "spot"
...
}
...
}Задеплоили, проверяем, есть ли лейблы
kubectl get nodes -L node-role,node-type
NAME STATUS ROLES AGE VERSION NODE-ROLE NODE-TYPE
ip-10-1-123-114.ec2.internal Ready <none> 70d v1.31.4-eks-aeac579 infrastructure on-demand
ip-10-1-14-194.ec2.internal Ready <none> 42m v1.31.6-eks-aad632c applications on-demand
ip-10-1-24-165.ec2.internal Ready <none> 52s v1.31.6-eks-aad632c applications spot
Видим свои лейблы:
-
NODE-TYPE, тип ноды - нам нужно как раз это- - spot
- - on-demand
Ок, лейбл повесили, теперь ноды с разных нод-групп имеют лейбл, по которому мы определяем кто есть кто.
А что же дальше?
Дальше нам нужно научить "какой-то" компонент обсервабилити кубернетиса собирать его.
У нас есть метрика с именем
kube_node_labels от компонента kube-state-metricsКомпонент
kube-state-metrics вы можете ставить разными способами: от оператора, отдельный манифест, стак набор, да не важно.Смотрим в прометиусе/ВМ - метрика есть, но наших новых лейблов нет.
Как бы вы его не ставили, добавьте в его конфиг такой параметр
kube-state-metrics:
...
extraArgs:
- --metric-labels-allowlist=nodes=[node-type,node-role]
Тем самым, мы разрешаем обогащать метрику новыми лейблами из списка.
* Звездочку писать не рекомендую - этим вы лишь будете занимать сильно больше лишнего места в хранилище прометиуса/викиторииметрикс.
Применяем, смотрим в графане - красота(скриншот).
sum(kube_node_labels) by (label_node_type)
Результат: пару простых движений и у нас есть график в графане сколько каких нод у нас было в нужный момент времени.
Видим график и понимаем "ага, нам есть над чем работать, надо сделать тюнинг спот инстансов больше, чем он деманд, чтобы платить меньше", но об этом мы поговорим в следующий раз.
* параметр extraArgs может отличаться синтаксисом вашего чарта, читайте документацию по тому способу, как вы ставили куб стейт метрикс.
👍11👏1
#бытовое #AI #всратость
Либо мои промпты не ок, либо IA как зумеры🤣
Не умеет рисовать циферблат часов с указанным временем🤣
Потратил некоторое время, чтобы нарисовать изображение с
Либо мои промпты не ок, либо IA как зумеры
Не умеет рисовать циферблат часов с указанным временем
Потратил некоторое время, чтобы нарисовать изображение с
циферблатом часов, показывающими 19:30 для презентации, но в итоге просто спёр изображение со стоков без вотермарки.Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
😁6
#одинденьизжизни #longread #kubernetes
Импровизация.
Лонгрид.
Да-да, часть моей работы это импровизация.
Зачастую бывает ситуация, что мне надо что-то решить, а я ну воообще не понимаю что это такое.
Сложилась такая ситуация, что у нас перестал работать стабильно некий сервис.
Пользователи/коллеги жалуются: "при работе с фронтенд приложением видим ошибку ****, помогает рестарт нескольких подов в кубере".
Речь идёт про DEV, но потенциально может аффектить и PROD часть.
Продакшн нам нельзя ломать, иначе меня уволят и мне нечем будет хвастать в интернетах успехами своих успехов.
Идём разбираться.
Какая ошибка? Ошибка в вебе звучит примерно так
Я честно говоря хер знает что такое инвоук, что такое дапр и уж тем более не знаю почему такая ошибка возникает.
И почему тут вообще ресолв, с*ка. Причем тут внутренний DNS. Вы поехавшие что-ли?
В подобных случаях я строго не рекомендую пользоваться нейронками.
Во-первых конкретно в подобных случаях вы не знаете проект(как я), во-вторых, не знаете все 500 вводных, что важны для промпта и вы их просто пропускаете и нейронка не даст ни-ког-да вам точного ответа. Я не знаю примерно ничего, даже с чего начать и нейронка тут не поможет, лишь запутает.
Ок, смотрим что такое DAPR.
Читаем официальную документацию. https://dapr.io/
На основании документации выносим для себя определение что это.
DAPR (Distributed Application Runtime) - это фреймворк для упрощения разработки микросервисов, предоставляющий готовые решения для обмена сообщениями, управления состоянием и взаимодействия сервисов. Используется для создания масштабируемых и устойчивых распределённых приложений.
Ага, нихера не понятно. Очередная всратость для кубернетеса.
Что-то должна упростить, осталось понять кому она упрощает и как.
Смотрим, а что же у нас есть.
У нас есть отдельный неймспейс, в котором стоит
- dapr оператор
- dapr dashboard
- dapr-sidecar-injector
- dapr-scheduler
и всякое подобное.
Почитал логи, порестартил поды, посмотрел ивенты. Ничего не понятно.
Не понимаю чем это должно мне помочь, читаю дальше и разбираюсь по коду.
А как деплоится этот проблемный сервис?
По аннотациям видно, что генерация манифеста идёт через хелмчарт.
Ага, дошёл до helm чарта, у нас есть параметр-аннотация для дапра.
Понимаю, что при добавлении
Для каждого сервиса, где включен этот параметр, добавляется сайдкар.
Круто, хоть куда то сдвинулся в понимании что есть что.
Импровизация.
Лонгрид.
Да-да, часть моей работы это импровизация.
Зачастую бывает ситуация, что мне надо что-то решить, а я ну воообще не понимаю что это такое.
Сложилась такая ситуация, что у нас перестал работать стабильно некий сервис.
Пользователи/коллеги жалуются: "при работе с фронтенд приложением видим ошибку ****, помогает рестарт нескольких подов в кубере".
Речь идёт про DEV, но потенциально может аффектить и PROD часть.
Продакшн нам нельзя ломать, иначе меня уволят и мне нечем будет хвастать в интернетах успехами своих успехов.
Идём разбираться.
Какая ошибка? Ошибка в вебе звучит примерно так
{
“errorCode”: “ERR_DIRECT_INVOKE”,
“message”: “failed to invoke, id: REPLACEMESERVICENAME, err: failed to resolve address for ‘REPLACEMESERVICENAME-dapr.REPLACEMENAMESPACE.svc.cluster.local’: lookup REPLACEMESERVICENAME-dapr.REPLACEMENAMESPACE.svc.cluster.local on 10.0.12.10:53: no such host”
}Я честно говоря хер знает что такое инвоук, что такое дапр и уж тем более не знаю почему такая ошибка возникает.
И почему тут вообще ресолв, с*ка. Причем тут внутренний DNS. Вы поехавшие что-ли?
В подобных случаях я строго не рекомендую пользоваться нейронками.
Во-первых конкретно в подобных случаях вы не знаете проект(как я), во-вторых, не знаете все 500 вводных, что важны для промпта и вы их просто пропускаете и нейронка не даст ни-ког-да вам точного ответа. Я не знаю примерно ничего, даже с чего начать и нейронка тут не поможет, лишь запутает.
Ок, смотрим что такое DAPR.
Читаем официальную документацию. https://dapr.io/
На основании документации выносим для себя определение что это.
DAPR (Distributed Application Runtime) - это фреймворк для упрощения разработки микросервисов, предоставляющий готовые решения для обмена сообщениями, управления состоянием и взаимодействия сервисов. Используется для создания масштабируемых и устойчивых распределённых приложений.
Ага, нихера не понятно. Очередная всратость для кубернетеса.
Что-то должна упростить, осталось понять кому она упрощает и как.
Смотрим, а что же у нас есть.
У нас есть отдельный неймспейс, в котором стоит
- dapr оператор
- dapr dashboard
- dapr-sidecar-injector
- dapr-scheduler
и всякое подобное.
Почитал логи, порестартил поды, посмотрел ивенты. Ничего не понятно.
Не понимаю чем это должно мне помочь, читаю дальше и разбираюсь по коду.
А как деплоится этот проблемный сервис?
>ky pods REPLACEMESERVICENAME-7766b4d5c-w66vc
apiVersion: v1
kind: Pod
metadata:
annotations:
dapr.io/app-id: REPLACEMESERVICENAME
...
dapr.io/enabled: "true"
...
labels:
app: REPLACEMESERVICENAME
...
dapr.io/app-id: REPLACEMESERVICENAME
dapr.io/metrics-enabled: "true"
dapr.io/sidecar-injected: "true"
...
metrics_scrape_enabled: "true"
metrics_scrape_from_pods: "true"
pod-template-hash: 7766b4d5c
release: REPLACEMESERVICENAME
tier: web
track: stable
По аннотациям видно, что генерация манифеста идёт через хелмчарт.
Ага, дошёл до helm чарта, у нас есть параметр-аннотация для дапра.
Понимаю, что при добавлении
dapr:
enabled: true
Для каждого сервиса, где включен этот параметр, добавляется сайдкар.
Круто, хоть куда то сдвинулся в понимании что есть что.
👍5❤1
#одинденьизжизни #longread #kubernetes
Промежуточное мнение: у нас есть N сервисов, между собой они используют dapr сайдкар контейнеры, который инжектится при помощи оператора и сайдкар инжектора при добавлении параметра в values файле.
Ага, ну хоть что-то.
Смотрим а как вообще роутинг устроен:
- в пределах кубера
- за пределами кластера кубера
Внутри кубера через DAPR (ну то есть через SVC адрес), снаружи через кастомный ингресс контроллер с кучей стрёмных аннотаций и хидеров.
Давай, Алекс, решать, куда будем копать.
Логика самой первой ошибки подсказывает, что ошибка не на уровне ингресса.
И как бы мне не хотелось с кровью выкорчевать весь этот кастомный ингресс контроллер из левой репы и сделать "по нормальному", мне сейчас надо чинить сервис и траблшутить ,а не правда матку рубить и настраивать как по книжке.
ПлАчу, засовываю своё негодование в известное место и забиваю на ингресс, иду в сторону service сущностей кубера.
Что мы имеет на данный момент? В валуес файл добавили параметр, оператор добавляет сайдкар, другие сервисы обращаются по адресу service к падающему сервису и получают иногда(с*ка, да как так то??!) ошибку.
Причём рестарт пода помогает.
Методом наблюдательности глаз вижу, что у нас на самом деле ДВЕ проблемы.
Первая проблема - у некоторых подов, где параметр стоит, нет сайдкара.
Я совершенно не знаю как это случилось и почему и как такое детектировать.
Делаем рестарт пода - появляется сайдкар с dapr.
Чтобы "поиграться" в будущем с такими ситуациями, мне нужен алёрт, который будет это отслеживать и рапортовать мне в слак. Я увижу проблемную ситуацию и буду иметь возможность в реалтайме траблшутить.
Пишем алерт
Тут мы проверяем есть ли поды, у которых есть аннотация на сайдкар дапра и матчим это с подами, у которых нет сайдкар-контейнера с именем daprd(украл название из чарта). То есть если сайдкара нет, где он должен быть, я получу оповещение.
Вторая проблема, которую вижу -
Как такое детектировать? Оно же не всегда.
Идём в документацию кубернетиса. Читаем что же такое может случится, что адрес service есть, но ресолва нет.
Лейблы? Селекторы? Херекторы? Я не знаю.
Документация сходу ничего не подсказывает и вот тут я иду в нейронку и спрашиваю напрямую "какие бывают случаи, когда у меня дапр сайдкары и в какой-то момент времени service есть но ресолва нет". Помучав вопросами я понимаю, что проблема в kubernetes
Получив ключевые слова от нейроники я снова ухожу в документацию кубернетис.
Оказывается если ПОД не реди, то из endpoints пропадает IP адрес POD и service в кубере перестаёт ресолвится.
Ура! Зацепка! Под нот реди.
Промежуточное мнение: у нас есть N сервисов, между собой они используют dapr сайдкар контейнеры, который инжектится при помощи оператора и сайдкар инжектора при добавлении параметра в values файле.
Ага, ну хоть что-то.
Смотрим а как вообще роутинг устроен:
- в пределах кубера
- за пределами кластера кубера
Внутри кубера через DAPR (ну то есть через SVC адрес), снаружи через кастомный ингресс контроллер с кучей стрёмных аннотаций и хидеров.
Давай, Алекс, решать, куда будем копать.
Логика самой первой ошибки подсказывает, что ошибка не на уровне ингресса.
И как бы мне не хотелось с кровью выкорчевать весь этот кастомный ингресс контроллер из левой репы и сделать "по нормальному", мне сейчас надо чинить сервис и траблшутить ,а не правда матку рубить и настраивать как по книжке.
ПлАчу, засовываю своё негодование в известное место и забиваю на ингресс, иду в сторону service сущностей кубера.
Что мы имеет на данный момент? В валуес файл добавили параметр, оператор добавляет сайдкар, другие сервисы обращаются по адресу service к падающему сервису и получают иногда(с*ка, да как так то??!) ошибку.
Причём рестарт пода помогает.
Методом наблюдательности глаз вижу, что у нас на самом деле ДВЕ проблемы.
Первая проблема - у некоторых подов, где параметр стоит, нет сайдкара.
Я совершенно не знаю как это случилось и почему и как такое детектировать.
Делаем рестарт пода - появляется сайдкар с dapr.
Чтобы "поиграться" в будущем с такими ситуациями, мне нужен алёрт, который будет это отслеживать и рапортовать мне в слак. Я увижу проблемную ситуацию и буду иметь возможность в реалтайме траблшутить.
Пишем алерт
- alert: DAPR_ibanni_1
expr: |-
(
sum(kube_pod_annotations{annotation_dapr_io_enabled="true"}) by (cluster, exported_namespace, pod)
) unless (
sum(kube_pod_container_info{container="daprd"}) by (cluster, exported_namespace, pod)
)
for: 5m
annotations:
summary: "DAPR sidecar is not running on `{{ $labels.cluster }}`/`{{ $labels.exported_namespace }}`/`{{ $labels.pod }}`"
Тут мы проверяем есть ли поды, у которых есть аннотация на сайдкар дапра и матчим это с подами, у которых нет сайдкар-контейнера с именем daprd(украл название из чарта). То есть если сайдкара нет, где он должен быть, я получу оповещение.
Вторая проблема, которую вижу -
"что-то" "где-то" "как-то" происходит и перестаёт ресолвится.Как такое детектировать? Оно же не всегда.
Идём в документацию кубернетиса. Читаем что же такое может случится, что адрес service есть, но ресолва нет.
Лейблы? Селекторы? Херекторы? Я не знаю.
Документация сходу ничего не подсказывает и вот тут я иду в нейронку и спрашиваю напрямую "какие бывают случаи, когда у меня дапр сайдкары и в какой-то момент времени service есть но ресолва нет". Помучав вопросами я понимаю, что проблема в kubernetes
endpoints.Получив ключевые слова от нейроники я снова ухожу в документацию кубернетис.
Оказывается если ПОД не реди, то из endpoints пропадает IP адрес POD и service в кубере перестаёт ресолвится.
Ура! Зацепка! Под нот реди.
👍6
Лезем в конфигурацию, тут есть и стартап пробы и лайвнесс и рединес.
Наша формула "что-то" "где-то" "как-то" приобретает очертания.
ПОД не проходит проверку лайвнес/рединесс пробы, меняет состояние на нод реди, его IP адрес удаляется из endpoints и ресолв перестаёт работать для ДРУГИХ сервисов по его имени service.
Пилим второй алёрт, чтобы детектировать (ну не буду же я постоянно сидеть с этой проблемой или ждать гневного письма босса).
Тут я отсеял велеро, который за каким-то рожном сюда попадал и я просто отфильтровал его, даже не хочу и 0.0001мс тратить на траблшутинг ещё и велеро.
Теперь у нас есть два алёрта, которые как минимум мне просигнализируют раньше пользователей и коллег, что у нас беда.
Уходим на обед.
.
..
...
"
Попался, дапр тебя подери.
Вижу ситуацию, пишу коллегам в слак "
А проба не проходит, вот да, видимо по ивентам, по дескрайбу, по стейту.
В некоторых случаях есть даже рестарты, exit code НЕ 137/OOM - для ДРУГИХ подов с похожей проблемой.
А что в логах? А в логах у нас ничего.
Лезем к разработчикам, смотрим, что там dotnet и включаем debug левел прям для dev стенда, а что вы мне сделаете.
Уходим допивать чай.
.
..
...
Спустя время снова алёрт.
Методом метрик понимаем, что в целом проблема с 1-2 приложениями в кубере, они как бы core часть и к ним по servicename лезут другие приложения и если этот падает или недоступен - лежит весь продукт.
Уже есть логи и мы видим, что в логах у нас
То есть не на уровне kubelet/кубера, а на уровне приложения внутри.
Смотрим в графане CPU/Memory usage, фильтруем по имени деплоймента и видим исторически, что все без исключения ПОДы текут по памяти как барышни на концерте Энрике Иглесиаса.
Пишем разработке "мы вроде нашли проблему, у нас память течёт".
Они снимают дамп(а я не умею(((( и научится не успел, они сняли раньше) и уходят на перекур.
Спустя пару часов выкатывают фикс, несколько часов тестирования, смотрим по метрикам - всё ок.
Проходит ещё 1-2 дня и жалобы заканчиваются, алёртов тоже нет.
Проблема, при которой не работал ресолв, решилась.
Что было: приложение текло по памяти, ничего не писало в логи, его не убивали по ООМ, он просто переставал работать. Некорректные настройки liveness probes позволяли ему 503-ть при пробах, он переходил в not ready, его IP адрес пропадал из Endpoint k8s, переставал ресолвится по service имени, весь продукт падал.
Сейчас всё ок.
Количество реплик больше 1 на конкретно данном приложении сделать нельзя, оно не масштабируется, и даже стратегия там ReCreate. Ну вот такое приложение. Это не ко мне вопрос. Только 1 реплика.
Касательно "почему на некоторые поды не добавлялся сайдкар" у меня ответа нет, но алерт есть и при случае я потраблшутю и его.
Итоги.
Виноват ли был тут дапр?
Нужно ли мне было лезть в логи оператора или инжектора?
Стоит ли бесится от кастомного ингресса?
А я всё ещё не знаю, мне хватило и того, что саму проблему я починил.
Не знаю и всё. Может дапр и хорош. Может я просто дурак и не так копал изначально.
Может разработчики негодяи.
Может я просто деревня и мог бы сразу догадаться что не так.
Не догадался. Пришлось нырнуть и хорошенько разобраться.
Из плюсов:
- узнал про эту технологию
- написал лонгрид о чём я думаю в такие моменты и как работает моя голова
- очередной раз доказал самому себе, что стартовать траблшутинг с нейронки не стоит, она бы 10000% завела бы меня не туда. Потом пользоваться можно, но не со старта.
- починили приложение и всё начало работать стабильно
Минусы:
- опять потратил куча времени, никто не оценит человеко-часы таких погружений
Наша формула "что-то" "где-то" "как-то" приобретает очертания.
ПОД не проходит проверку лайвнес/рединесс пробы, меняет состояние на нод реди, его IP адрес удаляется из endpoints и ресолв перестаёт работать для ДРУГИХ сервисов по его имени service.
Пилим второй алёрт, чтобы детектировать (ну не буду же я постоянно сидеть с этой проблемой или ждать гневного письма босса).
- alert: DAPR_ibanni_2
expr: |-
kube_pod_status_ready{condition!="true", exported_namespace!="velero"} > 0
and on (pod, exported_namespace, cluster)
kube_pod_annotations{annotation_dapr_io_enabled="true"}
for: 30s
labels:
severity: critical
annotations:
summary: "DAPR. No route to `{{ $labels.cluster }}`/`{{ $labels.exported_namespace }}`/`{{ $labels.pod }}`"
Тут я отсеял велеро, который за каким-то рожном сюда попадал и я просто отфильтровал его, даже не хочу и 0.0001мс тратить на траблшутинг ещё и велеро.
Теперь у нас есть два алёрта, которые как минимум мне просигнализируют раньше пользователей и коллег, что у нас беда.
Уходим на обед.
.
..
...
"
Тревога, тревога, волк унес зайчат!" - кричит мне слак и я бегу с кухни в кабинет.Попался, дапр тебя подери.
Вижу ситуацию, пишу коллегам в слак "
всё под контролём, Алекс всё знает и чинит уже".А проба не проходит, вот да, видимо по ивентам, по дескрайбу, по стейту.
В некоторых случаях есть даже рестарты, exit code НЕ 137/OOM - для ДРУГИХ подов с похожей проблемой.
А что в логах? А в логах у нас ничего.
Лезем к разработчикам, смотрим, что там dotnet и включаем debug левел прям для dev стенда, а что вы мне сделаете.
Уходим допивать чай.
.
..
...
Спустя время снова алёрт.
Методом метрик понимаем, что в целом проблема с 1-2 приложениями в кубере, они как бы core часть и к ним по servicename лезут другие приложения и если этот падает или недоступен - лежит весь продукт.
Уже есть логи и мы видим, что в логах у нас
outofmemory.То есть не на уровне kubelet/кубера, а на уровне приложения внутри.
Смотрим в графане CPU/Memory usage, фильтруем по имени деплоймента и видим исторически, что все без исключения ПОДы текут по памяти как барышни на концерте Энрике Иглесиаса.
Пишем разработке "мы вроде нашли проблему, у нас память течёт".
Они снимают дамп(а я не умею(((( и научится не успел, они сняли раньше) и уходят на перекур.
Спустя пару часов выкатывают фикс, несколько часов тестирования, смотрим по метрикам - всё ок.
Проходит ещё 1-2 дня и жалобы заканчиваются, алёртов тоже нет.
Проблема, при которой не работал ресолв, решилась.
Что было: приложение текло по памяти, ничего не писало в логи, его не убивали по ООМ, он просто переставал работать. Некорректные настройки liveness probes позволяли ему 503-ть при пробах, он переходил в not ready, его IP адрес пропадал из Endpoint k8s, переставал ресолвится по service имени, весь продукт падал.
Сейчас всё ок.
Количество реплик больше 1 на конкретно данном приложении сделать нельзя, оно не масштабируется, и даже стратегия там ReCreate. Ну вот такое приложение. Это не ко мне вопрос. Только 1 реплика.
Касательно "почему на некоторые поды не добавлялся сайдкар" у меня ответа нет, но алерт есть и при случае я потраблшутю и его.
Итоги.
Виноват ли был тут дапр?
Нужно ли мне было лезть в логи оператора или инжектора?
Стоит ли бесится от кастомного ингресса?
А я всё ещё не знаю, мне хватило и того, что саму проблему я починил.
Не знаю и всё. Может дапр и хорош. Может я просто дурак и не так копал изначально.
Может разработчики негодяи.
Может я просто деревня и мог бы сразу догадаться что не так.
Не догадался. Пришлось нырнуть и хорошенько разобраться.
Из плюсов:
- узнал про эту технологию
- написал лонгрид о чём я думаю в такие моменты и как работает моя голова
- очередной раз доказал самому себе, что стартовать траблшутинг с нейронки не стоит, она бы 10000% завела бы меня не туда. Потом пользоваться можно, но не со старта.
- починили приложение и всё начало работать стабильно
Минусы:
- опять потратил куча времени, никто не оценит человеко-часы таких погружений
👍12🔥6🤔2
#aws #rds
Короткий материал на уровне senior+
Нырни на самое дно. Без страховки.
Иногда, когда проект достиг своего максимума на данный момент, приходится оптимизировать уже не софт и не пайплайны, а саму инфраструктуру.
Например параметры движка или базу.
Так и вышло в этот раз.
Традиционные параметры типа CPU/memory usage, connections, memory usage, latency, IOPS, lags, cache, CRUD throughput, slow logs и прочее мы научились мониторить и алёртить, что заставило нас оптимизировать запросы к бд и серьёзно снизило нагрузку.
Совсем недавно мы нырнули глубже и поменяли пару параметров в ущерб потери 1 секунды данных в случае аутейджа со стороны Амазон.
Данный проект не использует критически важные операции для транзакций типа финансовых операций, так что мы имеем право это включить. Если у вас финансовые операции или любые критичные операции вам НЕЛЬЗЯ это включать. Нельзя и запомните это.
Значение 2 означает, что журнал транзакций (redo log) записывается в буфер операционной системы при каждой фиксации (commit), но сброс на диск происходит только раз в секунду
- Улучшает производительность, так как уменьшает операции ввода-вывода диска
- Снижает надежность: возможна потеря транзакций последней секунды при сбое сервера/ОС
- Компромисс между производительностью (выше) и надежностью (ниже) по сравнению со значением 1
Значение 1 означает, что система разрешает возможную потерю данных для увеличения производительности
- Значительно ускоряет операции фиксации транзакций
- Снижает гарантии сохранности данных
- Может привести к потере транзакций при сбоях
Результат дал о себе знать почти сразу, но нам явно придётся ещё несколько раз нырять для более точного тюнинга. Будем наблюдать и изменять под себя.
DevOps это не всегда общение, ямлоделие, пайплайны и кубер.
Иногда это тюнинг БД, когда все остальные элементы уже исчерпаны или нет на это бюджета(выше тип инстанса, gravitron v4, больше read реплик, RDS proxy, queries tuning etc).
Ну и код для примера:
Короткий материал на уровне senior+
Нырни на самое дно. Без страховки.
Иногда, когда проект достиг своего максимума на данный момент, приходится оптимизировать уже не софт и не пайплайны, а саму инфраструктуру.
Например параметры движка или базу.
Так и вышло в этот раз.
Традиционные параметры типа CPU/memory usage, connections, memory usage, latency, IOPS, lags, cache, CRUD throughput, slow logs и прочее мы научились мониторить и алёртить, что заставило нас оптимизировать запросы к бд и серьёзно снизило нагрузку.
Совсем недавно мы нырнули глубже и поменяли пару параметров в ущерб потери 1 секунды данных в случае аутейджа со стороны Амазон.
Данный проект не использует критически важные операции для транзакций типа финансовых операций, так что мы имеем право это включить. Если у вас финансовые операции или любые критичные операции вам НЕЛЬЗЯ это включать. Нельзя и запомните это.
innodb_flush_log_at_trx_commitЗначение 2 означает, что журнал транзакций (redo log) записывается в буфер операционной системы при каждой фиксации (commit), но сброс на диск происходит только раз в секунду
- Улучшает производительность, так как уменьшает операции ввода-вывода диска
- Снижает надежность: возможна потеря транзакций последней секунды при сбое сервера/ОС
- Компромисс между производительностью (выше) и надежностью (ниже) по сравнению со значением 1
innodb_trx_commit_allow_data_lossЗначение 1 означает, что система разрешает возможную потерю данных для увеличения производительности
- Значительно ускоряет операции фиксации транзакций
- Снижает гарантии сохранности данных
- Может привести к потере транзакций при сбоях
Результат дал о себе знать почти сразу, но нам явно придётся ещё несколько раз нырять для более точного тюнинга. Будем наблюдать и изменять под себя.
DevOps это не всегда общение, ямлоделие, пайплайны и кубер.
Иногда это тюнинг БД, когда все остальные элементы уже исчерпаны или нет на это бюджета(выше тип инстанса, gravitron v4, больше read реплик, RDS proxy, queries tuning etc).
Ну и код для примера:
resource "aws_rds_cluster_parameter_group" "this" {
...
parameter {
apply_method = "immediate"
name = "innodb_flush_log_at_trx_commit"
value = "2"
}
parameter {
apply_method = "immediate"
name = "innodb_trx_commit_allow_data_loss"
value = "1"
}
}👍6🔥3