Це багатосторінкова версія цього розділу для друку. Натисніть тут, щоб надрукувати.

Повернутися до звичайного перегляду сторінки.

Workload API

Стан функціоналу: Beta починаючи з Kubernetes v1.37; стандартно вимкнено
Докладніше про цей функціонал

Щоб скористатися цією функцією, вам (або адміністратору кластера) потрібно увімкнути функціональну можливість GenericWorkload для всіх відповідних компонентів у вашому кластері.

Перегляньте Увімкнення або вимкнення функціональних можливостей для отримання додаткової інформації.

Ресурс Workload API визначає вимоги до планування та структуру багатоподового застосунку. У той час як контролери робочого навантаження, такі як Job, керують станом виконання застосунку, Workload визначає, як слід планувати групи Pods. Контролер Job є єдиним вбудованим контролером, який створює обʼєкти PodGroup з PodGroupTemplates ресурсу Workload під час виконання.

Що таке Workload?

Ресурс Workload API є частиною групи API scheduling.k8s.io/v1beta1 (і ваш кластер повинен мати цю групу API увімкнену, а також функціональну можливість GenericWorkload, перш ніж ви зможете скористатися цим API).

Workload є статичним, довгоживучим шаблоном політики. Він визначає, які політики планування слід застосовувати до груп Podʼів, але самостійно не відстежує стан виконання. Стан виконання планування підтримується обʼєктами PodGroup, які контролери створюють з PodGroupTemplates ресурсу Workload.

Структура API

Workload складається з двох полів: списку PodGroupTemplates та необовʼязкового посилання на контролер. Вся специфікація Workload є незмінною після створення: ви не можете змінювати наявні шаблони, додавати нові шаблони або видаляти шаблони з podGroupTemplates.

PodGroupTemplates

Список spec.podGroupTemplates визначає окремі компоненти вашого робочого навантаження. Наприклад, завдання машинного навчання може мати шаблон driver та шаблон worker.

Кожен елемент у podGroupTemplates повинен мати:

  1. Унікальне поле name, яке буде використовуватися для посилання на шаблон у spec.podGroupTemplateRef обʼєкта PodGroup.
  2. Політику планування (basic або gang).

Кожен елемент також може мати поля пріоритету та режиму розладу.

Примітка:

У v1.36 поля пріоритету та режиму розладу вмикалися функціональною можливістю WorkloadAwarePreemption. Цю функціональну можливість було обʼєднано з GenericWorkload у v1.37.

Максимальна кількість PodGroupTemplates в одному Workload становить 8.

apiVersion: scheduling.k8s.io/v1beta1
kind: Workload
metadata:
  name: training-job-workload
  namespace: some-ns
spec:
  controllerRef:
    apiGroup: batch
    kind: Job
    name: training-job
  podGroupTemplates:
  - name: workers
    schedulingPolicy:
      gang:
        # gang може бути запланована тільки в тому випадку, якщо одночасно можуть працювати 4 пода.
        minCount: 4
    priorityClassName: high-priority
    disruptionMode:
      all: {}

Коли контролер робочого навантаження створює PodGroup з одного з цих шаблонів, він копіює schedulingPolicy у власну специфікацію PodGroup. Зміни в Workload впливають лише на новостворені PodGroups, а не на наявні.

Посилання на обʼєкт керування робочим навантаженням

Поле controllerRef звʼязує Workload з конкретним обʼєктом вищого рівня, що визначає застосунок, наприклад Job або власний CRD. Це корисно для спостереження та інструментів. Ці дані не використовуються для планування або управління Workload.

CompositePodGroupTemplates

Стан функціоналу: Alpha починаючи з Kubernetes v1.37; стандартно вимкнено
Докладніше про цей функціонал

Щоб скористатися цією функцією, вам (або адміністратору кластера) потрібно увімкнути функціональну можливість CompositePodGroup для всіх відповідних компонентів у вашому кластері.

Перегляньте Увімкнення або вимкнення функціональних можливостей для отримання додаткової інформації.

Коли увімкнено функціональну можливість CompositePodGroup та групу API scheduling.k8s.io/v1alpha3, ви можете використовувати CompositePodGroupTemplates для визначення багаторівневих ієрархічних вимог до планування у Workload. Ці вимоги можуть включати забезпечення вкладених топологічних обмежень на різних рівнях інфраструктури кластера (багаторівневе топологічно-орієнтоване планування), планування «все або нічого» для дочірніх груп (багаторівневе групове планування) або політики розладу на рівні групи.

CompositePodGroupTemplates можна визначити за допомогою поля spec.compositePodGroupTemplates в API Workload. Під час виконання контролери робочого навантаження створюють обʼєкти CompositePodGroup та PodGroup з цих шаблонів для підтримки стану планування ієрархії під час виконання. У той час як обʼєкти PodGroup керують групами Podʼів на кінцевих рівнях, обʼєкти CompositePodGroup представляють проміжні групи, які забезпечують виконання політик планування для дочірніх груп.

Примітка:

У специфікації Workload поля spec.compositePodGroupTemplates та spec.podGroupTemplates утворюють обʼєднання: Workload повинен визначати або spec.podGroupTemplates (для пласких робочих навантажень), або spec.compositePodGroupTemplates (для ієрархічних робочих навантажень), але не може визначати обидва.

Структура та обмеження

Поле spec.compositePodGroupTemplates визначає проміжні шаблони в дереві ієрархії шаблонів груп. Кожен елемент представляє шаблон для CompositePodGroup і може містити:

  • Дочірні шаблони: вкладені CompositePodGroupTemplates (для проміжних груп) або PodGroupTemplates (для кінцевих груп, що містять Podʼи).
  • Політику планування: визначає, як плануються дочірні групи в межах цієї складової групи:
    • basic: дочірні групи приймаються та плануються незалежно.
    • gang: забезпечує багаторівневе планування «все або нічого» для дочірніх груп. Вимагає minGroupCount, який визначає мінімальну кількість дочірніх груп, які повинні бути заплановані одночасно, щоб складова група була реалізованою.
  • Обмеження планування: необовʼязкові топологічні обмеження для багаторівневого топологічно-орієнтованого планування.
  • Пріоритет, політика витіснення та режим розладу: необовʼязкові priorityClassName, disruptionMode (Single або All) та preemptionPolicy для витіснення з урахуванням навантаження.

Щоб забезпечити стабільність кластера та ефективність панелі управління, ієрархія шаблонів груп застосовує такі обмеження:

  • Максимальна глибина вкладеності: ієрархія шаблонів груп підтримує максимальну глибину 4 рівні.
  • Обмеження списку: кожен список compositePodGroupTemplates та podGroupTemplates суворо обмежений максимум 8 елементами.

Примітка:

Наразі ви не можете додавати нові або видаляти наявні CompositePodGroupTemplates. Ви можете лише змінювати значення minCount у політиці групового планування, визначеній у кінцевих PodGroupTemplates.

Приклад

Наступний приклад визначає ієрархічний Workload з шаблоном CompositePodGroup, який забезпечує групове планування для двох дочірніх шаблонів PodGroup (minGroupCount: 2), кожен з яких визначає власну політику групового планування:

apiVersion: scheduling.k8s.io/v1alpha3
kind: Workload
metadata:
  name: gang-of-gangs-workload
  namespace: default
spec:
  compositePodGroupTemplates:
  - name: root
    schedulingPolicy:
      gang:
        # Вимагає, щоб обидві дочірні PodGroup були заплановані разом
        minGroupCount: 2
    podGroupTemplates:
    - name: workers-a
      schedulingPolicy:
        gang:
          # Вимагає, щоб 4 Podʼи в цій групі були заплановані
          minCount: 4
    - name: workers-b
      schedulingPolicy:
        gang:
          # Вимагає, щоб 4 Podʼи в цій групі були заплановані
          minCount: 4

Групове планування з Job

Стан функціоналу: Alpha починаючи з Kubernetes v1.36; стандартно вимкнено
Докладніше про цей функціонал

Щоб скористатися цією функцією, вам (або адміністратору кластера) потрібно увімкнути функціональну можливість WorkloadWithJob для всіх відповідних компонентів у вашому кластері.

Перегляньте Увімкнення або вимкнення функціональних можливостей для отримання додаткової інформації.

Коли функціональна можливість WorkloadWithJob увімкнена, контролер Job компілює конфігурацію .spec.scheduling завдання в обʼєкти Workload та PodGroup перед тим, як створити будь-які Podʼи. Ви вмикаєте групове планування, встановивши .spec.scheduling.schedulingPolicy.gang у Job; пропущений gang.minCount типово дорівнює .spec.parallelism завдання, тому всі Podʼи повинні бути заплановані одночасно, перш ніж будь-який з них буде привʼязаний до вузлів.

Коли .spec.scheduling пропущено, Job зазвичай використовує політику basic, яка зберігає стандартне планування под за подом. У будь-якому випадку контролер Job створює Workload та PodGroup за вас, тому вам не потрібно створювати їх самостійно. Інші контролери робочих навантажень (наприклад, JobSet) можуть самостійно керувати своїми обʼєктами Workload та PodGroup.

Повний набір полів планування та приклади дивіться у розділі Інтеграція з Workload API.

Що далі

1 - Групове планування Podʼів: Розлад та пріоритети

Стан функціоналу: Beta починаючи з Kubernetes v1.37; стандартно вимкнено
Докладніше про цей функціонал

Щоб скористатися цією функцією, вам (або адміністратору кластера) потрібно увімкнути функціональну можливість GenericWorkload для всіх відповідних компонентів у вашому кластері.

Перегляньте Увімкнення або вимкнення функціональних можливостей для отримання додаткової інформації.

PodGroup може оголосити режим розладу. Цей режим визначає, як планувальник може зчинити розлад для PodGroup, що працює, наприклад, щоб розмістити PodGroup з вищим пріоритетом. PodGroup також має пріоритет, який перевизначає пріоритет окремих Podʼів з групи для подій витіснення з урахуванням навантаження.

Типи режимів розладу

Примітка:

У v1.36 поля priority або disruptionMode обʼєкта PodGroup враховуються лише в режимі витіснення з урахуванням навантаження. Під час фази планування подів планувальник не враховує поля priority або disruptionMode обʼєкта PodGroup. Це обмеження більше не застосовується у v1.37.

API підтримує два режими розладу: Single та All. Стандартний режим — Single.

Single

Режим Single вказує планувальнику розглядати всі Podʼи в групі як окремі сутності, дозволяючи незалежний розлад окремого пода з PodGroup.

All

Режим All підкреслює семантику "все або нічого" для розладу. Він вказує планувальнику, що всі поди з PodGroup повинні отримати сигнал розладу одночасно.

CompositePodGroup

Стан функціоналу: Alpha починаючи з Kubernetes v1.37; стандартно вимкнено
Докладніше про цей функціонал

Щоб скористатися цією функцією, вам (або адміністратору кластера) потрібно увімкнути функціональну можливість CompositePodGroup для всіх відповідних компонентів у вашому кластері.

Перегляньте Увімкнення або вимкнення функціональних можливостей для отримання додаткової інформації.

CompositePodGroup також може оголосити disruptionMode у своїй специфікації, який визначає, як планувальник зчиняє розлад дочірніх груп у межах складової групи під час подій витіснення.

API підтримує два режими розладу для CompositePodGroups:

  • Single: дозволяє окремим дочірнім групам у межах CompositePodGroup отримати розлад незалежно під час витіснення.
  • All: забезпечує семантику розладу "все або нічого" для всієї ієрархії CompositePodGroup. Якщо будь-який Pod, що міститься в ієрархії нижче цього CompositePodGroup, має бути витіснений, усі Podʼи з усієї ієрархії мають бути витіснені.

Якщо не вказано, стандартний режим — Single.

Примітка:

У v1.37 група може встановити свій режим розладу на All і мати дочірні групи з режимом Single. У такому випадку режим All верхнього рівня перевизначає режими Single нащадків.

Така конфігурація не рекомендується через неоднозначну семантику.

Пріоритет групи Podʼів

PodGroup використовує ту ж концепцію PriorityClass, що й окремі Podʼи. Після створення одного або кількох PriorityClasses, ви можете створити PodGroup, яка вказує одне з цих імен PriorityClass у своїй специфікації. Контролер допуску пріоритету використовує поле priorityClassName і заповнює ціле значення пріоритету. Якщо клас пріоритету не знайдено, PodGroup відхиляється. Коли priorityClassName не встановлено для PodGroup, Kubernetes шукає стандартне значення (PriorityClass з globalDefault, встановленим у true). Якщо немає PriorityClass з globalDefault, встановленим у true, PodGroup без priorityClassName має пріоритет нуль.

Пріоритет PodGroup є авторитетним пріоритетом для всіх подів у групі під час подій витіснення з урахуванням навантаження. Це значення також використовується для впорядкування PodGroup у черзі планування. Якщо пріоритети окремих подів, що формують цю PodGroup, відрізняються від пріоритету PodGroup, PodGroup не буде запланована з помилкою all pods in a single pod group should have the same priority as the pod group (усі поди в одній групі подів повинні мати такий самий пріоритет, як і сама група подів).

Коли увімкнено функціональну можливість PodGroupPreemptionPolicy, PodGroup також має поле preemptionPolicy. Це поле також береться з PriorityClass. Воно є авторитетним полем для всіх подів у групі та визначає, чи може PodGroup виконувати витіснення подів і груп подів з нижчим пріоритетом, щоб звільнити місце для себе. Коли функціональну можливість увімкнено, усі Podʼи в PodGroup повинні мати той самий preemptionPolicy, що й PodGroup. Інакше PodGroup не буде запланована з помилкою all pods in a single pod group should have the same preemption policy as the pod group's preemption policy (усі поди в одній групі подів повинні мати ту саму політику витіснення, що й політика витіснення цієї групи подів). Коли PodGroup має preemptionPolicy: Never, вона не виконуватиме витіснення з урахуванням робочого навантаження. Якщо функціональну можливість вимкнено, усі Podʼи, що формують PodGroup, повинні мати однаковий preemptionPolicy. Інакше PodGroup не буде запланована з помилкою all pods in a single pod group should have the same preemption policy (усі поди в одній групі подів повинні мати однакову політику витіснення).

Наступний YAML є прикладом конфігурації PodGroup, яка використовує PriorityClass high-priority, що відповідає цілому значенню пріоритету 1000000. Контролер допуску пріоритету перевіряє специфікацію та визначає пріоритет PodGroup як 1000000.

apiVersion: scheduling.k8s.io/v1beta1
kind: PodGroup
metadata:
  namespace: ns-1
  name: job-1
spec:
  priorityClassName: high-priority

Пріоритет CompositePodGroup

Стан функціоналу: Alpha починаючи з Kubernetes v1.37; стандартно вимкнено
Докладніше про цей функціонал

Щоб скористатися цією функцією, вам (або адміністратору кластера) потрібно увімкнути функціональну можливість CompositePodGroup для всіх відповідних компонентів у вашому кластері.

Перегляньте Увімкнення або вимкнення функціональних можливостей для отримання додаткової інформації.

API CompositePodGroup також має поля priorityClassName та priority, і їх визначення виконується так само, як і для PodGroups, через контролер допуску пріоритету.

Пріоритет кореневого CompositePodGroup діє як авторитетний пріоритет для всіх дочірніх груп і Podʼів у межах його ієрархії під час подій витіснення з урахуванням навантаження. Усі Podʼи в межах однієї ієрархії груп повинні мати точно такий самий пріоритет, який має дорівнювати пріоритету кореневого CompositePodGroup.

Значення пріоритету також використовується для впорядкування кореневих CompositePodGroups в активній черзі планування.

Примітка:

У v1.37 планувальник не перевіряє, чи мають некореневі групи значення пріоритету, що дорівнює пріоритету кореневого CompositePodGroup.

PreemptionPolicy у CompositePodGroup

Стан функціоналу: Alpha починаючи з Kubernetes v1.37; стандартно вимкнено
Докладніше про цей функціонал

Щоб скористатися цією функцією, вам (або адміністратору кластера) потрібно увімкнути функціональну можливість PodGroupPreemptionPolicy для всіх відповідних компонентів у вашому кластері.

Перегляньте Увімкнення або вимкнення функціональних можливостей для отримання додаткової інформації.

API CompositePodGroup також має поле preemptionPolicy, і його визначення виконується точно так само, як і для API PodGroup.

Значення preemptionPolicy кореневого CompositePodGroup визначає, чи може бути викликане витіснення з урахуванням навантаження для розміщення його Podʼів під час планування, якщо це необхідно:

  • політика PreemptLowerPriority дозволяє витісняти жертв з нижчим пріоритетом;
  • політика Never вимикає витіснення з урахуванням навантаження для цього кореневого CompositePodGroup.

Усі Podʼи в межах однієї ієрархії груп повинні мати точно таку саму політику витіснення, яка має дорівнювати політиці витіснення кореневого CompositePodGroup.

Якщо функціональну можливість вимкнено, кореневому CompositePodGroup буде дозволено виконувати витіснення, якщо жоден з Podʼів, що належить до ієрархії групи, не має preemptionPolicy зі значенням Never.

Примітка:

У v1.37, коли функціональну можливість увімкнено, планувальник не перевіряє, чи мають некореневі групи політику витіснення, що дорівнює політиці витіснення кореневого CompositePodGroup.

Що далі

2 - Політики планування PodGroup

Стан функціоналу: Beta починаючи з Kubernetes v1.37; стандартно вимкнено
Докладніше про цей функціонал

Щоб скористатися цією функцією, вам (або адміністратору кластера) потрібно увімкнути функціональну можливість GenericWorkload для всіх відповідних компонентів у вашому кластері.

Перегляньте Увімкнення або вимкнення функціональних можливостей для отримання додаткової інформації.

Кожна PodGroup повинна оголосити політику планування у своєму полі spec.schedulingPolicy. Ця політика визначає, як планувальник обробляє колекцію Podʼів у групі.

Типи політик

Поле schedulingPolicy підтримує два типи політик: basic та gang. Ви повинні вказати лише одну.

Політика basic

Політика basic вказує планувальнику оцінювати всі Pod за принципом «наскільки це можливо». На відміну від політики gang, PodGroup, що використовує політику basic, вважається реалізованою незалежно від того, скільки її Podʼів на даний момент підлягають плануванню.

Основною причиною використання політики basic є організація Podʼів у групу для кращої спостережуваності та управління, при цьому вони все одно оцінюються разом у рамках єдиного атомарного циклу планування PodGroup.

Ця політика підходить для груп, які не потребують одночасного запуску, але логічно належать до одного цілого, або для створення можливості для обмежень на рівні групи, які не передбачають розміщення за принципом «все або нічого».

schedulingPolicy:
  basic: {}

Політика gang

Політика gang забезпечує планування «все або нічого». Це необхідно для сильно звʼязаних робочих навантажень, де частковий запуск призводить до блокувань або втрати ресурсів.

Цю політику можна використовувати для Jobs або будь-якого іншого пакетного процесу, де всі працівники повинні працювати одночасно, щоб зробити прогрес.

Політика gang вимагає параметра minCount, який визначає мінімальну кількість Podʼів, які повинні бути заплановані одночасно, щоб група була прийнятною:

schedulingPolicy:
  gang:
    # Кількість Podʼів, які повинні бути заплановані одночасно
    # для того, щоб група була прийнята.
    minCount: 4

Встановлення політик через PodGroupTemplates

Під час використання Workload API, ви визначаєте політики планування всередині PodGroupTemplates. Контролер робочого навантаження копіює політику з шаблону в кожну створену PodGroup, роблячи PodGroup самодостатньою. Зміни в шаблонах Workload впливають лише на новостворені PodGroup, а не на наявні.

Для автономних PodGroup (створених без Workload) ви встановлюєте spec.schedulingPolicy безпосередньо на самій PodGroup.

Політики в CompositePodGroups

Стан функціоналу: Alpha починаючи з Kubernetes v1.37; стандартно вимкнено
Докладніше про цей функціонал

Щоб скористатися цією функцією, вам (або адміністратору кластера) потрібно увімкнути функціональну можливість CompositePodGroup для всіх відповідних компонентів у вашому кластері.

Перегляньте Увімкнення або вимкнення функціональних можливостей для отримання додаткової інформації.

Коли увімкнено функціональну можливість CompositePodGroup та групу API scheduling.k8s.io/v1alpha3 групи API, CompositePodGroupTemplates у Workload та обʼєкти CompositePodGroup також оголошують політику планування.

У той час як політика планування в PodGroup керує колекцією окремих Podʼів, політика планування CompositePodGroup керує її безпосередніми дочірніми групами (які можуть бути як обʼєктами CompositePodGroup, так і PodGroup).

Типи політик для CompositePodGroups

Подібно до PodGroups, поле spec.schedulingPolicy обʼєкта CompositePodGroup підтримує два типи:

  • basic: дочірні групи в межах CompositePodGroup оцінюються та приймаються незалежно.
  • gang: забезпечує багаторівневе планування "все або нічого" для дочірніх груп. CompositePodGroup є реалізованою лише якщо принаймні minGroupCount дочірніх груп можуть бути заплановані одночасно.
schedulingPolicy:
  gang:
    # Мінімальна кількість дочірніх груп, які повинні бути заплановані
    # одночасно, щоб ця складова група була прийнята.
    minGroupCount: 2

Встановлення складених політик через шаблони

Під час використання Workload API, політики планування для CompositePodGroups визначаються всередині CompositePodGroupTemplates. Контролери робочого навантаження копіюють schedulingPolicy, вказану в шаблонах, у кожен CompositePodGroup, створений під час виконання. На відміну від кінцевих PodGroupTemplates, де minCount можна оновлювати, minGroupCount у CompositePodGroupTemplate є незмінним.

Що далі

3 - Топологічно-орієнтоване планування робочих навантажень

Стан функціоналу: Alpha починаючи з Kubernetes v1.36; стандартно вимкнено
Докладніше про цей функціонал

Щоб скористатися цією функцією, вам (або адміністратору кластера) потрібно увімкнути функціональну можливість TopologyAwareWorkloadScheduling для всіх відповідних компонентів у вашому кластері.

Перегляньте Увімкнення або вимкнення функціональних можливостей для отримання додаткової інформації.

Топологічно-орієнтоване планування робочих навантажень (Topology-Aware Scheduling, TAS) є функцією Workload API, яка оптимізує розміщення Podʼів у межах кластера.

TAS забезпечує, щоб усі Podʼи в межах PodGroup були розміщені в одному топологічному домені, наприклад, в одній серверній стійці або в одній зоні. Це мінімізує затримки між Podʼами та запобігає фрагментації робочого навантаження по інфраструктурі кластера.

Топологічно-орієнтоване планування з політикою gang

При застосуванні до PodGroup з політикою планування gang, TAS симулює потенційне розміщення (placement) всієї групи Pod одночасно. Це гарантує, що принаймні зазначена кількість minCount Podʼів може розміститися разом в одному топологічному домені перед виділенням ресурсів. Якщо не знайдено жодного можливого розміщення, вся PodGroup не може бути запланованою.

Цей підхід рекомендується для робочих навантажень, таких як розподілене навчання AI та ML, які строго потребують близькості для мінімізації затримок між Podʼами.

Якщо до PodGroup додаються нові Podʼи, де деякі Podʼи вже заплановані (наприклад, якщо Podʼи перестворюються), планувальник змусить всі нові Podʼи розміститися в тому ж топологічному домені, де наразі знаходяться поточні Podʼи. Якщо в цьому конкретному домені недостатньо ресурсів для нових Podʼів, вони залишаться в стані очікування — навіть якщо це означає, що на даний момент буде заплановано менше ніж minCount Podʼів.

Примітка:

Починаючи з версії v1.36 топологічно-орієнтоване планування не викликає примусового виділення ресурсів для робочих навантажень або Podʼів. Якщо не знайдено жодного можливого розміщення без примусового виділення ресурсів, PodGroup стає незапланованою.

Топологічно-орієнтоване планування з політикою basic

Використання TAS з політикою планування basic може призводити до непослідовної поведінки. Планувальник може спостерігати лише підмножину Podʼів під час входу в цикл планування PodGroup — тому можливість розміщення оцінюється лише для спостережуваних Podʼів, а не для всієї PodGroup. Щоб частково помʼякшити це обмеження, можна використовувати шлюзи планування, щоб затримати планування PodGroup до тих пір, поки всі Podʼи в PodGroup не будуть у черзі планування.

Якщо не знайдено жодного можливого розміщення для всієї PodGroup, може бути запланована лише підмножина Podʼів, і вони гарантовано відповідатимуть обмеженням планування.

Якщо до PodGroup додаються нові Podʼи, де деякі Podʼи вже заплановані, планувальник діятиме так само, як у випадку політики gang — змушуючи нові Podʼи розміститися в тому ж домені, якщо є достатньо ресурсів (у протилежному випадку нові Podʼи залишаться в стані очікування).

Налаштування API: обмеження планування

Кожна PodGroup (або PodGroupTemplate) може опціонально оголосити поле schedulingConstraints, яке інтерпретується алгоритмом планування PodGroup на основі розміщення. Якщо обмеження визначені в PodGroupTemplate, вони будуть скопійовані до вказаних PodGroup.

Починаючи з версії Kubernetes v1.36, API підтримує топологічні обмеження.

Примітка:

Починаючи з версії Kubernetes v1.36, ви можете вказати лише одне топологічне обмеження для кожної PodGroup.

Топологічне обмеження

Щоб визначити топологічне обмеження для PodGroup, потрібно встановити key, який відповідає мітці вузла Kubernetes, що представляє цільовий топологічний домен (наприклад, стійку або зону). Планувальник суворо забезпечує, щоб усі Podʼи в межах PodGroup були розміщені на вузлах, які мають однакове значення для цієї мітки.

Ось приклад PodGroup, налаштованої з топологічним обмеженням:

apiVersion: scheduling.k8s.io/v1beta1
kind: PodGroup
metadata:
  name: example-podgroup
spec:
  schedulingPolicy:
    gang:
      minCount: 4
  schedulingConstraints:
    topology:
      - key: topology.example.com/rack

Багаторівневе топологічно-орієнтоване планування

Стан функціоналу: Alpha починаючи з Kubernetes v1.37; стандартно вимкнено
Докладніше про цей функціонал

Щоб скористатися цією функцією, вам (або адміністратору кластера) потрібно увімкнути функціональну можливість CompositePodGroup для всіх відповідних компонентів у вашому кластері.

Перегляньте Увімкнення або вимкнення функціональних можливостей для отримання додаткової інформації.

Складні робочі навантаження можуть вимагати спільного розміщення їхніх Podʼів на різних рівнях інфраструктури кластера. Наприклад, усе робоче навантаження може потребувати запуску в межах однієї зони доступності, тоді як різні частини цього робочого навантаження можуть вимагати суворого спільного розміщення в межах конкретних серверних стійок.

Такі багаторівневі вимоги до спільного розміщення можна виразити за допомогою API CompositePodGroup та вказуючи топологічні обмеження на різних рівнях ієрархії груп.

Використання API CompositePodGroup вимагає увімкнення функціональної можливості CompositePodGroup та групи API scheduling.k8s.io/v1alpha3 групи API.

Визначення багаторівневих топологічних обмежень

Кожна група в ієрархії CompositePodGroup може вказати топологічне обмеження, яке гарантує, що всі нащадкові Podʼи цієї групи будуть заплановані в тому самому топологічному домені, що відповідає обмеженню цієї групи.

Під час ієрархічного планування планувальник визначає ці обмеження зверху вниз. Зокрема, топологічні домени, які розглядаються під час планування дочірньої групи, обмежені топологічним доменом, що відповідає розміщенню, прийнятому батьківською групою.

Kubernetes не накладає жодних суворих вимог на фізичну ієрархію топологічних міток — топологічні ключі є довільними мітками вузлів. Однак порядок, у якому ви вказуєте топологічні обмеження від батьківської до дочірньої групи, визначає порядок, у якому планувальник поділяє топологічні домени.

Примітка:

Починаючи з версії Kubernetes v1.37, ви можете вказати лише одне топологічне обмеження в кожному CompositePodGroup.

Приклад

Наступний приклад налаштовує Workload, у якому батьківський CompositePodGroupTemplate обмежує все робоче навантаження однією зоною доступності (topology.example.com/zone), тоді як два дочірні елементи PodGroupTemplate (workers та driver) обмежують свої відповідні Podʼи серверними стійками (topology.example.com/rack) у межах цієї зони:

apiVersion: scheduling.k8s.io/v1alpha3
kind: Workload
metadata:
  name: example-workload
spec:
  compositePodGroupTemplates:
  - name: root
    schedulingPolicy:
      gang:
        minGroupCount: 2
    schedulingConstraints:
      topology:
      - key: topology.example.com/zone
    podGroupTemplates:
    - name: workers
      schedulingPolicy:
        gang:
          minCount: 8
      schedulingConstraints:
        topology:
        - key: topology.example.com/rack
    - name: driver
      schedulingPolicy:
        gang:
          minCount: 1
      schedulingConstraints:
        topology:
        - key: topology.example.com/rack

Після створення обʼєкта Workload відповідні обʼєкти груп створюються таким чином:

  • Кореневий CompositePodGroup, що посилається на шаблон root.
  • Два дочірні обʼєкти PodGroup (workers та driver), кожен з яких посилається на кореневий CompositePodGroup як на свою батьківську групу.
apiVersion: scheduling.k8s.io/v1alpha3
kind: CompositePodGroup
metadata:
  name: workload-root
spec:
  workloadRef:
    workloadName: example-workload
    templateName: root
  schedulingPolicy:
    gang:
      minGroupCount: 2
  schedulingConstraints:
    topology:
    - key: topology.example.com/zone
---
apiVersion: scheduling.k8s.io/v1beta1
kind: PodGroup
metadata:
  name: workload-workers
spec:
  parentCompositePodGroupName: workload-root
  workloadRef:
    workloadName: example-workload
    templateName: workers
  schedulingPolicy:
    gang:
      minCount: 8
  schedulingConstraints:
    topology:
    - key: topology.example.com/rack
---
apiVersion: scheduling.k8s.io/v1beta1
kind: PodGroup
metadata:
  name: workload-driver
spec:
  parentCompositePodGroupName: workload-root
  workloadRef:
    workloadName: example-workload
    templateName: driver
  schedulingPolicy:
    gang:
      minCount: 1
  schedulingConstraints:
    topology:
    - key: topology.example.com/rack

Під час планування планувальник спочатку обирає зону доступності для workload-root. Потім він поділяє вузли в цій зоні за стійками, щоб знайти можливі розміщення на стійках для workload-workers та workload-driver у межах обраної зони.

Наприклад, розглянемо кластер із пʼятьма вузлами, позначеними таким чином:

Вузолtopology.example.com/zonetopology.example.com/rack
node-azone-1rack-1
node-bzone-1rack-1
node-czone-1rack-2
node-dzone-2rack-1
node-ezone-2rack-3

Під час обробки workload-root планувальник оцінює можливі розміщення на всіх вузлах кластера на основі топологічного ключа topology.example.com/zone:

Оцінене можливе розміщенняВузли в можливому розміщенні
zone-1node-a, node-b, node-c
zone-2node-d, node-e

Під час оцінки можливих розміщень для workload-workers планувальник поділяє лише вузли в межах розміщення, прийнятого workload-root, на основі топологічного ключа topology.example.com/rack:

Батьківське розміщенняОцінене можливе розміщенняВузли в можливому розміщенні
zone-1rack-1node-a, node-b
zone-1rack-2node-c
zone-2rack-1node-d
zone-2rack-3node-e

Можливі розміщення, згенеровані для спорідненої PodGroup workload-driver, ідентичні тим, що згенеровані для workload-workers, оскільки обидві групи вказують той самий топологічний ключ (topology.example.com/rack).

Що далі

4 - API модулів планування та бібліотека workloadbuilder

Базові елементи API планування, що можуть використовуватися багаторазово, які вбудовані контролери робочих навантажень (як вбудовані, так і зовнішні) інтегрують у свої власні API, а також спільна бібліотека workloadbuilder, яка компілює їх у об’єкти Workload, PodGroup та CompositePodGroup.
Стан функціоналу: Beta починаючи з Kubernetes v1.37; стандартно вимкнено
Докладніше про цей функціонал

Щоб скористатися цією функцією, вам (або адміністратору кластера) потрібно увімкнути функціональну можливість GenericWorkload для всіх відповідних компонентів у вашому кластері.

Перегляньте Увімкнення або вимкнення функціональних можливостей для отримання додаткової інформації.

Workload-Aware Scheduling визначає набір багаторазово використовуваних будівельних блоків API у групі API scheduling.k8s.io. Автори контролерів вбудовують ці примітиви у свої власні API, щоб користувачі виражали намір щодо планування (групове планування, топологія, поведінка розладу) з узгодженою схемою в усій екосистемі, а спільна бібліотека workloadbuilder компілює цей намір в орієнтовані на планувальник обʼєкти Workload, PodGroup та CompositePodGroup.

Вбудованим споживачем цих будівельних блоків сьогодні є контролер Job, який контролюється функціональною можливістю WorkloadWithJob .

Будівельні блоки багаторазового використання

Будівельні блоки — це строго типізовані структури Go у групі API scheduling.k8s.io/v1alpha3. Вони призначені для авторів контролерів: контролер вбудовує ці структури у свій власний тип API як поля, а бібліотека workloadbuilder компілює їх. Назви типів слідують двом конвенціям: типи кінцевого рівня мають префікс WorkloadPodGroup... (наприклад, WorkloadPodGroupSchedulingPolicy), а багаторівневі варіанти — WorkloadCompositePodGroup....

Кожен контролер обирає назви полів та структуру, які є ідіоматичними для його власного API, тому ці блоки не навʼязують фіксованої форми верхнього рівня. Хоча це не є суворо обовʼязковим, рекомендується використовувати стандартні назви полів та структуру, щоб користувач, який налаштував групове планування на ресурсі одного контролера, впізнавав ті самі опції на ресурсі іншого.

Щоб прийняти будівельні блоки, контролер додає ті з них, які хоче підтримувати, як поля у своїх власних типах. Наприклад, API Job групує всі чотири з них в один тип, доступний за адресою spec.scheduling:

type JobSchedulingConfiguration struct {
    SchedulingPolicy      *schedulingv1alpha3.WorkloadPodGroupSchedulingPolicy
    SchedulingConstraints *schedulingv1alpha3.WorkloadPodGroupSchedulingConstraints
    DisruptionMode        *schedulingv1alpha3.WorkloadPodGroupDisruptionMode
    ResourceClaims        []schedulingv1alpha3.WorkloadPodGroupResourceClaim
}

Інший контролер може вкладати ті самі блоки для кожного компонента багаточастинного робочого навантаження або підтримувати лише їх підмножину.

Політика планування

Блок політики планування несе ті самі політики basic та gang, що й spec.schedulingPolicy PodGroup. Див. політики планування PodGroup для пояснення, що означає кожна політика та як планувальник її застосовує.

Єдина відмінність полягає в тому, що мінімальна кількість gang у блоці є необовʼязковою. Користувачі можуть залишити minCount невстановленим, і в цьому випадку контролер надає стандартне значення, яке має сенс для його власної області; контролер Job, наприклад, використовує паралелізм Job.

Обмеження планування

Блок обмежень планування несе топологічні обмеження, задокументовані в топологічно-орієнтованому плануванні робочих навантажень: ключ мітки вузла, що називає домен (наприклад, стійку або зону), який повинен бути спільним для кожного Podʼа в групі, з не більш ніж одним топологічним обмеженням на групу. Контролери повинні заморозити поле після створення, оскільки обмеження є незмінними в скомпільованому Workload.

Режим розладу

Блок режиму розладу визначає, чи можуть Podʼи групи отримати розлад індивідуально (single) або лише як єдине ціле (all), що відповідає режимам розладу Pod та PodGroup, задокументованим у розладі та пріоритеті групи Pod.

Бібліотека відхиляє комбінації, які не мають сенсу. Наприклад, забороняє режим розладу all для PodGroups з BasicSchedulingPolicy, оскільки одиниця витіснення не повинна бути більшою за одиницю планування — група, запланована под за подом, не має одиниці на рівні групи для витіснення або розладу.

Заявки на ресурси

Блок заявок на ресурси виражає, які заявки динамічного виділення ресурсів є спільними для кожного Podʼа в групі, а не виділяються на кожен Pod окремо. Кожен запис називає заявку в межах групи та вказує або на наявний ResourceClaim, або на ResourceClaimTemplate, з якого вона генерується. Група може оголосити не більше чотирьох заявок.

Podʼи споживають пристрої, виділені групі, оголошуючи відповідну заявку у власній специфікації, використовуючи те саме імʼя та посилаючись на той самий обʼєкт.

Композитні будівельні блоки

Багаторівневі контролери, які оркеструють інші контролери (наприклад, JobSet, що створює Jobs), координують групу груп. Для цього рівня API надає аналогічний набір примітивів з префіксом WorkloadCompositePodGroup... (наприклад, WorkloadCompositePodGroupSchedulingPolicy). Вони слідують тим самим формам, що й блоки кінцевого рівня, за винятком того, що композитна політика gang використовує minGroupCount (мінімальну кількість дочірніх груп, які повинні бути заплановані разом) замість minCount кінцевого рівня. Збереження окремих типів кінцевого та композитного рівнів дозволяє кожному рівню ієрархії розвиватися незалежно.

Приклад: інтеграція з Job

Контролер Job є вбудованим прикладом використання цих блоків. Користувач заповнює spec.scheduling Job, а контролер компілює його в Workload та PodGroup. Див. інтеграцію з Workload API для повного маніфесту Job, стандартних значень, які застосовуються, коли spec.scheduling пропущено, та які поля ви можете змінювати після створення.

Бібліотека workloadbuilder

workloadbuilder — це спільна бібліотека Go, яка перетворює намір контролера щодо планування в орієнтовані на планувальник Workload та його обʼєкти PodGroup/CompositePodGroup під час виконання, тому кожен контролер не реалізовує повторно стандартні значення, перевірку та компіляцію шаблонів. Вона розроблена як для вбудованих контролерів (таких як контролер Job), так і для сторонніх контролерів (таких як JobSet або Kubeflow TrainJob), які вбудовують її як будь-яку іншу залежність Go. Вона постачається з k8s.io/component-helpers/scheduling/schedulingv1/workloadbuilder.

Бібліотека споживає будівельні блоки scheduling.k8s.io/v1alpha3 та компілює їх в обʼєкти Workload та PodGroup scheduling.k8s.io/v1beta1, тоді як обʼєкти CompositePodGroup залишаються scheduling.k8s.io/v1alpha3.

Як контролер її використовує

Контролер описує своє робоче навантаження як дерево вузлів WorkloadItem, по одному на кожен логічний компонент. Вузол без дочірніх елементів стає одним PodGroupTemplate, тоді як вузол з дочірніми елементами стає CompositePodGroupTemplate над ними — саме так багаторівневий контролер представляє групу груп. Кожен вузол несе:

  • стандартну конфігурацію — власні стандартні значення контролера для всього, що користувач залишає невстановленим. Саме тут контролер вирішує, наприклад, що неналаштований Job залишається на плануванні basic.
  • вхідні дані — намір користувача, взятий з API контролера. Контролер записує кожен будівельний блок разом із шляхом до поля, на якому він розташований, щоб помилки перевірки вказували на точне поле, яке встановив користувач.
  • необовʼязкові зворотні виклики, які коригують обʼєднану конфігурацію. Саме так контролер надає контекстно-залежне стандартне значення, наприклад, заповнює невстановлену мінімальну кількість gang з паралелізму Job.

Потім контролер передає це дерево Builder і проходить через чотири виклики:

  1. NewBuilder створює будівельник з дерева, а також імʼя, простір імен та посилання на власника для обʼєкта, який буде створено. Власник стає посиланням на контролер Workload, яке використовується для виявлення та прибирання сміття.
  2. Validate розвʼязує дерево та повідомляє про будь-які проблеми як список помилок полів, які контролер повертає з власної перевірки API.
  3. BuildWorkload компілює дерево в Workload. Результат кешується, тому з одного скомпільованого результату можна створити кілька PodGroups.
  4. NewPodGroup створює PodGroup під час виконання з одного зі скомпільованих шаблонів, називаючи шаблон, з якого він повинен бути створений.
builder := workloadbuilder.NewBuilder(item, opts)
if errs := builder.Validate(ctx, workloadbuilder.ValidationInput{}); len(errs) > 0 {
    // reject the request
}
workload, err := builder.BuildWorkload()
podGroup, err := builder.NewPodGroup("trainer-pg", item.Name)

Для повних, робочих версій цього потоку, включаючи те, як контролер Job його підключає, див. приклади в довіднику пакунка.

Перевірка конфігурації планування

Validate перевіряє конфігурацію на двох рівнях:

  • Структурна перевірка самих будівельних блоків: обовʼязкові поля, діапазони значень, правило, що рівно один член обʼєднання встановлений, та незмінність. Ці перевірки походять з правил декларативної перевірки, згенерованих з типів API.
  • Перевірки політики контролера, які декларативна перевірка не може виразити: списки дозволених значень, описані нижче, та міжпольові правила, такі як відхилення режиму розладу all разом з політикою basic.

Перевірка також відрізняється між створенням та оновленням обʼєкта. Під час оновлення бібліотека додатково забезпечує поля, які заморожуються після створення, що означає, що контролер повинен надати раніше збережену конфігурацію разом з новою. Під час створення немає з чим порівнювати, тому ці перевірки не застосовуються.

Відмова від декларативної перевірки

Чи потрібен вам перший рівень, залежить від того, де працює ваш контролер, і одна опція керує ним:

  • Сторонні контролери залишають декларативну перевірку увімкненою, що є стандартним значенням. Ніщо інше не застосовує ці структурні правила до власного ресурсу, тому один виклик Validate покриває обидва рівні.
  • Вбудовані контролери встановлюють DisableDeclarativeValidation, оскільки сервер API вже виконує декларативну перевірку вбудованих блоків під час перевірки батьківського обʼєкта. Пропуск першого рівня дозволяє уникнути перевірки тих самих полів двічі, залишаючи Validate виконувати лише перевірки політики контролера.

Вибір опцій планування

Оскільки типи будівельних блоків є спільними для контролерів, майбутні випуски можуть додавати опції планування, які не мають сенсу для кожного контролера. Щоб нові опції не просочувалися непомітно, workloadbuilder використовує модель списку дозволених значень: контролер оголошує політики та режими розладу, які він підтримує, а Validate відхиляє все, що виходить за межі цього набору, повідомляючи про помилку за шляхом до поля блоку, що порушує правила.

Тому опції типово заборонені. Коли вводиться нова політика, наявний контролер продовжує її відхиляти, доки його супроводжувачі не розширять список дозволених значень, що для стороннього контролера означає також оновлення його вбудованої копії бібліотеки.

builder := workloadbuilder.NewBuilder(item, workloadbuilder.BuildOptions{
    Owner:                  owner,
    AllowedPolicies:        []workloadbuilder.SchedulingPolicyOption{workloadbuilder.BasicPolicy, workloadbuilder.GangPolicy},
    AllowedDisruptionModes: []workloadbuilder.DisruptionModeOption{workloadbuilder.SingleMode, workloadbuilder.AllMode},
})
allErrs := builder.Validate(ctx, workloadbuilder.ValidationInput{})

Створення PodGroups з наявного Workload

Коли Workload вже існує, незалежно від того, чи він скомпільований батьківським контролером, чи створений вручну, дочірній контролер, який керує лише PodGroup під час виконання, використовує натомість NewBuilderFromExistingWorkload. Цей будівельник створює обʼєкти PodGroup з наданого Workload, використовуючи власне посилання на власника. Він нічого не перевіряє та не компілює, тому наявний Workload ніколи не перекомпілюється.

builder := workloadbuilder.NewBuilderFromExistingWorkload(parentWorkload, workloadbuilder.BuildOptions{Owner: owner})
podGroup, err := builder.NewPodGroup("trainer-pg", "trainer-pgt-0")

Що далі