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

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

Динамічне виділення ресурсів

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.35
More information about this feature

This is a stable feature in Kubernetes, and has been since version v1.35. It was first available in the v1.30 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate DynamicResourceAllocation, Kubernetes ignores it but does not report any error.

Цей розділ знайомить з динамічним виділенням ресурсів (Dynamic Resource Allocation, DRA) у Kubernetes.

DRA — можливість Kubernetes, яка дозволяє запитувати ресурси та спільно використовувати їх між Podʼами. Часто такими ресурсами є приєднані пристрої, як-от апаратні прискорювачі.

З DRA драйвери пристроїв і адміністратори кластера визначають класи пристроїв, які робочі навантаження можуть запитувати (claim). Kubernetes виділяє відповідні пристрої конкретним запитам (claims) і розміщує відповідні 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 - Як працює DRA

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

Як працює виділення ресурсів з DRA

Наступні розділи описують робочий процес для різних типів користувачів DRA та для системи Kubernetes під час динамічного виділення ресурсів.

Робочий процес для користувачів

  1. Створення драйвера: власники пристроїв або сторонні організації створюють драйвери, які можуть створювати та керувати ResourceSlices у кластері. Ці драйвери за бажанням також створюють DeviceClasses, які визначають категорію пристроїв та як їх запитувати.
  2. Конфігурація кластера: адміністратори кластера створюють кластери, підключають пристрої до вузлів і встановлюють драйвери пристроїв DRA. Адміністратори кластера за бажанням створюють DeviceClasses, які визначають категорії пристроїв та як їх запитувати.
  3. Заявки на ресурси: оператори навантаження створюють ResourceClaimTemplates або ResourceClaims, які запитують конкретні конфігурації пристроїв у межах DeviceClass. На тому ж етапі оператори навантаження модифікують свої маніфести Kubernetes, щоб запитувати ці ResourceClaimTemplates або ResourceClaims.

Робочий процес для Kubernetes

  1. Створення ResourceSlice: драйвери в кластері створюють ResourceSlices, які представляють один або кілька пристроїв у керованому пулі подібних пристроїв.

  2. Створення навантаження: панель управління кластера перевіряє нові навантаження на наявність посилань на ResourceClaimTemplates або на конкретні ResourceClaims.

    • Якщо навантаження використовує ResourceClaimTemplate, контролер з імʼям resourceclaim-controller генерує ResourceClaims для навантаження.
    • Якщо навантаження використовує конкретний ResourceClaim, Kubernetes перевіряє, чи існує цей ResourceClaim у кластері. Якщо ResourceClaim не існує, Podʼи не будуть розгорнуті.
  3. Фільтрація ResourceSlice: для кожного Podʼа Kubernetes перевіряє ResourceSlices у кластері, щоб знайти пристрій, який задовольняє всі наступні критерії:

    • Вузли, які можуть отримати доступ до ресурсів, мають право запускати Pod.
    • ResourceSlice має невиділені ресурси, які відповідають вимогам ResourceClaim Podʼа.
  4. Виділення ресурсів: після знаходження відповідного ResourceSlice для ResourceClaim Podʼа, планувальник Kubernetes оновлює ResourceClaim з деталями виділення ресурсів. Планувальник використовує стратегію першого підходящого варіанту та оцінює пули та ResourceSlices у лексикографічному порядку за їхніми іменами. Драйвери можуть пріоритизувати конкретні розділи ресурсів або пули, відповідно називаючи їх. Для отримання додаткової інформації див. Іменування та пріоритизація.

  5. Планування 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 since 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 since Kubernetes v1.36; (стандартно вимкнено)
More information about this feature

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

See Enable Or Disable Feature Gates for more information.

Пристрої, якими керує 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.

2 - Спостережуваність динамічних ресурсів

Ця сторінка описує, як спостерігати за статусом і справністю ресурсів, які динамічно виділяються за допомогою DRA.

Спостережуваність динамічних ресурсів

Ви можете перевірити статус динамічно виділених ресурсів, використовуючи будь-який із наступних методів:

Метрики пристроїв kubelet

Служба gRPC PodResourcesLister kubelet дозволяє вам контролювати пристрої, що використовуються. Повідомлення DynamicResource надає інформацію, специфічну для динамічного виділення ресурсів, таку як назва пристрою та назва заявки. Детальніше див. Моніторинг ресурсів втулків пристроїв.

Статус пристрою ResourceClaim

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.37; (стандартно увімкнено)
More information about this feature

This is a stable feature in Kubernetes, and has been since version 1.37. It was first available in the v1.32 release.

Драйвери DRA можуть повідомляти специфічні для драйвера дані статусу пристрою для кожного виділеного пристрою в полі status.devices ResourceClaim. Наприклад, драйвер може перелічувати IP-адреси, призначені пристрою мережевого інтерфейсу. Оновлення цього поля вимагає спеціальних синтетичних дозволів RBAC, див. Посібник із зміцнення безпеки — динамічне виділення ресурсів та Посилення безпеки динамічного виділення ресурсів у вашому кластері.

Точність інформації, яку драйвер додає до поля status.devices ResourceClaim, залежить від драйвера. Оцінюйте драйвери, щоб вирішити, чи можете ви покладатися на це поле як на єдине джерело інформації про пристрої.

Якщо ви вимкнете функціональну можливість DRAResourceClaimDeviceStatus, поле status.devices автоматично очищається під час зберігання ResourceClaim. Статус пристрою ResourceClaim підтримується, коли з боку драйвера DRA можливо оновити наявний ResourceClaim, у якому встановлено поле status.devices.

У наведеному нижче прикладі поле status.devices ResourceClaim було заповнено драйвером (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 ResourceClaim із цим пристроєм відхиляється. Коли пристрій вивільняється (видаляється з status.allocation.devices), відповідний запис у status.devices автоматично видаляється.

Детальніше про поле status.devices див. у довіднику API ResourceClaim.

Моніторинг справності пристроїв

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.36; (стандартно увімкнено)

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

Щоб використовувати цю функціональність, функціональна можливість 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 since Kubernetes v1.36; (стандартно вимкнено)
More information about this feature

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

See Enable Or Disable Feature Gates for more information.

Ви можете запитувати доступність пристроїв у пулах ресурсів за допомогою API ResourcePoolStatusRequest. Це забезпечує видимість того, скільки пристроїв доступно, виділено або недоступно в пулах ресурсів DRA вашого кластера.

Щоб перевірити статус пулу ресурсів:

  1. Створіть 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
    
  2. Дочекайтеся, поки контролер обробить запит:

    kubectl wait --for=condition=Complete resourcepoolstatusrequest/check-gpus --timeout=30s
    
  3. Прочитайте статус, щоб побачити доступність пулу:

    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 (помилка).
  4. Видаліть запит, коли закінчите:

    kubectl delete resourcepoolstatusrequest/check-gpus
    

Обʼєкти ResourcePoolStatusRequest обробляються один раз контролером у kube-controller-manager. Специфікація є незмінною після створення, а весь обʼєкт стає незмінним після заповнення статусу. Щоб отримати оновлені дані про доступність, видаліть і перестворіть запит. Завершені запити автоматично очищаються через 1 годину.

Ця функція вимагає явних дозволів RBAC на ресурс ResourcePoolStatusRequest. Жодна типова ClusterRole не включає цей дозвіл.

Статус пулу ресурсів контролюється функціональною можливістю DRAResourcePoolStatus у kube-apiserver та kube-controller-manager.

Підсумок розділів

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature

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

See Enable Or Disable Feature Gates for more information.

Один фізичний пристрій, такий як GPU, може бути опублікований як кілька типів розділів (наприклад, повний GPU проти половинного розділу MIG), які використовують ті самі спільні лічильники. Оскільки ці розділи конкурують за ту саму базову ємність, проста кількість пристроїв не показує, скільки пристроїв кожного типу ще можна виділити. Для пулів з пристроями, що розділяються на розділи представлення partitionSummary відповідає на це питання. Для кожного типу розділу воно повідомляє:

  • attribute: повне імʼя атрибута пристрою, значення якого групує цей запис. Це spec.partitionTypeAttribute обʼєкта ResourceSlice або spec.defaultPartitionTypeAttribute запиту, коли ResourceSlice не оголошує жодного.
  • type: значення цього атрибута на пристрої (наприклад, Full або Half).
  • total: кількість пристроїв цього типу розділу в пулі.
  • allocatable: скільки додаткових пристроїв цього типу розділу ще можна було б виділити з урахуванням поточного споживання спільних лічильників.

Названий атрибут має бути рядковим атрибутом. Якщо атрибут типу розділу пристрою, що розділяється на розділи, відсутній або не є рядком (наприклад, ціле число, булеве значення або версія), пул повідомляє про помилку перевірки замість підсумку розділів. Немає спеціальної обробки для атрибутів типу список; нерядковий атрибут просто не є дійсним атрибутом типу розділу.

Щоб створити це представлення, драйвер позначає кожен пристрій, що розділяється на розділи, рядковим атрибутом, значення якого називає тип розділу, і вказує цей атрибут у полі partitionTypeAttribute обʼєкта ResourceSlice:

apiVersion: resource.k8s.io/v1
kind: ResourceSlice
# ...
spec:
  # Кожен пристрій, що розділяється на розділи, у цьому ResourceSlice має цей атрибут; пристрої,
  # які мають однакове значення, несуть однакові витрати на спільний лічильник.
  partitionTypeAttribute: gpu.example.com/profile

Якщо драйвер ще не оновлено для оголошення partitionTypeAttribute, запит все одно може отримати підсумок розділів, вказавши резервний атрибут у своїй специфікації. Власний partitionTypeAttribute ResourceSlice завжди має перевагу; типове значення на рівні запиту застосовується лише до пристроїв, чий ResourceSlice не оголошує його:

apiVersion: resource.k8s.io/v1alpha3
kind: ResourcePoolStatusRequest
metadata:
  name: check-gpu-partitions
spec:
  driver: gpu.example.com
  # Запасний атрибут групування для ResourceSlice, які не оголошують власного.
  defaultPartitionTypeAttribute: gpu.example.com/profile

Коли ні ResourceSlice, ні запит не вказують атрибут, пул з пристроями, що розділяються на розділи, не повідомляє partitionSummary.

Представлення partitionSummary контролюється функціональною можливістю DRAPartitionableDevicesType у kube-apiserver та kube-controller-manager, яка, своєю чергою, вимагає увімкнення функціональних можливостей DRAResourcePoolStatus та DRAPartitionableDevices.

Підсумок спільного використання

Для пулів, що містять пристрої, які можуть спільно використовуватися (пристрої, які встановлюють allowMultipleAllocations і можуть споживатися кількома заявками), shareableSummary повідомляє сукупне використання ємності в межах пулу:

  • fullyAvailableDevices: пристрої, що можуть спільно використовуватися, у яких не спожито жодної ємності.
  • partiallyAvailableDevices: пристрої, що можуть спільно використовуватися, у яких спожито частину, але не всю ємність.
  • capacity: для кожної назви ємності сукупні обсяги total, consumed та available (total мінус consumed, ніколи не відʼємне) у межах пулу.

shareableSummary заповнюється лише тоді, коли принаймні один пристрій у пулі може спільно використовуватися. Він є частиною функції статусу пулу ресурсів (функціональна можливість DRAResourcePoolStatus) і не вимагає DRAPartitionableDevicesType; пристрої, що можуть спільно використовуватися, які він підсумовує, походять із функції споживчої ємності.

Метадані пристроїв DRA в контейнерах

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.37

Драйвери DRA можуть надавати метадані пристроїв, такі як атрибути пристроїв (адреси шини PCI або UUID опосередкованих (mediated) пристроїв) та мережеву конфігурацію, безпосередньо контейнерам у вигляді JSON-файлів. Це дозволяє застосункам дізнаватися інформацію про виділені пристрої без запитів до API Kubernetes або використання власних контролерів.

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

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

Протокол метаданих пристроїв

Протокол складається з чотирьох правил:

  1. Шляхи до файлів. Файли метаданих розташовані всередині контейнерів у /var/run/kubernetes.io/dra-device-attributes. Для безпосередньо вказаного ResourceClaim шлях має вигляд resourceclaims/<claimName>/<requestName>/<driverName>-metadata.json. Для заявки, створеної з ResourceClaimTemplate, шлях має вигляд 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.

  2. JSON API. Кожен файл є потоком одного або кількох обʼєктів DeviceMetadata. Кожен обʼєкт має apiVersion та kind, відповідно до домовленостей API Kubernetes. Ті самі метадані кодуються один раз для кожної налаштованої версії API в порядку, вибраному драйвером. Споживачі використовують першу версію, яку вони можуть декодувати, і пропускають невідомі версії. Пошкоджений обʼєкт у відомій версії є помилкою.

  3. Покоління. Початковий файл має metadata.generation, встановлене на 1. Кожне оновлення збільшує покоління, щоб споживачі могли виявляти зміни.

  4. Надання контейнеру. Бібліотека втулка 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).

Схема містить:

  • Стандартні метадані обʼєкта для ResourceClaim, включаючи її назву, простір імен, UID та покоління метаданих.
  • Необовʼязкове podClaimName для заявки, згенерованої з ResourceClaimTemplate.
  • Список запитів. Кожен запит має обовʼязкову назву та список виділених пристроїв.
  • Драйвер, пул та назву для кожного пристрою.
  • Необовʼязкові атрибути пристроїв та мережеві дані.

Значення атрибутів використовують те саме представлення, що й атрибути пристроїв ResourceSlice. Кожен атрибут має рівно одне скалярне значення (int, bool, string або version) або значення списку (ints, bools, strings або versions). Значення ємності пристроїв не включаються в метадані пристроїв.

Мережеві дані можуть містити interfaceName, ips та hardwareAddress. Про обмеження полів див. документацію API DeviceMetadata.

Наведений нижче приклад показує один обʼєкт у потоці метаданих для пристрою GPU, виділеного через ResourceClaimTemplate:

{
  "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 або еквівалентний механізм.

3 - Функції DRA

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

Пристрої, що розділяються на розділи

СТАН ФУНКЦІОНАЛУ: Beta since 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 since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature

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

See Enable Or Disable Feature Gates for more information.

Групи сумісності пристроїв дозволяють драйверу 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 since Kubernetes v1.36; (стандартно увімкнено)

Функція споживчої ємності дозволяє одним і тим самим пристроям споживатися кількома незалежними ResourceClaim, при цьому планувальник Kubernetes керує тим, скільки ємності пристрою використовує кожна заявка. Це аналогічно тому, як Podʼи можуть спільно використовувати ресурси на вузлі; ResourceClaim можуть спільно використовувати ресурси на пристрої.

Драйвер пристрою може встановити поле allowMultipleAllocations, додане в .spec.devices обʼєкта ResourceSlice, щоб дозволити виділення цього пристрою кільком незалежним ResourceClaim або кільком запитам у межах одного ResourceClaim.

Коли ви запитуєте рівно один вид пристрою в ResourceClaim, встановіть spec.devices.requests[].exactly.capacity, щоб вказати вимоги до ресурсів пристрою для кожного виділення. Для пріоритетного списку різних альтернатив встановіть capacity у відповідних записах spec.devices.requests[].firstAvailable[].

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

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

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

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

Деталізована авторизація статусу

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.36; (стандартно увімкнено)

Починаючи з Kubernetes v1.36, DRA застосовує детальні перевірки авторизації для оновлень статусу ResourceClaim, використовуючи синтетичні субресурси та дієслова, що враховують вузли.

Інструкції з посилення безпеки, включаючи приклади RBAC для планувальника та драйверів DRA, див. у Посібнику із зміцнення безпеки — динамічне виділення ресурсів.

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

Необовʼязкові операції з вузлами

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature

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

See Enable Or Disable Feature Gates for more information.

У динамічному виділенні ресурсів (DRA) kubelet координується з локальним для вузла драйвером через gRPC, щоб підготувати виділені пристрої перед запуском контейнера (NodePrepareResources) та скасувати їх підготовку після завершення роботи Podʼа (NodeUnprepareResources). Хоча така схема є критичною для локального для вузла обладнання, такого як GPU або FPGA, деякі ресурси керуються повністю в панелі управління і не потребують жодного локального налаштування на вузлі.

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

Конфігурація драйвера

Автори драйверів можуть вказати поле skipNodeOperations у .spec.skipNodeOperations обʼєкта ResourceSlice. Це поле є списком унікальних рядків, які вказують локальні для вузла операції, що мають бути пропущені для всіх пристроїв у цьому 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 виділяє пристрій для ResourceClaim, він копіює список 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 читає результати виділення. Якщо всі виділені пристрої для певного драйвера в межах ResourceClaim пропускають конкретну операцію, kubelet повністю оминає виклик цього хука gRPC для цього драйвера.

Експлуатаційні міркування

Оновлення драйвера на місці

Оскільки налаштування skipNodeOperations копіюється з ResourceSlice у ResourceClaim під час виділення, запущені Podʼи та активні виділення зберігають те налаштування, яке діяло на момент їх планування.

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

Інтеграція з оголошеними функціями вузла

Щоб запобігти плануванню Podʼів на вузлах, де kubelet не підтримує пропуск операцій DRA (що призвело б до збою kubelet в очікуванні відсутнього втулка вузла), ця функція інтегрується з Оголошеними функціями вузла. Коли Pod використовує ResourceClaim із налаштованим skipNodeOperations, планувальник Kubernetes перевіряє, що цільовий вузол оголошує підтримку функції DRAOptionalNodeOperations у своєму .status.declaredFeatures, перш ніж планувати Pod.

Необовʼязкові операції з вузлами контролюються функціональною можливістю DRAOptionalNodeOperations у kube-apiserver, kube-scheduler та kubelet.

4 - Позначки taint та toleration пристроїв

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

Позначки taint та toleration пристроїв

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.37
More information about this feature

This is a stable feature in Kubernetes, and has been since version v1.37. It was first available in the v1.33 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate DRADeviceTaints, Kubernetes ignores it but does not report any error.

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

Ефект "NoExecute" передбачає "NoSchedule" і, крім того, спричиняє виселення всіх Podʼів, які вже були заплановані. Це виселення реалізовано в контролері виселення за позначками taint пристроїв у kube-controller-manager шляхом видалення відповідних Podʼів.

Ефект "None" ігнорується планувальником і контролером виселення. Драйвери DRA можуть використовувати його для передачі виняткових ситуацій адміністраторам або іншим контролерам, наприклад, погіршення справності пристрою. Адміністратори також можуть використовувати його для пробних запусків виселення Podʼів у DeviceTaintRules (детальніше про це нижче).

ResourceClaims можуть толерувати позначки taint. Якщо taint толерується, його ефект не застосовується. Порожній toleration відповідає всім позначкам taint. Toleration можна обмежити певними ефектами та/або певними парами ключ/значення. Toleration може перевіряти, що певний ключ існує, незалежно від його значення, або перевіряти конкретні значення ключа. Детальніше про це зіставлення див. у концепціях taint вузлів.

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

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

Ви можете додавати позначки taint до пристроїв наступними способами, використовуючи вид API DeviceTaintRule.

Позначки taint, встановлені драйвером

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

Позначки taint, встановлені адміністратором

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.37
More information about this feature

This is a stable feature in Kubernetes, and has been since version v1.37. It was first available in the v1.35 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate DRADeviceTaintRules, Kubernetes ignores it but does not report any error.

Адміністратор або компонент панелі управління може позначити пристрої без необхідності вказувати драйверу DRA включати позначки taint у свою інформацію про пристрої в ResourceSlices. Вони роблять це, створюючи DeviceTaintRules. Кожен DeviceTaintRule додає одну позначку taint пристроям, які відповідають селектору пристроїв. Без такого селектора жодні пристрої не позначаються. Це ускладнює випадкове виселення всіх Podʼів, які використовують ResourceClaims, якщо селектор випадково пропущено.

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

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

Драйвери можуть використовувати стабільні назви, як-от "gpu-0", які приховують, який саме пристрій наразі призначено цій назві. Щоб підтримати позначення конкретного екземпляра обладнання, у DeviceTaintRule можна використовувати селектори CEL для зіставлення з унікальним ID-атрибутом, специфічним для постачальника, якщо драйвер підтримує його для свого обладнання.

Taint застосовується, доки існує DeviceTaintRule. Його можна змінювати та видаляти в будь-який час. Ось один приклад DeviceTaintRule для вигаданого драйвера DRA:

apiVersion: resource.k8s.io/v1
kind: DeviceTaintRule
metadata:
  name: example
spec:
  # Уся апаратна інсталяція для цього
  # конкретного драйвера не працює.
    # Виселити всі Podʼи і не планувати нові.
  deviceSelector:
    driver: dra.example.com
  taint:
    key: dra.example.com/unhealthy
    value: Broken
    effect: NoExecute

kube-apiserver автоматично відстежує, коли було створено цю позначку taint, встановлюючи поле timeAdded у spec. Період дії toleration починається з цієї позначки часу. Під час оновлень, які змінюють ефект (див. імітований процес виселення нижче), 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ʼи виселяються шляхом їх видалення. Зазвичай це відбувається дуже швидко, за винятком випадків, коли toleration для taint відкладає це на певний період або коли є дуже багато Podʼів, які потрібно виселити. Коли це займає більше часу, повідомлення надає інформацію про поточний статус:

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

Для effect: None повідомлення надає інформацію про кількість відповідних пристроїв, скільки з них виділено та скільки Podʼів було б виселено, якби ефект був NoExecute. Це можна використовувати для пробного запуску перед фактичним запуском виселення:

  • Створіть DeviceTaintRule з бажаними селекторами та effect: None.

  • Перегляньте повідомлення:

    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. Їх позначення запобігає виділенню для нових Podʼів. Лише виділені пристрої спричиняють виселення Podʼів, які їх використовують.

  • Відредагуйте DeviceTaintRule та змініть ефект на NoExecute.