存储类
本文档描述了 Kubernetes 中的 StorageClass 概念。建议您熟悉volume和persistent volume。
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。
当 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 无法为需要默认设置的 PersistentVolumeClaims 应用该默认值。
如果或当默认 StorageClass 可用时,控制平面会识别所有未设置 storageClassName
的现有 PVC。对于 storageClassName
值为空或没有此键的 PVC,控制平面会更新这些 PVC,将其 storageClassName
设置为新的默认 StorageClass。如果你有一个现有的 PVC 的 storageClassName
为 ""
,并且你配置了默认 StorageClass,则此 PVC 不会被更新。
为了继续绑定 storageClassName
设置为 ""
的 PV(即使存在默认 StorageClass),你需要将关联的 PVC 的 storageClassName
设置为 ""
。
供应者
每个 StorageClass 都有一个供应者,它决定了使用哪个卷插件来供应 PV。此字段必须指定。
卷插件 | 内置供应者 | 配置示例 |
---|---|---|
AzureFile | ✓ | Azure File |
CephFS | - | - |
FC | - | - |
FlexVolume | - | - |
iSCSI | - | - |
Local | - | Local |
NFS | - | NFS |
PortworxVolume | ✓ | Portworx Volume |
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 动态创建的 PersistentVolume 将具有在类的 reclaimPolicy
字段中指定的回收策略,该策略可以是 Delete
或 Retain
。如果创建 StorageClass 对象时未指定 reclaimPolicy
,则默认值为 Delete
。
手动创建并通过 StorageClass 管理的 PersistentVolume 将具有创建时分配给它们的回收策略。
卷扩容
可以将 PersistentVolume 配置为可扩容。这允许你通过编辑相应的 PVC 对象,请求更大的存储容量来调整卷的大小。
当底层 StorageClass 将 allowVolumeExpansion
字段设置为 true 时,以下类型的卷支持卷扩容。
卷类型 | 卷扩容所需的 Kubernetes 版本 |
---|---|
Azure File | 1.11 |
CSI | 1.24 |
FlexVolume | 1.13 |
Portworx | 1.11 |
rbd | 1.11 |
注意
你只能使用卷扩容功能来增大卷,而不能缩小它。挂载选项
由 StorageClass 动态创建的 PersistentVolume 将具有在该类的 mountOptions
字段中指定的挂载选项。
如果卷插件不支持挂载选项但指定了挂载选项,则供应将失败。挂载选项在类或 PV 上均未进行验证。如果挂载选项无效,则 PV 挂载会失败。
卷绑定模式
volumeBindingMode
字段控制何时进行卷绑定和动态供应。未设置时,默认使用 Immediate
模式。
Immediate
模式表示 PersistentVolumeClaim 创建后立即进行卷绑定和动态供应。对于拓扑受限且无法从集群中所有节点全局访问的存储后端,PersistentVolume 的绑定或供应将在不知道 Pod 调度要求的情况下进行。这可能导致 Pod 无法调度。
集群管理员可以通过指定 WaitForFirstConsumer
模式来解决此问题,该模式会延迟 PersistentVolume 的绑定和供应,直到使用该 PersistentVolumeClaim 的 Pod 创建为止。PersistentVolume 将根据 Pod 的调度约束指定的拓扑结构进行选择或供应。这些约束包括但不限于资源需求、节点选择器、Pod 亲和性和反亲和性,以及污点和容忍度。
以下插件支持使用 WaitForFirstConsumer
进行动态供应
- CSI 卷,前提是特定的 CSI 驱动程序支持此功能
以下插件支持使用 WaitForFirstConsumer
进行预创建 PersistentVolume 绑定
- CSI 卷,前提是特定的 CSI 驱动程序支持此功能
local
注意
如果你选择使用 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.33 不包含 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
: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 策略可以在 StorageClass 中使用
storagePolicyName
参数指定。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 支持的文件系统类型。默认值:"ext4"
。imageFormat
:Ceph RBD 镜像格式,"1" 或 "2"。默认值为 "2"。imageFeatures
:此参数是可选的,仅在你将imageFormat
设置为 "2" 时使用。当前支持的功能仅为layering
。默认值为 "",表示未开启任何功能。
Azure Disk
Kubernetes 1.33 不包含 azureDisk
卷类型。
azureDisk
树内存储驱动程序在 Kubernetes v1.19 版本中被弃用,然后在 v1.27 版本中被完全移除。
Kubernetes 项目建议你使用Azure Disk 第三方存储驱动程序作为替代。
Azure File (已弃用)
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-<accountName>-secret
readOnly
:一个标志,指示存储是否将挂载为只读。默认为 false,表示读写挂载。此设置也会影响 VolumeMounts 中的ReadOnly
设置。
在存储供应期间,会创建一个由 secretName
命名的 Secret,用于存储挂载凭据。如果集群同时启用了RBAC和Controller Roles,则为集群角色 system:controller:persistent-volume-binder
添加资源 secret
的 create
权限。
在多租户环境中,强烈建议明确设置 secretNamespace
的值,否则存储账号凭据可能会被其他用户读取。
Portworx Volume (已弃用)
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.33 中不支持动态制备;但是,仍然应创建一个 StorageClass 以延迟卷绑定,直到 Pod 实际调度到适当的节点。这由 WaitForFirstConsumer
卷绑定模式指定。
延迟卷绑定允许调度器在为 PersistentVolumeClaim 选择合适的 PersistentVolume 时考虑 Pod 的所有调度约束。