Kubernetes v1.35 新特性:Mutable PersistentVolume Node Affinity 详解
① 背景与问题(解决了什么痛点)
在 Kubernetes 的日常运维中,PersistentVolume(PV)和 PersistentVolumeClaim(PVC)是管理持久化存储的核心资源。然而,在以往的版本中,PV 的 nodeAffinity 是不可变的,这意味着一旦 PV 被创建并绑定到某个节点,就无法再动态修改其调度策略。
这种限制在以下场景中带来了显著的问题:
场景一:集群扩容或节点变更
当集群中的节点发生变化时,例如新增了高性能 SSD 节点或需要将负载从旧节点迁移至新节点,原有的 PV 可能仍然绑定在旧节点上,导致新的 Pod 无法调度到更合适的节点,影响性能和资源利用率。
场景二:动态调整存储策略
某些应用可能需要根据不同的工作负载类型(如训练、推理、日志等)动态选择不同类型的存储节点。但若 PV 的 nodeAffinity 不可变,就无法灵活地支持这种动态调整。
场景三:故障恢复与维护
当某个节点出现故障或需要维护时,如果 PV 的 nodeAffinity 不可变,Pod 可能无法自动迁移到其他可用节点,导致服务中断。
这些痛点促使 Kubernetes 团队在 v1.35 版本中引入了 Mutable PersistentVolume Node Affinity 功能,允许用户在 PV 创建后动态更新其 nodeAffinity 策略,从而实现更灵活、更智能的存储调度。
② 核心概念/技术原理
什么是 Node Affinity?
Node Affinity 是 Kubernetes 中用于控制 Pod 调度到特定节点的机制。它通过 nodeSelector 或 nodeAffinity 字段来定义节点标签匹配规则。例如,可以指定 Pod 只能运行在带有 storage=ssd 标签的节点上。
在之前的版本中,PV 的 nodeAffinity 是只读的,只能在创建时定义,不能在后续修改。这导致了上述提到的各种问题。
Mutable Node Affinity 的核心变化
在 v1.35 中,Kubernetes 引入了对 PV 的 nodeAffinity 字段的动态更新支持。这意味着:
- 用户可以在 PV 创建后,通过
kubectl patch或直接编辑 YAML 文件的方式,修改nodeAffinity。 - Kubernetes 控制平面会检测到这一变化,并重新评估 PV 的可用性。
- 如果当前节点不再满足新的
nodeAffinity条件,系统会尝试将 PVC 绑定到符合新条件的节点上。
注意:该功能目前仍处于 Alpha 阶段,需在 kube-apiserver 和 kube-controller-manager 中启用相应的 Feature Gate。
技术实现方式
- 在 API Server 中,PV 的
nodeAffinity字段被标记为可写。 - 控制器(如 Volume Controller)会监听 PV 的变化,并根据新的 nodeAffinity 重新评估其可用性。
- 如果 PV 无法满足新的 nodeAffinity,则会触发 PVC 的重新绑定流程。
③ 实战案例/代码示例(重点章节)
场景描述:动态调整存储节点
假设我们有一个 AI 训练平台,其中训练任务需要高 IOPS 的存储,而日志任务则只需要普通存储。我们希望根据任务类型动态调整 PV 的 nodeAffinity。
步骤一:创建初始 PV(使用普通存储节点)
apiVersion: v1
kind: PersistentVolume
metadata:
name: training-pv
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: standard
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: storage
operator: In
values:
- standard
hostPath:
path: /mnt/data
我们可以用 kubectl apply 命令创建这个 PV:
kubectl apply -f training-pv.yaml
然后查看 PV 状态:
kubectl get pv training-pv
输出结果如下:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
training-pv 100Gi RWO Retain Available standard 1m
步骤二:创建 PVC 并绑定 PV
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: training-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
volumeName: training-pv
执行命令:
kubectl apply -f training-pvc.yaml
此时 PVC 会被绑定到 training-pv,并运行在带有 storage=standard 标签的节点上。
步骤三:动态更新 PV 的 nodeAffinity
现在,我们希望将该 PV 从 standard 节点迁移到 ssd 节点。我们可以使用 kubectl patch 来更新 PV 的 nodeAffinity。
kubectl patch pv training-pv --type merge -p '{"spec":{"nodeAffinity":{"required":{"nodeSelectorTerms":[{"matchExpressions":[{"key":"storage","operator":"In","values":["ssd"]}]}]}}}'
或者直接编辑 PV:
kubectl edit pv training-pv
在编辑界面中,找到 spec.nodeAffinity 并将其改为:
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: storage
operator: In
values:
- ssd
保存并退出。
步骤四:验证 PV 是否成功迁移
再次查看 PV 状态:
kubectl get pv training-pv
输出应显示状态变为 Available,并且可能已不再绑定到原来的 PVC(取决于是否配置了自动重新绑定)。
步骤五:重新绑定 PVC
如果 PVC 未自动重新绑定,可以手动删除 PVC 并重新创建:
kubectl delete pvc training-pvc
kubectl apply -f training-pvc.yaml
此时,PVC 应该被绑定到新的 PV,并运行在 storage=ssd 的节点上。
④ 架构设计/方案对比
传统方案 vs 新特性方案
| 特性 | 传统方案(v1.34 及之前) | 新特性(v1.35) |
|---|---|---|
| nodeAffinity 是否可变 | 不可变 | 可变 |
| 修改方式 | 无法直接修改,需重建 PV | 支持 kubectl patch 或直接编辑 |
| 自动重新绑定 | 无 | 支持 |
| 使用门槛 | 较高(需删除并重建) | 较低(直接更新即可) |
| 适用场景 | 静态存储分配 | 动态存储分配、弹性伸缩 |
架构图说明
以下是 PV nodeAffinity 变化的流程图(使用 Mermaid 语法):
⑤ 优劣势评估/选型建议
优势分析
- 灵活性提升:支持动态调整存储节点,适应更多业务场景。
- 减少人工干预:无需删除和重建 PV 即可修改 nodeAffinity。
- 增强自动化能力:结合 Operator 或自定义控制器,可实现更智能的存储调度策略。
- 提升资源利用率:避免因 nodeAffinity 不可变而导致的资源浪费。
劣势分析
- Alpha 功能:目前仍处于 Alpha 阶段,稳定性有待验证。
- 兼容性风险:旧版本 Kubernetes 不支持此功能,升级需谨慎。
- 配置复杂度增加:需要更细致的 nodeAffinity 策略设计。
- 潜在冲突风险:如果多个 PV 共享相同的 nodeAffinity 策略,可能会导致资源争抢。
选型建议
-
推荐使用场景:
- 需要动态调整存储策略的 AI/ML 平台
- 多租户环境下的存储隔离
- 混合云或跨数据中心部署
-
不推荐使用场景:
- 对稳定性要求极高的生产环境(建议等待 Beta 或 GA 版本)
- 使用较旧版本的 Kubernetes(低于 v1.35)
- 不熟悉 nodeAffinity 策略的团队
⑥ 总结与延伸
Kubernetes v1.35 引入的 Mutable PersistentVolume Node Affinity 是一个非常实用的功能,尤其适用于需要动态调整存储策略的场景。通过这项改进,我们可以更灵活地管理存储资源,提高系统的弹性和效率。
虽然该功能仍处于 Alpha 阶段,但在实际测试中已经展现出良好的稳定性和实用性。对于正在构建或优化 AI/ML 平台、云原生架构的企业来说,这是一个值得关注和尝试的新特性。
延伸思考
未来,随着 Kubernetes 生态的不断完善,我们可以期待更多关于存储调度的高级功能,例如:
- 基于负载的自动调度策略
- 多级 nodeAffinity 支持
- 与 CSI 插件的深度集成
如果你正在使用 Kubernetes 进行大规模存储管理,不妨尝试在测试环境中体验这一新特性,并反馈你的使用感受给社区,帮助 Kubernetes 更加完善。
更多推荐


所有评论(0)