API будівельних блоків планування та бібліотека workloadbuilder

API будівельних блоків планування та бібліотека workloadbuilder

Примітиви API планування багаторазового використання, які контролери робочих навантажень, як вбудовані, так і сторонні, вбудовують у свої власні API, а також спільна бібліотека workloadbuilder, яка компілює їх в обʼєкти Workload, PodGroup та CompositePodGroup.
СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the GenericWorkload feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Планування з урахуванням робочого навантаження (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ʼом, не має одиниці на рівні групи для витіснення або порушення.

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

Блок заявок на ресурси виражає, які заявки динамічного виділення ресурсів є спільними для кожного 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), які підключають її через vendor, як будь-яку іншу залежність 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 створює builder із дерева разом із назвою, простором імен та посиланням на власника для обʼєкта, який буде створено. Власник стає посиланням на контролер 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 відхиляє все, що виходить за межі цього набору, повідомляючи про помилку за шляхом до поля блоку, що порушує правила.

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

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. Цей builder створює обʼєкти PodGroup з наданого Workload, використовуючи власне посилання на власника. Він нічого не перевіряє та не компілює, тому наявний Workload ніколи не перекомпілюється.

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

Що далі

Змінено November 01, 2026 at 1:20 PM PST: [uk] Use «порушення» for disruption (98c5b43c1a)