Kubernetes v1.35: Розширені оператори tolerations для підтримки числових порівнянь (Alpha)
Багато кластерів Kubernetes у промисловому середовищі поєднують вузли на вимогу (вищий рівень SLA) та спотові вузли або вузли з можливістю витіснення (нижчий рівень SLA), щоб оптимізувати витрати й водночас зберегти надійність критичних робочих навантажень. Командам платформи потрібен безпечний типовий варіант, який тримає більшість робочих навантажень подалі від ризикованих потужностей і водночас дозволяє окремим робочим навантаженням явно погоджуватися на них із чіткими пороговими значеннями, як-от «Я можу толерувати вузли з імовірністю відмови до 5%».
Сьогодні taints і tolerations у Kubernetes можуть перевіряти збіг точних значень або наявність ключа, але не можуть порівнювати числові пороги. Вам довелося б створювати дискретні категорії taint, використовувати зовнішні контролери допуску або погоджуватися на неоптимальні рішення щодо розміщення.
У Kubernetes v1.35 ми представляємо розширені оператори tolerations (Extended Toleration Operators) як альфа-можливість. Це вдосконалення додає оператори Gt (більше ніж) і Lt (менше ніж) до spec.tolerations, що дозволяє ухвалювати рішення про планування на основі порогових значень і відкриває нові можливості для розміщення на основі SLA, оптимізації витрат і розподілу робочих навантажень з урахуванням продуктивності.
Розвиток tolerations
Історично Kubernetes підтримував два основні оператори tolerations:
Equal: toleration відповідає taint, якщо ключ і значення точно збігаютьсяExists: toleration відповідає taint, якщо ключ існує, незалежно від значення
Хоча ці оператори добре працювали для категорійних сценаріїв, для числових порівнянь їх було недостатньо. Починаючи з v1.35, ми усуваємо цю прогалину.
Розглянемо такі реальні ситуації:
- Вимоги SLA: планувати робочі навантаження з високою доступністю тільки на вузлах із ймовірністю відмови нижче певного порогу
- Оптимізація витрат: дозволити чутливим до витрат пакетним завданням виконуватися на дешевших вузлах, які перевищують певне значення вартості за годину
- Гарантії продуктивності: забезпечити, щоб чутливі до затримок застосунки виконувалися тільки на вузлах, де дискові IOPS або пропускна здатність мережі перевищують мінімальні пороги
Без операторів числового порівняння оператори кластерів мусили вдаватися до обхідних рішень, таких як створення декількох дискретних значень taint або використання зовнішніх контролерів допуску, жоден з яких не масштабується добре і не забезпечує гнучкості, необхідної для динамічного планування на основі порогових значень.
Навіщо розширювати tolerations замість використання NodeAffinity?
Ви можете запитати: NodeAffinity вже підтримує числові оператори порівняння, тож навіщо розширювати tolerations? Хоча NodeAffinity добре підходить для вираження вподобань Podʼів, taints і tolerations дають важливі операційні переваги:
- Орієнтованість на політику: NodeAffinity задається для кожного Podʼа окремо, тож кожне робоче навантаження має явно відмовлятися від ризикованих вузлів. Taints інвертують контроль — вузли оголошують свій рівень ризику, і лише Podʼи з відповідними tolerations можуть на них потрапити. Це дає безпечнішу типову поведінку: більшість Podʼів тримаються подалі від spot/preemptible вузлів, якщо явно не погодилися на них.
- Семантика виселення: NodeAffinity не вміє виселяти. Taints підтримують ефект
NoExecuteзtolerationSeconds, що дозволяє операторам виконувати drain і виселяти Podʼи, коли SLA вузла погіршується або спотові екземпляри отримують повідомлення про завершення роботи. - Ергономіка експлуатації: централізована політика на боці вузла узгоджується з іншими захисними taints, як-от disk-pressure і memory-pressure, що робить керування кластером інтуїтивнішим.
Це вдосконалення зберігає добре зрозумілу модель безпеки taints і tolerations, водночас уможливлюючи розміщення на основі порогових значень для планування з урахуванням SLA.
Представляємо оператори Gt та Lt
Kubernetes v1.35 представляє два нові оператори для tolerations:
Gt(більше ніж): toleration спрацьовує, якщо числове значення taint більше за значення tolerationLt(менше ніж): toleration спрацьовує, якщо числове значення taint менше за значення toleration
Коли Pod толерує taint з Lt, це означає: «Я можу толерувати вузли, де цей показник менший за мій поріг». Оскільки tolerations дозволяють планування, Pod може працювати на вузлах, де значення taint більше за значення toleration. Думайте про це так: «Я толерую вузли, які перевищують мої мінімальні вимоги».
Ці оператори працюють з числовими значеннями taint і дозволяють планувальнику приймати складні рішення щодо розміщення на основі безперервних метрик, а не дискретних категорій.
Примітка:
Числові значення для операторів Gt і Lt мають бути додатними 64-бітними цілими числами без нулів на початку. Наприклад, "100" є дійсним, але "0100" (з нулем на початку) і "0" (нульове значення) не допускаються.
Оператори Gt і Lt працюють з усіма ефектами taint: NoSchedule, NoExecute і PreferNoSchedule.
Випадки використання та приклади
Розгляньмо, як розширені оператори tolerations розвʼязують реальні завдання планування.
Приклад 1: Захист спотових екземплярів за допомогою порогових значень SLA
Багато кластерів поєднують вузли на вимогу та спотові вузли або вузли з можливістю витіснення для оптимізації витрат. Спотові вузли дають значну економію, але мають вищий рівень відмов. Ви хочете, щоб більшість робочих навантажень типово уникала спотових вузлів, і водночас дозволити окремим робочим навантаженням явно погоджуватися на них із чіткими межами SLA.
Спочатку додайте до спотових вузлів taint з їхньою ймовірністю відмови (наприклад, 15% відмов на рік):
apiVersion: v1
kind: Node
metadata:
name: spot-node-1
spec:
taints:
- key: "failure-probability"
value: "15"
effect: "NoExecute"
Вузли на вимогу мають набагато нижчий рівень відмов:
apiVersion: v1
kind: Node
metadata:
name: ondemand-node-1
spec:
taints:
- key: "failure-probability"
value: "2"
effect: "NoExecute"
Критичні робочі навантаження можуть задавати суворі вимоги до SLA:
apiVersion: v1
kind: Pod
metadata:
name: payment-processor
spec:
tolerations:
- key: "failure-probability"
operator: "Lt"
value: "5"
effect: "NoExecute"
tolerationSeconds: 30
containers:
- name: app
image: payment-app:v1
Цей Pod буде плануватися тільки на вузлах з failure-probability менше 5 (тобто ondemand-node-1 з 2%, але не spot-node-1 з 15%). Ефект NoExecute з tolerationSeconds: 30 означає, що якщо SLA вузла погіршується (наприклад, хмарний провайдер змінює значення taint), Pod отримує 30 секунд для коректного завершення роботи перед примусовим виселенням.
Тим часом відмовостійке пакетне завдання може явно погодитися на спотові екземпляри:
apiVersion: v1
kind: Pod
metadata:
name: batch-job
spec:
tolerations:
- key: "failure-probability"
operator: "Lt"
value: "20"
effect: "NoExecute"
containers:
- name: worker
image: batch-worker:v1
Це пакетне завдання толерує вузли з імовірністю відмови до 20%, тому може виконуватися як на вузлах на вимогу, так і на спотових вузлах, максимально заощаджуючи кошти ціною вищого ризику.
Приклад 2: Розміщення робочих навантажень ШІ за рівнями GPU
Робочі навантаження ШІ та машинного навчання часто мають специфічні вимоги до обладнання. За допомогою розширених операторів tolerations ви можете створювати рівні GPU-вузлів і гарантувати, що робочі навантаження потраплять на обладнання відповідної потужності.
Додайте до вузлів GPU taint з їхнім показником обчислювальної потужності:
apiVersion: v1
kind: Node
metadata:
name: gpu-node-a100
spec:
taints:
- key: "gpu-compute-score"
value: "1000"
effect: "NoSchedule"
---
apiVersion: v1
kind: Node
metadata:
name: gpu-node-t4
spec:
taints:
- key: "gpu-compute-score"
value: "500"
effect: "NoSchedule"
Важке навчальне навантаження може вимагати високопродуктивних GPU:
apiVersion: v1
kind: Pod
metadata:
name: model-training
spec:
tolerations:
- key: "gpu-compute-score"
operator: "Gt"
value: "800"
effect: "NoSchedule"
containers:
- name: trainer
image: ml-trainer:v1
resources:
limits:
nvidia.com/gpu: 1
Це гарантує, що Pod для навчання плануватиметься лише на вузлах з показником обчислювальної потужності понад 800 (як-от вузол A100), і не потрапить на GPU нижчого рівня, які сповільнили б навчання.
Тим часом робочі навантаження інференсу з менш суворими вимогами можуть використовувати будь-який доступний GPU:
apiVersion: v1
kind: Pod
metadata:
name: model-inference
spec:
tolerations:
- key: "gpu-compute-score"
operator: "Gt"
value: "400"
effect: "NoSchedule"
containers:
- name: inference
image: ml-inference:v1
resources:
limits:
nvidia.com/gpu: 1
Приклад 3: Розміщення робочого навантаження з оптимізацією витрат
Для пакетної обробки або некритичних робочих навантажень ви можете мінімізувати витрати, запускаючи їх на дешевших вузлах, навіть якщо вони мають нижчі характеристики продуктивності.
До вузлів можна додати taint з їхнім рейтингом вартості:
spec:
taints:
- key: "cost-per-hour"
value: "50"
effect: "NoSchedule"
Чутливе до вартості пакетне завдання може задати, наскільки дорогі вузли воно готове толерувати:
tolerations:
- key: "cost-per-hour"
operator: "Lt"
value: "100"
effect: "NoSchedule"
Це пакетне завдання плануватиметься на вузлах, що коштують менше 100 доларів за годину, і уникатиме дорожчих вузлів. У поєднанні з пріоритетами планування Kubernetes це дозволяє реалізувати складні стратегії розподілу за вартістю, за яких критичні робочі навантаження отримують преміум-вузли, а пакетні робочі навантаження ефективно використовують бюджетні ресурси.
Приклад 4: Розміщення на основі продуктивності
Застосунки з інтенсивним використанням сховища часто потребують гарантій мінімальної продуктивності диска. За допомогою розширених операторів tolerations ви можете забезпечити дотримання цих вимог на рівні планування.
tolerations:
- key: "disk-iops"
operator: "Gt"
value: "3000"
effect: "NoSchedule"
Ця toleration гарантує, що Pod планується тільки на вузли, де disk-iops перевищує 3000. Оператор Gt означає «Мені потрібні вузли, у яких значення більше за цей мінімум».
Як використовувати цю можливість
Розширені оператори tolerations є альфа-можливістю в Kubernetes v1.35. Щоб спробувати її:
Увімкніть функціональну можливість на API-сервері та планувальнику:
--feature-gates=TaintTolerationComparisonOperators=trueДодайте до вузлів taints з числовими значеннями метрик, важливих для ваших потреб планування:
kubectl taint nodes node-1 failure-probability=5:NoSchedule kubectl taint nodes node-2 disk-iops=5000:NoScheduleВикористовуйте нові оператори у специфікаціях ваших Podʼів:
spec: tolerations: - key: "failure-probability" operator: "Lt" value: "1" effect: "NoSchedule"
Примітка:
Оскільки це альфа-можливість, розширені оператори tolerations можуть змінитися в майбутніх випусках, тож у промислових середовищах їх слід використовувати обережно. Завжди спершу ретельно тестуйте їх у непромислових кластерах.Що далі?
Ця альфа-версія — лише початок. Збираючи відгуки від спільноти, ми плануємо:
- Додати підтримку виразів CEL (Common Expression Language) у tolerations і спорідненості вузлів (node affinity) для ще гнучкішої логіки планування, зокрема порівняння семантичних версій
- Поліпшити інтеграцію з автоматичним масштабуванням кластерів для планування потужностей з урахуванням порогових значень
- Перевести можливість у бета-версію, а згодом і в GA зі стабільністю, придатною для промислового використання
Нам особливо цікаво дізнатися про ваші випадки використання! Чи є у вас сценарії, в яких планування на основі порогових значень вирішило б проблеми? Чи є додаткові оператори або можливості, які ви хотіли б бачити?
Як долучитися
Розвиток цієї можливості веде спільнота SIG Scheduling. Приєднуйтесь до нас, щоб спілкуватися зі спільнотою та ділитися своїми ідеями й відгуками щодо цієї можливості та не тільки.
Звʼязатися із супровідниками цієї можливості можна тут:
- Slack: #sig-scheduling у Kubernetes Slack
- Список розсилки: kubernetes-sig-scheduling@googlegroups.com
З питаннями щодо розширених операторів tolerations звертайтеся до спільноти SIG Scheduling. Чекаємо на ваші відгуки!
Як дізнатися більше?
- Taints та Tolerations — основи
- Оператори числового порівняння — докладніше про використання операторів
GtіLt - KEP-5471: Extended Toleration Operators for Threshold-Based Placement