Планирование Kubernetes

Обзор

kube-scheduler — это основной компонент плоскости управления kubernetes, чье поведение по умолчанию заключается в распределении стручков по узлам при балансировке использования ресурсов между стручками и узлами. В терминах обывателя это означает, что kube-scheduler работает на плоскости управления и распределяет рабочую нагрузку на кластер Kubernetes.

В этой статье мы подробно рассмотрим использование планирования Kubernetes: «Общее планирование», «Аффинити» и «Планирование выселений для Taint и Tolerance». И наконец, мы рассмотрим настройку производительности планировщика, т.е. тонкую настройку параметров планировщика под кластер.

Простое планирование

NodeName [1]

В простейшем планировании можно указать поле NodeName, которое позволяет Pod запускаться на соответствующем узле. Это показано в следующем списке ресурсов

apiVersion: v1
kind: Pod
metadata:
  name: netpod
spec:
  containers:
  - name: netbox
    image: cylonchau/netbox
  nodeName: node01  
Войдите в полноэкранный режим Выход из полноэкранного режима

С приведенным выше списком ресурсов Pod будет запущен на узле 01. Этот сценарий имеет ряд недостатков, таких как недостаточное количество ресурсных узлов и неизвестные имена узлов, и в целом он не рекомендуется.

$ kubectl describe pods netpod 
Name:         netpod
Namespace:    default

    ...

QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason   Age   From     Message
  ----    ------   ----  ----     -------
  Normal  Pulling  86s   kubelet  Pulling image "cylonchau/netbox"
  Normal  Pulled   17s   kubelet  Successfully pulled image "cylonchau/netbox"
  Normal  Created  17s   kubelet  Created container netbox
  Normal  Started  17s   kubelet  Started container netbox



$ kubectl get pods netpod  -o wide
NAME     READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
netpod   1/1     Running   0          48m   192.168.0.3   node01   <none>           <none>
Войдите в полноэкранный режим Выход из полноэкранного режима

Вывод выше показывает, что метод NodeName не запланирован планировщиком

nodeSelector [2]

label — очень важное понятие в kubernetes, обычно каждому рабочему узлу присваивается несколько меток, которые можно просмотреть с помощью команды

$ kubectl get node node01 --show-labels
NAME     STATUS   ROLES    AGE   VERSION    LABELS
node01   Ready    <none>   15h   v1.18.20   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node01,kubernetes.io/os=linux
Войдите в полноэкранный режим Выход из полноэкранного режима

nodeSelector выбирает узлы с определенной меткой или метками на основе этих меток. Например, если вам нужно запустить pod на определенном наборе узлов, вы можете установить nodeSelector в «PodSpec» как набор пар ключ-значение.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: netpod-nodeselector
spec:
  selector:
    matchLabels:
      app: netpod
  replicas: 2 
  template:
    metadata:
      labels:
        app: netpod
    spec:
      containers:
      - name: netbox
        image: cylonchau/netbox
      nodeSelector: 
        beta.kubernetes.io/os: linux
Войдите в полноэкранный режим Выход из полноэкранного режима

Для приведенного выше стручка планировщик Kubernetes найдет узлы с тегом beta.kubernetes.io/os: linux. О других встроенных тегах kubernetes см. [3]

Для селектора тегов, в конечном счете, он будет распределен по узлам с тегами

kubectl describe pod netpod-nodeselector-69fdb567d8-lcnv6 
Name:         netpod-nodeselector-69fdb567d8-lcnv6
Namespace:    default

    ...

QoS Class:       BestEffort
Node-Selectors:  beta.kubernetes.io/os=linux
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  8m18s  default-scheduler  Successfully assigned default/netpod-nodeselector-69fdb567d8-lcnv6 to node01
  Normal  Pulling    8m17s  kubelet            Pulling image "cylonchau/netbox"
  Normal  Pulled     7m25s  kubelet            Successfully pulled image "cylonchau/netbox"
  Normal  Created    7m25s  kubelet            Created container netbox
  Normal  Started    7m25s  kubelet            Started container netbox
Войдите в полноэкранный режим Выход из полноэкранного режима

Сродство узлов [4]

Сродство (Affinity) — это общая концепция для систем, использующих планирование, и обычно сродство возникает в параллельной (parallel) среде; в этой среде сродство обеспечивает возможность более эффективного выполнения стручка на одном узле, чем на других. и расчет сродства обычно состоит из множества условий. В целом, аффинити делится на «мягкое аффинити и жесткое аффинити

  • Soft Affinity, или мягкое сродство, — это когда планировщик держит задачи на одном и том же узле настолько, насколько это возможно. Это только попытка; если это невозможно, процесс переносится на другой узел
  • Hard affinity, жесткое сродство, принудительное привязывание задачи к определенному узлу.

Концепция affinity также поддерживается в kubernetes, и affinity — это алгоритм, формируемый совместно с nodeSelector. Жесткая близость определяется как requiredDuringSchedulingIgnoredDuringExecution; мягкая близость определяется как предпочитаемыйПри планированииИгнорируемыйПри выполнении

  • Жесткая близость (requiredDuringSchedulingIgnoredDuringExecution): должна быть выполнена, иначе планировщик не сможет запланировать Pod.
  • Мягкое сродство (preferredDuringSchedulingIgnoredDuringExecution): планировщик будет искать узлы, удовлетворяющие условию. Если ни один узел не соответствует требованиям, это правило будет проигнорировано, и планировщик все равно составит расписание Pod.

Сродство узлов

Описание параметров сродства узлов

Планировщик будет предпочитать планировать стручки на узлы, которые удовлетворяют выражению родства, указанному в этом поле, но он может выбрать узлы, которые нарушают одно или несколько выражений. Наиболее предпочтительным узлом является узел с наибольшей суммой весов, т.е. для каждого узла, удовлетворяющего всем требованиям планирования (запросы ресурсов, выражения сродства requiredDuringScheduling и т.д.), вычисляется сумма путем итерации по элементам этого поля Если узел соответствует соответствующим выражениям соответствия, то «weight » прибавляется к сумме; узел с наибольшей суммой является наиболее предпочтительным.

Если требование близости, указанное в этом поле, не выполняется во время отправки, капсула не будет отправлена на этот узел. Если требование близости, указанное в этом поле, больше не выполняется в какой-то момент во время выполнения стручка (например, из-за обновления), система может попытаться или не попытаться в конечном итоге исключить стручок из своего узла.

Диапазон аффинности применяется в разделе Pod.Spec со следующими параметрами.

Примечания: matchFields использует поля из списка ресурсов (kubectl get node -o yaml), в то время как matchExpressions соответствует тегам

Пример сродства узлов

Во введении выше показано, как сложные требования к планированию могут быть лучше выражены в Kubernetes относительно nodeSelector: сродство узлов, с использованием поля .spec.affinity.nodeAffinity в PodSpec для указания соответствующего конфигурация сродства.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: netpod-nodeselector
spec:
  selector:
    matchLabels:
      app: netpod
  replicas: 2 
  template:
    metadata:
      labels:
        app: netpod
    spec:
      containers:
      - name: netbox
        image: cylonchau/netbox
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 1
            preference:
              matchExpressions:
              - key: app
                operator: In
                values:
                - test
Войдите в полноэкранный режим Выход из полноэкранного режима

Приведенный выше список показывает, что когда тег app: test присутствует на узле, он будет отправлен на соответствующий узел, не имеет значения, если ни один узел не соответствует этим условиям, он будет отправлен на основе общего соответствия.

Когда присутствуют и жесткая, и мягкая политики, в зависимости от настройки, жесткая политика будет иметь более высокий приоритет, чем мягкая политика, даже если вес мягкой политики установлен на 100

apiVersion: apps/v1
kind: Deployment
metadata:
  name: netpod-nodeselector
spec:
  selector:
    matchLabels:
      app: netpod
  replicas: 2 
  template:
    metadata:
      labels:
        app: netpod
    spec:
      containers:
      - name: netbox
        image: cylonchau/netbox
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 1
            preference:
              matchExpressions:
              - key: app
                operator: In 
                values:
                - test
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: topology.kubernetes.io/zone
                operator: In
                values:
                - antarctica-east1
                - antarctica-west1
Войдите в полноэкранный режим Выход из полноэкранного режима

Вот сообщение об ошибке

Warning  FailedScheduling  4s (x3 over 24s)  default-scheduler  0/2 nodes are available: 2 node(s) didn't match node selector.
Войдите в полноэкранный режим Выход из полноэкранного режима

Сродство к стручкам [4]

Pod affinity и anti-affinity — это ограничения на то, на каких узлах может быть запланирован Pod, основанные на метке Pod, уже запущенного на узле, а не на метке узла. Например, X удовлетворяет одному или нескольким условиям для выполнения Y. В этот раз Pod удовлетворяет выполнению в X. Где X — домен топологии, а Y — правило.

Примечания: Официальная документация не рекомендует использовать эту функцию в кластерах с более чем сотней узлов. [5]

Конфигурация сродства стручков

Сродство и антисродство узла аналогичны сродству узла, диапазон сродства применяется в разделе Pod.Spec.podAffinity, который здесь не повторяется, см. раздел описания параметров сродства узла.

topologyKey, ==не допускается быть null==, это значение будет влиять на то, где развернут Pod, с точки зрения того, какая топология находится в соответствующем узле, который соответствует условию сродства, домен топологии topologyKey определяется меткой label.

В дополнение к topologyKey, селектор меток labelSelector и пространства имен namespaces доступны как альтернативы одного уровня

apiVersion: apps/v1
kind: Deployment
metadata:
  name: netpod-podaffinity
spec:
  selector:
    matchLabels:
      app: podaffinity
  replicas: 1 
  template:
    metadata:
      labels:
        app: podaffinity
    spec:
      containers:
      - name: podaffinity
        image: cylonchau/netbox
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - netpod
            topologyKey: zone
Войдите в полноэкранный режим Выход из полноэкранного режима

Если ни одна ботва не соответствует правилу, то статус ожидания

Warning  FailedScheduling  59s (x2 over 59s)  default-scheduler  0/2 nodes are available: 2 node(s) didn't match pod affinity rules, 2 node(s) didn't match pod affinity/anti-affinity.
Войдите в полноэкранный режим Выход из полноэкранного режима

Под анти-аффинность

Существуют сценарии, в которых некоторые узлы не должны иметь много ресурсов, т.е. некоторые узлы не хотят быть запланированными. Например, узел мониторинга не хочет иметь на себе много ресурсов из-за своей природы, или, в зависимости от конфигурации узла, узел более низкой конфигурации не хочет планировать много ресурсов; в этом случае планирование Pod, не соответствующее ожиданиям, ухудшит производительность сервиса, который он размещает. В этом случае требуется анти-аффинити (Anti-Affinity), чтобы держать Pod подальше от этой группы узлов.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: netpod-podaffinity
spec:
  selector:
    matchLabels:
      app: podaffinity
  replicas: 1 
  template:
    metadata:
      labels:
        app: podaffinity
    spec:
      containers:
      - name: podaffinity
        image: cylonchau/netbox
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - netpod
              topologyKey: zone
Войдите в полноэкранный режим Выход из полноэкранного режима

Пороки и терпимость [6]

Пятна

В то время как affinity и anti-affinity могут предотвратить запуск Pods на определенных узлах, существует также проблема того, что affinity и anti-affinity должны быть объявлены для узлов, которые работают или не хотят работать, и если вы забудете объявить их, они все равно будут отправлены на соответствующий узел. kubernetes также предоставляет способ выселения Pods, который заключается в taints ( Taints) и терпимости (Tolerations).

Чтобы создать пятно

kubectl taint nodes node1 key1=value1:NoSchedule

$ kubectl taint nodes mon01 role=monitoring:NoSchedule
Войдите в полноэкранный режим Выход из полноэкранного режима

Удаление пятна.

kubectl taint nodes node1 key1=value1:NoSchedule-
Войдите в полноэкранный режим Выход из полноэкранного режима

В дополнение к NoSchedule, существуют PreferNoSchedule и NoExecute

Допуски

Если узел испорчен, он автоматически исключается из планирования. Хотя планирование будет неудачным, когда часть Predicate выполняется на испорченном узле, толерантность — это то, что делает pod толерантным к taint на этом узле, т.е. pod с толерантностью может быть запланирован поверх испорченного узла.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: netpod-podaffinity
spec:
  selector:
    matchLabels:
      app: podaffinity
  replicas: 1 
  template:
    metadata:
      labels:
        app: podaffinity
    spec:
      containers:
      - name: podaffinity
        image: cylonchau/netbox
      tolerations:
      - key: "role"
        operator: "Equal"
        value: "monitoring"
        effect: "NoSchedule"
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - netpod
              topologyKey: zone
Войдите в полноэкранный режим Выход из полноэкранного режима

В tolerance есть специальное поле TolerationSeconds, которое указывает, как долго терпеть порчу, которое не установлено по умолчанию, т.е. порча будет терпеться вечно. Значение 0 или отрицательное число означает, что выселение понимается. == Действует только если taint равен NoExecute.

Атрибут operator имеет два значения Exists и Equal.

  • Если оператор Exists, атрибут value не требуется, поскольку суждение находится в испорченном случае.
  • Если оператор Equal, то это означает, что связь между ключом и значением равна $key=value$.

  • Пустой ключ и оператор Exists будет соответствовать всем, т.е. терпеть все пятна

  • Empty effect соответствует всем effect, т.е. соответствует всем пятнам; этот случай с условием будет допускать все типы пятен

Изгнание [7]

Боды выселяются, когда для taint установлено значение NoExecute, а условия выселения следующие.

  • Капсула, которая не терпит запятнанности, будет немедленно выселена.
  • Бод, который терпимо относится к taint, но не имеет настроенного атрибута tolerationSeconds, останется неизменным, т.е. узел останется привязанным к боду.
  • Бод, который терпимо относится к указанному taint и имеет настроенный атрибут tolerationSeconds, узел привязывается к боду только на настроенное время.

Kubernetes имеет встроенную функцию taint, при которой контроллер автоматически запятнает узел.

  • node.kubernetes.io/not-ready: Сбой узла. Соответствует Ready = False из NodeCondition.

  • node.kubernetes.io/unreachable: Контроллер узла не может получить доступ к узлу. Соответствует NodeCondition Ready= Unknown.

  • node.kubernetes.io/memory-pressure: давление на память узла.

  • node.kubernetes.io/disk-pressure: Дисковое давление узла.

  • node.kubernetes.io/pid-pressure: Узел имеет PID-давление.

  • node.kubernetes.io/network-unavailable: Сеть узла недоступна.

  • node.kubernetes.io/unschedulable: Node не является планируемым.

Примечания: Свойство Kubernetes node.kubernetes.io/not-ready и свойство node.kubernetes.io/unreachable добавляют ограничение по времени допуска <#code tolerationSeconds=300. То есть, после обнаружения проблемы в бутоне он будет оставаться связанным в течение 5 минут.

Распределение приоритетов и преимущественное использование

В kubernetes также предусмотрен механизм приоритетов для стручков. С помощью механизма приоритетов можно обеспечить преимущественное использование ресурсов в параллельных системах. При преимущественном использовании стручки с более высоким приоритетом будут запланированы раньше стручков с более низким приоритетом, когда они еще не запланированы, а стручки с более низким приоритетом могут быть вытеснены стручками с более высоким приоритетом, когда ресурсы недоступны.

Функция приоритета предоставляется PriorityClasses. PriorityClasses используются как ресурсы на уровне кластера, а не на уровне пространства имен, и используются только для объявления уровней приоритетов.

value используется в качестве уровня приоритета, чем больше число, тем выше уровень приоритета. А name — это имя данного уровня приоритета, аналогично другим значениям имени ресурса, содержание значения должно соответствовать ограничениям домена DNS.

globalDefault является уровнем приоритета по умолчанию в кластере, и только один PriorityClass может быть установлен на true.

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for XYZ service pods only."
Войдите в полноэкранный режим Выход из полноэкранного режима

Примечания:

  • Если в кластере не существует PriorityClass, все существующие Pods будут иметь приоритет 0.
  • Когда globalDefault=true установлен для кластера, это не изменяет приоритет уже существующих Pods. Это верно только для Pods, созданных после PriorityClass globalDefault=true.
  • Если PriorityClass удаляется, существующие Подсистемы, которые все еще используют этот PriorityClass, остаются неизменными, а вновь созданные Подсистемы не могут использовать этот PriorityClass.

Невыкуп

Когда preemptionPolicy: Never, Стручок не будет вытеснять другие Стручки, но если он не запланирован, он будет оставаться в очереди планирования, ожидая быть запланированным, пока не будут выполнены требования. ==Не вытесняющие стручки могут быть вытеснены другими стручками с высоким приоритетом==

Примечания: preemptionPolicy в Kubernetes v1.24 [stable]

preemptionPolicy настроена как невытесняющая, с параметром по умолчанию PreemptLowerPriority; это означает, что капсулам с более высоким приоритетом разрешено вытеснять капсулы с более низким приоритетом. if preemptionPolicy: Никогда, означает, что Pod является невытесняющим.

Ниже приведен пример конфигурации без права выкупа

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority-nonpreempting
value: 1000000
preemptionPolicy: Never
globalDefault: false
description: "This priority class will not cause other pods to be preempted."
Войдите в полноэкранный режим Выход из полноэкранного режима

Когда приоритет настроен, контроллер приоритетного доступа будет использовать значение соответствующего PriorityClass, настроенного в priorityClassName для заполнения приоритета текущего Pod, или отклонит его, если не будет найдена соответствующая политика преимущественного использования.

Ниже приведен пример настройки приоритета в бутоне

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  priorityClassName: high-priority
Войдите в полноэкранный режим Выход из полноэкранного режима

Преемственность

Когда Pod создается, он попадает в очередь и ждет, когда его запланируют. планировщик выбирает Pod из очереди и пытается запланировать его на узел. Если не найдено ни одного узла, который бы отвечал всем заданным требованиям Под, то для Pending Под включается предварительное использование. Когда бод ищет подходящий узел, т.е. пытается упредить узел, один или несколько бодов с более низким приоритетом, чем текущий бод, удаляются из этого узла, позволяя текущему боду быть отправленным в соответствующий узел. Когда из узла выселяется бод с более низким приоритетом, текущий бод может быть запланирован на этот узел, этот процесс известен как предварительное вымогательство preemption.

А узел, который предоставляет ресурсы, готовые к выселению, становится номинированным узлом (nominated Node), и когда Pod вытесняет узел, его nominatedNodeName помечается как имя этого узла, хотя, конечно, за пометкой не обязательно следует имя узла, который должен быть вытеснен. Например, если другой узел становится доступным в то время, когда текущий Pod ожидает выселения Pod с более низким приоритетом, Pod будет вытеснен на этот узел.

Ссылка

[1] Создайте Pod, который будет запланирован на определенном узле

[2] nodeSelector

[3] метки аннотации пятна

[4] аффинность и антиаффинность

[5] сродство и антисродство

[6] запятнанность и терпимость

[7] выселения

[8] приоритетная преференция

Оцените статью
devanswers.ru
Добавить комментарий