---
layout: blog
title: "Kubernetes 1.26:可追溯的默认 StorageClass"
date: 2023-01-05
slug: retroactive-default-storage-class
---
**作者:** Roman Bednář (Red Hat)
**译者:** Michael Yao (DaoCloud)
Kubernetes v1.25 引入了一个 Alpha 特性来更改默认 StorageClass 被分配到 PersistentVolumeClaim (PVC) 的方式。
启用此特性后,你不再需要先创建默认 StorageClass,再创建 PVC 来分配类。
此外,任何未分配 StorageClass 的 PVC 都可以在后续被更新。此特性在 Kubernetes 1.26 中已进阶至 Beta。
有关如何使用的更多细节,请参阅 Kubernetes
文档[可追溯的默认 StorageClass 赋值](/zh-cn/docs/concepts/storage/persistent-volumes/#retroactive-default-storageclass-assignment),
你还可以阅读了解为什么 Kubernetes 项目做了此项变更。
## 为什么 StorageClass 赋值需要改进 {#why-did-sc-assignment-need-improvements}
用户可能已经熟悉在创建时将默认 StorageClasses 分配给**新** PVC 的这一类似特性。
这个目前由[准入控制器](/zh-cn/docs/reference/access-authn-authz/admission-controllers/#defaultstorageclass)处理。
但是,如果在创建 PVC 时没有定义默认 StorageClass 会怎样?
那用户最终将得到一个永远不会被赋予存储类的 PVC。结果是没有存储会被制备,而 PVC 有时也会“卡在”这里。
一般而言,两个主要场景可能导致 PVC “卡住”,并在后续造成更多问题。让我们仔细看看这两个场景。
### 更改默认 StorageClass {#changing-default-storageclass}
启用这个 Alpha 特性后,管理员想要更改默认 StorageClass 时会有两个选项:
1. 在移除与 PVC 关联的旧 StorageClass 之前,创建一个新的 StorageClass 作为默认值。
这将导致在短时间内出现两个默认值。此时,如果用户要创建一个 PersistentVolumeClaim,
并将 storageClassName 设置为 null
(指代默认 StorageClass),
则最新的默认 StorageClass 将被选中并指定给这个 PVC。
2. 先移除旧的默认值再创建一个新的默认 StorageClass。这将导致短时间内没有默认值。
接下来如果用户创建一个 PersistentVolumeClaim,并将 storageClassName 设置为 null
(指代默认 StorageClass),则 PVC 将永远处于 Pending
状态。
一旦默认 StorageClass 可用,用户就不得不通过删除并重新创建 PVC 来修复这个问题。
### 集群安装期间的资源顺序 {#resource-ordering-during-cluster-installation}
如果集群安装工具需要创建镜像仓库这种有存储要求的资源,很难进行合适地排序。
这是因为任何有存储要求的 Pod 都将依赖于默认 StorageClass 的存在与否。
如果默认 StorageClass 未被定义,Pod 创建将失败。
## 发生了什么变化 {#what-changed}
我们更改了 PersistentVolume (PV) 控制器,以便将默认 StorageClass 指定给
storageClassName 设置为 `null` 且未被绑定的所有 PersistentVolumeClaim。
我们还修改了 API 服务器中的 PersistentVolumeClaim 准入机制,允许将取值从未设置值更改为实际的 StorageClass 名称。
### Null `storageClassName` 与 `storageClassName: ""` - 有什么影响? {#null-vs-empty-string}
此特性被引入之前,这两种赋值就其行为而言是相同的。storageClassName 设置为 `null` 或 `""`
的所有 PersistentVolumeClaim 都会被绑定到 storageClassName 也设置为 `null` 或
`""` 的、已有的 PersistentVolume 资源。
启用此新特性时,我们希望保持此行为,但也希望能够更新 StorageClass 名称。
考虑到这些限制,此特性更改了 `null` 的语义。
具体而言,如果有一个默认 StorageClass,`null` 将可被理解为 “给我一个默认值”,
而 `""` 表示 “给我 StorageClass 名称也是 `""` 的 PersistentVolume”,
所以行为将保持不变。
综上所述,我们更改了 `null` 的语义,使其行为取决于默认 StorageClass 定义的存在或缺失。
下表显示了所有这些情况,更好地描述了 PVC 何时绑定及其 StorageClass 何时被更新。
PVC storageClassName = "" |
PVC storageClassName = null |
||
---|---|---|---|
未设置默认存储类 | PV storageClassName = "" |
binds | binds |
PV without storageClassName | binds | binds | |
设置了默认存储类 | PV storageClassName = "" |
binds | 存储类更新 |
PV without storageClassName | binds | 存储类更新 |