本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
Kubernetes v1.26:追溯性默认 StorageClass
Kubernetes v1.25 版本引入了一个 Alpha 功能,用于更改默认 StorageClass 分配给 PersistentVolumeClaim (PVC) 的方式。启用该功能后,你不再需要先创建默认 StorageClass,然后再创建 PVC 来分配该类。此外,任何未分配 StorageClass 的 PVC 都可以稍后更新。此功能在 Kubernetes v1.26 中升级为 Beta。
你可以在 Kubernetes 文档中阅读追溯性默认 StorageClass 分配以了解更多使用细节,或者继续阅读以了解 Kubernetes 项目为何进行此更改。
为何 StorageClass 分配需要改进
用户可能已经熟悉一个类似的功能,该功能在创建时为新的 PVC 分配默认 StorageClass。这目前由准入控制器处理。
但是,如果在创建 PVC 时没有定义默认的 StorageClass 会怎样呢?用户最终会得到一个永远不会被分配类的 PVC。结果,不会有存储被制备,PVC 会在这一点上“卡住”。通常,两种主要场景可能导致“卡住”的 PVC 并引发后续问题。让我们仔细看看每一种情况。
更改默认 StorageClass
启用 Alpha 功能后,当管理员想要更改默认 StorageClass 时,有两种选择:
在移除与 PVC 关联的旧默认 StorageClass 之前,创建一个新的 StorageClass 作为默认。这会导致在短时间内存在两个默认值。此时,如果用户创建一个 storageClassName 设置为
null
(意味着使用默认 StorageClass)的 PersistentVolumeClaim,则会选择并分配最新的默认 StorageClass 给此 PVC。先移除旧的默认值,再创建一个新的默认 StorageClass。这会导致短时间内没有默认值。随后,如果用户创建一个 storageClassName 设置为
null
(意味着使用默认 StorageClass)的 PersistentVolumeClaim,该 PVC 将永远处于Pending
状态。用户必须通过删除 PVC 并在默认 StorageClass 可用后重新创建它来解决此问题。
集群安装期间的资源排序
如果集群安装工具需要创建需要存储的资源,例如镜像仓库,那么很难正确地确定顺序。这是因为任何需要存储的 Pod 都依赖于默认 StorageClass 的存在,如果未定义,则无法创建。
发生了什么变化
我们已经更改了 PersistentVolume (PV) 控制器,以便为任何 storageClassName 设置为 null
的未绑定 PersistentVolumeClaim 分配一个默认的 StorageClass。我们还修改了 API 服务器中的 PersistentVolumeClaim 准入,以允许将值从未设置更改为实际的 StorageClass 名称。
storageClassName
为 Null 与 storageClassName: ""
- 有关系吗?
在此功能引入之前,这些值在行为上是等效的。任何 storageClassName 设置为 null
或 ""
的 PersistentVolumeClaim 都会绑定到一个 storageClassName 也设置为 null
或 ""
的现有 PersistentVolume 资源。
启用此新功能后,我们希望保持这种行为,但同时也能更新 StorageClass 名称。考虑到这些限制,该功能改变了 null
的语义。如果存在默认 StorageClass,null
将转换为“给我一个默认的”,而 ""
将意味着“给我一个也具有 ""
StorageClass 名称的 PersistentVolume”。在没有 StorageClass 的情况下,行为将保持不变。
总结以上内容,我们改变了 null
的语义,使其行为取决于是否存在默认 StorageClass 的定义。
下表显示了所有这些情况,以更好地描述 PVC 何时绑定以及其 StorageClass 何时更新。
PVCstorageClassName = "" | PVCstorageClassName= null | ||
---|---|---|---|
没有默认类 | PVstorageClassName = "" | 绑定 | 绑定 |
没有storageClassName | 绑定 | 绑定 | |
有默认类 | PVstorageClassName = "" | 绑定 | 类更新 |
没有storageClassName | 绑定 | 类更新 |
如何使用它
如果你想在 Alpha 阶段测试该功能,你需要在 kube-controller-manager 和 kube-apiserver 中启用相关的功能门控。使用 --feature-gates
命令行参数。
--feature-gates="...,RetroactiveDefaultStorageClass=true"
试驾
如果你想看到该功能实际运行,并验证它在你的集群中是否正常工作,可以尝试以下操作:
定义一个基本的 PersistentVolumeClaim
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-1 spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi
在没有默认 StorageClass 的情况下创建 PersistentVolumeClaim。PVC 不会制备或绑定(除非已存在一个合适的 PV),并将保持在
Pending
状态。kubectl get pvc
输出类似于此
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc-1 Pending
将一个 StorageClass 配置为默认。
kubectl patch sc -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
输出类似于此
storageclass.storage.k8s.io/my-storageclass patched
验证 PersistentVolumeClaims 现在已正确制备,并已用新的默认 StorageClass 追溯性地更新。
kubectl get pvc
输出类似于此
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc-1 Bound pvc-06a964ca-f997-4780-8627-b5c3bf5a87d8 1Gi RWO my-storageclass 87m
新指标
为了帮助你看到该功能按预期工作,我们还引入了一个新的 retroactive_storageclass_total
指标,用于显示 PV 控制器尝试更新 PersistentVolumeClaim 的次数,以及 retroactive_storageclass_errors_total
指标,用于显示这些尝试中有多少次失败了。
参与进来
我们始终欢迎新的贡献者,所以如果你想参与进来,可以加入我们的 Kubernetes 存储特别兴趣小组(SIG)。
如果你想分享反馈,可以在我们的公共 Slack 频道上进行。
特别感谢所有提供出色审查、分享宝贵见解并帮助实现此功能的贡献者(按字母顺序排列):
- Deep Debroy (ddebroy)
- Divya Mohan (divya-mohan0209)
- Jan Šafránek (jsafrane)
- Joe Betz (jpbetz)
- Jordan Liggitt (liggitt)
- Michelle Au (msau42)
- Seokho Son (seokho-son)
- Shannon Kularathna (shannonxtreme)
- Tim Bannister (sftim)
- Tim Hockin (thockin)
- Wojciech Tyczynski (wojtek-t)
- Xing Yang (xing-yang)