Динамічне виділення ресурсів
Основний динамічний розподіл ресурсів зі структурованими параметрами:
Kubernetes v1.30 [alpha]
(стандартно увімкнено: false)Динамічне виділення ресурсів в контролері панелі управління:
Kubernetes v1.26 [alpha]
(стандартно увімкнено: false)Динамічне виділення ресурсів — це API для запиту та спільного використання ресурсів між Podʼами та контейнерами всередині Podʼа. Це узагальнення API для постійних томів для загальних ресурсів. Зазвичай ці ресурси є пристроями, такими як GPU.
Драйвери сторонніх ресурсів відповідають за відстеження та підготовку ресурсів, а виділення ресурсів здійснюється Kubernetes за допомогою структурованих параметрів (введених у Kubernetes 1.30). Різні види ресурсів підтримують довільні параметри для визначення вимог та ініціалізації.
Коли драйвер надає контролер панелі управління, драйвер самостійно керує виділенням ресурсів у співпраці з планувальником Kubernetes.
Перш ніж ви розпочнете
Kubernetes v1.31 включає підтримку API на рівні кластера для динамічного виділення ресурсів, але це потрібно включити явно. Ви також повинні встановити драйвер ресурсів для конкретних ресурсів, які мають бути керовані за допомогою цього API. Якщо ви не використовуєте Kubernetes v1.31, перевірте документацію для цієї версії Kubernetes.
API
Група API resource.k8s.io/v1alpha3
надає наступні типи:
- ResourceClaim
- Визначає запит на доступ до ресурсів у кластері для використання робочими навантаженнями. Наприклад, якщо робоче навантаження потребує пристрою прискорювача з певними властивостями, саме так виражається цей запит. Розділ статусу відстежує, чи було виконано цей запит і які конкретні ресурси було виділено.
- ResourceClaimTemplate
- Визначає специфікацію та деякі метадані для створення ResourceClaims. Створюється користувачем під час розгортання робочого навантаження. Kubernetes автоматично створює та видаляє ResourceClaims для кожного Podʼа.
- DeviceClass
- Містить заздалегідь визначені критерії вибору для певних пристроїв та їх конфігурацію. DeviceClass створюється адміністратором кластера під час встановлення драйвера ресурсів. Кожен запит на виділення пристрою в ResourceClaim повинен посилатися на один конкретний DeviceClass.
- PodSchedulingContext
- Використовується внутрішньо панеллю управління та драйверами ресурсів для координації планування Podʼів, коли ResourceClaims потрібно виділити для Podʼа, і ці ResourceClaims використовують контролер панелі управління.
- ResourceSlice
- Використовується зі структурованими параметрами для публікації інформації про ресурси, які доступні у кластері.
Розробник драйвера ресурсів вирішує, чи хоче він самостійно керувати виділенням ресурсів за допомогою контролера панелі управління або ж покластися на виділення через Kubernetes за допомогою структурованих параметрів. Власний контролер забезпечує більшу гнучкість, але автоматичне масштабування кластера не буде надійно працювати для ресурсів, прив’язаних до вузла. Структуровані параметри дозволяють автоматичне масштабування кластера, але можуть не задовольнити всі випадки використання.
Коли драйвер використовує структуровані параметри, всі параметри, що вибирають пристрої, визначаються в ResourceClaim і DeviceClass за допомогою вбудованих типів. Параметри конфігурації можуть бути вбудовані туди як довільні обʼєкти JSON.
PodSpec
core/v1
визначає ResourceClaims, які потрібні для Podʼа в полі resourceClaims
. Записи в цьому списку посилаються або на ResourceClaim, або на ResourceClaimTemplate. При посиланні на ResourceClaim всі Podʼи, які використовують цей PodSpec (наприклад, всередині Deployment або StatefulSet), спільно використовують один екземпляр ResourceClaim. При посиланні на ResourceClaimTemplate, кожен Pod отримує свій власний екземпляр.
Список resources.claims
для ресурсів контейнера визначає, чи отримує контейнер доступ до цих екземплярів ресурсів, що дозволяє спільне використання ресурсів між одним або кількома контейнерами.
Нижче наведено приклад для умовного драйвера ресурсів. Для цього Podʼа буде створено два обʼєкти ResourceClaim, і кожен контейнер отримає доступ до одного з них.
apiVersion: resource.k8s.io/v1alpha3
kind: DeviceClass
name: resource.example.com
spec:
selectors:
- cel:
expression: device.driver == "resource-driver.example.com"
---
apiVersion: resource.k8s.io/v1alpha2
kind: ResourceClaimTemplate
metadata:
name: large-black-cat-claim-template
spec:
spec:
devices:
requests:
- name: req-0
deviceClassName: resource.example.com
selectors:
- cel:
expression: |-
device.attributes["resource-driver.example.com"].color == "black" &&
device.attributes["resource-driver.example.com"].size == "large"
–--
apiVersion: v1
kind: Pod
metadata:
name: pod-with-cats
spec:
containers:
- name: container0
image: ubuntu:20.04
command: ["sleep", "9999"]
resources:
claims:
- name: cat-0
- name: container1
image: ubuntu:20.04
command: ["sleep", "9999"]
resources:
claims:
- name: cat-1
resourceClaims:
- name: cat-0
resourceClaimTemplateName: large-black-cat-claim-template
- name: cat-1
resourceClaimTemplateName: large-black-cat-claim-template
Планування
З контролером панелі управління
На відміну від вбудованих ресурсів (CPU, RAM) та розширених ресурсів (керованих пристроєм драйвера, оголошуваних kubelet), без структурованих параметрів планувальник не має знань про те, які динамічні ресурси доступні в кластері та як вони можуть бути розподілені для задоволення вимог певного ResourceClaim. За це відповідальні драйвери ресурсів. Вони відмічають ResourceClaims як "allocated", як тільки для них зарезервовано ресурси. Це також показує планувальнику, де в кластері доступний ResourceClaim.
Коли Pod планується до виконання, планувальник перевіряє всі ResourceClaims, необхідні для Pod, і створює обʼєкт PodScheduling, де інформує драйвери ресурсів, відповідальні за ці ResourceClaims, про вузли, які планувальник вважає підходящими для Pod. Драйвери ресурсів відповідають, виключаючи вузли, які не мають достатньо ресурсів драйвера. Як тільки планувальник має цю інформацію, він вибирає один вузол та зберігає цей вибір в обʼєкті PodScheduling. Потім драйвери ресурсів виділяють свої ResourceClaims так, щоб ресурси були доступні на цьому вузлі. Після завершення цього процесу Pod стає запланованим.
У рамках цього процесу також для Podʼа резервуються ResourceClaims. Наразі ResourceClaims можуть використовуватися або ексклюзивно одним Podʼом, або необмеженою кількістю Podʼів.
Одна з ключових особливостей полягає в тому, що Podʼи не заплановані на вузол, поки всі їх ресурси не будуть виділені та зарезервовані. Це дозволяє уникати сценарію, коли Pod запланований на один вузол, а потім не може працювати там, що погано, оскільки такий очікуючий Pod також блокує всі інші ресурси, такі як RAM або CPU, які були відведені для нього.
Примітка:
Планування Podʼів, які використовують ResourceClaims, буде повільнішим через додаткову комунікацію, яка потрібна. Зверніть увагу, що це також може вплинути на Podʼи, які не використовують ResourceClaims, оскільки під час обробки Podʼа з ResourceClaims робиться лише один виклик API, що блокується, і тому планування наступного Podʼа затримується.Зі структурованими параметрами
Коли драйвер використовує структуровані параметри, планувальник бере на себе відповідальність за виділення ресурсів для ResourceClaim, кожного разу, коли Pod потребує їх. Він робить це, отримуючи повний список доступних ресурсів з обʼєктів ResourceSlice, відстежуючи, які з цих ресурсів вже були виділені наявним ResourceClaim, а потім вибираючи з тих ресурсів, що залишилися.
Єдиний тип підтримуваних ресурсів зараз — це пристрої. Пристрій має імʼя та кілька атрибутів та можливостей. Вибір пристроїв здійснюється за допомогою виразів CEL, які перевіряють ці атрибути та можливості. Крім того, набір вибраних пристроїв також може бути обмежений наборами, які відповідають певним обмеженням.
Обраний ресурс фіксується у статусі ResourceClaim разом з будь-якими вендор-специфічними налаштуваннями, тому коли Pod збирається запуститися на вузлі, драйвер ресурсу на вузлі має всю необхідну інформацію для підготовки ресурсу.
За допомогою структурованих параметрів планувальник може приймати рішення без спілкування з будь-якими драйверами ресурсів DRA. Він також може швидко планувати кілька Podʼів, зберігаючи інформацію про виділення ресурсів для ResourceClaim у памʼяті та записуючи цю інформацію в обʼєкти ResourceClaim у фоні, одночасно з привʼязкою Podʼа до вузла.
Моніторинг ресурсів
Kubelet надає службу gRPC для забезпечення виявлення динамічних ресурсів запущених Podʼів. Для отримання додаткової інформації про точки доступу gRPC дивіться звіт про виділення ресурсів.
Попередньо заплановані Podʼи
Коли ви, або інший клієнт API, створюєте Pod із вже встановленим spec.nodeName
, планувальник пропускається. Якщо будь-який ResourceClaim, потрібний для цього Podʼа, ще не існує, не виділений або не зарезервований для Podʼа, то kubelet не зможе запустити Pod і періодично перевірятиме це, оскільки ці вимоги можуть бути задоволені пізніше.
Така ситуація також може виникнути, коли підтримка динамічного виділення ресурсів не була увімкнена в планувальнику на момент планування Podʼа (різниця версій, конфігурація, feature gate і т. д.). kube-controller-manager виявляє це і намагається зробити Pod працюючим, провокуючи виділення та/або резервування потрібних ResourceClaims.
Примітка:
Це працює лише для ресурсів драйверів, які не використовують структуровані параметри.Краще уникати цього оминаючи планувальник, оскільки Pod, який призначений для вузла, блокує нормальні ресурси (ОЗП, ЦП), які потім не можуть бути використані для інших Podʼів, поки Pod є застряглим. Щоб запустити Pod на певному вузлі, при цьому проходячи через звичайний потік планування, створіть Pod із селектором вузла, який точно відповідає бажаному вузлу:
apiVersion: v1
kind: Pod
metadata:
name: pod-with-cats
spec:
nodeSelector:
kubernetes.io/hostname: назва-призначеного-вузла
...
Можливо, ви також зможете змінити вхідний Pod під час допуску, щоб скасувати поле .spec.nodeName
і використовувати селектор вузла замість цього.
Увімкнення динамічного виділення ресурсів
Динамічне виділення ресурсів є альфа-функцією та увімкнуто лише тоді, коли увімкнуто функціональну можливість DynamicResourceAllocation
та групу API resource.k8s.io/v1alpha3
. Для отримання деталей щодо цього дивіться параметри kube-apiserver --feature-gates
та --runtime-config
. Також варто увімкнути цю функцію в kube-scheduler, kube-controller-manager та kubelet.
Коли драйвер ресурсів використовує контролер панелі управління, крім DynamicResourceAllocation
, також потрібно увімкнути функціональну можливість DRAControlPlaneController
.
Швидка перевірка того, чи підтримує кластер Kubernetes цю функцію, полягає у виведенні обʼєктів DeviceClass за допомогою наступної команди:
kubectl get deviceclasses
Якщо ваш кластер підтримує динамічне виділення ресурсів, відповідь буде або список обʼєктів DeviceClass, або:
No resources found
Якщо це не підтримується, буде виведено помилку:
error: the server doesn't have a resource type "deviceclasses"
Контролер панелі управління підтримується, коли є можливість створити обʼєкт ResourceClaim, де поле spec.controller
встановлене. Якщо DRAControlPlaneController
вимкнено, це поле автоматично очищується під час збереження ResourceClaim.
Типова конфігурація kube-scheduler вмикає втулок "DynamicResources" лише в разі увімкнення feature gate та при використанні конфігурації API v1. Налаштування конфігурації може змінюватися, щоб включити його.
Крім увімкнення функції в кластері, також потрібно встановити драйвер ресурсів. Для отримання додаткової інформації звертайтеся до документації драйвера.
Що далі
- Для отримання додаткової інформації про дизайн дивіться KEP: Dynamic Resource Allocation with Structured Parameters та Dynamic Resource Allocation with Control Plane Controller.