Kubernetes v1.35: расширенные операторы допусков для числовых сравнений (альфа)
Многие производственные кластеры Kubernetes объединяют узлы по запросу (on-demand, с высоким SLA) и спотовые/вытесняемые (spot/preemptible, с низким SLA), чтобы снизить затраты, не жертвуя надёжностью критичных рабочих нагрузок. Командам платформы нужно безопасное поведение по умолчанию, при котором большинство нагрузок не попадает на рискованные узлы, — и одновременно возможность для отдельных нагрузок явно указать порог допустимого риска, например: «я готов работать на узлах с вероятностью отказа не выше 5%».
Сегодня пометки (taints) и допуски (tolerations) в Kubernetes позволяют сопоставить точное значение или проверить существование ключа, но не умеют сравнивать числовые пороги. Приходится создавать отдельные категории пометок, использовать внешние контроллеры допуска (admission controllers) или мириться с неоптимальными решениями при планировании.
В Kubernetes v1.35 мы вводим расширенные операторы допусков (Extended Toleration Operators) как альфа-функцию. Улучшение добавляет операторы Gt (больше, Greater Than) и Lt (меньше, Less Than) в spec.tolerations, что открывает возможности для планирования на основе пороговых значений: размещение с учётом SLA, оптимизация затрат и распределение нагрузки с учётом производительности.
Эволюция допусков
Исторически Kubernetes поддерживал два основных оператора допусков:
Equal-
Допуск совпадает с пометкой, если ключ и значение в точности равны.
Exists-
Допуск совпадает с пометкой, если ключ существует, независимо от значения.
Эти операторы хорошо работали для категориальных сценариев, но не справлялись с числовыми сравнениями. Начиная с v1.35 этот пробел устранён.
Рассмотрим реальные сценарии:
Требования SLA: планировать высокодоступные нагрузки только на узлах, у которых вероятность отказа не превышает заданного порога. Оптимизация затрат: разрешить ресурсоёмким пакетным задачам (batch jobs) выполняться на более дешёвых узлах, превышающих определённую стоимость в час. Гарантии производительности: обеспечить запуск латентно-чувствительных приложений только на узлах, у которых дисковый IOPS или пропускная способность сети не ниже минимального порога.
Без операторов числового сравнения администраторам кластеров приходилось прибегать к обходным решениям: создавать множество дискретных значений пометок или подключать внешние контроллеры допуска. Ни то ни другое не масштабируется и не даёт достаточной гибкости для динамического планирования по порогам.
Почему расширять допуски, а не использовать NodeAffinity?
Закономерный вопрос: NodeAffinity уже поддерживает операторы числового сравнения — зачем тогда расширять допуски? NodeAffinity — мощный инструмент для выражения предпочтений пода, однако пометки и допуски дают важные операционные преимущества:
Ориентация на политики: NodeAffinity задаётся на уровне пода, то есть каждая нагрузка должна явно отказываться от рискованных узлов. Пометки инвертируют управление: узел сам объявляет свой уровень риска, и только поды с подходящими допусками могут на нём оказаться. Это более безопасное поведение по умолчанию: большинство подов не попадёт на спотовые узлы, если явно не разрешит этого.
Семантика вытеснения: NodeAffinity не умеет вытеснять поды. Пометки поддерживают эффект NoExecute совместно с tolerationSeconds, что позволяет операторам корректно освобождать и вытеснять поды при деградации SLA узла или при получении уведомления о завершении спотового экземпляра.
Удобство эксплуатации: централизованная политика на стороне узла согласована с другими защитными пометками — disk-pressure и memory-pressure, что делает управление кластером более интуитивным.
Это улучшение сохраняет хорошо понятную модель безопасности пометок и допусков, добавляя к ней пороговое размещение для планирования с учётом SLA.
Операторы Gt и Lt
В Kubernetes v1.35 для допусков вводятся два новых оператора:
Gt(Greater Than)-
Допуск совпадает, если числовое значение пометки больше значения допуска.
Lt(Less Than)-
Допуск совпадает, если числовое значение пометки меньше значения допуска.
Когда под допускает пометку с оператором Lt, это означает: «я готов работать на узлах, у которых эта метрика меньше моего порога». Поскольку допуск разрешает планирование, под может выполняться на узлах, где значение пометки больше значения допуска. Иными словами: «я терплю узлы, превышающие мои минимальные требования».
Операторы работают с числовыми значениями пометок и позволяют планировщику принимать сложные решения о размещении на основе непрерывных метрик, а не дискретных категорий.
|
Примечание
|
Числовые значения для операторов |
Операторы Gt и Lt работают со всеми эффектами пометок: NoSchedule, NoExecute и PreferNoSchedule.
Варианты использования и примеры
Рассмотрим, как расширенные операторы допусков решают реальные задачи планирования.
Пример 1: защита от спотовых узлов с помощью порогов SLA
Многие кластеры сочетают узлы по запросу и спотовые, чтобы оптимизировать затраты. Спотовые узлы значительно дешевле, но чаще отказывают. Желательно, чтобы большинство нагрузок по умолчанию избегало спотовых узлов, а определённые нагрузки могли явно выбирать их в рамках чётких 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 узла ухудшится (например, облачный провайдер изменит значение пометки), под получит 30 секунд на graceful-завершение перед принудительным вытеснением.
Тем временем отказоустойчивое пакетное задание может явно выбрать спотовые узлы:
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: размещение AI-нагрузок по уровням GPU
Нагрузки в области искусственного интеллекта и машинного обучения нередко предъявляют конкретные требования к оборудованию. С помощью расширенных операторов допусков можно создавать уровни 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"
Тяжёлая задача обучения модели может потребовать высокопроизводительные 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
Это гарантирует, что под с обучением запланируется только на узлах с вычислительным показателем выше 800 (например, на узле с A100), не попав на GPU младшего уровня, которые замедлили бы обучение.
Нагрузки инференса (inference) с менее высокими требованиями могут использовать любой доступный 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: размещение нагрузок с оптимизацией затрат
Для пакетной обработки или некритичных нагрузок может быть важно минимизировать затраты, запуская задачи на более дешёвых узлах, даже если те обладают более низкими характеристиками производительности.
Узлы можно пометить рейтингом стоимости:
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:
- key: "disk-iops"
operator: "Gt"
value: "3000"
effect: "NoSchedule"
Этот допуск гарантирует, что под запланируется только на узлах, у которых disk-iops превышает 3000. Оператор Gt здесь означает: «мне нужны узлы с показателем выше этого минимума».
Как использовать эту функцию
Расширенные операторы допусков — это альфа-функция Kubernetes v1.35. Чтобы попробовать её:
-
Включите feature gate на 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"
|
Примечание
|
Поскольку это альфа-функция, расширенные операторы допусков могут измениться в будущих релизах. Используйте их в продакшне с осторожностью и обязательно предварительно тестируйте в непродакшн-кластерах. |
Что дальше?
Этот альфа-релиз — лишь начало. По мере сбора обратной связи от сообщества мы планируем:
-
Добавить поддержку CEL-выражений (Common Expression Language) в допуски и node affinity для ещё более гибкой логики планирования, включая сравнение семантических версий.
-
Улучшить интеграцию с автомасштабированием кластера для планирования ёмкости с учётом порогов.
-
Перевести функцию в бета-статус, а затем в GA с производственной стабильностью.
Нам особенно интересны ваши сценарии использования! Есть ли у вас задачи, которые решило бы пороговое планирование? Каких операторов или возможностей вам не хватает?
Участие в разработке
Функция развивается силами сообщества SIG Scheduling. Присоединяйтесь, чтобы обменяться идеями и обратной связью.
Связаться с мейнтейнерами функции можно через:
-
Slack: #sig-scheduling в Kubernetes Slack
-
Список рассылки: kubernetes-sig-scheduling@googlegroups.com
По вопросам, связанным непосредственно с расширенными операторами допусков, обращайтесь в сообщество SIG Scheduling. Будем рады услышать вас!
Дополнительные материалы
-
/docs/concepts/scheduling-eviction/taint-and-toleration/[Пометки и допуски] — основы работы механизма.
-
/docs/concepts/scheduling-eviction/taint-and-toleration/#numeric-comparison-operators[Операторы числового сравнения] — подробности использования
GtиLt. -
KEP-5471: Extended Toleration Operators for Threshold-Based Placement — предложение по улучшению.