Как вы уже знаете, в своей домашней лаборатории я использую кластер Kubernetes, развернутый на Talos Linux. Периодически у меня отключают электроэнергию, ИБП не спасают при длительном отключении. Я настроил правила, которые завершают работу всех нод Proxmox при отключении более 6 минут. После восстановления узлы кластера запускаются, но запускаются в разное время, что приводит к неравномерному распределению нагрузки: некоторые узлы перегружены, в то время как другие простаивают.
Scheduling в Kubernetes — это процесс назначения ожидающих подов к узлам, выполняемый компонентом под названием kube-scheduler. Решения планировщика о том, можно ли и где разместить под, определяются его настраиваемой политикой, состоящей из набора правил, называемых предикатами и приоритетами. Эти решения зависят от состояния кластера Kubernetes в момент появления нового пода для планирования.
Поскольку кластеры Kubernetes очень динамичны и их состояние меняется со временем, может возникнуть необходимость переместить уже работающие поды на другие узлы по различным причинам:
- Некоторые узлы простаивают или перегружены
- Первоначальное решение о размещении пода больше не актуально, так как на узлы были добавлены или удалены метки или "taints", и требования affinity пода к узлу больше не выполняются
- Некоторые узлы вышли из строя, и их поды были перемещены на другие узлы
- В кластер добавлены новые узлы
В результате в кластере могут оказаться поды, размещенные не там, где хотелось. Такую балансировку Kubernetes сам делать не умеет и мне приходилось вручную балансировать нагрузку. Как вы понимаете — это не наш метод, я хочу, чтобы Kubernetes все делал сам.
Для решения этой проблемы я установил Descheduler — компонент Kubernetes, предназначенный для перераспределения подов между узлами с целью выравнивания нагрузки и повышения эффективности использования ресурсов. Descheduler анализирует текущую загрузку узлов и перемещает поды с перегруженных узлов на менее загруженные, обеспечивая более равномерное распределение нагрузки в кластере. Descheduler, основываясь на своей политике, находит такие поды, которые можно переместить, и вытесняет их (evict). Descheduler сам не планирует замену вытесненных подов, а полагается на стандартный планировщик для этого.
Установка Descheduler с помощью Helm
Для установки Descheduler я использовал Helm-чарт, доступный в официальном репозитории.
helm repo add descheduler https://kubernetes-sigs.github.io/descheduler/
helm upgrade descheduler descheduler/descheduler \
--install \
--kubeconfig ./kubeconfig \
--namespace kube-system \
--version 0.31.0
По умолчанию Descheduler устанавливается в виде CronJob, который запускается каждые две минуты для анализа и эвакуации подов. Перед установкой можно настроить параметры, такие как расписание запуска и политики вытеснения подов, в файле values.yaml
, но я оставил значения по умолчанию.
Настройка политик Descheduler
Descheduler использует файл политики (DeschedulerPolicy
), в котором определяются стратегии для эвакуации подов. В моем случае я оставил стратегии по умолчанию. В Descheduler по умолчанию включены следующие политики, каждая из которых выполняет определённые функции для оптимизации работы кластера Kubernetes:
- Удаление дублирующихся подов (RemoveDuplicates): эта политика выявляет и удаляет поды, которые были случайно созданы в нескольких экземплярах, что помогает освободить ресурсы и предотвратить избыточное использование.
- Удаление подов с чрезмерным количеством перезапусков (RemovePodsHavingTooManyRestarts): эта политика нацелена на поды, которые перезапускались более 100 раз, включая перезапуски инициализационных контейнеров. Такие поды могут указывать на проблемы в приложении, и их удаление способствует стабильности кластера.
- Удаление подов, нарушающих привязку к узлам (RemovePodsViolatingNodeAffinity): эта политика удаляет поды, которые больше не соответствуют требованиям привязки к узлам, например, если узлы были помечены или изменены, и поды больше не удовлетворяют этим условиям.
- Удаление подов, нарушающих ограничения (taints) узлов (RemovePodsViolatingNodeTaints): эта политика нацелена на поды, размещённые на узлах с ограничениями (taints), которые несовместимы с толерантностями подов, что может привести к неправильному функционированию приложений.
- Удаление подов, нарушающих правила раздельного существования (affinity) между подами (RemovePodsViolatingInterPodAntiAffinity): эта политика удаляет поды, которые нарушают правила раздельного существования между подами, обеспечивая, чтобы поды, которые не должны размещаться вместе, были разделены.
- Удаление подов, нарушающих ограничения распределения по топологии (RemovePodsViolatingTopologySpreadConstraint): эта политика удаляет поды, которые не соответствуют ограничениям распределения по топологии, помогая равномерно распределить поды по различным зонам отказа или другим топологическим доменам.
- Низкая загрузка узлов (LowNodeUtilization): эта политика определяет узлы с использованием ресурсов ниже 20% по CPU, памяти и количеству подов и перемещает поды на более загруженные узлы, чтобы освободить недогруженные узлы для возможного масштабирования вниз.
Мониторинг и обновление Descheduler
После установки рекомендуется последить за логами CronJob Descheduler для оценки его работы. У меня все прошло хорошо, проблем не возникло.
Итоги
Я очень доволен! Descheduler спас меня от ручной работы, теперь мой кластер сам себя чинит и балансирует и мне не нужно проверять все ли в порядке. А больше ничего и не требуется.