Распределение рабочей нагрузки в процессе работы
Базовая функциональность Kubernetes не предусматривает перераспределение рабочей нагрузки в процессе работы. В Nova Container Platform для поддержки оптимального распределения и использования ресурсов используется компонент Descheduler. Размещение подов дополнительно задают классы приоритета и правила topologySpreadConstraints платформенных компонентов.
Descheduler на основе заданных критериев периодически оценивает нагрузку и вытесняет поды.
Descheduler запускается в Nova Container Platform с политикой, заданной в ConfigMap nova-descheduler в namespace nova-descheduler.
Descheduler каждые 15 минут вытесняет поды, которые удовлетворяют включенной в ConfigMap политике.
|
Время, после которого будут вытеснены поды, зависит от настройки |
1. Классы приоритета
Платформа создает классы приоритета (PriorityClass) с меткой app.kubernetes.io/managed-by: Nova. Чем больше value, тем выше приоритет пода при планировании. У всех классов в таблице параметр preemptionPolicy равен PreemptLowerPriority: при нехватке ресурсов на узле под может вытеснить поды с меньшим приоритетом.
Поды с системными классами приоритета Kubernetes (system-cluster-critical, system-node-critical) Descheduler не вытесняет. Классы ниже к системным не относятся, поэтому Descheduler может перераспределять поды с этими классами.
| Имя | value |
Назначение |
|---|---|---|
|
900000 |
Самый высокий приоритет. Критичные платформенные компоненты, необходимые для доступности кластера. |
|
800000 |
Важные платформенные сервисы: мониторинг, логирование, управление сертификатами. |
|
600000 |
Дополнительные платформенные нагрузки, в том числе модули. |
|
400000 |
Критичные прикладные нагрузки. |
|
200000 |
Пакетные задачи, плановые Job и неинтерактивные нагрузки. |
|
100000 |
Самый низкий приоритет. Фоновые сервисы, нагрузки для разработки и некритичные задачи. |
Класс base-low задан как класс по умолчанию (globalDefault: true). Его получают поды, у которых не указан priorityClassName.
Классы platform-critical, platform-high и platform-medium предназначены для компонентов платформы. Для своих приложений укажите priorityClassName в спецификации пода: app-critical для критичных прикладных нагрузок и batch-low для пакетных задач, плановых Job и неинтерактивных нагрузок.
2. Настройки политики Descheduler
Параметр gracePeriodSeconds: 60 задает время в секундах, за которое вытесняемый под может завершить свои процессы до удаления.
2.1. DefaultEvictor
DefaultEvictor обеспечивает вытеснение подов таким образом, чтобы результирующий под поместился хотя бы на одном доступном узле, если указана опция nodeFit: true.
- name: "DefaultEvictor"
args:
nodeFit: true
2.2. RemoveDuplicates
Политика RemoveDuplicates удаляет дублирующие поды: на узле должен быть запущен только один под от одного контроллера. Если на одном узле находятся два пода от одного контроллера, descheduler удаляет дублирующий под.
- name: ProfileName
pluginConfig:
- name: "RemoveDuplicates"
plugins:
balance:
enabled:
- "RemoveDuplicates"
2.3. RemovePodsViolatingTopologySpreadConstraint
Политика RemovePodsViolatingTopologySpreadConstraint вытесняет поды, которые нарушают правила topologySpreadConstraints. Учитываются ограничения DoNotSchedule и ScheduleAnyway.
Плагин включен в стратегию balance вместе с LowNodeUtilization и RemoveDuplicates.
- name: "RemovePodsViolatingTopologySpreadConstraint"
args:
constraints:
- DoNotSchedule
- ScheduleAnyway
2.4. RemoveFailedPods
Политика RemoveFailedPods вытесняет поды, которые завершились с ошибкой и в течение установленного времени minPodLifetimeSeconds не восстановились, за исключением подов, принадлежащих типам, перечисленным в excludeOwnerKinds.
- name: "RemoveFailedPods"
args:
excludeOwnerKinds:
- "Job"
minPodLifetimeSeconds: 900
2.5. PodLifeTime
Политика PodLifeTime вытесняет с узлов поды в состояниях Pending и PodInitializing, которые находятся в этих состояниях дольше 30 минут.
- name: "PodLifeTime"
args:
maxPodLifeTimeSeconds: 1800
states:
- "Pending"
- "PodInitializing"
2.6. RemovePodsHavingTooManyRestarts
Политика RemovePodsHavingTooManyRestarts удаляет с узлов поды, имеющие более 50 перезапусков контейнеров (включая init-контейнеры).
- name: "RemovePodsHavingTooManyRestarts"
args:
podRestartThreshold: 50
includingInitContainers: true
2.7. RemovePodsViolatingNodeTaints
Политика RemovePodsViolatingNodeTaints удаляет поды, нарушающие условия taint на узлах. Например, под, имеющий toleration и запущенный на узле с соответствующим taint, будет вытеснен с узла, если taint на узле будет изменен или удален.
Настроенные taint можно посмотреть в настройке политики.
- name: "RemovePodsViolatingNodeTaints"
args:
excludedTaints:
- node.kubernetes.io/memory-pressure
- node.kubernetes.io/disk-pressure
- node.kubernetes.io/pid-pressure
- node.kubernetes.io/unschedulable
- node.kubernetes.io/network-unavailable
2.8. RemovePodsViolatingNodeAffinity
Политика RemovePodsViolatingNodeAffinity обеспечивает соблюдение подами правил affinity. Если поды не соответствуют правилам affinity, поды вытесняются с узла.
Настроенные правила affinity:
-
requiredDuringSchedulingIgnoredDuringExecution -
preferredDuringSchedulingIgnoredDuringExecution
- name: "RemovePodsViolatingNodeAffinity"
args:
nodeAffinityType:
- "requiredDuringSchedulingIgnoredDuringExecution"
- "preferredDuringSchedulingIgnoredDuringExecution"
2.9. RemovePodsViolatingInterPodAntiAffinity
Политика RemovePodsViolatingInterPodAntiAffinity удаляет поды, нарушившие правила anti-affinity.
- name: "RemovePodsViolatingInterPodAntiAffinity"
2.10. LowNodeUtilization
Политика LowNodeUtilization перераспределяет поды с нагруженных узлов на ненагруженные. Узлы в кластере отслеживаются по CPU, памяти и подам (в процентах). После превышения порога, указанного в политике, выполняется перераспределение подов.
|
Настройка учитывает не реальное потребление ресурсов на узле, а реквесты у подов. |
- name: ProfileName
pluginConfig:
- name: "LowNodeUtilization"
args:
thresholds:
"cpu" : 40
"memory": 40
"pods": 20
targetThresholds:
"cpu" : 80
"memory": 80
"pods": 60
plugins:
balance:
enabled:
- "LowNodeUtilization"
3. Пример настроенной политики Descheduler
policy.yaml
apiVersion: "descheduler/v1alpha2"
kind: "DeschedulerPolicy"
gracePeriodSeconds: 60
profiles:
- name: Default
pluginConfig:
- name: "DefaultEvictor"
args:
nodeFit: true
- name: "RemoveDuplicates"
- name: "RemovePodsViolatingTopologySpreadConstraint"
args:
constraints:
- DoNotSchedule
- ScheduleAnyway
- name: "RemoveFailedPods"
args:
excludeOwnerKinds:
- "Job"
minPodLifetimeSeconds: 900
- name: "PodLifeTime"
args:
maxPodLifeTimeSeconds: 1800
states:
- "Pending"
- "PodInitializing"
- name: "RemovePodsHavingTooManyRestarts"
args:
podRestartThreshold: 50
includingInitContainers: true
- name: "RemovePodsViolatingNodeTaints"
args:
excludedTaints:
- node.kubernetes.io/memory-pressure
- node.kubernetes.io/disk-pressure
- node.kubernetes.io/pid-pressure
- node.kubernetes.io/unschedulable
- node.kubernetes.io/network-unavailable
- name: "RemovePodsViolatingNodeAffinity"
args:
nodeAffinityType:
- "requiredDuringSchedulingIgnoredDuringExecution"
- "preferredDuringSchedulingIgnoredDuringExecution"
- name: "RemovePodsViolatingInterPodAntiAffinity"
- name: "LowNodeUtilization"
args:
thresholds:
"cpu" : 40
"memory": 40
"pods": 20
targetThresholds:
"cpu" : 80
"memory": 80
"pods": 60
plugins:
deschedule:
enabled:
- "RemovePodsViolatingInterPodAntiAffinity"
- "RemovePodsViolatingNodeAffinity"
- "RemovePodsViolatingNodeTaints"
- "RemovePodsHavingTooManyRestarts"
- "PodLifeTime"
- "RemoveFailedPods"
balance:
enabled:
- "LowNodeUtilization"
- "RemoveDuplicates"
- "RemovePodsViolatingTopologySpreadConstraint"
При обновлении платформы старая политика сохраняется в ConfigMap nova-descheduler-deprecated.
4. Размещение платформенных компонентов
Для перечисленных ниже компонентов платформы заданы правила topologySpreadConstraints. Правила нужны, чтобы после сбоя, недоступности узла или планового обслуживания поды снова размещались по разным узлам.
Компоненты разворачиваются в 2-3 репликах, если инфраструктурных, worker- или ingress-узлов больше одного:
-
nova-cert-manager -
nova-cert-manager-cainjector -
nova-cert-manager-webhook -
nova-metrics-server -
nova-prometheus-adapter -
nova-reflector -
nova-reloader -
nova-thanos-query-frontend -
nova-thanos-query -
nova-ingress-public-controller -
nova-ingress-internal-controller
Пример правила:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: nova-release-ingress-public
Поля правила:
-
topologyKey: kubernetes.io/hostname— распределять поды по разным узлам. -
labelSelector— учитывать только поды с указанными метками. В примере это поды с меткойapp.kubernetes.io/name: nova-release-ingress-public. -
maxSkew: 1— разница в числе подов между узлами не больше 1. Например, допустимо 2 пода на одном узле и 1 на другом. Размещение 3 пода на одном узле и 1 на другом нарушает правило. -
whenUnsatisfiable: ScheduleAnyway— если равномерно разложить поды нельзя, потому что не хватает узлов или ресурсов, под все равно запускается, даже если правило нарушено.
Вытеснение подов, которые нарушают эти правила, выполняет плагин RemovePodsViolatingTopologySpreadConstraint.