Kubernetes v1.35:扩展容忍运算符以支持数值比较(Alpha)
Source: Kubernetes Blog
Source: …
概述
许多生产环境的 Kubernetes 集群会混合使用 按需(更高 SLA)和 Spot / 可抢占(更低 SLA)节点,以在保持关键工作负载可靠性的同时优化成本。平台团队需要一个安全的默认设置,使大多数工作负载远离风险容量,同时允许特定工作负载通过显式阈值(例如“我可以容忍节点的故障概率最高 5 %”)自行选择。
目前,Kubernetes 的污点(taints)和容忍(tolerations)只能匹配精确值或检查是否存在,无法比较数值阈值。常见的变通办法包括:
- 创建离散的污点类别
- 使用外部准入控制器
- 接受次优的调度决策
在 Kubernetes v1.35 中,我们引入了 扩展容忍运算符(alpha)。此增强在 spec.tolerations 中添加了 Gt(大于)和 Lt(小于)运算符,使基于阈值的调度决策成为可能,进而为基于 SLA 的放置、成本优化以及性能感知的工作负载分配打开新局面。
容忍度的演进
历史上,Kubernetes 支持两种主要的容忍度运算符:
| 操作符 | 行为 |
|---|---|
| 等于 | 如果键 和 值完全相等,则匹配污点 |
| 存在 | 如果键存在(不论值为何),则匹配污点 |
这些在分类场景下表现良好,但在数值比较方面不足。从 v1.35 开始,我们填补了这一空白。
数值运算符启用的真实场景
- SLA 要求 – 仅在故障概率 低于 阈值的节点上调度高可用工作负载。
- 成本优化 – 允许对成本敏感的批处理作业在成本每小时超过特定值的更便宜节点上运行。
- 性能保证 – 确保对延迟敏感的应用仅在磁盘 IOPS 或网络带宽 高于 最小阈值的节点上运行。
如果没有数值比较运算符,集群运维人员不得不采用难以扩展且缺乏灵活性的变通办法。
为什么扩展 tolerations 而不是使用 NodeAffinity?
NodeAffinity 已经支持数值比较运算符,为什么还要把它们加到 tolerations?
| 方面 | NodeAffinity | Taints & Tolerations |
|---|---|---|
| 策略导向 | 按 Pod;每个工作负载必须显式选择不使用风险节点。 | 节点侧策略;节点声明其风险等级,只有带匹配 tolerations 的 Pod 才能落在其上。更安全的默认。 |
| 驱逐语义 | 无驱逐能力。 | 支持 NoExecute 效果和 tolerationSeconds,在节点 SLA 降级或 Spot 实例收到终止通知时实现平滑排空。 |
| 运维便利性 | 分散在多个 Pod 规范中。 | 集中式、节点侧策略与现有安全 taint(如 disk-pressure、memory-pressure)保持一致。 |
扩展 tolerations 保持了人们熟悉的安全模型,同时为基于 SLA 的调度提供了阈值式的放置能力。
介绍 Gt 和 Lt 运算符
Kubernetes v1.35 为容忍度(tolerations)添加了两个新运算符:
| Operator | Meaning |
|---|---|
| Gt (Greater‑Than) | 当 污点的数值 小于 容忍度的值 时匹配。 |
| Lt (Less‑Than) | 当 污点的数值 大于 容忍度的值 时匹配。 |
当 Pod 对带有 Lt 的污点进行容忍时,它表示“我可以容忍该指标 低于 我的阈值的节点”。由于容忍度允许调度,Pod 可以运行在污点值 高于 容忍度值的节点上——即“我容忍高于我的最低要求的节点”。
这些运算符适用于 数值型污点值,并可用于 所有污点效果:NoSchedule、NoExecute 和 PreferNoSchedule。
注意
Gt和Lt的数值必须是正的 64 位整数,不能有前导零。例如,"100"是有效的,但"0100"(前导零)和"0"(零值)均不被允许。
用例与示例
示例 1 – 使用 SLA 阈值的 Spot 实例保护
许多集群混合使用按需和 Spot/抢占式节点以优化成本。Spot 节点可以节省费用,但故障率更高。目标:大多数工作负载默认避免使用 Spot 节点,而特定工作负载可以在明确的 SLA 边界内选择使用。
1️⃣ 使用其故障概率对 Spot 节点进行污点标记(例如,年故障率 15 %)
apiVersion: v1
kind: Node
metadata:
name: spot-node-1
spec:
taints:
- key: "failure-probability"
value: "15"
effect: "NoExecute"
2️⃣ 使用较低故障率对按需节点进行污点标记
apiVersion: v1
kind: Node
metadata:
name: ondemand-node-1
spec:
taints:
- key: "failure-probability"
value: "2"
effect: "NoExecute"
3️⃣ 需要严格 SLA 的关键工作负载(≤ 5 % 故障概率)
apiVersion: v1
kind: Pod
metadata:
name: payment-processor
spec:
tolerations:
- key: "failure-probability"
operator: "Lt"
value: "5"
effect: "NoExecute"
tolerationSeconds: 30 # 当节点的 SLA 降低时的宽限期
containers:
- name: app
image: payment-app:v1
结果:该 Pod 仅会调度到 failure-probability 小于 5 的节点上(即 ondemand-node-1,值为 2)。NoExecute 效果配合 tolerationSeconds: 30 为 Pod 提供 30 秒的宽限期,以便在节点污点值变化时优雅关闭。
4️⃣ 容错批处理作业,明确选择使用 Spot 实例
apiVersion: v1
kind: Pod
metadata:
name: batch-job
spec:
tolerations:
- key: "failure-probability"
operator: "Gt"
value: "10"
effect: "NoExecute"
tolerationSeconds: 60
containers:
- name: worker
image: batch-worker:v2
结果:该 Pod 能容忍故障概率 大于 10 的节点(即 Spot 节点)。如果 Spot 节点的故障概率随后降至阈值以下,Pod 将在 60 秒宽限期后被驱逐。
示例 2 – AI 工作负载的 GPU 分层放置
1. 使用计算能力分数对 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"
2. 重训练工作负载 – 需要高性能 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 上。
3. 推理工作负载 – 可使用任何可用的 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
该 Pod 将调度到任何计算分数 > 400 的节点上,覆盖 A100 和 T4 节点。
示例 3 – 成本优化的工作负载放置
1. 使用成本评级对节点进行污点标记
spec:
taints:
- key: "cost-per-hour"
value: "50"
effect: "NoSchedule"
2. 对成本敏感的批处理作业 – 只容忍低成本节点
tolerations:
- key: "cost-per-hour"
operator: "Lt"
value: "100"
effect: "NoSchedule"
*该作业将调度到成本 < $100 / hour 的节点上,避免使用更昂贵
k-iops"
operator: "Gt"
value: "3000"
effect: "NoSchedule"
该 Pod 只会调度到 disk-iops 超过 3000 的节点上。
如何使用此功能
Extended Toleration Operators 是 Kubernetes v1.35 中的 alpha 特性。
-
在 API 服务器和调度器上 启用特性门:
--feature-gates=TaintTolerationComparisonOperators=true -
使用表示调度需求相关指标的数值 污点(taint)您的节点:
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"
注意
- 作为 alpha 特性,Extended Toleration Operators 可能在后续版本中发生变化。
- 在生产环境中使用时请谨慎,并首先在非生产集群中进行充分测试。
接下来是什么?
此 alpha 版仅是开始。随着我们收集社区反馈,计划:
- 在容忍度和节点亲和性中添加对 CEL(通用表达式语言) 表达式的支持,以实现更灵活的调度逻辑,包括语义版本比较。
- 改进与 集群自动伸缩 的集成,实现阈值感知的容量规划。
- 将该功能提升至 beta,最终达到 GA,具备生产就绪的稳定性。
我们特别希望了解您的使用案例!
您是否有阈值调度可以解决的问题场景?
您希望看到哪些额外的运算符或功能?
Getting Involved
该功能由 SIG Scheduling 社区驱动。欢迎加入我们,分享想法和反馈:
- Slack:
#sig-scheduling(Kubernetes Slack 工作区) - 邮件列表:
kubernetes-sig-scheduling@googlegroups.com
如有关于扩展容忍度运算符的具体咨询,请联系 SIG Scheduling 社区。期待您的来信!
了解更多
- 污点和容忍 – 节点‑Pod 调度的基础
- 数值比较运算符 – 使用
Gt和Lt运算符的细节 - KEP‑5471: 阈值驱动放置的扩展容忍运算符