这篇文章已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已不再正确。

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 时有两种选择

  1. 在移除与 PVC 关联的旧 StorageClass 之前,创建一个新的 StorageClass 作为默认。这会导致在短时间内存在两个默认。此时,如果用户创建一个将 storageClassName 设置为 null 的 PersistentVolumeClaim(表示默认 StorageClass),则将选择最新的默认 StorageClass 并分配给此 PVC。

  2. 首先移除旧的默认 StorageClass,然后创建一个新的默认 StorageClass。这会导致在短时间内没有默认 StorageClass。随后,如果用户创建一个将 storageClassName 设置为 null 的 PersistentVolumeClaim(表示默认 StorageClass),则该 PVC 将永远处于 Pending 状态。用户必须通过删除 PVC 并在默认 StorageClass 可用后重新创建它来解决此问题。

集群安装期间的资源顺序

如果集群安装工具需要创建需要存储的资源,例如镜像仓库,则很难正确设置顺序。这是因为任何需要存储的 Pod 都依赖于默认 StorageClass 的存在,并且如果未定义默认 StorageClass,则无法创建这些 Pod。

发生了什么变化

我们更改了 PersistentVolume (PV) 控制器,使其能够为任何 storageClassName 设置为 null 的未绑定 PersistentVolumeClaim 分配默认 StorageClass。我们还修改了 API Server 中的 PersistentVolumeClaim 准入,允许将未设置的值更改为实际的 StorageClass 名称。

Null storageClassNamestorageClassName: "" - 有区别吗?

在引入此功能之前,这些值在行为上是相同的。任何将 storageClassName 设置为 null"" 的 PersistentVolumeClaim 都将绑定到 storageClassName 也设置为 null"" 的现有 PersistentVolume 资源。

启用此新功能后,我们希望保持这种行为,同时也能更新 StorageClass 名称。考虑到这些限制,此功能改变了 null 的语义。如果存在默认 StorageClass,则 null 将转换为“给我一个默认”,而 "" 则表示“给我一个 StorageClass 名称也为 "" 的 PersistentVolume”。在没有 StorageClass 的情况下,行为将保持不变。

总结上述内容,我们更改了 null 的语义,使其行为取决于默认 StorageClass 定义的存在与否。

下表展示了所有这些情况,以便更好地描述 PVC 何时绑定以及其 StorageClass 何时更新。

启用追溯式默认 StorageClass 时的 PVC 绑定行为
PVCstorageClassName = ""PVCstorageClassName= null
没有默认类时PVstorageClassName = ""绑定绑定
没有 PVstorageClassName绑定绑定
有默认类时PVstorageClassName = ""绑定类更新
没有 PVstorageClassName绑定类更新

如何使用

如果你想在功能处于 Alpha 阶段时测试它,你需要启用 kube-controller-manager 和 kube-apiserver 中的相关 Feature Gate。使用 --feature-gates 命令行参数。

--feature-gates="...,RetroactiveDefaultStorageClass=true"

试用

如果你想查看此功能实际运行并验证它在你的集群中正常工作,你可以尝试以下操作

  1. 定义一个基本的 PersistentVolumeClaim

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: pvc-1
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi
    
  2. 在没有默认 StorageClass 时创建 PersistentVolumeClaim。此 PVC 将不会供应或绑定(除非已存在一个现有且合适的 PV),并将保持 Pending 状态。

    kubectl get pvc
    

    输出类似于此

    NAME      STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    pvc-1     Pending   
    
  3. 配置一个 StorageClass 作为默认。

    kubectl patch sc -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
    

    输出类似于此

    storageclass.storage.k8s.io/my-storageclass patched
    
  4. 验证 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 Storage 特别兴趣小组 (SIG)。

如果你想分享反馈,可以在我们的公共 Slack 频道上进行。

特别感谢所有提供出色评审、分享宝贵见解并帮助实现此功能的贡献者(按字母顺序排列)