Какова оптимальная стратегия планирования для контейнеров K8s? - PullRequest
1 голос
/ 25 апреля 2020

Вот с чем я работаю. У меня есть 3 ноды в GKE

  1. n1s1 (3,75 ГБ)
  2. n1s2 (7,5 ГБ)
  3. n1s4 (15 ГБ)

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

1GB, 2GB, 4GB, 6GB, 8GB, 10GB, 12GB, 14GB

Как лучше всего связать модуль с пулом узлов для максимальной эффективности?

Пока у меня есть 3 стратегии.

Для каждой конфигурации модуля определите «законный пул узлов» . Это наименьший пул узлов, который может вместить конфигурацию pod в идеальном мире. Таким образом, для модуля на 2 ГБ это n1s1, но для модуля на 4 ГБ это будет n1s2.

  1. Планирование модуля только на его законном пуле узлов.
  2. Планирование только модуля на его законном пуле узлов или на один пул узлов выше этого.
  3. Планирование модуля только в любом пуле узлов, где он в настоящее время может go.

Какая из этих или любых других стратегий минимизирует трату ресурсов?

=======

Ответы [ 2 ]

1 голос
/ 27 апреля 2020

Я бы использовал сочетание Taints и Tolerations и Сродство к узлу .

Taints и допуски работают вместе, чтобы гарантировать, что модули не запланированы на неподходящие узлы. Один или несколько вредов наносятся на узел; это означает, что узел не должен принимать какие-либо модули, которые не переносят вредные воздействия. Допуски применяются к стручкам и позволяют (но не требуют) стручкам планировать на узлы с соответствующими портами.

Вы можете установить порчу на узле kubectl taint nodes node1 key=value:NoSchedule

У запаха есть ключ key, значение value и эффект запаха NoSchedule. Это означает, что ни один модуль не сможет планировать на node1, если у него нет соответствующего допуска.

Пока вы пишете pod yaml, вы можете указать PodSpec и добавить допуск, который будет сопоставьте порчу, созданную на node1, что позволит pod с допуском быть запланированным на node1

tolerations:
- key: "key"
  operator: "Equal"
  value: "value"
  effect: "NoSchedule"

или

tolerations:
- key: "key"
  operator: "Exists"
  effect: "NoSchedule"

Taints и допуски гибкий способ отклонять блоки от узлов или удалять блоки, которые не должны работать. Вот несколько вариантов использования:

  • выделенные узлы : если вы хотите выделить набор узлов для эксклюзивного использования определенным набором пользователей, вы можете добавить портите эти узлы (скажем, kubectl taint nodes nodename dedicated=groupName:NoSchedule), а затем добавьте соответствующий допуск к их модулям (это было бы проще всего сделать, написав собственный контроллер доступа ). Модульам с допусками будет разрешено использовать испорченные (выделенные) узлы, а также любые другие узлы в кластере. Если вы хотите выделить для них узлы и , гарантирующие, что они только используют выделенные узлы, то вы должны дополнительно добавить метку, похожую на зазор, к тому же набору узлов (например, dedicated=groupName), и контроллер доступа должен дополнительно добавить сходство узлов, чтобы требовать, чтобы модули могли планировать только на узлы, помеченные dedicated=groupName.

  • Узлы со специальным оборудованием : В кластере, где небольшое подмножество узлов имеет специализированное аппаратное обеспечение (например, графические процессоры), желательно оставлять блоки, которым не требуется специализированное аппаратное обеспечение, от этих узлов, таким образом оставляя место для модулей, которые поступают позже. нужно специализированное оборудование. Это можно сделать, испортив узлы, которые имеют специализированное оборудование (например, kubectl taint nodes nodename special=true:NoSchedule или kubectl taint nodes nodename special=true:PreferNoSchedule) и добавив соответствующий допуск для модулей, которые используют специальное оборудование. Как и в случае использования выделенных узлов, возможно, проще всего применить допуски с помощью пользовательского контроллера доступа . Например, рекомендуется использовать Extended Resources для представления специального оборудования, добавить в узлы вашего специального оборудования расширенное имя ресурса и запустить контроллер доступа ExtendedResourceToleration . Теперь, поскольку узлы испорчены, на них не запланированы никакие модули без допусков. Но когда вы отправляете модуль, который запрашивает расширенный ресурс, контроллер доступа ExtendedResourceToleration автоматически добавит правильный допуск к модулю, и этот модуль будет планировать на специальных аппаратных узлах. Это гарантирует, что эти специальные аппаратные узлы предназначены для модулей, запрашивающих такое оборудование, и вам не нужно вручную добавлять допуски в ваши модули.

  • Выселения на основе Taint : Настраиваемое поведение вытеснения для каждого модуля при наличии проблем с узлом, которое описано в следующем разделе.

Что касается node affinity :

концептуально аналогичен nodeSelector - он позволяет вам ограничивать, на какие узлы ваш модуль может планироваться, основываясь на метках на узле.

В настоящее время существует два типа сходства узлов, называемые requiredDuringSchedulingIgnoredDuringExecution и preferredDuringSchedulingIgnoredDuringExecution. Вы можете думать о них как о «жестких» и «мягких», соответственно, в том смысле, что первый определяет правила, которым должно быть выполнено для того, чтобы модуль планировался на узле (точно так же как nodeSelector, но используя более выразительный синтаксис), в то время как последний указывает предпочтения , которые планировщик попытается применить, но не будет гарантировать. Часть имен «IgnoredDuringExecution» означает, что, подобно тому, как работает nodeSelector, если метки на узле изменяются во время выполнения так, что правила соответствия на модуле больше не выполняются, модуль все равно будет продолжать работать на узле , В будущем мы планируем предложить requiredDuringSchedulingRequiredDuringExecution, который будет точно таким же, как requiredDuringSchedulingIgnoredDuringExecution, за исключением того, что он будет высвобождать модули из узлов, которые перестают удовлетворять требованиям сходства узлов модулей.

Таким образом, пример requiredDuringSchedulingIgnoredDuringExecution будет «запускать модуль только на узлах с процессорами Intel», а в качестве примера preferredDuringSchedulingIgnoredDuringExecution будет «попытаться запустить этот набор модулей в зоне отказа XYZ, но если это невозможно, то разрешить некоторым запускаться в другом месте».

Узел сходства задается как поле nodeAffinity поля affinity в PodSpe c.

...

Новый синтаксис сходства узлов поддерживает следующие операторы: In, NotIn, Exists, DoesNotExist, Gt, Lt. Вы можете использовать NotIn и DoesNotExist для достижения антиаффинного поведения узлов или использовать портить ноды для отталкивания модулей от указанных c узлов.

Если указать оба nodeSelector и nodeAffinity, оба должны быть выполнены для того, чтобы модуль был запланирован на узле-кандидате.

Если указать несколько nodeSelectorTerms, связанных с типами nodeAffinity, то модуль может быть запланировано на узел , только если все nodeSelectorTerms могут быть удовлетворены.

Если вы задаете несколько matchExpressions, связанных с nodeSelectorTerms, то модуль может быть запланирован на узел если один из удовлетворяет matchExpressions.

1 голос
/ 25 апреля 2020

Почему бы вам сначала иметь 3 таких пула? Как правило, вы хотите использовать самый большой тип экземпляра, который дает вам менее 110 стручков на узел (что является жестким ограничением по умолчанию). Задача планировщика состоит в том, чтобы оптимизировать упаковку для вас, и это довольно хорошо с настройками по умолчанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...