存储类
本文档描述了 Kubernetes 中 StorageClass 的概念。建议熟悉卷和持久卷。
StorageClass 为管理员提供了一种描述他们所提供的存储“类别”的方式。不同的类别可能映射到服务质量级别、备份策略或由集群管理员确定的任意策略。Kubernetes 本身对这些类别代表什么没有固定的看法。
Kubernetes 中存储类的概念类似于某些其他存储系统设计中的“配置文件”。
StorageClass 对象
每个 StorageClass 都包含 `provisioner`、`parameters` 和 `reclaimPolicy` 字段,这些字段用于在需要动态提供属于该类的 PersistentVolume 以满足 PersistentVolumeClaim (PVC) 时。
StorageClass 对象的名称很重要,它决定了用户如何请求特定类。管理员在首次创建 StorageClass 对象时设置类的名称和其他参数。
作为管理员,你可以指定一个默认 StorageClass,它适用于任何未请求特定类的 PVC。有关更多详细信息,请参阅PersistentVolumeClaim 概念。
以下是一个 StorageClass 示例
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: low-latency
annotations:
storageclass.kubernetes.io/is-default-class: "false"
provisioner: csi-driver.example-vendor.example
reclaimPolicy: Retain # default value is Delete
allowVolumeExpansion: true
mountOptions:
- discard # this might enable UNMAP / TRIM at the block storage layer
volumeBindingMode: WaitForFirstConsumer
parameters:
guaranteedReadWriteLatency: "true" # provider-specific
默认 StorageClass
你可以将一个 StorageClass 标记为集群的默认 StorageClass。有关设置默认 StorageClass 的说明,请参阅更改默认 StorageClass。
当 PVC 未指定 `storageClassName` 时,将使用默认 StorageClass。
如果你的集群中有多个 StorageClass 的`storageclass.kubernetes.io/is-default-class` 注解设置为 true,然后你创建了一个未设置 `storageClassName` 的 PersistentVolumeClaim,Kubernetes 将使用最近创建的默认 StorageClass。
注意
你应该尝试在集群中只保留一个标记为默认的 StorageClass。Kubernetes 允许你有多个默认 StorageClass 的原因是为了实现无缝迁移。你可以创建 PersistentVolumeClaim 而不为新的 PVC 指定 `storageClassName`,即使集群中不存在默认 StorageClass 也可以。在这种情况下,新的 PVC 将按照你定义的方式创建,并且该 PVC 的 `storageClassName` 将保持未设置状态,直到默认 StorageClass 可用。
你可以拥有一个没有任何默认 StorageClass 的集群。如果你没有将任何 StorageClass 标记为默认(并且例如,云提供商也没有为你设置一个),那么 Kubernetes 无法为需要默认 StorageClass 的 PersistentVolumeClaim 应用该默认值。
如果或当默认 StorageClass 可用时,控制平面会识别任何现有的没有 `storageClassName` 的 PVC。对于 `storageClassName` 值为空或没有此键的 PVC,控制平面会更新这些 PVC 以将 `storageClassName` 设置为与新的默认 StorageClass 匹配。如果你有一个现有的 PVC,其 `storageClassName` 为 `""`,并且你配置了一个默认 StorageClass,则此 PVC 不会被更新。
为了继续绑定到 `storageClassName` 设置为 `""` 的 PV(在存在默认 StorageClass 的情况下),你需要将关联的 PVC 的 `storageClassName` 设置为 `""`。
制备器
每个 StorageClass 都有一个制备器,它决定了用于制备 PV 的卷插件。此字段必须指定。
卷插件 | 内部制备器 | 配置示例 |
---|---|---|
AzureFile | ✓ | Azure 文件 |
CephFS | - | - |
FC | - | - |
FlexVolume | - | - |
iSCSI | - | - |
Local | - | Local |
NFS | - | NFS |
PortworxVolume | ✓ | Portworx 卷 |
RBD | - | Ceph RBD |
VsphereVolume | ✓ | vSphere |
你不仅限于指定此处列出的“内部”制备器(其名称以“kubernetes.io”为前缀并随 Kubernetes 一起发布)。你还可以运行和指定外部制备器,它们是遵循 Kubernetes 定义的规范的独立程序。外部制备器的作者对其代码的存储位置、制备器的发布方式、运行方式、使用的卷插件(包括 Flex)等拥有完全的自由裁量权。仓库 kubernetes-sigs/sig-storage-lib-external-provisioner 包含一个用于编写实现大部分规范的外部制备器的库。一些外部制备器列在仓库 kubernetes-sigs/sig-storage-lib-external-provisioner 下。
例如,NFS 没有提供内部制备器,但可以使用外部制备器。第三方存储厂商提供自己的外部制备器的情况也存在。
回收策略
由 StorageClass 动态创建的 PersistentVolumes 将具有在该类的 `reclaimPolicy` 字段中指定的回收策略,该策略可以是 `Delete` 或 `Retain`。如果在创建 StorageClass 对象时未指定 `reclaimPolicy`,则默认为 `Delete`。
手动创建并通过 StorageClass 管理的 PersistentVolumes 将具有在创建时分配的任何回收策略。
卷扩容
PersistentVolumes 可以配置为可扩容。这允许你通过编辑相应的 PVC 对象并请求新的更大存储量来调整卷大小。
当底层 StorageClass 将 `allowVolumeExpansion` 字段设置为 true 时,以下卷类型支持卷扩容。
卷类型 | 卷扩容所需的 Kubernetes 版本 |
---|---|
Azure 文件 | 1.11 |
CSI | 1.24 |
FlexVolume | 1.13 |
Portworx | 1.11 |
rbd | 1.11 |
注意
你只能使用卷扩容功能来增加卷,而不能缩小卷。挂载选项
由 StorageClass 动态创建的 PersistentVolumes 将具有在该类的 `mountOptions` 字段中指定的挂载选项。
如果卷插件不支持挂载选项但指定了挂载选项,则制备将失败。挂载选项在类或 PV 上均不进行验证。如果挂载选项无效,则 PV 挂载失败。
卷绑定模式
`volumeBindingMode` 字段控制卷绑定和动态制备何时发生。未设置时,默认为 `Immediate` 模式。
`Immediate` 模式表示一旦 PersistentVolumeClaim 创建,就会发生卷绑定和动态制备。对于受拓扑限制且无法从集群中所有节点全局访问的存储后端,PersistentVolumes 将在不知道 Pod 调度要求的情况下进行绑定或制备。这可能导致 Pod 无法调度。
集群管理员可以通过指定 `WaitForFirstConsumer` 模式来解决此问题,该模式将延迟 PersistentVolume 的绑定和制备,直到创建使用 PersistentVolumeClaim 的 Pod。PersistentVolumes 将根据 Pod 调度约束指定的拓扑进行选择或制备。这些约束包括但不限于资源要求、节点选择器、Pod 亲和性与反亲和性以及污点和容忍度。
以下插件支持带有动态制备的 `WaitForFirstConsumer`
- CSI 卷,前提是特定的 CSI 驱动程序支持此功能
以下插件支持带有预创建 PersistentVolume 绑定的 `WaitForFirstConsumer`
- CSI 卷,前提是特定的 CSI 驱动程序支持此功能
本地
注意
如果你选择使用 `WaitForFirstConsumer`,请不要在 Pod 规约中使用 `nodeName` 来指定节点亲和性。如果在此情况下使用 `nodeName`,调度器将被绕过,PVC 将保持 `pending` 状态。
相反,你可以使用 `kubernetes.io/hostname` 的节点选择器
apiVersion: v1
kind: Pod
metadata:
name: task-pv-pod
spec:
nodeSelector:
kubernetes.io/hostname: kube-01
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: task-pv-claim
containers:
- name: task-pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage
允许的拓扑
当集群操作员指定 `WaitForFirstConsumer` 卷绑定模式时,在大多数情况下不再需要将制备限制到特定拓扑。但是,如果仍然需要,可以指定 `allowedTopologies`。
此示例演示了如何将已制备卷的拓扑限制到特定区域,并应作为受支持插件的 `zone` 和 `zones` 参数的替代品。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standard
provisioner: example.com/example
parameters:
type: pd-standard
volumeBindingMode: WaitForFirstConsumer
allowedTopologies:
- matchLabelExpressions:
- key: topology.kubernetes.io/zone
values:
- us-central-1a
- us-central-1b
参数
StorageClass 具有描述属于该存储类的卷的参数。根据 `provisioner` 的不同,可能会接受不同的参数。当省略参数时,将使用一些默认值。
一个 StorageClass 最多可以定义 512 个参数。参数对象的总长度(包括其键和值)不能超过 256 KiB。
AWS EBS
Kubernetes 1.34 不包含 `awsElasticBlockStore` 卷类型。
AWSElasticBlockStore 树内存储驱动程序在 Kubernetes v1.19 版本中被弃用,然后在 v1.27 版本中完全移除。
Kubernetes 项目建议你使用树外 AWS EBS 存储驱动程序。
以下是 AWS EBS CSI 驱动程序的 StorageClass 示例
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
parameters:
csi.storage.k8s.io/fstype: xfs
type: io1
iopsPerGB: "50"
encrypted: "true"
tagSpecification_1: "key1=value1"
tagSpecification_2: "key2=value2"
allowedTopologies:
- matchLabelExpressions:
- key: topology.ebs.csi.aws.com/zone
values:
- us-east-2c
`tagSpecification`: 带有此前缀的标签将应用于动态制备的 EBS 卷。
AWS EFS
要配置 AWS EFS 存储,你可以使用树外 AWS_EFS_CSI_DRIVER。
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: efs-sc
provisioner: efs.csi.aws.com
parameters:
provisioningMode: efs-ap
fileSystemId: fs-92107410
directoryPerms: "700"
- `provisioningMode`: 由 Amazon EFS 制备的卷类型。目前,仅支持基于接入点的制备(`efs-ap`)。
- `fileSystemId`: 创建接入点所在的 文件系统。
- `directoryPerms`: 接入点创建的根目录的目录权限。
有关更多详细信息,请参阅 AWS_EFS_CSI_Driver 动态制备 文档。
NFS
要配置 NFS 存储,你可以使用树内驱动程序或 Kubernetes 的 NFS CSI 驱动程序(推荐)。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: example-nfs
provisioner: example.com/external-nfs
parameters:
server: nfs-server.example.com
path: /share
readOnly: "false"
- `server`: 服务器是 NFS 服务器的主机名或 IP 地址。
- `path`: NFS 服务器导出的路径。
- `readOnly`: 一个标志,指示存储是否以只读方式挂载(默认为 false)。
Kubernetes 不包含内部 NFS 制备器。你需要使用外部制备器为 NFS 创建 StorageClass。以下是一些示例
vSphere
vSphere 存储类有两种制备器:
树内制备器已弃用。有关 CSI 制备器的更多信息,请参见Kubernetes vSphere CSI 驱动程序和vSphereVolume CSI 迁移。
CSI 制备器
vSphere CSI StorageClass 制备器与 Tanzu Kubernetes 集群配合使用。有关示例,请参阅 vSphere CSI 仓库。
vCP 制备器
以下示例使用 VMware Cloud Provider (vCP) StorageClass 制备器。
创建一个具有用户指定磁盘格式的 StorageClass。
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast provisioner: kubernetes.io/vsphere-volume parameters: diskformat: zeroedthick
`diskformat`:`thin`、`zeroedthick` 和 `eagerzeroedthick`。默认值:`"thin"`。
在用户指定的数据存储上创建一个具有磁盘格式的 StorageClass。
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast provisioner: kubernetes.io/vsphere-volume parameters: diskformat: zeroedthick datastore: VSANDatastore
`datastore`: 用户还可以在 StorageClass 中指定数据存储。卷将创建在 StorageClass 中指定的数据存储上,在本例中为 `VSANDatastore`。此字段是可选的。如果未指定数据存储,则卷将创建在用于初始化 vSphere Cloud Provider 的 vSphere 配置文件中指定的数据存储上。
Kubernetes 内的存储策略管理
使用现有 vCenter SPBM 策略
vSphere 存储管理最重要的功能之一是基于策略的管理。存储策略基于管理 (SPBM) 是一种存储策略框架,可在广泛的数据服务和存储解决方案中提供统一的控制平面。SPBM 使 vSphere 管理员能够克服前期存储制备挑战,例如容量规划、差异化服务级别和管理容量余量。
SPBM 策略可以使用 `storagePolicyName` 参数在 StorageClass 中指定。
Kubernetes 中对 Virtual SAN 策略的支持
vSphere 基础设施 (VI) 管理员将能够在动态卷制备期间指定自定义 Virtual SAN 存储能力。你现在可以在动态卷制备期间以存储能力的形式定义存储要求,例如性能和可用性。存储能力要求将转换为 Virtual SAN 策略,然后在创建持久卷(虚拟磁盘)时将其推送到 Virtual SAN 层。虚拟磁盘分布在 Virtual SAN 数据存储上以满足要求。
你可以查看基于存储策略的卷动态制备以获取有关如何使用存储策略进行持久卷管理的更多详细信息。
有几个vSphere 示例,你可以尝试在 Kubernetes 中为 vSphere 进行持久卷管理。
Ceph RBD (已弃用)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/rbd # This provisioner is deprecated
parameters:
monitors: 198.19.254.105:6789
adminId: kube
adminSecretName: ceph-secret
adminSecretNamespace: kube-system
pool: kube
userId: kube
userSecretName: ceph-secret-user
userSecretNamespace: default
fsType: ext4
imageFormat: "2"
imageFeatures: "layering"
`monitors`: Ceph 监视器,逗号分隔。此参数是必需的。
`adminId`: 能够在池中创建映像的 Ceph 客户端 ID。默认为 "admin"。
`adminSecretName`: `adminId` 的 Secret 名称。此参数是必需的。提供的 Secret 必须具有 "kubernetes.io/rbd" 类型。
`adminSecretNamespace`: `adminSecretName` 的命名空间。默认为 "default"。
`pool`: Ceph RBD 池。默认为 "rbd"。
`userId`: 用于映射 RBD 映像的 Ceph 客户端 ID。默认为与 `adminId` 相同。
`userSecretName`: 用于映射 RBD 映像的 `userId` 的 Ceph Secret 名称。它必须与 PVC 位于同一命名空间中。此参数是必需的。提供的 Secret 必须具有 "kubernetes.io/rbd" 类型,例如通过以下方式创建
kubectl create secret generic ceph-secret --type="kubernetes.io/rbd" \ --from-literal=key='QVFEQ1pMdFhPUnQrSmhBQUFYaERWNHJsZ3BsMmNjcDR6RFZST0E9PQ==' \ --namespace=kube-system
`userSecretNamespace`: `userSecretName` 的命名空间。
`fsType`: Kubernetes 支持的 fsType。默认值:`"ext4"`。
`imageFormat`: Ceph RBD 映像格式,"1" 或 "2"。默认为 "2"。
`imageFeatures`: 此参数是可选的,仅当您将 `imageFormat` 设置为 "2" 时才应使用。目前支持的功能仅为 `layering`。默认为 "",并且未启用任何功能。
Azure 磁盘
Kubernetes 1.34 不包含 `azureDisk` 卷类型。
`azureDisk` 树内存储驱动程序在 Kubernetes v1.19 版本中被弃用,然后在 v1.27 版本中完全移除。
Kubernetes 项目建议你使用 Azure Disk 第三方存储驱动程序。
Azure 文件 (已弃用)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: azurefile
provisioner: kubernetes.io/azure-file
parameters:
skuName: Standard_LRS
location: eastus
storageAccount: azure_storage_account_name # example value
- `skuName`: Azure 存储帐户 SKU 层。默认值为空。
- `location`: Azure 存储帐户位置。默认值为空。
- `storageAccount`: Azure 存储帐户名称。默认为空。如果未提供存储帐户,则会搜索与资源组关联的所有存储帐户,以查找与 `skuName` 和 `location` 匹配的存储帐户。如果提供了存储帐户,它必须与集群位于同一资源组中,并且 `skuName` 和 `location` 将被忽略。
- `secretNamespace`: 包含 Azure 存储帐户名称和密钥的 Secret 命名空间。默认为 Pod 所在的命名空间。
- `secretName`: 包含 Azure 存储帐户名称和密钥的 Secret 名称。默认为 `azure-storage-account-
-secret` - `readOnly`: 一个标志,指示存储是否以只读方式挂载。默认为 false,表示读/写挂载。此设置也将影响 VolumeMounts 中的 `ReadOnly` 设置。
在存储制备期间,将为挂载凭据创建一个名为 `secretName` 的 Secret。如果集群同时启用了 RBAC 和 控制器角色,请为集群角色 `system:controller:persistent-volume-binder` 添加资源 `secret` 的 `create` 权限。
在多租户环境中,强烈建议显式设置 `secretNamespace` 的值,否则存储帐户凭据可能会被其他用户读取。
Portworx 卷 (已弃用)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: portworx-io-priority-high
provisioner: kubernetes.io/portworx-volume # This provisioner is deprecated
parameters:
repl: "1"
snap_interval: "70"
priority_io: "high"
- `fs`: 要布局的文件系统:`none/xfs/ext4`(默认:`ext4`)。
- `block_size`: 块大小,以 Kbytes 为单位(默认值:`32`)。
- `repl`: 要提供的同步副本数量,以复制因子 `1..3` 的形式(默认值:`1`)。此处预期为字符串,即 `"1"` 而非 `1`。
- `priority_io`: 决定卷是从高性能存储还是低优先级存储创建 `high/medium/low`(默认值:`low`)。
- `snap_interval`: 触发快照的时间间隔,以分钟为单位。快照是基于与之前快照的差异的增量快照,0 表示禁用快照(默认值:`0`)。此处预期为字符串,即 `"70"` 而非 `70`。
- `aggregation_level`: 指定卷将分发的块数,0 表示非聚合卷(默认值:`0`)。此处预期为字符串,即 `"0"` 而非 `0`
- `ephemeral`: 指定卷在卸载后是否应清除或应持久化。`emptyDir` 用例可以将此值设置为 true,而 `persistent volumes` 用例(例如 Cassandra 等数据库)应设置为 false,`true/false`(默认值 `false`)。此处预期为字符串,即 `"true"` 而非 `true`。
Local
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner # indicates that this StorageClass does not support automatic provisioning
volumeBindingMode: WaitForFirstConsumer
Kubernetes 1.34 中的本地卷不支持动态制备;但是,仍应创建 StorageClass 以延迟卷绑定,直到 Pod 实际调度到适当的节点。这由 `WaitForFirstConsumer` 卷绑定模式指定。
延迟卷绑定允许调度器在为 PersistentVolumeClaim 选择合适的 PersistentVolume 时考虑 Pod 的所有调度约束。