Багато робочих кластерів Kubernetes поєднують вузли на вимогу (вищий рівень SLA) та спот-вузли/вузли з правом витіснення (нижчий рівень SLA) для оптимізації витрат при збереженні надійності критичних робочих навантажень. Команди платформи потребують безпечного стандартного варіанту, який утримує більшість робочих навантажень подалі від ризикованих потужностей, одночасно дозволяючи певним робочим навантаженням підключатися з явними пороговими значеннями, такими як «Я можу толерувати вузли з імовірністю відмови до 5%».
Сьогодні Kubernetes taints і tolerations можуть відповідати точним значенням або перевіряти наявність, але вони не можуть порівнювати числові пороги. Вам потрібно буде створити дискретні категорії taint, використовувати зовнішні контролери допуску або приймати рішення про розміщення, що не є оптимальними.
У Kubernetes v1.35 ми впроваджуємо розширені оператори толерантності як альфа-функцію. Це вдосконалення додає оператори Gt (більше ніж) і Lt (менше ніж) до spec.tolerations, що дозволяє приймати рішення про планування на основі порогових значень, які відкривають нові можливості для розміщення на основі SLA, оптимізації витрат і розподілу робочих навантажень з урахуванням продуктивності.
Історично Kubernetes підтримував два основні оператора толерантності:
Equal: толерантність відповідає позначці taint, якщо ключ і значення є абсолютно однаковимиExists: толерантність відповідає позначці taint, якщо ключ присутній, незалежно від значенняХоча ці функції добре працювали для категорійних сценаріїв, вони не підходили для числових порівнянь. Починаючи з версії 1.35, ми усуваємо цю прогалину.
Розглянемо такі реальні ситуації:
Без операторів числового порівняння оператори кластерів мусили вдаватися до обхідних рішень, таких як створення декількох дискретних значень taint або використання зовнішніх контролерів допуску, жоден з яких не масштабується добре і не забезпечує гнучкості, необхідної для динамічного планування на основі порогових значень.
Ви можете запитати: NodeAffinity вже підтримує числові оператори порівняння, тож навіщо розширювати толерантності? Хоча NodeAffinity є потужним інструментом для вираження налаштувань подів, taints і tolerations надають важливі операційні переваги:
NoExecute з tolerationSeconds, що дозволяє операторам виводити та виселяти поди, коли SLA вузла погіршується або спотові інстанції отримують повідомлення про припинення.Це вдосконалення зберігає добре зрозумілу модель безпеки позначок і толерантності, одночасно забезпечуючи розміщення на основі порогових значень для планування з урахуванням SLA.
Kubernetes v1.35 представляє два нових оператори для толерантності:
Gt (більше ніж): толерантність застосовується, якщо числове значення taint більше за значення толерантностіLt (менше ніж): толерантність застосовується, якщо числове значення taint менше за значення толерантностіКоли под толерує taint з Lt, це означає: «Я можу толерувати вузли, де цей показник менший за мій поріг». Оскільки толерантності дозволяють планувати, под може працювати на вузлах, де значення taint більше за значення толерантності. Подумайте про це так: «Я можу працювати з вузлами, які перевищують мої мінімальні вимоги».
Ці оператори працюють з числовими значеннями taint і дозволяють планувальнику приймати складні рішення щодо розміщення на основі безперервних метрик, а не дискретних категорій.
Числові значення для операторів Gt і Lt повинні бути додатними 64-бітними цілими числами без нулів на початку. Наприклад, "100"є дійсним, але "0100" (з нулем на початку) і "0" (нульове значення) не допускаються.
Оператори Gt і Lt працюють з усіма ефектами taint: NoSchedule, NoExecute і PreferNoSchedule.
Давайте розглянемо, як розширені оператори толерантності вирішують реальні завдання планування.
Багато кластерів поєднують вузли на вимогу та спотові/преемптивні вузли для оптимізації витрат. Спотові вузли забезпечують значну економію, але мають вищий рівень відмов. Ви хочете, щоб більшість робочих навантажень стандартно уникало спотових вузлів, дозволяючи при цьому певним робочим навантаженням підключатися з чіткими межами SLA.
Спочатку позначте спотові вузли з їхньою ймовірністю відмови (наприклад, 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
Цей под буде плануватися тільки на вузлах з failure-probability менше 5 (тобто ondemand-node-1 з 2%, але не spot-node-1 з 15%). Ефект NoExecute з tolerationSeconds: 30 означає, що якщо SLA вузла погіршується (наприклад, хмарний провайдер змінює значення taint), под отримує 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%, тому воно може виконуватися як на вузлах на вимогу, так і на спотових вузлах, що дозволяє максимально заощадити кошти, приймаючи при цьому більш високий ризик.
Робочі навантаження ШІ та машинного навчання часто мають специфічні вимоги до апаратного забезпечення. За допомогою операторів розширеної толерантності ви можете створювати рівні вузлів GPU та забезпечувати розміщення робочих навантажень на апаратному забезпеченні з відповідною потужністю.
Позначте вузли GPU за їхнім показником обчислювальної потужності:
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"
Велике навантаження під час тренувань може вимагати високопродуктивних графічних процесорів:
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
Це гарантує, що под для тренування буде плануватися лише на вузлах з показником обчислювальної потужності більше 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
Для пакетної обробки або некритичних робочих навантажень ви можете мінімізувати витрати, запускаючи їх на дешевших вузлах, навіть якщо вони мають нижчі характеристики продуктивності.
Вузли можуть бути позначені їхнім рейтингом вартості:
spec:
taints:
- key: "cost-per-hour"
value: "50"
effect: "NoSchedule"
Вразливе до вартості пакетне завдання може виражати свою толерантність до дорогих вузлів:
tolerations:
- key: "cost-per-hour"
operator: "Lt"
value: "100"
effect: "NoSchedule"
Ця пакетна задача буде плануватися на вузлах, вартість яких становить менше 100 доларів за годину, але уникатиме більш дорогих вузлів. У поєднанні з пріоритетами планування Kubernetes це дозволяє реалізувати складні стратегії розподілу витрат, за якими критичні робочі навантаження отримують преміум-вузли, а пакетні робочі навантаження ефективно використовують бюджетні ресурси.
Застосунки, що вимагають великого обсягу памʼяті, часто потребують мінімальних гарантій продуктивності диска. За допомогою операторів розширеної толерантності ви можете забезпечити дотримання цих вимог на рівні планування.
tolerations:
- key: "disk-iops"
operator: "Gt"
value: "3000"
effect: "NoSchedule"
Ця толерантність гарантує, що под планується тільки на вузлах, де disk-iops перевищує 3000. Оператор Gt означає «Мені потрібні вузли, які перевищують цей мінімум».
Розширені оператори толерантності є альфа-функцією в Kubernetes v1.35. Щоб спробувати її:
Увімкніть функціональнe можливість у вашому API-сервері та планувальнику:
--feature-gates=TaintTolerationComparisonOperators=true
Позначте ваші вузли числовими значеннями, що представляють метрики, релевантні для ваших потреб планування:
kubectl taint nodes node-1 failure-probability=5:NoSchedule
kubectl taint nodes node-2 disk-iops=5000:NoSchedule
Використовуйте нові оператори у специфікаціях ваших подів:
spec:
tolerations:
- key: "failure-probability"
operator: "Lt"
value: "1"
effect: "NoSchedule"
Ця альфа-версія — лише початок. Збираючи відгуки від спільноти, ми плануємо:
Нам особливо цікаво дізнатися про ваші випадки використання! Чи є у вас сценарії, в яких планування на основі порогових значень вирішило б проблеми? Чи є додаткові оператори або можливості, які ви хотіли б бачити?
Ця функція підтримується спільнотою SIG Scheduling. Приєднуйтесь до нас, щоб долучитися до спільноти та поділитися своїми ідеями та відгуками щодо цієї функції та інших питань.
Ви можете звʼязатися з адміністраторами цієї функції за адресою:
З питаннями або конкретними запитаннями, повʼязаними з операторами розширеної толерантності, звертайтеся до спільноти SIG Scheduling. Чекаємо на ваші повідомлення!
Gt та Lt