Поиск по сайту:

Что такое Pod Affinity и Anti-Affinity в Kubernetes?


Kubernetes — это распределенная система, предназначенная для масштабирования реплик ваших сервисов в нескольких физических средах. Во многих случаях это хорошо работает «из коробки». Планировщик Kubernetes автоматически размещает ваши поды (экземпляры контейнеров) на узлах (рабочих машинах), у которых достаточно ресурсов для их поддержки.

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

В Kubernetes есть несколько механизмов, которые позволяют планировщику направлять процесс принятия решений таким образом, чтобы поды оказывались на определенных узлах. В этой статье мы сосредоточимся конкретно на понятиях «близость» и «анти-близость», которые дают вам детальный контроль над планированием. Сходства определяют правила, которые либо должны, либо должны быть соблюдены, прежде чем под можно будет выделить узлу.

Как работает аффинити?

Соответствия используются для выражения ограничений планирования подов, которые могут соответствовать характеристикам узлов-кандидатов и подов, которые уже работают на этих узлах. Pod, который имеет «близость» к данному узлу, с большей вероятностью будет назначен на него; и наоборот, «антиблизость» снижает вероятность того, что это будет запланировано. Общий баланс этих весов используется для определения окончательного размещения каждого модуля.

Оценки сходства могут давать как жесткие, так и мягкие результаты. «Жесткий» результат означает, что узел должен иметь характеристики, определенные выражением сходства. «Мягкие» привязки действуют как предпочтение, указывая планировщику, что ему следует использовать узел с характеристиками, если он доступен. Узел, который не соответствует условию, все равно будет выбран при необходимости.

Типы состояния близости

В настоящее время существует два различных вида сходства, которые вы можете определить:

  • Привязка узлов – используется для ограничения узлов, которые могут получать Pod, путем сопоставления меток этих узлов. Сходство узла можно использовать только для установки положительного сходства, привлекающего поды к узлу.
  • Связь между модулями — используется для ограничения узлов, которые могут получать модуль, путем сопоставления меток существующих модулей, уже запущенных на каждом из этих узлов. Inter-Pod Affinity может быть как притягивающим, так и отталкивающим анти-родством.

В простейшем возможном примере под, который включает условие привязки к узлу label=value, будет запланирован только для узлов с меткой label=value. Pod с тем же условием, но определенный как межмодульное соответствие, будет назначен на узел, на котором уже размещен Pod с меткой label=value.

Настройка сходства узлов

Node Affinity имеет два различных подтипа:

  • requiredDuringSchedulingIgnoredDuringExecution – это жесткое сопоставление сходства, требующее, чтобы узел соответствовал заданным вами ограничениям.
  • preferredDuringSchedulingIgnoredDuringExecution – это «мягкое» сопоставление для выражения предпочтения, которое игнорируется, если оно не может быть выполнено.

Часть этих подробных имен IgnoredDuringExecution указывает на то, что сходство учитывается только при планировании подов. После того, как Pod добрался до Node, сходство не переоценивается. Изменения в узле не приведут к выселению пода из-за измененных значений сходства. В будущем выпуске Kubernetes может быть добавлена поддержка этого поведения с помощью зарезервированной фразы requiredDuringSchedulingRequiredDuringExecution.

Привязки узлов привязываются к модулям через их поле манифеста spec.affinity.nodeAffinity:

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  containers:
    - name: demo-container
    # ...
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
            - key: hardware-class
              operator: In
              values:
                - a
                - b
                - c
          - matchExpressions:
            - key: internal
              operator: Exists

Этот манифест создает жесткое правило привязки, которое назначает модуль на узел, отвечающий следующим критериям:

  • Он имеет метку hardware-class со значением a, b или c.
  • Он имеет метку internal с любым значением.

Вы можете добавить дополнительные условия, повторив предложение matchExpressions. Поддерживаемые операторы для сравнения значений: In, NotIn, Exists, DoesNotExist, Gt (больше) и Lt (меньше).

Предложения matchExpression, сгруппированные в одном предложении nodeSelectorTerms, объединяются логическим оператором AND. Все они должны соответствовать поду, чтобы получить близость к определенному узлу. Вы также можете использовать несколько предложений nodeSelectorTerms; они будут объединены как логическая операция ИЛИ. Вы можете легко собрать сложные критерии планирования, используя обе эти структуры.

Подобным образом настраиваются «мягкие» настройки расписания. Используйте nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution вместо или вместе с requiredDuringSchedulingIgnoredDuringExecution для их настройки. Определите каждое из ваших необязательных ограничений как предложение matchExpressions в поле preference:

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  containers:
    - name: demo-container
    # ...
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: hardware-class
            operator: In
            values:
              - a
              - b
              - c

В правилах, основанных на предпочтениях, есть дополнительное поле weight, которое принимает целое число от 1 до 100. Каждый узел, соответствующий предпочтениям, имеет свой общий вес сходства, увеличенный на заданную величину; узел, получивший наибольший общий вес, будет выделен поду.

Настройка привязки между модулями

Inter-Pod Affinities очень похожи на Node Affinities, но имеют некоторые важные отличия. «Жесткий» и «мягкий» режимы указываются с помощью одних и тех же полей requiredDuringSchedulingIgnoredDuringExecution и preferredDuringSchedulingIgnoredDuringExecution. Они должны быть вложены в поля spec.affinity.podAffinity или spec.affinity.podAntiAffinity в зависимости от того, хотите ли вы увеличить или уменьшить соответствие Pod после успешного совпадения.

Вот простой пример, демонстрирующий как аффинность, так и анти-аффинность:

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  containers:
    - name: demo-container
    # ...
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
              - key: hardware-class
                operator: In
                values:
                  - a
                  - b
                  - c
          topologyKey: topology.kubernetes.io/zone
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 1
          podAffinityTerm:
            - labelSelector:
                matchExpressions:
                  - key: app-component
                    operator: In
                    values:
                      - background-worker
          topologyKey: topology.kubernetes.io/zone

Формат немного отличается от Node Affinity. Каждое ограничение matchExpressions должно быть вложено в labelSelector. Для мягких совпадений это, в свою очередь, должно быть расположено в podAffinityTerm. Привязки Pod также предлагают сокращенный набор операторов сравнения: вы можете использовать In, NotIn, Exists и DoesNotExist.

Для привязки пода требуется поле topologyKey. Это используется для ограничения общего набора узлов, которые считаются подходящими для планирования, до оценки matchExpressions. Приведенные выше правила запланируют модуль Pod на узел с меткой topology.kubernetes.io/zone и существующий модуль с меткой hardware-class, для которой задано значение a. , b или c. Узлы, у которых также есть под с меткой app-component=background-worker, получат уменьшенную аффинити.

Сходства между модулями — это мощный механизм управления совместным размещением модулей. Однако они оказывают существенное влияние на производительность: Kubernetes предостерегает от их использования в кластерах с более чем несколькими сотнями узлов. Каждый новый запрос на планирование пода должен проверять каждый второй под на всех других узлах для оценки совместимости.

Другие ограничения планирования

Хотя в этой статье мы сосредоточились на сходствах, Kubernetes также предоставляет другие механизмы ограничений планировщика. Обычно это более простые, но менее автоматизированные подходы, которые хорошо работают для небольших кластеров и развертываний.

Самым основным ограничением является поле nodeSelector. Он определяется в модулях как набор пар ключ-значение меток, которые должны существовать на узлах, на которых размещается модуль:

apiVersion: v1
kind: Pod
metadata:
  name: demo
spec:
  containers:
    - name: demo
      # ...
  nodeSelector:
    hardware-class: a
    internal: true

Этот манифест указывает Kubernetes планировать Pod только для узлов с метками hardware-class: a и internal: true.

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

Заключение

Аффинити и анти-аффинити используются для настройки универсальных ограничений планирования подов в Kubernetes. По сравнению с другими параметрами, такими как nodeSelector, сопоставления сложны, но дают вам больше способов определить совместимые узлы.

Соответствия могут действовать как программные предпочтения, которые сигнализируют Kubernetes об «идеальной» среде пода, даже если она не может быть немедленно удовлетворена. Система также обладает уникальной способностью фильтровать узлы на основе их существующих рабочих нагрузок, чтобы вы могли применять правила совместного размещения подов.

И последний момент, который следует отметить, это то, что близость — это не конец процесса планирования. Pod с сильным вычисленным сходством с узлом может оказаться в другом месте из-за входных данных Node taints. Этот механизм позволяет вам управлять запросами планирования с точки зрения ваших узлов. Порчи активно отталкивают входящие поды к другим узлам, что эффективно противоположно магнитному притяжению сродства. Селекторы узлов, привязки, пороки и допуски сбалансированы, чтобы определить окончательное расположение каждого нового пода в кластере.




Все права защищены. © Linux-Console.net • 2019-2024