#kubernetes #azure #aks #troubleshooting #argo #dapr #api
Ныряем в Azure AKS API.
Часть 1 из 2.
У нас болел кубернетис апи.
Болел долго, со вкусом.
Словно мужчина 30+ лет с температурой 37.2, с опекой рядом кудахтающей супруги.
Мы честно хотели его вылечить, но у меня лично никогда не было глубокого опыта дебага апи, часть команды было просто пофиг. Вроде работает? Хорошо. Бизнес, само собой, такими вещами и не интересуется.
Это вызывало массу сайд эффектов: 4 или 5 из моих историй это следствие загрузки K8S API.
Работа операторов, работа кеды и dcs демоушн.
Однажды мненадо было списать много времени по трекеру интересно разобраться с причиной.
Путь первый. Невежественность.
В кластере много компонентов, которые работают с кубернетес апи.
ArgoCD, Kyverno, десятки операторов. Много всего.
Первый мой шаг - поэтапно вырубать контроллеры
То есть я тупо один за одним вырубал какие-то компоненты.
и ждал. 30-60 минут, есть ли эффект.
Конечно же предупреждая коллег, и в случае необходимости тут же скейлил вверх.
Эта идея была тупая, я убил несколько часов/дней.
Никакого результата.
Путь второй. Наивность.
Дальше я выбрал путь наивности - ходил по приложениям, операторам и где мог, подкручивал параметры, чтобы обращения к АПИ был реже. Всякие реконсилейшн у арго, демоушн патрони, частота запросов кеда оператора и так далее.
Помогло ли это? Нет. Стало ли лучше? Глобально - да, ведь я просто оттюнил к лучшему.
К пункту наивности я бы добавил все мои попытки разобраться "что не так с апи по метрикам".
Метрики никак и никогда не дают информации кто же даёт основную нагрузку.
Путь третий. Просветление.
Очевидно предыдущие попытки были унылы и тупы.
Почитал интернет, нейронки, документацию.
Первым делом включаю аудит-лог.
Azure-Kubernetes-Monitoring-Diagnostic settings.
Дальше включаю для Kubernetes API и сохранение в Log Analytics workspace.
Сохраняю, иду в
Там выбираю Logs и ищу сперва все ошибки.
Вижу кучу ошибок.
Ок, начнем с рандом частой ошибки:
Не заостряю внимание на продукте, мне он знаком (можно почитать на https://github.com/dapr/dapr/).
По ошибке проблема сервиса(хоть и странный адрес), а есть ли он?
Он есть.
Почему возникает эта ошибка?Сперва смотрю валуес
Нет ничего интересно, как и в нашем values файле.
Иду в чарт и качаю его к себе https://github.com/dapr/helm-charts/blob/master/dapr-1.14.2.tgz
Вижу кучу темплейтов, хелперсов, CRD.
В CRD указано, что сам оператор реплейсит CRD.
То есть оператор время от времени должен реплейсить неймспейс внутри CRD с
А он не реплейсит. Хорошо, меняю сам руками, смотрю результат.
Радуюсь, иду в логи - а там снова ошибка.
Непонятно. Возвращаюсь обратно а там
Да камон.
Ныряем в Azure AKS API.
Часть 1 из 2.
У нас болел кубернетис апи.
Болел долго, со вкусом.
Словно мужчина 30+ лет с температурой 37.2, с опекой рядом кудахтающей супруги.
Мы честно хотели его вылечить, но у меня лично никогда не было глубокого опыта дебага апи, часть команды было просто пофиг. Вроде работает? Хорошо. Бизнес, само собой, такими вещами и не интересуется.
Это вызывало массу сайд эффектов: 4 или 5 из моих историй это следствие загрузки K8S API.
Работа операторов, работа кеды и dcs демоушн.
Однажды мне
Путь первый. Невежественность.
В кластере много компонентов, которые работают с кубернетес апи.
ArgoCD, Kyverno, десятки операторов. Много всего.
Первый мой шаг - поэтапно вырубать контроллеры
То есть я тупо один за одним вырубал какие-то компоненты.
kubectl scale --replicas 0 sts/name
kubectl scale --replicas 0 deploy/name
и ждал. 30-60 минут, есть ли эффект.
Конечно же предупреждая коллег, и в случае необходимости тут же скейлил вверх.
Эта идея была тупая, я убил несколько часов/дней.
Никакого результата.
Путь второй. Наивность.
Дальше я выбрал путь наивности - ходил по приложениям, операторам и где мог, подкручивал параметры, чтобы обращения к АПИ был реже. Всякие реконсилейшн у арго, демоушн патрони, частота запросов кеда оператора и так далее.
Помогло ли это? Нет. Стало ли лучше? Глобально - да, ведь я просто оттюнил к лучшему.
К пункту наивности я бы добавил все мои попытки разобраться "что не так с апи по метрикам".
Метрики никак и никогда не дают информации кто же даёт основную нагрузку.
Путь третий. Просветление.
Очевидно предыдущие попытки были унылы и тупы.
Почитал интернет, нейронки, документацию.
Первым делом включаю аудит-лог.
Azure-Kubernetes-Monitoring-Diagnostic settings.
Дальше включаю для Kubernetes API и сохранение в Log Analytics workspace.
Сохраняю, иду в
Log Analytics workspace.Там выбираю Logs и ищу сперва все ошибки.
AKSControlPlane
| where Category == "kube-apiserver" and Level == "ERROR"
| limit 40
| project TimeGenerated, Level, Message
Вижу кучу ошибок.
Ок, начнем с рандом частой ошибки:
cacher (subscriptions.dapr.io): unexpected ListAndWatch error: failed to list dapr.io/v1alpha1, Kind=Subscription: conversion webhook for dapr.io/v2alpha1, Kind=Subscription failed: Post "https://dapr-webhook.replaceme.svc:443/convert?timeout=30s": service "dapr-webhook" not found; reinitializing...
Не заостряю внимание на продукте, мне он знаком (можно почитать на https://github.com/dapr/dapr/).
По ошибке проблема сервиса(хоть и странный адрес), а есть ли он?
kubectl get svc -n dapr-system | grep webhook
dapr-webhook ClusterIP 10.0.12.141 <none> 443/TCP
Он есть.
Почему возникает эта ошибка?Сперва смотрю валуес
helm show values dapr/dapr --version 1.14.2
Нет ничего интересно, как и в нашем values файле.
Иду в чарт и качаю его к себе https://github.com/dapr/helm-charts/blob/master/dapr-1.14.2.tgz
Вижу кучу темплейтов, хелперсов, CRD.
В CRD указано, что сам оператор реплейсит CRD.
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
...
spec:
group: dapr.io
conversion:
strategy: Webhook
webhook:
clientConfig:
service:
namespace: replaceme # Patched by post-install webhook
То есть оператор время от времени должен реплейсить неймспейс внутри CRD с
replaceme на реальный dapr-system.А он не реплейсит. Хорошо, меняю сам руками, смотрю результат.
kubectl edit crd subscriptions.dapr.io
customresourcedefinition.apiextensions.k8s.io/subscriptions.dapr.io edited
kubectl get crd subscriptions.dapr.io -o yaml | grep namespace
namespace: dapr-system
Радуюсь, иду в логи - а там снова ошибка.
Непонятно. Возвращаюсь обратно а там
kubectl get crd subscriptions.dapr.io -o yaml | grep namespace
namespace: replaceme
Да камон.
👍8
#kubernetes #azure #aks #troubleshooting #argo #dapr #api
Часть 2 из 2.
Думаю ну может я дурак, Меняю снова, уже не иду в логи, А проверяю на месте.
И картина там такая:
Бррр, как такое возможно.
Иду в гугл, нейронку, мне говорят "а ты посмотри - кто последний то меняет объект?".
Смотрю
Пффф, а арго то тут причем?
Снова меняю, снова смотрю - да, арго меняет обратно неймспейс на дефолт.
Иду в репозиторий арго, но там просто
Ну и
А больше мы ничего не меняем.
Снова документация, гугл.
Оказалось вот что:
- арго выкачивает ВЕСЬ чарт, внутри есть директория CRD и там внутри дефолт(путь к чарту был выше, внутри есть CRD директория с манифестами).
Промежуточное описание проблемы:
каждый N период времени оператор DAPR меняет namespace в CRD, тут же сам applicationset DAPR переходит в OutOfSync, арго начинает резко синкать, подтягивает весь чарт, видит, что поменялся CRD и меняет на дефолт. И так по кругу. Насилие ради насилия.
Я и коллега начали фиксить это несколькими вариантами через
Затем снова руками меняю неймспейс, смотрю - ура.
Неймспейс больше не ревратится, в аудит логе АПИ ошибки(этой) больше нет.
Да, арго больше не меняет.
Нагрузку снизили на ... на 4%. Мало, но уже что-то.
Выключаю аудит лог(он оооооооооочень дорогой), закрываю одну из саб-тасок касательно АПИ.
Ещё раз описание ишшуи:
- задеплоили арго аппликейшнсет через сторонний чарт с DAPR
- арго создаёт все сущности через хелмп темплейт (даже те, о которых мы в явном виде не знали)
- затем вебхук от оператора дапр переписывает CRD
- арго при синке видит дифф по CRD и переписывыает его снова
- и так по кругу
Пока не глянешь в кишки и не добавишь в игнор - насилие над апи кубера, так как весь функционал арго и дапра - через кубер апи.
Итог:
- я научился смотреть в логи аудита по Azure AKS API
- сгорел от дурости DAPR оператора и ArgoCD оператора в попытках переписать друг за другом CRD
- узнал про игноры в арго (вообще есть и иные решения для проблемы, но игнор самый простой)
- снизил нагрузку на 4% лишь с одним фиксом
Впереди ещё несколько подходов к апи, есть десятки других ошибок, буду с каждой разбираться отдельно.
Это оказалось интересно.
Часть 2 из 2.
Думаю ну может я дурак, Меняю снова, уже не иду в логи, А проверяю на месте.
И картина там такая:
kubectl edit crd subscriptions.dapr.io
customresourcedefinition.apiextensions.k8s.io/subscriptions.dapr.io edited
kubectl get crd subscriptions.dapr.io -o yaml | grep namespace
namespace: dapr-system
kubectl get crd subscriptions.dapr.io -o yaml | grep namespace
namespace: replaceme
Бррр, как такое возможно.
Иду в гугл, нейронку, мне говорят "а ты посмотри - кто последний то меняет объект?".
Смотрю
kubectl get crd subscriptions.dapr.io -o jsonpath='{.metadata.managedFields[*].manager}' | tr ' ' '\n' | sort | uniq -c
1 argocd-controller
1 kube-apiserver
1 kubectl-edit
1 operatorПффф, а арго то тут причем?
Снова меняю, снова смотрю - да, арго меняет обратно неймспейс на дефолт.
Иду в репозиторий арго, но там просто
---
name: dapr
namespace: dapr-system
repoURL: https://dapr.github.io/helm-charts/
targetRevision: 1.14.2
chart: dapr
Ну и
applicationset есть.А больше мы ничего не меняем.
Снова документация, гугл.
Оказалось вот что:
- арго выкачивает ВЕСЬ чарт, внутри есть директория CRD и там внутри дефолт(путь к чарту был выше, внутри есть CRD директория с манифестами).
Промежуточное описание проблемы:
каждый N период времени оператор DAPR меняет namespace в CRD, тут же сам applicationset DAPR переходит в OutOfSync, арго начинает резко синкать, подтягивает весь чарт, видит, что поменялся CRD и меняет на дефолт. И так по кругу. Насилие ради насилия.
Я и коллега начали фиксить это несколькими вариантами через
applicationset, типа---
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
...
template:
...
spec:
...
ignoreDifferences:
...
- group: apiextensions.k8s.io
kind: CustomResourceDefinition
name: subscriptions.dapr.io
jqPathExpressions:
- .spec.conversion.webhook.clientConfig.service.namespace
Затем снова руками меняю неймспейс, смотрю - ура.
Неймспейс больше не ревратится, в аудит логе АПИ ошибки(этой) больше нет.
Да, арго больше не меняет.
Нагрузку снизили на ... на 4%. Мало, но уже что-то.
Выключаю аудит лог(он оооооооооочень дорогой), закрываю одну из саб-тасок касательно АПИ.
Ещё раз описание ишшуи:
- задеплоили арго аппликейшнсет через сторонний чарт с DAPR
- арго создаёт все сущности через хелмп темплейт (даже те, о которых мы в явном виде не знали)
- затем вебхук от оператора дапр переписывает CRD
- арго при синке видит дифф по CRD и переписывыает его снова
- и так по кругу
Пока не глянешь в кишки и не добавишь в игнор - насилие над апи кубера, так как весь функционал арго и дапра - через кубер апи.
Итог:
- я научился смотреть в логи аудита по Azure AKS API
- сгорел от дурости DAPR оператора и ArgoCD оператора в попытках переписать друг за другом CRD
- узнал про игноры в арго (вообще есть и иные решения для проблемы, но игнор самый простой)
- снизил нагрузку на 4% лишь с одним фиксом
Впереди ещё несколько подходов к апи, есть десятки других ошибок, буду с каждой разбираться отдельно.
Это оказалось интересно.
1❤10👍7🔥5
#kubernetes #secrets #api
(заметка не несёт никакой ценности, лишь мысли)
Иногда, для самого себя, я провожу теоретические, вперемешку с практическими, изыскания.
Выбираю узкопрофильную тему и ковыряю, пока не дохожу до кишков.
Это может быть знания зачем
Практической ценности такие изыскания обычно не имеют, это больше любопытство и разминка для ума. Лишь иногда попадаются настоящие "бриллианты".
Мне захотелось узнать, а какие есть способы, чтобы снизить нагрузку на Kubernetes API.
Все мы знаем про кучу операторов, которые не хило нагружают апишку, но что, если снизить средствами самого кубера?
У нас есть несколько
https://kubernetes.io/docs/reference/using-api/api-concepts/
Знания и поиск по документации привел к тому, что есть
То есть каждый раз при этих действиях идёт
Сам по себе секрет, просто лежащий в кубере, никакой нагрузки не несёт.
Пока secret не примонтирован(как переменная или файл) и пока не было рестарта/скейла/редеплоя, апишку никто не дёргает.
Однако при активном скейлинге (все мои проекты), это прям попадание в точку.
Да, вочей хватает.
Затем мои поиски вывели на отличную опцию
https://kubernetes.io/docs/concepts/configuration/secret/#secret-immutable
С этой опцией нельзя поменять значение секрета. Его можно только реплейснуть или удалить и создать с нуля.
Копнув дальше, я узнал, что тут можно немного снизить нагрузку из-за интересного механизма.
"О господи! Оно!" - подумал я. Это было нечто новое, захотелось сразу использовать. И сразу в проде😀
Начал смотреть какие есть реализации:
- исправление своих чартов, чтобы секреты были иммутабл и были хуки(иначе при редеплое и изменении секрета хелм упадёт с ошибкой).
- написание мутейшн хука или оператора, который все задеплоенные секреты помечает сразу иммутабл, а все команды переучить, чтобы в их чартах были хуки
В целом неплохая картина: немного изменил флоу в командах по релизам, добавил хуки, все секреты в кубе иммутабл и получаем:
- меньше латенси WATCH и CONNECT запросов (проверено, кубер 1.33, Linode)
- меньшее количество WATCH запросов (проверено, кубер 1.33, Linode + AWS)
- меньше памяти в ETCD. Это теоретически, большинство клауд провайдеров не дают прямой доступ к метрикам ETCD(я тестировал на AWS + linode), а потому доказать не могу. Барметал с нуля поднимать лень, так что пусть это окажется лишь теорией.
Всё выглядит как сказка, а что на деле?
Тут я вспомнил, что работал в замечательном банке с синим логотипом, и там до сих пор во всех департаментах работают очень крутые инженеры (всем привет, кто читает, вы солнышки❤️).
Тема интересная, заменшил в паблик чате @kubernetes_ru и меня тут же спустили на землю.
Оказалось что ребята это уже пробовали у себя и быстро от этого ушли.
Беда в том , что если такой
Проверил - да, у меня есть много секретов общих для нескольких деплойментов.
Безусловно это ставит крест на моей задумке, баги мне не нужны ради 1.5-3% экономии нагрузки.
Ладно, время на изыскания вышло, эх, и на этот раз не бриллиант.😭
(заметка не несёт никакой ценности, лишь мысли)
Иногда, для самого себя, я провожу теоретические, вперемешку с практическими, изыскания.
Выбираю узкопрофильную тему и ковыряю, пока не дохожу до кишков.
Это может быть знания зачем
EXPOSE в докер файле и на что это влияет, какая разница между cgroup v1 и cgroup v2 или различия хранилищ для больших данных и миллиардов мелких файлов по 6 KB.Практической ценности такие изыскания обычно не имеют, это больше любопытство и разминка для ума. Лишь иногда попадаются настоящие "бриллианты".
Мне захотелось узнать, а какие есть способы, чтобы снизить нагрузку на Kubernetes API.
Все мы знаем про кучу операторов, которые не хило нагружают апишку, но что, если снизить средствами самого кубера?
У нас есть несколько
VERBs.https://kubernetes.io/docs/reference/using-api/api-concepts/
Знания и поиск по документации привел к тому, что есть
WATCH запрос, который идёт каждый раз от kubelet, когда стартует под или скейлится или происходит редеплой через любую из стратегий, при использовании секрета кубернетиса.То есть каждый раз при этих действиях идёт
WATCH.Сам по себе секрет, просто лежащий в кубере, никакой нагрузки не несёт.
Пока secret не примонтирован(как переменная или файл) и пока не было рестарта/скейла/редеплоя, апишку никто не дёргает.
Однако при активном скейлинге (все мои проекты), это прям попадание в точку.
Да, вочей хватает.
sum by (verb) (rate(apiserver_request_total{ cluster=~"$cluster"}[$__rate_interval]))Затем мои поиски вывели на отличную опцию
immutable в секретах (вру, я слышал и знал о ней раньше, но прям в проде не использовал).https://kubernetes.io/docs/concepts/configuration/secret/#secret-immutable
С этой опцией нельзя поменять значение секрета. Его можно только реплейснуть или удалить и создать с нуля.
Копнув дальше, я узнал, что тут можно немного снизить нагрузку из-за интересного механизма.
"если секрет иммутабл, то кублет(с каждой ноды) не делает WATCH запрос в апишку".
"О господи! Оно!" - подумал я. Это было нечто новое, захотелось сразу использовать. И сразу в проде
Начал смотреть какие есть реализации:
- исправление своих чартов, чтобы секреты были иммутабл и были хуки(иначе при редеплое и изменении секрета хелм упадёт с ошибкой).
- написание мутейшн хука или оператора, который все задеплоенные секреты помечает сразу иммутабл, а все команды переучить, чтобы в их чартах были хуки
В целом неплохая картина: немного изменил флоу в командах по релизам, добавил хуки, все секреты в кубе иммутабл и получаем:
- меньше латенси WATCH и CONNECT запросов (проверено, кубер 1.33, Linode)
sum(rate(apiserver_request_duration_seconds_sum{job=~"kubernetes-apiservers|apiserver", cluster=~"$cluster"}[$__rate_interval])) by (verb)
/
sum(rate(apiserver_request_duration_seconds_count{job=~"kubernetes-apiservers|apiserver", cluster=~"$cluster"}[$__rate_interval])) by (verb)- меньшее количество WATCH запросов (проверено, кубер 1.33, Linode + AWS)
sum by (verb) (rate(apiserver_request_total{ cluster=~"$cluster"}[$__rate_interval]))- меньше памяти в ETCD. Это теоретически, большинство клауд провайдеров не дают прямой доступ к метрикам ETCD(я тестировал на AWS + linode), а потому доказать не могу. Барметал с нуля поднимать лень, так что пусть это окажется лишь теорией.
Всё выглядит как сказка, а что на деле?
Тут я вспомнил, что работал в замечательном банке с синим логотипом, и там до сих пор во всех департаментах работают очень крутые инженеры (всем привет, кто читает, вы солнышки❤️).
Тема интересная, заменшил в паблик чате @kubernetes_ru и меня тут же спустили на землю.
Оказалось что ребята это уже пробовали у себя и быстро от этого ушли.
Беда в том , что если такой
immutable секрет замонитирован на ноде более, чем в один под(разные деплойменты) то такой секрет не подтянется при изменим даже при рестарте.Проверил - да, у меня есть много секретов общих для нескольких деплойментов.
Безусловно это ставит крест на моей задумке, баги мне не нужны ради 1.5-3% экономии нагрузки.
Ладно, время на изыскания вышло, эх, и на этот раз не бриллиант.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤1