Динамічне виділення ресурсів
Стан функціоналу:
Stable починаючи з Kubernetes v1.35
Докладніше про цей функціонал
Це стабільна функція в Kubernetes, яка загальнодоступна починаючи з версії v1.35. Вперше вона зʼявилась у випуску v1.30. Ви більше не можете вимкнути або відмовитися від цієї функції чи поведінки (це заблоковано); якщо ви явно встановите значення для повʼязаної функціональної можливості DynamicResourceAllocation, Kubernetes проігнорує це, але не повідомить про помилку.
Цей розділ знайомить з динамічним виділенням ресурсів (Dynamic Resource Allocation, DRA) у Kubernetes.
DRA — функція Kubernetes, яка дозволяє вам запитувати ресурси та ділитися ними з іншими Podʼами. Ці ресурси часто приєднуються до пристроїв, наприклад, до апаратних прискорювачів.
З DRA драйвери пристроїв і адміністратори кластерів визначають класи пристроїв, які доступні для заявки в робочих навантаженнях. Kubernetes виділяє відповідні пристрої для конкретних заявок і розміщує відповідні Podʼи на вузлах, які можуть отримати доступ до виділених пристроїв.
Виділення ресурсів за допомогою DRA схоже на динамічне надання томів, в якому ви використовуєте PersistentVolumeClaims, щоб запитати ємність сховища від класів сховища і запитувати заявлену ємність для використання у ваших Podʼах.
Переваги DRA
DRA надає гнучкий спосіб категоризації, запиту та використання пристроїв у вашому кластері. Використання DRA має такі переваги:
- Гнучке фільтрування пристроїв: використовуйте загальну мову виразів (CEL) для виконання детального фільтрування за конкретними атрибутами пристроїв.
- Спільне використання пристроїв: діліться одним і тим же ресурсом між кількома контейнерами або Podʼами, посилаючись на відповідну заявку на ресурс.
- Конфігурація пристроїв: прикріплюйте специфічні для постачальника конфігурації пристроїв до вашої заявки на ресурс, що дозволяє конфігурувати пристрої для кожного робочого навантаження окремо, а не для кожного вузла, як це відбувається сьогодні.
- Централізована категоризація пристроїв: драйвери пристроїв і адміністратори кластерів можуть використовувати класи пристроїв, щоб надати операторам застосунків категорії апаратного забезпечення, які оптимізовані для різних випадків використання. Наприклад, ви можете створити клас пристроїв, оптимізований за вартістю для загальних робочих навантажень, і клас пристроїв високої продуктивності для критичних завдань.
- Спрощені запити Podʼів: за допомогою DRA операторам застосунків не потрібно вказувати кількість пристроїв у запитах ресурсів Podʼа. Замість цього Pod посилається на заявку на ресурс, а конфігурація пристроїв у цій заявці застосовується до Podʼа.
Ці переваги забезпечують значні поліпшення в робочому процесі виділення пристроїв у порівнянні з втулками пристроїв, які вимагають запитів пристроїв для кожного контейнера, не підтримують спільне використання пристроїв і не підтримують фільтрацію пристроїв на основі виразів.
Типи користувачів DRA
Процес використання DRA для виділення пристроїв включає такі типи користувачів:
Власник пристрою: відповідає за пристрої. Власники пристроїв можуть бути комерційними постачальниками, оператором кластера або іншою сутністю. Щоб використовувати DRA, пристрої повинні мати драйвери, сумісні з DRA, які виконують такі дії:
- Створюють ResourceSlices, які надають Kubernetes інформацію про вузли та ресурси.
- Оновлюють ResourceSlices, коли змінюється ємність ресурсів у кластері.
- Налаштовують пристрої відповідно до заявки та приєднують їх до контейнерів через Container Device Interface (CDI).
- За бажанням створюють DeviceClasses, які оператори робочих навантажень можуть використовувати для заявки на пристрої.
Адміністратор кластера: відповідає за налаштування кластерів і вузлів, підключення пристроїв, установку драйверів та подібні завдання. Щоб використовувати DRA, адміністратори кластерів виконують такі дії:
- Підключають пристрої до вузлів.
- Встановлюють драйвери пристроїв, які підтримують DRA.
- За бажанням створюють DeviceClasses, які оператори робочих навантажень можуть використовувати для заявки на пристрої.
Оператор робочих навантажень: відповідає за розгортання та управління робочими навантаженнями в кластері. Щоб використовувати DRA для виділення пристроїв для Podʼів, оператори робочих навантажень виконують такі дії:
- Створюють ResourceClaims або ResourceClaimTemplates, щоб запитати конкретні конфігурації в межах DeviceClasses.
- Розгортають робочі навантаження, які використовують конкретні ResourceClaims або ResourceClaimTemplates.
Обмеження
- Планувальник Kubernetes не підтримує витіснення для ресурсів DRA. Це означає, що наявний Pod, який працює на вузлі і використовує ресурси DRA, не може бути витіснений Podʼом з вищим пріоритетом, який також потребує ресурси DRA. Pod з високим пріоритетом залишатиметься в стані очікування, поки пристрій не стане доступним, що відбувається, коли конфліктуючий Pod завершує роботу або видаляється вручну.
Що далі
1 - Обʼєкти API DRA
Ця сторінка описує види API Kubernetes, які динамічне виділення ресурсів (DRA) використовує для категоризації, запиту та виділення пристроїв.
Термінологія DRA
DRA використовує такі види API Kubernetes для забезпечення основної функціональності виділення ресурсів. Усі ці види API включені вгрупу API resource.k8s.io/v1 .
- DeviceClass
- Визначає категорію пристроїв, які можуть бути запитані, і те, як вибрати конкретні атрибути пристроїв у заявках. Параметри DeviceClass можуть дорівнювати нулю або більше пристроїв у ResourceSlices. Щоб запитувати пристрої з DeviceClass, ResourceClaims вибирають певні атрибути пристрою.
- ResourceClaim
- Описує запити на доступ до приєднаних ресурсів, таких як пристрої, у кластері. Вимоги до ресурсу надають Podʼам доступ до певного ресурсу. ResourceClaims можуть створюватися операторами робочого навантаження або генеруватися Kubernetes на основі шаблону ResourceClaimTemplate.
- ResourceClaimTemplate
- Визначає шаблон, який Kubernetes використовує для створення запитів на ресурси (ResourceClaims) для робочого навантаження. Шаблони ResourceClaimTemplates надають Podʼам доступ до окремих схожих ресурсів. Кожний запит ресурсу, який Kubernetes генерує на основі шаблону, привʼязується до певного Podʼа. Коли Pod завершує роботу, Kubernetes видаляє відповідну заявку на ресурс.
- ResourceSlice
- Представляє собою один або декілька ресурсів, приєднаних до вузлів, таких як пристрої. Драйвери створюють розділи ресурсу і керують ними у кластері. Коли ResourceClaim створюється і використовується у Podʼі, Kubernetes використовує ResourceSlices для пошуку вузлів, які мають доступ до заявлених ресурсів. Kubernetes виділяє ресурси для ResourceClaim і планує роботу Podʼа на вузлі, який може отримати доступ до ресурсів.
DeviceClass
DeviceClass дозволяє адміністраторам кластера або драйверам пристроїв визначати категорії пристроїв у кластері. Класи пристроїв вказують операторам, які пристрої вони можуть запитувати і як вони можуть запитувати ці пристрої. Ви можете використовувати загальну мову виразів (CEL) для вибору пристроїв на основі певних атрибутів. ResourceClaim, яка посилається на DeviceClass, може потім запитувати певні конфігурації в межах DeviceClass.
Щоб створити DeviceClass, див. Налаштування DRA у кластері.
ResourceClaims та ResourceClaimTemplates
ResourceClaim визначає ресурси, які потрібні робочому навантаженню. Кожен ResourceClaim має запити (requests), які посилаються на DeviceClass і вибирають пристрої з цього DeviceClass. ResourceClaims також можуть використовувати селектори (selectors) для фільтрації пристроїв, які відповідають певним вимогам, і можуть використовувати обмеження (constraints) для обмеження пристроїв, які можуть задовольнити запит. ResourceClaims можуть створюватися операторами робочого навантаження або генеруватися Kubernetes на основі шаблону ResourceClaimTemplate. Шаблон ResourceClaimTemplate визначає шаблон, який Kubernetes може використовувати для автоматичного створення ResourceClaims для Podʼів.
Використання ResourceClaims та ResourceClaimTemplates
Метод, який ви використовуєте, залежить від ваших вимог, як показано нижче:
- ResourceClaim: ви хочете, щоб кілька Podʼів мали спільний доступ до певних пристроїв. Ви вручну керуєте життєвим циклом ResourceClaims, які створюєте.
- ResourceClaimTemplate: ви хочете, щоб Podʼи мали незалежний доступ до окремих, схожих за конфігурацією пристроїв. Kubernetes генерує ResourceClaims з специфікації в ResourceClaimTemplate. Тривалість кожного згенерованого ResourceClaim привʼязується до тривалості існування відповідного Podʼа.
- PodGroup ResourceClaimTemplate: ви хочете, щоб PodGroups мали незалежний доступ до окремих, схожих за конфігурацією пристроїв, які можуть бути спільно використані їхніми Podʼами. Kubernetes генерує один ResourceClaim для PodGroup з специфікації в ResourceClaimTemplate. Тривалість кожного згенерованого ResourceClaim привʼязується до тривалості існування відповідного PodGroup. Це вимагає, щоб функція
DRAWorkloadResourceClaims була увімкнена.
Коли ви визначаєте робоче навантаження, ви можете використовувати Загальну мову виразів (CEL) для фільтрації за конкретними атрибутами пристроїв або ємністю. Доступні параметри для фільтрації залежать від пристрою та драйверів.
Якщо ви безпосередньо посилаєтеся на конкретний ResourceClaim у Pod, цей ResourceClaim повинен вже існувати в тому ж просторі імен, що й Pod. Якщо ResourceClaim не існує в просторі імен, Pod не буде заплановано. Ця поведінка подібна до того, як PersistentVolumeClaim повинен існувати в тому ж просторі імен, що й Pod, який посилається на нього.
Ви можете посилатися на автоматично згенерований ResourceClaim у Podʼі, але це не рекомендується, оскільки автоматично згенеровані ResourceClaims привʼязані до тривалості існування Podʼа або PodGroup, який викликав генерацію.
Щоб дізнатися, як запитувати ресурси за допомогою одного з цих методів, див. Виділення пристроїв для робочих навантажень з DRA.
Список пріоритетів
Стан функціоналу:
Stable починаючи з Kubernetes v1.36; стандартно увімкнено
Докладніше про цей функціонал
Це стабільна функція в , яка загальнодоступна починаючи з версії 1.36. Вперше вона зʼявилась у випуску v1.33.
Ви можете надати список пріоритетів підзапитів для запитів у ResourceClaim або ResourceClaimTemplate. Планувальник вибере перший підзапит, який можна виконати. Це дозволяє користувачам вказувати альтернативні пристрої, які можуть бути використані робочим навантаженням, якщо первинний вибір недоступний.
У наведеному нижче прикладі ResourceClaimTemplate запитує пристрій з кольором чорний і розміром великий. Якщо пристрій з цими атрибутами недоступний, Pod не може бути заплановано. Завдяки функції списку пріоритетів можна вказати другий варіант, який запитує два пристрої з кольором білий і розміром малий. Великий чорний пристрій буде наданий, якщо він доступний. Якщо ні, але два маленькі білі пристрої доступні, Pod все ще зможе працювати.
apiVersion: resource.k8s.io/v1
kind: ResourceClaimTemplate
metadata:
name: prioritized-list-claim-template
spec:
spec:
devices:
requests:
- name: req-0
firstAvailable:
- name: large-black
deviceClassName: resource.example.com
selectors:
- cel:
expression: |-
device.attributes["resource-driver.example.com"].color == "black" &&
device.attributes["resource-driver.example.com"].size == "large"
- name: small-white
deviceClassName: resource.example.com
selectors:
- cel:
expression: |-
device.attributes["resource-driver.example.com"].color == "white" &&
device.attributes["resource-driver.example.com"].size == "small"
count: 2
Якщо под відповідає вимогам для декількох вузлів у кластері, планувальник використовуватиме індекс обраних субзапитів із будь-яких пріоритетних списків як один із вхідних параметрів під час оцінки кожного вузла. Отже, вузли, які можуть виділити пристрої, запитувані в субзапиті з вищим рейтингом, мають більшу ймовірність бути обраними, ніж вузли, які можуть виділити пристрої лише для субзапитів з нижчим рейтингом.
Рішення приймається для кожного Podʼа окремо, тому якщо Pod є членом ReplicaSet або подібної групи, ви не можете розраховувати на те, що всі члени групи матимуть однаковий субзапит. Ваше навантаження повинно бути здатним пристосуватися до цього.
Workload ResourceClaims
Стан функціоналу:
Beta починаючи з Kubernetes v1.37; стандартно вимкнено
Коли ви організовуєте Podʼи за допомогою Workload API, ви можете резервувати ResourceClaims для цілих PodGroups замість окремих Podʼів і генерувати ResourceClaimTemplates для PodGroup замість одного Podʼа, що дозволяє Podʼам у PodGroup спільно використовувати доступ до пристроїв, виділених для згенерованого ResourceClaim.
Ця функція вирішує дві проблеми:
- Список
status.reservedFor API ResourceClaim може містити лише 256 елементів. Оскільки kube-scheduler записує в цей список лише окремі Podʼи, лише 256 Podʼів можуть спільно використовувати один ResourceClaim. Завдяки можливості запису PodGroups у status.reservedFor, ResourceClaim можуть спільно використовувати значно більше ніж 256 Podʼів. - Podʼи можуть спільно використовувати ResourceClaim лише тоді, коли відома його точна назва. Для складних робочих навантажень, що реплікують групи Podʼів, ResourceClaims, якими спільно користуються Podʼи в кожній групі, потрібно створювати та видаляти явно, коли набір груп масштабується вгору та вниз. Генеруючи ResourceClaims для кожної PodGroup, один ResourceClaimTemplate може стати основою для ResourceClaims, які автоматично реплікуються та можуть спільно використовуватися Podʼами у PodGroup.
API PodGroup визначає поле spec.resourceClaims з такою самою структурою та подібним значенням, як і поле spec.resourceClaims в API Pod:
apiVersion: scheduling.k8s.io/v1beta1
kind: PodGroup
metadata:
name: training-group
namespace: some-ns
spec:
...
resourceClaims:
- name: pg-claim
resourceClaimName: my-pg-claim
- name: pg-claim-template
resourceClaimTemplateName: my-pg-template
Як і заявки, зроблені Podʼами, заявки для PodGroup, що визначають resourceClaimName, посилаються на ResourceClaim за іменем. Заявки, що визначають resourceClaimTemplateName, посилаються на ResourceClaimTemplate, який реплікується в один ResourceClaim для всієї PodGroup, який може бути спільно використаний її Podʼами.
Коли Pod визначає заявку з name, resourceClaimName та resourceClaimTemplateName, які всі збігаються з однією з spec.resourceClaims його PodGroup, kube-scheduler резервує ResourceClaim для PodGroup замість Podʼа. Якщо заявка Podʼа не збігається з жодною заявкою його PodGroup, kube-scheduler резервує ResourceClaim для Podʼа. У будь-якому випадку резервування записується в status.reservedFor ResourceClaim. Резервування PodGroup та відповідне виділення ресурсів зберігаються в ResourceClaim до видалення PodGroup, навіть якщо група більше не має Podʼа.
Коли заявка Podʼа, що збігається з заявкою PodGroup, визначає resourceClaimTemplateName, тоді для PodGroup генерується один ResourceClaim. Інші Podʼи в групі, які визначають ту ж саму заявку, будуть використовувати цей згенерований ResourceClaim замість того, щоб створювати новий ResourceClaim для кожного Podʼа. Незалежно від того, чи збігається заявка resourceClaimTemplateName з заявкою PodGroup, імʼя згенерованого ResourceClaim записується в status.resourceClaimStatuses Podʼа.
Заявка PodGroup, що збігається з ResourceClaimTemplate, спонукає до створення ResourceClaim лише тоді, коли увімкнено функцію DRAWorkloadResourceClaims. Замість створення окремих ResourceClaims для кожного Podʼа, коли функцію вимкнено, жоден ResourceClaim не створюється, щоб запобігти створенню помилкових окремих ResourceClaims під час оновлень кластера або розгортань/відкатів функції між kube-apiserver та kube-controller-manager.
ResourceClaims, згенеровані з ResourceClaimTemplate для PodGroup, слідують життєвому циклу PodGroup. ResourceClaim створюється, коли існують як PodGroup, так і його ResourceClaimTemplate. ResourceClaim видаляється після видалення PodGroup і коли ResourceClaim більше не зарезервований.
Розглянемо наступний приклад:
apiVersion: scheduling.k8s.io/v1beta1
kind: PodGroup
metadata:
name: training-group
namespace: some-ns
spec:
...
resourceClaims:
- name: pg-claim
resourceClaimName: my-pg-claim
- name: pg-claim-template
resourceClaimTemplateName: my-pg-template
---
apiVersion: v1
kind: Pod
metadata:
name: training-group-pod-1
namespace: some-ns
spec:
...
schedulingGroup:
podGroupName: training-group
resourceClaims:
- name: pod-claim
resourceClaimName: my-pod-claim
- name: pod-claim-template
resourceClaimTemplateName: my-pod-template
- name: pg-claim
resourceClaimName: my-pg-claim
- name: pg-claim-template
resourceClaimTemplateName: my-pg-template
У цьому прикладі PodGroup training-group має один Pod на імʼя training-group-pod-1. Заявки Podʼа pod-claim та pod-claim-template не збігаються з жодною заявкою PodGroup, тому ці заявки не впливають на PodGroup: ResourceClaim my-pod-claim стає зарезервованим для Podʼа, а ResourceClaim, згенерований з ResourceClaimTemplate my-pod-template, також стає зарезервованим для Podʼа. Заявки pg-claim та pg-claim-template збігаються з заявками PodGroup. ResourceClaim my-pg-claim стає зарезервованим для PodGroup, а ResourceClaim, згенерований з ResourceClaimTemplate my-pg-template, також стає зарезервованим для PodGroup.
Повʼязування ResourceClaims з ресурсами Workload API контролюється функціональною можливістю DRAWorkloadResourceClaims у kube-apiserver, kube-controller-manager, kube-scheduler та kubelet.
ResourceSlice
Кожен ResourceSlice представляє один або декілька пристроїв у пулі. Пулом керує драйвер пристрою, який створює та керує ResourceSlices. Ресурси у пулі можуть бути представлені одним ResourceSlice або охоплювати декілька ResourceSlice.
ResourceSlices надають корисну інформацію користувачам пристроїв і планувальнику, а також мають вирішальне значення для динамічного розподілу ресурсів. Кожен ResourceSlice повинен містити наступну інформацію:
- Resource pool: група з одного або декількох ресурсів, якими керує драйвер. Пул може охоплювати більше ніж один ResourceSlice. Зміни в ресурсах пулу повинні бути поширені на всі ResourceSlices у цьому пулі. Драйвер пристрою, який керує пулом, відповідає за забезпечення цього.
- Devices: пристрої в керованому пулі. ResourceSlice може перераховувати кожен пристрій у пулі або підмножину пристроїв у пулі. ResourceSlice визначає інформацію про пристрій, таку як атрибути, версії та ємність. Користувачі пристроїв можуть вибирати пристрої для виділення, фільтруючи за інформацією про пристрої в ResourceClaims або в DeviceClasses.
- Nodes: вузли, які можуть отримувати доступ до ресурсів. Драйвери можуть вибирати, які вузли можуть отримувати доступ до ресурсів, чи це всі вузли в кластері, один названий вузол або вузли, які мають специфічні мітки вузлів.
Драйвери використовують контролер для узгодження ResourceSlices у кластері з інформацією, яку має опублікувати драйвер. Цей контролер перезаписує будь-які ручні зміни, такі як створення або модифікація ResourceSlices користувачами кластера.
Розгляньте наступний приклад ResourceSlice:
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: cat-slice
spec:
driver: "resource-driver.example.com"
pool:
generation: 1
name: "black-cat-pool"
resourceSliceCount: 1
# Поле allNodes визначає, чи може будь-який вузол кластера отримати доступ до пристрою.
allNodes: true
devices:
- name: "large-black-cat"
attributes:
color:
string: "black"
size:
string: "large"
cat:
bool: true
Цим ResourceSlice керує драйвер resource-driver.example.com у пулі black-cat-pool. Поле allNodes: true вказує на те, що будь-який вузол кластера може отримати доступ до пристроїв. У ResourceSlice є один пристрій на імʼя large-black-cat з наступними атрибутами:
color: blacksize: largecat: true
DeviceClass може вибрати цей ResourceSlice за допомогою цих атрибутів, а ResourceClaim може відфільтрувати певні пристрої у цьому DeviceClass.
Іменування та пріоритизація
Порядок, у якому планувальник Kubernetes оцінює пристрої для виділення, визначається лексикографічним сортуванням імен ResourceSlice та пулів ресурсів. Планувальник використовує стратегію першого підходящого варіанту, що означає, що він вибирає перший доступний пристрій, який задовольняє вимоги заявки.
Це дозволяє впливати на пріоритет розподілу ресурсів за допомогою імен, призначених пулам та ResourceSlices. Зверніть увагу, що пули без умов привʼязки завжди оцінюються перед тими, що мають умови привʼязки, незалежно від їхніх імен.
Для драйверів, створених за допомогою пакунка Go k8s.io/dynamic-resources/kubeletplugin або контролера ResourceSlice з цього модуля, ці компоненти автоматично обробляють назви ResourceSlice, щоб забезпечити їх оцінку в порядку, визначеному драйвером.
Адміністративний доступ
Стан функціоналу:
Stable починаючи з Kubernetes v1.36; стандартно увімкнено
Докладніше про цей функціонал
Це стабільна функція в , яка загальнодоступна починаючи з версії 1.36. Вперше вона зʼявилась у випуску v1.32.
Ви можете позначити запит у ResourceClaim або ResourceClaimTemplate як такий, що має привілейовані можливості для завдань обслуговування та усунення несправностей. Запит з правами адміністратора надає доступ до пристроїв, які використовуються, і може увімкнути додаткові дозволи, якщо зробити пристрій доступним у контейнері:
apiVersion: resource.k8s.io/v1
kind: ResourceClaimTemplate
metadata:
name: large-black-cat-claim-template
spec:
spec:
devices:
requests:
- name: req-0
exactly:
deviceClassName: resource.example.com
allocationMode: All
adminAccess: true
Доступ адміністратора є привілейованим режимом, і його не слід надавати звичайним користувачам у кластерах з багатокористувацькою архітектурою. Поле adminAccess можуть використовувати лише ті користувачі, які мають дозвіл на створення обʼєктів ResourceClaim або ResourceClaimTemplate у просторах імен, позначених тегом resource.kubernetes.io/admin-access: "true" (з урахуванням регістру). Це гарантує, що користувачі, які не є адміністраторами, не зможуть зловживати цією функцією.
Доступ адміністратора контролюється функціональною можливістю DRAAdminAccess у kube-apiserver, kube-scheduler та kubelet.
Атрибути типу список
Стан функціоналу:
Alpha починаючи з Kubernetes v1.36; стандартно вимкнено
Ця функція покращує API ResourceSlice, дозволяючи драйверам DRA вказувати значення списків для атрибутів пристроїв замість лише скалярних значень. Це корисно для моделювання більш складних внутрішніх топологій вузлів, наприклад, коли CPU має суміжність з кількома коренями PCIe.
Для авторів ResourceClaim (кінцевих користувачів) це означає, що matchAttribute та distinctAttribute працюють краще для цих випадків.
matchAttribute — два атрибути повинні мати непорожній перетин списків, а не бути ідентичними (скалярні значення розглядаються як списки з одним елементом). Це означає, що якщо один драйвер публікує одне значення, наприклад, для кореня PCIe, а інший драйвер публікує список, обмеження виконується, якщо одне значення зʼявляється десь у списку.distinctAttribute — значення атрибутів повинні бути попарно незʼєднаними (жодне значення не є спільним між будь-якими двома пристроями)
Щоб допомогти авторам ResourceClaim використовувати атрибути, які можуть бути списками, у виразах CEL, ця функція також запроваджує функцію CEL includes().
# Scalar attribute (backward compatible)
# assume: device.attributes["dra.example.com"].model = "model-a"
device.attributes["dra.example.com"].model.includes("model-a") # true
device.attributes["dra.example.com"].model.includes("model-b") # false
# List-type attribute (requires DRAListTypeAttributes)
# assume: device.attributes["dra.example.com"].supported-models= ["model-a", "model-b"]
device.attributes["dra.example.com"].supported-models.includes("model-a") # true
device.attributes["dra.example.com"].supported-models.includes("model-c") # false
Деталі для авторів драйверів DRA
Зазвичай кожен DeviceAttribute містить точно одне скалярне значення: булеве, ціле число, рядок або рядок семантичної версії. Функція DRAListTypeAttributes розширює DeviceAttribute чотирма полями типу список, дозволяючи пристрою рекламувати кілька значень для одного атрибута:
bools — список булевих значеньints — список 64-бітних цілих чиселstrings — список рядків (кожен не більше 64 символів)versions — список рядків семантичних версій відповідно до специфікації semver.org 2.0.0 (кожен не більше 64 символів)
Загальна кількість окремих значень атрибутів на пристрій (скалярні поля плюс всі елементи списків разом) обмежена 48. Коли будь-який пристрій у ResourceSlice використовує цю функцію або інші розширені функції, такі як taints, ResourceSlice буде обмежений максимум 64 пристроями. Використовуйте атрибути типу список або інші розширені функції, такі як taints.
Ось приклад пристрою, який оголошує кілька підтримуваних моделей за допомогою атрибута рядка типу список:
kind: ResourceSlice
apiVersion: resource.k8s.io/v1
metadata:
name: example-resourceslice
spec:
nodeName: worker-1
pool:
name: pool
generation: 1
resourceSliceCount: 1
driver: dra.example.com
devices:
- name: gpu-0
attributes:
dra.example.com/supported-models:
strings:
- model-a
- model-b
Атрибути типу список контролюються функціональною можливістю DRAListTypeAttributes у kube-apiserver та kube-scheduler.
Похідні атрибути
Стан функціоналу:
Alpha починаючи з Kubernetes v1.37; стандартно вимкнено
Обмеження matchAttribute та distinctAttribute зазвичай вимагають, щоб пристрої публікували атрибути під точно такою ж назвою. Якщо драйвер GPU публікує pcie_locality, а драйвер NIC публікує pcie_root (або вбудовує ту саму інформацію в рядок на зразок numa0-pcie1), планувальник не має способу розпізнати, що вони представляють одне й те саме, тому пристрої від двох драйверів не можуть бути розміщені разом без попередньої домовленості про спільну назву атрибута.
derivedAttributes дозволяє вам подолати цю прогалину безпосередньо, не чекаючи, поки драйвери стандартизують спільні назви атрибутів. Додайте один або кілька записів derivedAttributes до запиту, у .spec.devices.requests[].exactly або .spec.devices.requests[].firstAvailable[]. Кожен запис визначає вираз CEL, який планувальник обчислює для кожного кандидата пристрою для цього запиту. Результат стає віртуальним атрибутом, на який можна посилатися з обмеження matchAttribute або distinctAttribute точно так само, як на атрибут пристрою, наданий драйвером.
apiVersion: resource.k8s.io/v1
kind: ResourceClaim
metadata:
name: gpu-nic-numa-alignment
spec:
devices:
requests:
- name: gpu
exactly:
deviceClassName: gpu.example.com
count: 1
derivedAttributes:
- name: derived/numa
expression: device.attributes["gpu.example.com"].numa
- name: nic
exactly:
deviceClassName: nic.example.com
count: 1
derivedAttributes:
- name: derived/numa
expression: device.attributes["nic.example.com"].numaNode
constraints:
- requests: ["gpu", "nic"]
matchAttribute: derived/numa
У цьому прикладі драйвери gpu та nic публікують інформацію про топологію під різними назвами атрибутів (numa та numaNode). Кожен запит обчислює спільне значення derived/numa з атрибутів власного пристрою, а обмеження matchAttribute вирівнює два запити за цим віртуальним атрибутом, навіть якщо базові драйвери ніколи не домовлялися про спільну назву атрибута.
Кілька речей, які варто знати про derivedAttributes:
- Іменування:
name має бути DNS-піддоменом, за яким слідує / та C-ідентифікатор, у тому ж форматі, що використовується для назв атрибутів, наданих драйвером (наприклад, example.com/numaNode або derived/numaNode). Якщо назва збігається з атрибутом, вже опублікованим драйвером, значення похідного атрибута затінює надане драйвером для зіставлення обмежень. Використовуйте префікс домену, який жоден драйвер не використовуватиме, наприклад derived/, якщо ви хочете уникнути ненавмисного затінення. Ви можете визначити до 32 похідних атрибутів на запит. - Повинен використовуватися обмеженням: кожен похідний атрибут повинен бути згаданий принаймні в одному обмеженні
matchAttribute або distinctAttribute, яке застосовується до запиту (або підзапиту), що його визначає. Інакше ResourceClaim не пройде перевірку. - Область та порядок обчислення:
expression обчислюється один раз для кожного кандидата пристрою, після того як власні селектори CEL запиту (.selectors[].cel) вже відфільтрували цей пристрій. Як результат, похідні атрибути не можуть бути використані у виразах селекторів і не доступні через device.attributes у середовищі CEL. - Тип результату:
expression має обчислюватися до скалярного значення (string, int, bool або семантичної версії) або, коли також увімкнено функціональну можливість DRAListTypeAttributes, до списку одного з цих скалярних типів. - Обмеження вартості: кожен вираз має максимальну довжину та обмеження на оцінену вартість обчислення CEL. Крім того, сукупна оцінена вартість усіх виразів
derivedAttributes у ResourceClaim також обмежена, щоб обмежити загальні накладні витрати, додані до однієї спроби планування. ResourceClaim відхиляється, якщо будь-яке з цих обмежень перевищено. - Помилки виконання переривають планування: якщо обчислення виразу завершується помилкою для кандидата пристрою, наприклад, тому що він посилається на атрибут, якого цей пристрій не має, планувальник перериває виділення, і Pod не може бути запланований, замість того щоб мовчки пропустити цей пристрій. Пишіть вирази обережно, наприклад, перевіряючи, що атрибут існує, перед його читанням.
Похідні атрибути контролюються функціональною можливістю DRADerivedAttributes у kube-apiserver та kube-scheduler.
Список стандартних атрибутів пристроїв, які можуть публікувати драйвери DRA, див. у довіднику Стандартні атрибути пристроїв.
Розширене виділення ресурсів за допомогою DRA
Стан функціоналу:
Stable починаючи з Kubernetes v1.37; стандартно увімкнено
Докладніше про цей функціонал
Це стабільна функція в , яка загальнодоступна починаючи з версії 1.37. Вперше вона зʼявилась у випуску v1.34.
Ви можете надати імʼя розширеного ресурсу для класу пристрою. Планувальник тоді вибере пристрої, які відповідають класу для запитів розширених ресурсів. Це дозволяє користувачам продовжувати використовувати запити розширених ресурсів у Podʼі для запиту або розширених ресурсів, наданих втулком пристрою, або пристроїв DRA. Той самий розширений ресурс може бути наданий або втулком пристрою, або DRA на одному єдиному вузлі кластера. Той самий розширений ресурс може бути наданий втулком пристрою на деяких вузлах, а DRA на інших вузлах у тому ж кластері.
У наведеному нижче прикладі класу пристрою надано extendedResourceName example.com/gpu. Якщо Pod запитує розширений ресурс example.com/gpu: 2, його можна запланувати на вузол з двома або більше пристроями, які відповідають класу пристрою.
apiVersion: resource.k8s.io/v1
kind: DeviceClass
metadata:
name: gpu.example.com
spec:
selectors:
- cel:
expression: device.driver == 'gpu.example.com' && device.attributes['gpu.example.com'].type
== 'gpu'
extendedResourceName: example.com/gpu
На додачу, користувачі можуть використовувати спеціальний розширений ресурс для виділення пристроїв без необхідності явно створювати ResourceClaim. Використовуючи префікс імені розширеного ресурсу deviceclass.resource.kubernetes.io/ та імʼя DeviceClass. Це працює для будь-якого DeviceClass, навіть якщо він не вказує на імʼя розширеного ресурсу. Кінцевий ResourceClaim міститиме запит на ExactCount вказаної кількості пристроїв цього DeviceClass.
Розширене виділення ресурсів DRA контролюється функціональною можливістю DRAExtendedResource у kube-apiserver, kube-scheduler, kube-controller-manager та kubelet.
Для практичного ознайомлення із запитом розширених ресурсів див. Призначення розширених ресурсів контейнеру.
2 - Як працює DRA
Ця сторінка описує, як Kubernetes виділяє пристрої робочим навантаженням за допомогою динамічного виділення ресурсів (DRA) і як попередньо заплановані Podʼи взаємодіють з цим процесом.
Як працює розподіл ресурсів з DRA
Наступні розділи описують робочий процес для різних типів користувачів DRA та для системи Kubernetes під час динамічного розподілу ресурсів.
Робочий процес для користувачів
- Створення драйвера: власники пристроїв або сторонні організації створюють драйвери, які можуть створювати та керувати ResourceSlices у кластері. Ці драйвери за бажанням також створюють DeviceClasses, які визначають категорію пристроїв та як їх запитувати.
- Конфігурація кластера: адміністратори кластера створюють кластери, підключають пристрої до вузлів і встановлюють драйвери пристроїв DRA. Адміністратори кластера за бажанням створюють DeviceClasses, які визначають категорії пристроїв та як їх запитувати.
- Запити на ресурси: оператори навантаження створюють ResourceClaimTemplates або ResourceClaims, які запитують конкретні конфігурації пристроїв у межах DeviceClass. На тому ж етапі оператори навантаження модифікують свої Kubernetes маніфести, щоб запитувати ці ResourceClaimTemplates або ResourceClaims.
Робочий процес для Kubernetes
Створення ResourceSlice: драйвери в кластері створюють ResourceSlices, які представляють один або кілька пристроїв у керованому пулі подібних пристроїв.
Створення навантаження: панель управління кластера перевіряє нові навантаження на наявність посилань на ResourceClaimTemplates або на конкретні ResourceClaims.
- Якщо навантаження використовує ResourceClaimTemplate, контролер з імʼям
resourceclaim-controller генерує ResourceClaims у навантаженні. - Якщо навантаження використовує конкретний ResourceClaim, Kubernetes перевіряє, чи існує цей ResourceClaim у кластері. Якщо ResourceClaim не існує, Podʼи не будуть розгорнуті.
Фільтрація ResourceSlice: для кожного Podʼа Kubernetes перевіряє ResourceSlices у кластері, щоб знайти пристрій, який задовольняє всі наступні критерії:
- Вузли, які можуть отримати доступ до ресурсів, мають право запускати Pod.
- ResourceSlice має нерозподілені ресурси, які відповідають вимогам ResourceClaim Podʼа.
Виділення ресурсів: після знаходження відповідного ResourceSlice для ResourceClaim Podʼа, планувальник Kubernetes оновлює ResourceClaim з деталями виділення ресурсів. Планувальник використовує стратегію першого підходящого варіанту та оцінює пули та ResourceSlices у лексикографічному порядку за їхніми іменами. Драйвери можуть пріоритизувати конкретні slices або пули, відповідно називаючи їх. Для отримання додаткової інформації див. Іменування та пріоритизація.
Планування Podʼів: коли виділення ресурсів завершено, планувальник розміщує Podʼи на вузлі, який може отримати доступ до виділеного ресурсу. Драйвер пристрою та kubelet на цьому вузлі координуються через gRPC, щоб налаштувати пристрій і доступ Podʼа до пристрою, якщо драйвер не оголосив необовʼязкові операції з вузлами для пристроїв, які не потребують локальної підготовки або очищення на вузлі.
Попередньо заплановані Podʼи
Коли ви, або інший клієнт API, створюєте Pod із вже встановленим spec.nodeName, планувальник пропускається. Якщо будь-який ResourceClaim, потрібний для цього Podʼа, ще не існує, не виділений або не зарезервований для Podʼа, то kubelet не зможе запустити Pod і періодично перевірятиме це, оскільки ці вимоги можуть бути задоволені пізніше.
Така ситуація також може виникнути, коли підтримка динамічного виділення ресурсів не була увімкнена в планувальнику на момент планування Podʼа (різниця версій, конфігурація, функціональна можливість і т. д.). kube-controller-manager виявляє це і намагається зробити Pod працюючим, шляхом резервування потрібних ResourceClaims. Однак, це працює лише якщо вони були виділені планувальником для якогось іншого Podʼа.
Краще уникати оминання планувальника, оскільки Pod, який призначений для вузла, блокує нормальні ресурси (памʼять, CPU), які потім не можуть бути використані для інших Podʼів, поки Pod застряг. Щоб запустити Pod на певному вузлі, при цьому проходячи через звичайний потік планування, створіть Pod із селектором вузла, який точно відповідає бажаному вузлу:
apiVersion: v1
kind: Pod
metadata:
name: pod-with-cats
spec:
nodeSelector:
kubernetes.io/hostname: name-of-the-intended-node
...
Можливо, ви також зможете змінити вхідний Pod під час допуску, щоб скасувати поле .spec.nodeName і використовувати селектор вузла замість цього.
Умови привʼязки пристрою
Стан функціоналу:
Beta починаючи з Kubernetes v1.36; стандартно увімкнено
Умови привʼязки пристрою дозволяють планувальнику Kubernetes затримувати привʼязку Podʼа до тих пір, поки зовнішні ресурси, такі як GPU з підключенням до фабрики або перепрограмовані FPGA, не будуть підтверджені як готові.
Ця поведінка очікування реалізована в фазі PreBind фреймворку планування. Під час цієї фази планувальник перевіряє, чи всі необхідні умови пристрою є виконаними, перш ніж продовжити з привʼязкою.
Це покращує надійність планування, уникаючи передчасної привʼязки, і дозволяє координацію з зовнішніми контролерами пристроїв.
Щоб використовувати цю функцію, драйвери пристроїв (зазвичай керовані власниками драйверів) повинні опублікувати наступні поля в розділі Device ResourceSlice. Адміністратори кластерів повинні увімкнути функціональні можливості DRADeviceBindingConditions і DRAResourceClaimDeviceStatus, щоб планувальник міг враховувати ці поля.
bindingConditions- Список типів станів, які повинні бути встановлені в True (у полі
.status.conditions асоційованого ResourceClaim), перш ніж Pod може бути привʼязаний. Ці стани зазвичай представляють сигнали готовності, такі як DeviceAttached або DeviceInitialized. bindingFailureConditions- Список типів станів, які, якщо встановлені в True у полі status.conditions асоційованого ResourceClaim, вказують на стан збою. Якщо будь-який з цих станів є True, планувальник скасує привʼязку та перенаправить Pod.
bindsToNode- якщо встановлено в
true, планувальник записує вибране імʼя вузла в полі status.allocation.nodeSelector асоційованого ResourceClaim. Це не впливає на spec.nodeSelector Podʼа. Натомість він встановлює селектор вузла всередині ResourceClaim, який зовнішні контролери можуть використовувати для виконання специфічних для вузла операцій, таких як підключення або підготовка пристроїв.
Усі типи станів, перераховані в bindingConditions і bindingFailureConditions, оцінюються з поля status.conditions асоційованого ResourceClaim. Зовнішні контролери відповідають за оновлення цих станів, використовуючи стандартну семантику станів Kubernetes (type, status, reason, message, lastTransitionTime).
Планувальник чекає до 600 секунд (стандартно), щоб усі bindingConditions стали True. Якщо тайм-аут досягається або будь-які bindingFailureConditions є True, планувальник очищає виділення та перенаправляє Pod. Адміністратор кластера може налаштувати тривалість цього тайм-ауту, редагуючи файл конфігурації kube-scheduler.
Приклад налаштування цього тайм-ауту в KubeSchedulerConfiguration наведено нижче:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: default-scheduler
pluginConfig:
- name: DynamicResources
args:
apiVersion: kubescheduler.config.k8s.io/v1
kind: DynamicResourcesArgs
bindingTimeout: 60s
Приклад
Нижче наведено приклад ResourceSlice, який ви можете побачити в кластері, де використовується драйвер DRA, і цей драйвер підтримує умови привʼязки:
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: gpu-slice-1
spec:
driver: dra.example.com
nodeSelector:
nodeSelectorTerms:
- matchExpressions:
- key: accelerator-type
operator: In
values:
- "high-performance"
pool:
name: gpu-pool
generation: 1
resourceSliceCount: 1
devices:
- name: gpu-1
attributes:
vendor:
string: "example"
model:
string: "example-gpu"
bindsToNode: true
bindingConditions:
- dra.example.com/is-prepared
bindingFailureConditions:
- dra.example.com/preparing-failed
Цей приклад ResourceSlice має такі властивості:
- ResourceSlice націлений на вузли з міткою
accelerator-type=high-performance, щоб планувальник використовував лише певний набір допустимих вузлів. - Планувальник вибирає один вузол з обраної групи (наприклад,
node-3) і встановлює поле status.allocation.nodeSelector в ResourceClaim на це імʼя вузла. - Стан привʼязки
dra.example.com/is-prepared вказує на те, що пристрій gpu-1 повинен бути підготовлений (стан is-prepared має статус True) перед привʼязкою. - Якщо підготовка пристрою
gpu-1 не вдалася (стан preparing-failed має статус True), планувальник скасовує привʼязку. - Планувальник чекає до 600 секунд (стандартно), щоб пристрій став готовим.
- Зовнішні контролери можуть використовувати селектор вузла в ResourceClaim для виконання операцій, специфічних для вузла, на вибраному вузлі.
Стани привʼязки пристроїв контролюються функціональною можливістю DRADeviceBindingConditions у kube-apiserver та kube-scheduler.
Ресурси вузла, доступні для виділення
Стан функціоналу:
Alpha починаючи з Kubernetes v1.36; стандартно вимкнено
Пристрої, що управляються DRA, можуть мати базову конфігурацію, яка складається з ресурсів, що розподіляються на рівні вузлів, таких як cpu, memory або hugepages. Ця функція інтегрує ці запити на основі DRA у стандартний розрахунок планувальника поряд зі звичайними запитами spec Podʼа на ці ресурси.
Драйвери DRA визначають, як пристрої споживають ресурси вузла, доступні для виділення, за допомогою двох різних моделей:
- Пряме зіставлення ресурсів (
mapping): пристрій DRA безпосередньо надає стандартний ресурс вузла (такий як власний пул ядер CPU або блок памʼяті). Розподіл ресурсів безпосередньо відповідає стандартній потужності CPU або памʼяті на вузлі. - Допоміжні накладні витрати пристрою (
overhead): пристрій DRA (такий як GPU або прискорювач) потребує ресурсів хосту (таких як оперативна памʼять хосту) як вторинних накладних витрат для роботи, коли його виділено для Podʼа або контейнера.
Рекомендації для авторів Podʼів
При створенні PodSpec з використанням заявок для цих типів пристроїв слід враховувати кілька моментів:
- Коли використовуються ресурси на рівні Podʼа, планувальник суворо перевіряє їх як для запитів, так і для лімітів контейнерів:
- Сума всіх запитів контейнерів і ресурсів заявок DRA не повинна перевищувати запити на рівні Podʼа; в іншому випадку Pod не зможе бути запланований.
- Ліміт кожного окремого контейнера плюс його виділення DRA не повинні перевищувати ліміти на рівні Podʼа; в іншому випадку Pod не зможе бути запланований.
- Загальна потреба контейнера в ресурсах є сумою його ресурсів на рівні контейнера та будь-яких ресурсів вузла з повʼязаних заявок на ресурс.
- Обмеження спільного використання заявок: заявки, що використовують пряме зіставлення ресурсів (
mapping), не можуть бути спільними між кількома Podʼами. Заявки для пристроїв з overhead можуть підтримувати спільне використання пристроїв, і накладні витрати відстежуються для кожного Podʼа або контейнера окремо. - Podʼи із заявками DRA підтримують зміну розміру на місці для стандартних запитів у
spec. Планувальник забезпечує, щоб змінені стандартні запити разом зі статичними виділеннями DRA все ще вміщувалися на вузлі.
Деталі для авторів драйверів DRA
Драйвери DRA оголошують цю базову конфігурацію ресурсів вузла, доступних для виділення, за допомогою поля nodeAllocatableResources для пристроїв у ResourceSlice. Це визначає перетворення запитуваного пристрою DRA або ємності у стандартні ресурси, які відстежуються у полі status.allocatable вузла (зверніть увагу, що розширені ресурси для цього поля не підтримуються). Це корисно як для драйверів, які безпосередньо надають власні ресурси (наприклад, драйвер DRA для CPU або памʼяті), так і для пристроїв, які потребують допоміжних залежностей від вузла (наприклад, прискорювач, якому потрібна памʼять хоста).
Поле nodeAllocatableResources підтримує два різні випадки використання:
- Зіставлення: використовується, коли пристрій DRA безпосередньо представляє стандартний ресурс (наприклад, драйвер DRA для CPU або памʼяті). Планувальник обчислює точну кількість, масштабуючи ємність за допомогою
capacityMultiplier або масштабуючи кількість пристроїв за допомогою deviceMultiplier. - Накладні витрати: використовується, коли пристрій потребує допоміжних залежностей від вузла (наприклад, памʼять хоста, яку споживає GPU). Це може бути визначено як фіксована вартість
perPod або змінна вартість perContainer, яка масштабується лінійно з кількістю контейнерів, що посилаються на пристрій.
Приклад: драйвер CPU DRA (Зіставлення)
Ось приклад, де драйвер CPU DRA відкриває сокет CPU як пул з 128 CPU, використовуючи споживчу ємність DRA. capacityKey повʼязує споживану ємність cpu.example.com/cpu безпосередньо зі стандартним ресурсом cpu, доступним на вузлі:
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: my-node-cpus
spec:
driver: cpu.example.com
nodeName: my-node
pool:
name: socket-cpus
generation: 1
resourceSliceCount: 1
devices:
- name: socket0cpus
allowMultipleAllocations: true
capacity:
"cpu.example.com/cpu": "128"
nodeAllocatableResources:
mapping:
cpu:
capacityKey: "cpu.example.com/cpu"
- name: socket1cpus
allowMultipleAllocations: true
capacity:
"cpu.example.com/cpu": "128"
nodeAllocatableResources:
mapping:
cpu:
capacityKey: "cpu.example.com/cpu"
capacityMultiplier: 1
Приклад: прискорювач з допоміжними ресурсами (Накладні витрати)
Ось приклад ресурсного слайсу, де прискорювач потребує додаткових 8Gi памʼяті на кожен Pod для функціонування:
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: my-node-xpus
spec:
driver: xpu.example.com
nodeName: my-node
pool:
name: xpu-pool
generation: 1
resourceSliceCount: 1
devices:
- name: xpu-model-x-001
attributes:
example.com/model:
string: "model-x"
nodeAllocatableResources:
overhead:
memory:
perPod: "8Gi"
Після того як Pod було успішно привʼязано до вузла, точні кількості ресурсів вузла, доступних для виділення, виділених через DRA, агрегуються kube-scheduler і вбудовуються безпосередньо у поле status.nodeAllocatableResourceClaimStatuses Podʼа. Це забезпечує чітку, постійну передачу від планувальника до kubelet.
Ключовим моментом є те, що kubelet нативно споживає цей API для ідеального узгодження системних меж:
- cgroups: cgroups Podʼа та контейнерів тепер включатимуть виділення на основі DRA, запобігаючи штучному обмеженню робочих навантажень ядром.
- Оцінки OOM:
kubelet враховує запити памʼяті DRA контейнера у його ефективному запиті памʼяті.
Ресурси вузла, доступні для виділення, є альфа-функцією і вмикаються, коли функціональну можливість DRANodeAllocatableResources увімкнено в kube-apiserver, kube-scheduler та kubelet.
3 - Спостережуваність динамічних ресурсів
Ця сторінка описує, як спостерігати за статусом і справністю ресурсів, які динамічно виділяються за допомогою DRA.
Спостережуваність динамічних ресурсів
Ви можете перевірити статус динамічно виділених ресурсів, використовуючи будь-який із наступних методів:
Метрики пристроїв kubelet
Служба gRPC PodResourcesLister kubelet дозволяє вам контролювати пристрої, що використовуються. Повідомлення DynamicResource надає інформацію, специфічну для динамічного виділення ресурсів, таку як назва пристрою та назва заявки. Детальніше див. Моніторинг ресурсів втулків пристроїв.
Статус пристрою ResourceClaim
Стан функціоналу:
Stable починаючи з Kubernetes v1.37; стандартно увімкнено
Докладніше про цей функціонал
Це стабільна функція в , яка загальнодоступна починаючи з версії 1.37. Вперше вона зʼявилась у випуску v1.32.
Драйвери DRA можуть повідомляти специфічні для драйвера дані статусу пристрою для кожного виділеного пристрою в полі status.devices заявки на ресурс. Наприклад, драйвер може перелічувати IP-адреси, призначені пристрою мережевого інтерфейсу. Оновлення цього поля вимагає спеціальних синтетичних дозволів RBAC, див. Посібник із зміцнення безпеки — динамічний розподіл ресурсів та Посилення безпеки динамічного розподілу ресурсів у вашому кластері.
Точність інформації, яку драйвер додає до поля status.devices заявки на ресурс, залежить від драйвера. Оцінюйте драйвери, щоб вирішити, чи можете ви покладатися на це поле як на єдине джерело інформації про пристрої.
Якщо ви вимкнете функціональну можливість DRAResourceClaimDeviceStatus, поле status.devices автоматично очищається під час зберігання заявки на ресурс. Статус пристрою заявки на ресурс підтримується, коли з боку драйвера DRA можливо оновити наявну заявку на ресурс, у якій встановлено поле status.devices.
У наведеному нижче прикладі поле status.devices заявки на ресурс було заповнено драйвером (resource-driver.example.com), відповідальним за керування виділеним пристроєм:
apiVersion: resource.k8s.io/v1
kind: ResourceClaim
metadata:
name: macvlan-eth0
spec:
...
status:
allocation:
devices:
results:
- device: eth0
driver: resource-driver.example.com
pool: nic-worker-a
request: macvlan-eth0
shareID: 8e7acdf9-0290-4ecd-a801-a654b021d2b7
consumedCapacity:
resource-driver.example.com/bandwidth: 1G
devices:
- conditions:
- lastTransitionTime: "2025-10-21T08:38:17Z"
message: Device successfully allocated and assigned to the pod
reason: NetworkReady
status: "True"
type: NetworkReady
device: eth0
driver: resource-driver.example.com
networkData:
hardwareAddress: 00:01:ec:84:fb:51
interfaceName: net1
ips:
- 10.10.1.2/24
- 2001:db8::1/64
pool: nic-worker-a
shareID: 8e7acdf9-0290-4ecd-a801-a654b021d2b7
Якщо пристрій не було виділено, запит драйвера на оновлення поля status.devices заявки на ресурс із цим пристроєм відхиляється. Коли пристрій вивільняється (видаляється з status.allocation.devices), відповідний запис у status.devices автоматично видаляється.
Детальніше про поле status.devices див. у довіднику API
ResourceClaim.
Моніторинг справності пристроїв
Стан функціоналу:
Beta починаючи з Kubernetes v1.36; стандартно увімкнено
Kubernetes надає механізм для моніторингу та звітування про справність динамічно виділених ресурсів інфраструктури. Для застосунків зі збереженям стану, що працюють на спеціалізованому обладнанні, критично важливо знати, коли пристрій вийшов з ладу або став несправним. Також корисно дізнаватися, чи відновлюється пристрій.
Щоб використовувати цю функціональність, функціональна можливість ResourceHealthStatus ResourceHealthStatus має бути увімкнена (бета та стандартно увімкнена з v1.36), а драйвер DRA має реалізовувати службу gRPC DRAResourceHealth.
Коли драйвер DRA виявляє, що виділений пристрій став несправним, він повідомляє цей статус назад до kubelet. Ця інформація про справність потім безпосередньо відображається в статусі Podʼа. kubelet заповнює поле allocatedResourcesStatus у статусі кожного контейнера, деталізуючи справність кожного пристрою, призначеного цьому контейнеру. Кожен запис про справність ресурсу може містити необовʼязкове поле message з додатковим контекстом, зрозумілим людині, про стан справності, наприклад, деталі помилки або причини збою.
Якщо kubelet не отримує оновлення про справність від драйвера DRA протягом періоду очікування, статус справності пристрою позначається як "Unknown". Драйвери DRA можуть налаштовувати цей період очікування для кожного пристрою окремо, встановлюючи поле health_check_timeout_seconds у повідомленні gRPC DeviceHealth. Якщо не вказано, kubelet використовує стандартний період очікування 30 секунд. Це дозволяє різним типам обладнання (наприклад, GPU, FPGA або пристроям зберігання) використовувати відповідні значення періоду очікування на основі їхніх характеристик звітування про справність.
Це забезпечує критично важливу видимість для користувачів і контролерів, щоб реагувати на збої обладнання. Для Podʼа, який зазнає збою, ви можете перевірити цей статус, щоб визначити, чи був збій повʼязаний із несправним пристроєм.
Примітка:
Статус справності пристрою не оновлюється в статусі Podʼа після завершення роботи Podʼа (наприклад, у стані Failed).Статус пулу ресурсів
Стан функціоналу:
Alpha починаючи з Kubernetes v1.36; стандартно вимкнено
Ви можете запитувати доступність пристроїв у пулах ресурсів за допомогою API ResourcePoolStatusRequest. Це забезпечує видимість того, скільки пристроїв доступно, виділено або недоступно в пулах ресурсів DRA вашого кластера.
Щоб перевірити статус пулу ресурсів:
Створіть ResourcePoolStatusRequest, вказавши назву драйвера (обовʼязково) та, за бажанням, обмеження на кількість повернутих пулів. Ви також можете обмежити його одним пулом, вказавши назву пулу:
apiVersion: resource.k8s.io/v1alpha3
kind: ResourcePoolStatusRequest
metadata:
name: check-gpus
spec:
driver: example.com/gpu
# Optional: filter to a specific pool
# poolName: my-pool
# Optional: limit number of pools returned (default: 100, max: 1000)
# limit: 10
Дочекайтеся, поки контролер обробить запит:
kubectl wait --for=condition=Complete resourcepoolstatusrequest/check-gpus --timeout=30s
Прочитайте статус, щоб побачити доступність пулу:
kubectl get resourcepoolstatusrequest/check-gpus -o yaml
Статус включає:
poolCount: загальна кількість пулів, що відповідають фільтру (може перевищувати кількість перелічених пулів, якщо результат обрізано обмеженням).pools: список деталей пулів, кожен з яких містить:driver та poolName: ідентифікують пул.generation: останнє покоління пулу, яке спостерігалось в ResourceSlices.resourceSliceCount: кількість ResourceSlices, що складають пул.totalDevices: загальна кількість пристроїв у пулі.allocatedDevices: пристрої, наразі виділені заявкам.availableDevices: пристрої, доступні для виділення
(totalDevices - allocatedDevices - unavailableDevices).unavailableDevices: пристрої, недоступні через позначки taint або інші стани.nodeName: вузол, повʼязаний із пулом, якщо такий є.validationError: встановлюється, коли дані пулу не вдалося повністю перевірити (наприклад, під час розгортання покоління). Коли встановлено, поля кількості пристроїв можуть бути невстановленими.partitionSummary: для пулів з пристроями, що розділяються на розділи, можливість виділення за типом розділу (див. Підсумок розділів).shareableSummary: для пулів з пристроями, що можуть спільно використовуватися, сукупне використання ємності (див. Підсумок спільного використання).
conditions: включає типи умов Complete (успіх) або Failed (помилка).
Видаліть запит, коли закінчите:
kubectl delete resourcepoolstatusrequest/check-gpus
Обʼєкти ResourcePoolStatusRequest обробляються один раз контролером у kube-controller-manager. Специфікація є незмінною після створення, а весь обʼєкт стає незмінним після заповнення статусу. Щоб отримати оновлені дані про доступність, видаліть і перестворіть запит. Завершені запити автоматично очищаються через 1 годину.
Ця функція вимагає явних дозволів RBAC на ресурс ResourcePoolStatusRequest. Жодна стандартна ClusterRole не включає цей дозвіл.
Статус пулу ресурсів контролюється функціональною можливістю DRAResourcePoolStatus у kube-apiserver та kube-controller-manager.
Підсумок розділу
Стан функціоналу:
Alpha починаючи з Kubernetes v1.37; стандартно вимкнено
Один фізичний пристрій, такий як GPU, може бути опублікований як кілька типів розділів (наприклад, повний GPU проти половинного розділу MIG), які використовують ті самі спільні лічильники. Оскільки ці розділи конкурують за ту саму базову ємність, проста кількість пристроїв не показує, скільки пристроїв кожного типу ще можна виділити. Для пулів з пристроями, що розділяються на розділи представлення partitionSummary відповідає на це питання. Для кожного типу розділу воно повідомляє:
attribute: повне імʼя атрибута пристрою, значення якого групує цей запис. Це spec.partitionTypeAttribute обʼєкта ResourceSlice або spec.defaultPartitionTypeAttribute запиту, коли розділ не оголошує жодного.type: значення цього атрибута на пристрої (наприклад, Full або Half).total: кількість пристроїв цього типу розділу в пулі.allocatable: скільки додаткових пристроїв цього типу розділу ще можна було б виділити з урахуванням поточного споживання спільних лічильників.
Названий атрибут має бути рядковим атрибутом. Якщо атрибут типу розділу пристрою, що розділяється на розділи, відсутній або не є рядком (наприклад, ціле число, булеве значення або версія), пул повідомляє про помилку перевірки замість підсумку розділів. Немає спеціальної обробки для атрибутів типу список; не-рядковий атрибут просто не є дійсним атрибутом типу розділу.
Щоб створити це представлення, драйвер позначає кожен пристрій, що розділяється на розділи, рядковим атрибутом, значення якого називає тип розділу, і вказує цей атрибут у полі partitionTypeAttribute обʼєкта ResourceSlice:
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
# ...
spec:
# Кожен пристрій, що підтримує розділення на розділи, у цьому сегменті має цей атрибут; пристрої,
# які мають однакове значення, несуть однакові витрати на спільний лічильник.
partitionTypeAttribute: gpu.example.com/profile
Якщо драйвер ще не оновлено для оголошення partitionTypeAttribute, запит все одно може отримати підсумок розділів, вказавши резервний атрибут у своїй специфікації. Власний partitionTypeAttribute розділу завжди має перевагу; стандартне значення на рівні запиту застосовується лише до пристроїв, чий розділ не оголошує його:
apiVersion: resource.k8s.io/v1alpha3
kind: ResourcePoolStatusRequest
metadata:
name: check-gpu-partitions
spec:
driver: gpu.example.com
# Запасний атрибут групування для фрагментів, у яких він не вказаний.
defaultPartitionTypeAttribute: gpu.example.com/profile
Коли ні розділ, ні запит не вказують атрибут, пул з пристроями, що розділяються на розділи, не повідомляє partitionSummary.
Представлення partitionSummary контролюється функціональною можливістю DRAPartitionableDevicesType у kube-apiserver та kube-controller-manager, яка, своєю чергою, вимагає увімкнення функціональних можливостей DRAResourcePoolStatus та DRAPartitionableDevices.
Підсумок спільного використання
Для пулів, що містять пристрої, які можуть спільно використовуватися (пристрої, які встановлюють allowMultipleAllocations і можуть споживатися кількома заявками), shareableSummary повідомляє сукупне використання ємності в межах пулу:
fullyAvailableDevices: пристрої, що можуть спільно використовуватися, з неспожитою ємністю.partiallyAvailableDevices: пристрої, що можуть спільно використовуватися, з частково спожитою ємністю.capacity: для кожної назви ємності сукупні обсяги total, consumed та available (total мінус consumed, ніколи не відʼємне) у межах пулу.
shareableSummary заповнюється лише тоді, коли принаймні один пристрій у пулі може спільно використовуватися. Він є частиною функції статусу пулу ресурсів (функціональна можливість DRAResourcePoolStatus) і не вимагає DRAPartitionableDevicesType; пристрої, що можуть спільно використовуватися, які він підсумовує, походять із функції споживчої ємності.
Стан функціоналу:
Beta починаючи з Kubernetes v1.37
Драйвери DRA можуть надавати метадані пристроїв, такі як атрибути пристроїв (адреси шини PCI або UUID медійованих пристроїв) та мережеву конфігурацію, безпосередньо контейнерам у вигляді JSON-файлів. Це дозволяє застосункам дізнаватися інформацію про виділені пристрої без запитів до API Kubernetes або використання власних контролерів.
KEP-5304 визначає протокол метаданих пристроїв, якого драйвери мають дотримуватися, щоб застосунки бачили узгоджену структуру в різних драйверах і кластерах. Бібліотека втулка kubelet DRA реалізує цей протокол.
Метадані пристроїв підпорядковуються тим самим правилам, що й доступ до пристроїв: вони доступні всередині контейнера лише тоді, коли цей контейнер запитує пристрій. Детальніше див. Запит пристроїв у робочих навантаженнях за допомогою DRA.
Протокол складається з чотирьох правил:
Шляхи до файлів. Файли метаданих розташовані всередині контейнерів у /var/run/kubernetes.io/dra-device-attributes. Для безпосередньо згаданої заявки на ресурс шлях має вигляд resourceclaims/<claimName>/<requestName>/<driverName>-metadata.json. Для заявки, створеної з шаблону заявки на ресурс, шлях має вигляд resourceclaimtemplates/<podClaimName>/<requestName>/<driverName>-metadata.json, де podClaimName — це pod.spec.resourceClaims[].name.
Коли запит використовує список пріоритетів, для сегмента шляху <requestName> використовується лише назва запиту верхнього рівня. Поле requests[].name у файлі містить повне посилання <request>/<subrequest>, наприклад gpu/high-memory.
Константи шляхів визначені в k8s.io/dynamic-resource-allocation/api/metadata.
JSON API. Кожен файл є потоком одного або кількох обʼєктів DeviceMetadata. Кожен обʼєкт має apiVersion та kind, відповідно до домовленостей API Kubernetes. Ті самі метадані кодуються один раз для кожної налаштованої версії API в порядку, вибраному драйвером. Споживачі використовують першу версію, яку вони можуть декодувати, і пропускають невідомі версії. Пошкоджений обʼєкт у відомій версії є помилкою.
Покоління. Початковий файл має metadata.generation, встановлене на 1. Кожне оновлення збільшує покоління, щоб споживачі могли виявляти зміни.
Надання контейнеру. Бібліотека втулка kubelet DRA використовує CDI для bind-mount кожного файлу лише для читання. Інші реалізації можуть використовувати інший механізм, якщо файл зʼявляється за необхідним шляхом і є доступним лише для читання.
Метадані пристроїв — це функція на стороні драйвера. Вона не має функціональної можливості Kubernetes і стандартно вимкнена у бібліотеці втулка kubelet DRA. Драйвер має увімкнути
функцію та явно вибрати версії, які він записує:
kubeletplugin.EnableDeviceMetadata(true, []schema.GroupVersion{
metadatav1beta1.SchemeGroupVersion,
metadatav1alpha1.SchemeGroupVersion,
})
Версія v1beta1 є обовʼязковою. Драйвер також може записувати v1alpha1 для сумісності зі старішими споживачами. Порядок у зрізі є порядком у потоці метаданих; фреймворк не сортує версії. Драйвери мають ставити найновішу версію першою. Увімкнення метаданих пристроїв без версій, без v1beta1 або з невідомою версією призводить до збою втулка під час запуску.
Для кожного підготовленого пристрою драйвер може заповнити Device.Metadata за допомогою kubeletplugin.DeviceMetadata. Драйвери мають включати атрибути, які вони публікують для цього пристрою в його ResourceSlice, щоб робочі навантаження бачили ту саму інформацію під час виконання. Драйвери можуть також включати атрибути, які мають значення лише під час виконання. Для мережевих пристроїв, драйвери можуть додавати назви інтерфейсів, IP-адреси та апаратні адреси після конфігурації CNI, викликаючи UpdateRequestMetadata.
Посилання на API втулка kubelet вище описують інтеграцію для авторів драйверів. Фреймворк DRA не визначає універсального прапора командного рядка, тому оператори кластерів вмикають функцію через конфігурацію розгортання, надану їхнім драйвером.
Коли увімкнено, бібліотека втулка kubelet DRA записує файли метаданих під час підготовки виділених пристроїв. Вона також записує специфікації CDI до /var/run/cdi за замовчуванням. Середовище виконання контейнерів має бути налаштоване на виявлення специфікацій CDI з цього каталогу. Бібліотека визначає мінімальну версію специфікації CDI, необхідну для кожної згенерованої специфікації.
Коли один запит виділяє пристрої від кількох драйверів DRA, кожен драйвер записує власний файл метаданих. Споживачі, які знають назву драйвера, мають побудувати точний шлях із назв заявки, запиту та драйвера. Споживачі Go можуть використовувати ReadResourceClaimMetadata або ReadResourceClaimTemplateMetadata, щоб прочитати та обʼєднати всі файли кожного драйвера для запиту.
Кожен обʼєкт у файлі метаданих відповідає API DeviceMetadata (metadata.resource.k8s.io/v1beta1).
Схема містить:
- Стандартні метадані обʼєкта для заявки на ресурс, включаючи її назву, простір імен, UID та покоління метаданих.
- Необовʼязкове
podClaimName для заявки, згенерованої з шаблону заявки на ресурс. - Список запитів. Кожен запит має обовʼязкову назву та список виділених пристроїв.
- Драйвер, пул та назву для кожного пристрою.
- Необовʼязкові атрибути пристроїв та мережеві дані.
Значення атрибутів використовують те саме представлення, що й атрибути пристроїв ResourceSlice. Кожен атрибут має рівно одне скалярне значення (int, bool, string або version) або значення списку (ints, bools, strings або versions). Значення ємності пристроїв не включаються в метадані пристроїв.
Мережеві дані можуть містити interfaceName, ips та hardwareAddress. Про обмеження полів див. документацію API DeviceMetadata.
Наведений нижче приклад показує один обʼєкт у потоці метаданих для пристрою GPU, виділеного через шаблон заявки на ресурс:
{
"kind": "DeviceMetadata",
"apiVersion": "metadata.resource.k8s.io/v1beta1",
"metadata": {
"name": "pod0-gpu-2kqrd",
"namespace": "gpu-test1",
"uid": "c7e7b22e-239b-4498-b27c-7f1344481e14",
"generation": 1
},
"podClaimName": "gpu",
"requests": [
{
"name": "gpu",
"devices": [
{
"driver": "gpu.example.com",
"pool": "worker-0",
"name": "gpu-0",
"attributes": {
"driverVersion": {
"version": "1.0.0"
},
"index": {
"int": 0
},
"model": {
"string": "LATEST-GPU-MODEL"
},
"uuid": {
"string": "gpu-18db0e85-99e9-c746-8531-ffeb86328b39"
}
}
}
]
}
]
}
Втулок kubelet DRA не перевіряє метадані перед їх записом. Споживачі Go можуть увімкнути згенеровану перевірку під час декодування потоку. Декодування та перевірка мають окремі результати: помилка перевірки не перешкоджає поверненню успішно декодованого обʼєкта. Про використання див. Доступ до метаданих пристроїв DRA.
Для негайних метаданих драйвер надає атрибути або мережеві дані під час підготовки заявки. Втулок kubelet DRA записує файл із поколінням 1 до запуску контейнера, що споживає.
Для відкладених метаданих драйвер може підготувати пристрій без атрибутів або мережевих даних. Початковий файл із поколінням 1 містить ідентичність пристрою. Пізніше драйвер викликає UpdateRequestMetadata, щоб атомарно замінити повний потік і збільшити покоління. Оновлення вимагає існування початкового файлу. Якщо підготовка пристрою не повертає жодних пристроїв для запиту, фреймворк не створює ні файлу метаданих, ні пристрою CDI метаданих для цього запиту.
Метадані залишаються доступними для кожного контейнера, що їх споживає, протягом усього життєвого циклу цього контейнера. Фреймворк видаляє файли метаданих та специфікації CDI після скасування підготовки заявки.
Щоб дізнатися, як використовувати метадані пристроїв у ваших робочих навантаженнях, див. Доступ до метаданих пристроїв DRA.
Власні драйвери, які не використовують бібліотеку втулка kubelet DRA, мають самостійно реалізувати протокол метаданих пристроїв. Це включає запис версіонованого потоку DeviceMetadata за правильними шляхами, збільшення metadata.generation при кожному оновленні та надання файлів лише для читання через CDI або еквівалентний механізм.
4 - Функції DRA
Ця сторінка описує необовʼязкові функції DRA для розширених випадків використання. Деякі з цих функцій вимагають підтримки з боку драйвера DRA. Для кожної функції зазначено її зрілість та функціональну можливість, яка її вмикає.
Пристрої, що розділяються на розділи
Стан функціоналу:
Beta починаючи з Kubernetes v1.36; стандартно увімкнено
Пристрої, представлені в DRA, не обовʼязково мають бути єдиним блоком, підключеним до однієї машини, але також можуть бути логічним пристроєм, що складається з кількох пристроїв, підключених до кількох машин. Ці пристрої можуть використовувати ресурси базових фізичних пристроїв, що перекриваються, тобто коли один логічний пристрій виділяється, інші пристрої стають недоступними.
В API ResourceSlice це представлено як список іменованих CounterSets, кожен з яких містить набір іменованих лічильників. Лічильники представляють ресурси, доступні на фізичному пристрої, які використовуються логічними пристроями, опублікованими через DRA.
Логічні пристрої можуть вказувати список ConsumesCounters. Кожен запис містить посилання на CounterSet та набір іменованих лічильників із кількостями, які вони споживатимуть. Отже, щоб пристрій можна було виділити, згадані набори лічильників повинні мати достатню кількість для лічильників, на які посилається пристрій.
CounterSets мають бути вказані в окремих ResourceSlices від пристроїв. Пристрої можуть споживати лічильники з будь-якого CounterSet, визначеного в тому самому пулі ресурсів, що й пристрій.
Ось приклад двох пристроїв, кожен з яких споживає 6Gi памʼяті зі спільного лічильника з 8Gi памʼяті. Таким чином, лише один із пристроїв може бути виділений у будь-який момент часу. Планувальник обробляє це, і це прозоро для споживача, оскільки API ResourceClaim не змінюється.
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: resourceslice-with-countersets
spec:
nodeName: worker-1
pool:
name: pool
generation: 1
resourceSliceCount: 2
driver: dra.example.com
sharedCounters:
- name: gpu-1-counters
counters:
memory:
value: 8Gi
---
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: resourceslice-with-devices
spec:
nodeName: worker-1
pool:
name: pool
generation: 1
resourceSliceCount: 2
driver: dra.example.com
devices:
- name: device-1
consumesCounters:
- counterSet: gpu-1-counters
counters:
memory:
value: 6Gi
- name: device-2
consumesCounters:
- counterSet: gpu-1-counters
counters:
memory:
value: 6Gi
Пристрої, що розділяються на розділи, контролюються функціональною можливістю DRAPartitionableDevices у kube-apiserver та kube-scheduler.
Групи сумісності пристроїв
Стан функціоналу:
Alpha починаючи з Kubernetes v1.37; стандартно вимкнено
Групи сумісності пристроїв дозволяють драйверу DRA оголошувати, які розділені пристрої можуть бути спільно виділені на тому самому фізичному обладнанні. Без цієї функції несумісні комбінації пристроїв виявляються лише тоді, коли kubelet готує Pod на вузлі — що призводить до невдалої підготовки. З групами сумісності планувальник відхиляє несумісні комбінації на етапі планування, до початку будь-якої роботи на стороні вузла.
Це найбільш корисно для обладнання, яке підтримує взаємовиключні режими роботи. Наприклад, GPU, який може працювати в режимі MIG або в режимі vGPU: пристрій у режимі MIG та пристрій у режимі vGPU не можуть бути спільно виділені, оскільки вони споживають ті самі фізичні ресурси несумісним чином. Оголошуючи compatibilityGroups, драйвер робить це обмеження видимим для планувальника.
Ця функція ґрунтується на пристроях, що розділяються на розділи: поле compatibilityGroups знаходиться в записах device.consumesCounters[], які існують лише для пристроїв, що розділяються на розділи. Обидві функціональні можливості DRADeviceCompatibilityGroups та DRAPartitionableDevices мають бути увімкнені в kube-apiserver та kube-scheduler.
Як це працює
Драйвер визначає список compatibilityGroups для кожного запису device.consumesCounters[] у ResourceSlice. Список містить щонайбільше 2 непрозорі рядкові назви, які представляють режим роботи або тип розділу цього пристрою на цьому конкретному наборі лічильників.
Коли планувальник виділяє кілька пристроїв, які використовують той самий набір лічильників, він обчислює перетин їхніх compatibilityGroups. Виділення успішне лише тоді, коли цей перетин не порожній — тобто кожен спільно виділений пристрій має принаймні одну спільну назву групи. Пристрої, які використовують різні набори лічильників, ніколи не порівнюються між собою.
Пристрій, який не оголошує жодних груп (невстановлений, nil або порожній список), розглядається як особливий випадок: він може бути спільно виділений лише з іншими пристроями без груп на тому самому наборі лічильників. Він ніколи не може бути спільно виділений з пристроєм, який оголошує одну або більше груп.
Обмеження застосовується до всіх заявок, що виділяються в одному циклі планування: якщо дві заявки кожна виділяє пристрій з того самого набору лічильників, перетин груп між заявками також забезпечується.
Приклад
Розглянемо GPU, який може працювати в режимі MIG або в режимі vGPU. Драйвер публікує два пристрої, кожен з яких споживає 4 GiB з того самого спільного лічильника памʼяті обсягом 8 GiB. Лише на основі ємності лічильника обидва пристрої могли б бути виділені разом. Кожен пристрій оголошує свій режим роботи як групу сумісності, роблячи два режими взаємовиключними:
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: gpu-counters
spec:
nodeName: worker-1
pool:
name: gpu-pool
generation: 1
resourceSliceCount: 2
driver: gpu.example.com
sharedCounters:
- name: gpu-0-memory
counters:
memory:
value: 8Gi
---
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: gpu-devices
spec:
nodeName: worker-1
pool:
name: gpu-pool
generation: 1
resourceSliceCount: 2
driver: gpu.example.com
devices:
- name: gpu-0-mig
consumesCounters:
- counterSet: gpu-0-memory
counters:
memory:
value: 4Gi
compatibilityGroups:
- mig
- name: gpu-0-vgpu
consumesCounters:
- counterSet: gpu-0-memory
counters:
memory:
value: 4Gi
compatibilityGroups:
- vgpu
У цьому прикладі:
gpu-0-mig належить до групи mig.gpu-0-vgpu належить до групи vgpu.
Якщо Pod або PodGroup запитує два пристрої з цього пулу, планувальник перевіряє, чи мають два вибрані пристрої спільну групу сумісності на наборі лічильників gpu-0-memory. Оскільки {"mig"} ∩ {"vgpu"} = ∅, пара відхиляється — навіть якщо набір лічильників має достатньо памʼяті для обох. Обидва запити можуть бути задоволені лише двома пристроями MIG (або двома пристроями vGPU) з пулу, де такі пари існують.
Обмеження
- Кожен запис
consumesCounters[] може оголошувати щонайбільше 2 назви груп. - Назви груп мають бути унікальними в межах одного запису.
- Назви груп є непрозорими для Kubernetes; вони мають значення лише в межах пулу драйвера, що їх публікує.
- Групи порівнюються для кожного набору лічильників окремо: групи на одному наборі лічильників не впливають на рішення про спільне виділення для іншого набору лічильників.
Безпека при різниці версій
Коли функціональну можливість DRADeviceCompatibilityGroups вимкнено (стандартно для альфа), kube-apiserver видаляє поле compatibilityGroups з будь-якого нового або оновленого ResourceSlice — якщо старий обʼєкт уже не мав цього поля встановленим. Тоді планувальник розглядає пристрої в будь-якому пулі, який раніше мав згруповані пристрої, як такі, що належать до неповного пулу, і повністю пропускає їх.
Лише непорожній список вважається встановленим полем: compatibilityGroups: null та compatibilityGroups: [] обробляються так само, як і пропуск поля. Пристрої з ними поводяться точно так само, як пристрої без груп — вони не змушують планувальник вважати пул неповним.
Групи сумісності пристроїв контролюються функціональною можливістю DRADeviceCompatibilityGroups у kube-apiserver та kube-scheduler. Функціональна можливість DRAPartitionableDevices також має бути увімкнена.
Споживча ємність
Стан функціоналу:
Beta починаючи з Kubernetes v1.36; стандартно увімкнено
Функція споживчої ємності дозволяє одним і тим самим пристроям споживатися кількома незалежними заявками на ресурси, при цьому планувальник Kubernetes керує тим, скільки ємності пристрою використовує кожна заявка. Це аналогічно тому, як Podʼи можуть спільно використовувати ресурси на вузлі; заявки на ресурси можуть спільно використовувати ресурси на пристрої.
Драйвер пристрою може встановити поле allowMultipleAllocations, додане в .spec.devices обʼєкта ResourceSlice, щоб дозволити виділення цього пристрою кільком незалежним заявкам на ресурси або кільком запитам у межах однієї заявки на ресурс.
Користувачі можуть встановити поле capacity, додане в spec.devices.requests обʼєкта ResourceClaim, щоб вказати вимоги до ресурсів пристрою для кожного виділення.
Для пристрою, який дозволяє кілька виділень, запитана ємність береться з, або споживається з, його загальної ємності, концепція, відома як споживча ємність. Тоді планувальник гарантує, що сукупна спожита ємність у всіх заявках не перевищує загальну ємність пристрою. Крім того, автори драйверів можуть використовувати обмеження requestPolicy для окремих ємностей пристроїв, щоб контролювати, як ці ємності споживаються. Наприклад, автор драйвера може вказати, що певна ємність споживається лише приростами по 1Gi.
Ось приклад мережевого пристрою, який дозволяє кілька виділень і містить споживчу ємність пропускної здатності.
kind: ResourceSlice
apiVersion: resource.k8s.io/v1
metadata:
name: resourceslice
spec:
nodeName: worker-1
pool:
name: pool
generation: 1
resourceSliceCount: 1
driver: dra.example.com
devices:
- name: eth1
allowMultipleAllocations: true
attributes:
name:
string: "eth1"
capacity:
bandwidth:
requestPolicy:
default: "1M"
validRange:
min: "1M"
step: "8"
value: "10G"
Споживчу ємність можна запитати, як показано в прикладі нижче.
apiVersion: resource.k8s.io/v1
kind: ResourceClaimTemplate
metadata:
name: bandwidth-claim-template
spec:
spec:
devices:
requests:
- name: req-0
exactly:
deviceClassName: resource.example.com
capacity:
requests:
bandwidth: 1G
Результат виділення міститиме спожиту ємність та ідентифікатор частки.
apiVersion: resource.k8s.io/v1
kind: ResourceClaim
...
status:
allocation:
devices:
results:
- consumedCapacity:
bandwidth: 1G
device: eth1
shareID: "a671734a-e8e5-11e4-8fde-42010af09327"
У цьому прикладі було вибрано пристрій, який допускає кілька виділень. Однак будь-який пристрій resource.example.com із принаймні запитаною пропускною здатністю 1G міг би задовольнити вимогу. Якби було вибрано пристрій, який не допускає кілька виділень, виділення призвело б до використання всього пристрою. Щоб примусово використовувати лише пристрої, які допускають кілька виділень, ви можете використати критерій CEL device.allowMultipleAllocations == true.
Обмеження DistinctAttribute
Коли ви запитуєте кілька пристроїв у заявці на ресурс, ви можете використати обмеження DistinctAttribute, щоб гарантувати, що кожен виділений пристрій має різне значення для вказаного атрибута. Це обмеження було введено разом із функцією споживчої ємності.
Обмеження DistinctAttribute особливо корисне під час роботи з пристроями, які допускають кілька виділень. Воно запобігає виділенню одного й того самого пристрою кілька разів у межах однієї заявки на ресурс, навіть якщо цей пристрій дозволяє кілька виділень.
Окрім запобігання дублюванню виділень, це обмеження допомагає оптимізувати продуктивність, гарантуючи розподіл пристроїв на основі їхніх атрибутів. Наприклад, ви можете використати його для розподілу пристроїв між різними NUMA-вузлами, щоб оптимізувати пропускну здатність памʼяті та зменшити конкуренцію.
Авторизація на основі детального статусу
Стан функціоналу:
Beta починаючи з Kubernetes v1.36; стандартно увімкнено
Починаючи з Kubernetes v1.36, DRA застосовує детальні перевірки авторизації для оновлень статусу ResourceClaim, використовуючи синтетичні субресурси та дієслова, що враховують вузли.
Інструкції з посилення безпеки, включаючи приклади RBAC для планувальника та драйверів DRA, див. у
Посібнику із зміцнення безпеки — динамічний розподіл ресурсів.
Покрокову процедуру для адміністратора кластера див. у Посиленні безпеки динамічного розподілу ресурсів у вашому кластері.
Необовʼязкові операції з вузлами
Стан функціоналу:
Alpha починаючи з Kubernetes v1.37; стандартно вимкнено
У динамічному виділенні ресурсів (DRA) kubelet координується з локальним для вузла драйвером через gRPC, щоб підготувати виділені пристрої перед запуском контейнера (NodePrepareResources) та скасувати їх підготовку після завершення роботи Podʼа (NodeUnprepareResources). Хоча така схема є критичною для локального для вузла обладнання, такого як GPU або FPGA, деякі ресурси керуються повністю в панелі управління і не потребують жодної локальної настройки на вузлі.
Функція необовʼязкових операцій з вузлами дозволяє драйверам ресурсів оголошувати, що певні локальні для вузла операції gRPC можуть бути пропущені. Після налаштування kubelet оминає пошук драйвера та виклики gRPC для цих пристроїв, усуваючи потребу розгортати та підтримувати порожні локальні для вузла драйвери на кожному робочому вузлі.
Конфігурація драйвера
Автори драйверів можуть вказати поле skipNodeOperations у
.spec.skipNodeOperations обʼєкта ResourceSlice. Це поле є списком унікальних рядків, які вказують локальні для вузла операції, що мають бути пропущені для всіх пристроїв у цьому розділі.
Допустимі значення:
"NodePrepareResources": пропускає виклики gRPC NodePrepareResources. Це значення не можна вказати, якщо "NodeUnprepareResources" також не вказано (або не вказано "*"). Це обмеження запобігає застряганню Podʼів у стані Terminating, якщо локальний для вузла втулок відсутній, оскільки втулок не перевіряється під час запуску Podʼа, коли підготовку пропущено."NodeUnprepareResources": пропускає виклики gRPC NodeUnprepareResources."*": пропускає всі локальні для вузла операції з ресурсами.
Ось приклад ResourceSlice для ресурсу панелі управління, який пропускає всі локальні для вузла операції:
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: control-plane-resources
spec:
nodeName: worker-1
pool:
name: central-pool
generation: 1
resourceSliceCount: 1
driver: control-plane.example.com
skipNodeOperations:
- "*"
devices:
- name: virtual-device-1
Результат виділення та виконання
Коли планувальник Kubernetes виділяє пристрій заявці на ресурс, він копіює список skipNodeOperations з ResourceSlice у результат виділення:
apiVersion: resource.k8s.io/v1
kind: ResourceClaim
...
status:
allocation:
devices:
results:
- device: virtual-device-1
driver: control-plane.example.com
pool: central-pool
skipNodeOperations:
- "*"
Коли Pod працює на вузлі, kubelet читає результати виділення. Якщо всі виділені пристрої для певного драйвера в межах заявки на ресурс пропускають конкретну операцію, kubelet повністю оминає виклик цього хука gRPC для цього драйвера.
Експлуатаційні міркування
Оновлення драйвера на місці
Оскільки налаштування skipNodeOperations копіюється з ResourceSlice у заявку на ресурс під час виділення, запущені Podʼи та активні виділення зберігають те налаштування, яке діяло на момент їх планування.
Якщо вимоги драйвера до операцій з вузлами оновлюються на місці (наприклад, змінюються з вимоги виконання операцій на їх пропуск), наявні заявки все ще використовуватимуть попередню конфігурацію. Щоб уникнути проблем, наприклад, зависання завершуваних Podʼів в очікуванні виведеного з експлуатації втулка вузла, адміністратори кластерів мають переконатися, що для драйвера не існує активних заявок, перш ніж змінювати його вимоги до операцій з вузлами або видаляти локальні для вузла DaemonSets драйвера.
Інтеграція з оголошеними функціями вузла
Щоб запобігти плануванню Podʼів на вузлах, де kubelet не підтримує пропуск операцій DRA (що призвело б до збою kubelet в очікуванні відсутнього втулка вузла), ця функція інтегрується з Оголошеними функціями вузла. Коли Pod використовує заявку на ресурс із налаштованим skipNodeOperations, планувальник Kubernetes перевіряє, що цільовий вузол оголошує підтримку функції DRAOptionalNodeOperations у своєму .status.declaredFeatures, перш ніж планувати Pod.
Необовʼязкові операції з вузлами контролюються функціональною можливістю DRAOptionalNodeOperations у kube-apiserver, kube-scheduler та kubelet.
Стан функціоналу:
Alpha починаючи з Kubernetes v1.36
Драйвери DRA можуть надавати метадані пристроїв, такі як атрибути пристроїв (адреси шини PCI або mdevUUID для пристроїв з опосередкованим керуванням) або мережеву конфігурацію, безпосередньо контейнерам у вигляді JSON-файлів. Це дозволяє застосункам усередині контейнера дізнаватися інформацію про виділені пристрої без запитів до API Kubernetes або створення власних контролерів.
KEP-5304 визначає протокол метаданих пристроїв, якого драйвери мають дотримуватися, щоб застосунки всередині контейнера бачили узгоджену структуру в різних драйверах і кластерах. Бібліотека втулка kubelet DRA реалізує цей протокол за вас; решта цього розділу описує, як ним користуватися.
Метадані пристроїв підпорядковуються тим самим правилам, що й доступ до пристроїв: вони доступні всередині контейнера лише тоді, коли цей контейнер запитує пристрій у своїй специфікації контейнера, і не інакше. Інструкції щодо запиту пристроїв DRA в Podʼах і контейнерах див. у Запиті пристроїв у робочих навантаженнях за допомогою DRA.
Протокол складається з чотирьох правил:
Шляхи до файлів. Файли метаданих розташовані всередині контейнерів у /var/run/kubernetes.io/dra-device-attributes. Для безпосередньо згаданої заявки на ресурс шлях має вигляд resourceclaims/<claimName>/<requestName>/<driverName>-metadata.json; для заявки, створеної з шаблону заявки на ресурс, шлях має вигляд resourceclaimtemplates/<podClaimName>/<requestName>/<driverName>-metadata.json (де podClaimName — це pod.spec.resourceClaims[].name).
У випадках, коли запит заявки на ресурс використовує функцію списку пріоритетів, для сегмента <requestName> у шляху до файлу використовується лише назва запиту верхнього рівня (тобто частина /<subrequest> відкидається). Усередині JSON-файлу поле requests[].name містить повне посилання <request>/<subrequest> (наприклад, gpu/high-memory), щоб споживачі могли визначити, яку альтернативу було виділено.
Константи шляхів визначені в k8s.io/dynamic-resource-allocation/api/metadata.
JSON API. Кожен файл є потоком одного або кількох обʼєктів DeviceMetadata, серіалізованих як версіонований JSON з apiVersion та kind, відповідно до конвенцій API Kubernetes. Ті самі метадані кодуються один раз для кожної підтримуваної версії API (спочатку найновіша). Усі обʼєкти в потоці семантично еквівалентні; споживачі мають використовувати перший обʼєкт, який вони можуть декодувати.
Покоління. Коли драйвер оновлює файл метаданих, вбудоване поле metadata.generation має збільшуватися, щоб споживачі могли виявляти зміни.
Надання контейнеру. Файли зазвичай надаються через CDI bind-mount, але інші механізми дозволені, якщо файл зʼявляється за правильним шляхом і є доступним лише для читання всередині контейнера.
Метадані пристроїв — це функція на стороні драйвера, яка не потребує жодних змін API Kubernetes або функціональних можливостей. Використання бібліотеки втулка kubelet DRA є поширеним способом реалізації драйвера, але драйвери можуть бути створені й іншими способами. Драйвери, які використовують втулок kubelet, вмикають цю функцію, передаючи опції EnableDeviceMetadata та MetadataVersions під час запуску втулка. MetadataVersions визначає, які версії API серіалізуються у файл метаданих, і має бути явно встановлена драйвером. Перегляньте документацію вашого драйвера DRA, щоб дізнатися, чи підтримуються метадані пристроїв і як їх увімкнути.
Коли метадані пристроїв увімкнено, драйвер генерує файли метаданих та специфікації CDI bind-mount під час підготовки виділених пристроїв для podʼа, до запуску контейнерів, що їх споживають. Метадані зʼявляються всередині контейнерів за добре відомими шляхами, як визначено вище.
Коли один запит виділяє пристрої від кількох драйверів DRA, кожен драйвер записує власний файл метаданих. Контейнери перелічують файли *-metadata.json у теці запиту, щоб виявити всі пристрої.
Пакунок Go k8s.io/dynamic-resource-allocation/devicemetadata надає утиліти для читання та декодування цих файлів метаданих застосунками всередині контейнера.
Кожен файл метаданих відповідає API DeviceMetadata (metadata.resource.k8s.io/v1alpha1). Наведений нижче приклад показує файл метаданих для пристрою GPU, виділеного через шаблон заявки на ресурс:
{
"kind": "DeviceMetadata",
"apiVersion": "metadata.resource.k8s.io/v1alpha1",
"metadata": {
"name": "pod0-gpu-2kqrd",
"namespace": "gpu-test1",
"uid": "c7e7b22e-239b-4498-b27c-7f1344481e14",
"generation": 1
},
"podClaimName": "gpu",
"requests": [
{
"name": "gpu",
"devices": [
{
"driver": "gpu.example.com",
"pool": "worker-0",
"name": "gpu-0",
"attributes": {
"driverVersion": {
"version": "1.0.0"
},
"index": {
"int": 0
},
"model": {
"string": "LATEST-GPU-MODEL"
},
"uuid": {
"string": "gpu-18db0e85-99e9-c746-8531-ffeb86328b39"
}
}
}
]
}
]
}
Драйвери надають метадані одним із двох способів:
- Негайні
- Драйвер заповнює метадані під час підготовки заявки на вузлі та записує файл метаданих до запуску контейнера. Це типово для драйверів GPU, де інформація про пристрій відома на момент підготовки.
- Відкладені
- У деяких випадках, наприклад для мережевого драйвера, інформація про пристрій недоступна під час виділення пристрою, але стає доступною після створення пісочниці podʼа. У таких випадках драйвер створює CDI-монтування з порожнім файлом метаданих і записує фактичні метадані пізніше через хук NRI, який виконується перед запуском контейнера. Це гарантує, що застосунки ніколи не побачать відсутній або частково записаний файл. Кожне оновлення має збільшувати
metadata.generation, щоб споживачі могли виявляти зміни. API MetadataUpdater у бібліотеці втулка kubelet DRA автоматично обробляє облік поколінь для авторів драйверів.
В обох випадках метадані залишаються доступними для кожного контейнера, що їх споживає, протягом усього життєвого циклу цього контейнера. Файли метаданих видаляються після завершення роботи всіх контейнерів у Podʼі.
Щоб дізнатися, як використовувати метадані пристроїв у ваших робочих навантаженнях, див. Доступ до метаданих пристроїв DRA.
Власні, створені вручну драйвери, які не використовують бібліотеку втулка kubelet DRA, мають самостійно реалізувати протокол метаданих пристроїв. Це означає запис JSON DeviceMetadata за правильними шляхами до файлів, збільшення metadata.generation при кожному оновленні та надання файлів лише для читання всередині контейнера через CDI або еквівалентний механізм.
5 - Позначки Taint та Toleration пристроїв
Ця сторінка описує позначки taint та toleration пристроїв в DRA, які дозволяють драйверам та адміністраторам не допускати Podʼи до певних пристроїв або виселяти Podʼи, які вже їх використовують.
Позначки taint та toleration пристроїв
Стан функціоналу:
Stable починаючи з Kubernetes v1.37
Докладніше про цей функціонал
Це стабільна функція в Kubernetes, яка загальнодоступна починаючи з версії v1.37. Вперше вона зʼявилась у випуску v1.33. Ви більше не можете вимкнути або відмовитися від цієї функції чи поведінки (це заблоковано); якщо ви явно встановите значення для повʼязаної функціональної можливості DRADeviceTaints, Kubernetes проігнорує це, але не повідомить про помилку.
Позначки taint пристроїв схожі на позначки taint вузлів: taint має рядковий ключ, рядкове значення та ефект. Ефект застосовується до заявки на ресурс, яка використовує позначений пристрій, і до всіх Podʼів, які посилаються на цю заявку на ресурс. Ефект "NoSchedule" запобігає плануванню цих Podʼів. Позначені пристрої ігноруються під час спроби виділити заявку на ресурс, оскільки їх використання перешкоджало б плануванню Podʼів.
Ефект "NoExecute" передбачає "NoSchedule" і, крім того, спричиняє виселення всіх Podʼів, які вже були заплановані. Це виселення реалізовано в контролері виселення за позначками taint пристроїв у kube-controller-manager шляхом видалення відповідних Podʼів.
Ефект "None" ігнорується планувальником і контролером виселення. Драйвери DRA можуть використовувати його для передачі виняткових ситуацій адміністраторам або іншим контролерам, наприклад, погіршення справності пристрою. Адміністратори також можуть використовувати його для пробних запусків виселення подів у DeviceTaintRules (детальніше про це нижче).
Заявки на ресурси можуть толерувати позначки taint. Якщо taint толерується, його ефект не застосовується. Порожня толерантність відповідає всім позначкам taint. Толерантність може бути обмежена певними ефектами та/або відповідати певним парам ключ/значення. Толерантність може перевіряти, що певний ключ існує, незалежно від того, яке значення він має, або вона може перевіряти конкретні значення ключа. Детальніше про це зіставлення див. у концепціях taint вузлів.
Виселення може бути відкладене шляхом толерування taint протягом певного періоду часу. Ця затримка починається в момент, коли taint додається до пристрою, що фіксується в полі taint.
Позначки taint застосовуються, як описано вище, також до заявок на ресурси, які виділяють "всі" пристрої на вузлі. Усі пристрої мають бути непозначеними, або всі їхні позначки taint мають толеруватися. Виділення пристрою з адміністративним доступом (описано вище) також не є винятком. Адміністратор, який використовує цей режим, має явно толерувати всі позначки taint, щоб отримати доступ до позначених пристроїв.
Ви можете додавати позначки taint до пристроїв наступними способами, використовуючи вид API DeviceTaintRule.
Позначки taint, встановлені драйвером
Драйвер DRA може додавати позначки taint до інформації про пристрій, яку він публікує в ResourceSlices. Зверніться до документації драйвера DRA, щоб дізнатися, чи використовує драйвер позначки taint і які їхні ключі та значення.
Позначки taint, встановлені адміністратором
Стан функціоналу:
Stable починаючи з Kubernetes v1.37
Докладніше про цей функціонал
Це стабільна функція в Kubernetes, яка загальнодоступна починаючи з версії v1.37. Вперше вона зʼявилась у випуску v1.35. Ви більше не можете вимкнути або відмовитися від цієї функції чи поведінки (це заблоковано); якщо ви явно встановите значення для повʼязаної функціональної можливості DRADeviceTaintRules, Kubernetes проігнорує це, але не повідомить про помилку.
Адміністратор або компонент панелі управління може позначити пристрої без необхідності вказувати драйверу DRA включати позначки taint у свою інформацію про пристрої в ResourceSlices. Вони роблять це, створюючи DeviceTaintRules. Кожен DeviceTaintRule додає одну позначку taint пристроям, які відповідають селектору пристроїв. Без такого селектора жодні пристрої не позначаються. Це ускладнює випадкове виселення всіх подів, які використовують заявки на ресурси, якщо селектор випадково пропущено.
Пристрої можуть бути вибрані шляхом вказання назви DeviceClass, драйвера, пулу та/або пристрою. DeviceClass вибирає всі пристрої, які вибираються селекторами в цьому DeviceClass. Лише з назвою драйвера адміністратор може позначити всі пристрої, якими керує цей драйвер, наприклад, під час проведення певного технічного обслуговування цього драйвера в усьому кластері. Додавання назви пулу може обмежити taint одним вузлом, якщо драйвер керує локальними для вузла пристроями.
Нарешті, додавання назви пристрою може вибрати один конкретний пристрій. Назва пристрою та назва пулу також можуть використовуватися окремо, якщо бажано. Наприклад, драйверам для локальних для вузла пристроїв рекомендується використовувати назву вузла як назву свого пулу. Тоді позначення за допомогою цієї назви пулу автоматично позначає всі пристрої на вузлі.
Драйвери можуть використовувати стабільні назви, як-от "gpu-0", які приховують, який саме пристрій наразі призначено цій назві. Щоб підтримати позначення конкретного екземпляра обладнання, у DeviceTaintRule можна використовувати селектори CEL для зіставлення з унікальним ID-атрибутом, специфічним для постачальника, якщо драйвер підтримує його для свого обладнання.
Taint застосовується, доки існує DeviceTaintRule. Його можна змінювати та видаляти в будь-який час. Ось один приклад DeviceTaintRule для вигаданого драйвера DRA:
apiVersion: resource.k8s.io/v1
kind: DeviceTaintRule
metadata:
name: example
spec:
# Уся апаратна інсталяція для цього
# конкретного драйвера не працює.
# Припинити роботу всіх подів і не планувати запуск нових.
deviceSelector:
driver: dra.example.com
taint:
key: dra.example.com/unhealthy
value: Broken
effect: NoExecute
kube-apiserver автоматично відстежує, коли було створено цю позначку taint, встановлюючи поле timeAdded у spec. Період толерантності починається з цієї позначки часу. Під час оновлень, які змінюють ефект (див. імітований процес виселення нижче), kube-apiserver автоматично оновлює позначку часу. Користувачі можуть контролювати позначку часу явно, встановлюючи поле під час створення DeviceTaintRule та змінюючи його на інше значення під час оновлення.
Статус містить стан, доданий контролером виселення:
kubectl describe devicetaintrules
Name: example
...
Spec:
Device Selector:
Driver: dra.example.com
Taint:
Effect: NoExecute
Key: dra.example.com/unhealthy
Time Added: 2025-11-05T18:15:37Z
Value: Broken
Status:
Conditions:
Last Transition Time: 2025-11-05T18:15:37Z
Message: 1 pod evicted since starting the controller.
Observed Generation: 1
Reason: Completed
Status: False
Type: EvictionInProgress
Events: <none>
Podʼи виселяються шляхом їх видалення. Зазвичай це відбувається дуже швидко, за винятком випадків, коли толерантність до taint відкладає це на певний період або коли є дуже багато подів, які потрібно виселити. Коли це займає більше часу, повідомлення надає інформацію про поточний статус:
2 pods need to be evicted in 2 different namespaces. 1 pod evicted since starting the controller.
Стан може використовуватися для перевірки того, чи виселення наразі активне:
kubectl wait --for=condition=EvictionInProgress=false DeviceTaintRule/example
Стережіться потенційної гонитви між планувальником і контролером, які спостерігають нову позначку taint у різний час, що може призвести до того, що поди все ще плануватимуться в момент, коли контролер вважає, що немає жодних, які потрібно виселити, і тому встановлює цей стан в False. На практиці ця гонитва стає дуже малоймовірною завдяки оновленню статусу лише після навмисної затримки в кілька секунд.
Для effect: None повідомлення надає інформацію про кількість відповідних пристроїв, скільки з них виділено та скільки podʼів було б виселено, якби ефект був NoExecute. Це можна використовувати для пробного запуску перед фактичним запуском виселення:
3 published devices selected. 1 allocated device selected.
1 pod would be evicted in 1 namespace if the effect was NoExecute.
This information will not be updated again. Recreate the DeviceTaintRule to trigger an update.
Опубліковані пристрої — це ті, що перелічені в ResourceSlices. Їх позначення запобігає виділенню для нових подів. Лише виділені пристрої спричиняють виселення подів, які їх використовують.
- Відредагуйте DeviceTaintRule та змініть ефект на
NoExecute.