Для улучшения работы сайта мы используем файлы cookies. Оставаясь на сайте, вы соглашаетесь с политикой обработки персональных данных.

Распределение рабочей нагрузки в процессе работы

Базовая функциональность Kubernetes не предусматривает перераспределение рабочей нагрузки в процессе работы. В Nova Container Platform для поддержки оптимального распределения и использования ресурсов используется компонент Descheduler. Размещение подов дополнительно задают классы приоритета и правила topologySpreadConstraints платформенных компонентов.

Descheduler на основе заданных критериев периодически оценивает нагрузку и вытесняет поды.

Descheduler запускается в Nova Container Platform с политикой, заданной в ConfigMap nova-descheduler в namespace nova-descheduler.

Descheduler каждые 15 минут вытесняет поды, которые удовлетворяют включенной в ConfigMap политике.

Время, после которого будут вытеснены поды, зависит от настройки minPodLifetimeSeconds.

1. Классы приоритета

Платформа создает классы приоритета (PriorityClass) с меткой app.kubernetes.io/managed-by: Nova. Чем больше value, тем выше приоритет пода при планировании. У всех классов в таблице параметр preemptionPolicy равен PreemptLowerPriority: при нехватке ресурсов на узле под может вытеснить поды с меньшим приоритетом.

Поды с системными классами приоритета Kubernetes (system-cluster-critical, system-node-critical) Descheduler не вытесняет. Классы ниже к системным не относятся, поэтому Descheduler может перераспределять поды с этими классами.

Имя value Назначение

platform-critical

900000

Самый высокий приоритет. Критичные платформенные компоненты, необходимые для доступности кластера.

platform-high

800000

Важные платформенные сервисы: мониторинг, логирование, управление сертификатами.

platform-medium

600000

Дополнительные платформенные нагрузки, в том числе модули.

app-critical

400000

Критичные прикладные нагрузки.

batch-low

200000

Пакетные задачи, плановые Job и неинтерактивные нагрузки.

base-low

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.