存储类
本文档介绍了 Kubernetes 中 StorageClass 的概念。建议您熟悉卷和持久卷。
StorageClass 提供了一种让管理员描述他们提供的存储类别的方法。不同的类别可以映射到服务质量级别,或备份策略,或由集群管理员确定的任意策略。Kubernetes 本身对类别代表什么没有预设的观点。
Kubernetes 的存储类概念类似于其他一些存储系统设计中的“配置文件”。
StorageClass 对象
每个 StorageClass 都包含 provisioner
、parameters
和 reclaimPolicy
字段,当需要动态配置属于该类的 PersistentVolume 以满足 PersistentVolumeClaim(PVC)时会使用这些字段。
StorageClass 对象的名称非常重要,用户可以通过它来请求特定的类。管理员在首次创建 StorageClass 对象时会设置类的名称和其他参数。
作为管理员,您可以指定适用于任何未请求特定类别的 PVC 的默认 StorageClass。有关更多详细信息,请参阅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 标记为默认值(并且例如云提供商没有为您设置),则 Kubernetes 无法对需要它的 PersistentVolumeClaim 应用默认值。
当默认 StorageClass 可用时,控制平面会识别没有 storageClassName
的任何现有 PVC。对于 storageClassName
的值为空或没有此键的 PVC,控制平面会更新这些 PVC 以将 storageClassName
设置为与新的默认 StorageClass 匹配。如果您有一个 storageClassName
为 ""
的现有 PVC,并且您配置了默认 StorageClass,则此 PVC 不会被更新。
为了在存在默认 StorageClass 的情况下,保持与 storageClassName
设置为 ""
的 PV 的绑定,您需要将关联的 PVC 的 storageClassName
设置为 ""
。
Provisioner
每个 StorageClass 都有一个 provisioner,用于确定用于配置 PV 的卷插件。必须指定此字段。
卷插件 | 内部 Provisioner | 配置示例 |
---|---|---|
AzureFile | ✓ | Azure 文件 |
CephFS | - | - |
FC | - | - |
FlexVolume | - | - |
iSCSI | - | - |
Local | - | Local |
NFS | - | NFS |
PortworxVolume | ✓ | Portworx 卷 |
RBD | - | Ceph RBD |
VsphereVolume | ✓ | vSphere |
您不仅限于指定此处列出的“内部” Provisioner(其名称以“kubernetes.io”为前缀,并与 Kubernetes 一起提供)。您还可以运行和指定外部 provisioner,这些 provisioner 是独立的程序,遵循 Kubernetes 定义的规范。外部 provisioner 的作者可以完全自行决定其代码的存储位置、provisioner 的交付方式、运行方式、它使用的卷插件(包括 Flex)等。kubernetes-sigs/sig-storage-lib-external-provisioner 存储库包含一个用于编写外部 provisioner 的库,该库实现了规范的大部分内容。一些外部 provisioner 列在 kubernetes-sigs/sig-storage-lib-external-provisioner 存储库下。
例如,NFS 不提供内部 provisioner,但可以使用外部 provisioner。在某些情况下,第三方存储供应商会提供自己的外部 provisioner。
回收策略
由 StorageClass 动态创建的 PersistentVolume 将具有在类的 reclaimPolicy
字段中指定的回收策略,该策略可以是 Delete
或 Retain
。如果在创建 StorageClass 对象时未指定 reclaimPolicy
,则默认值为 Delete
。
手动创建并通过 StorageClass 管理的 PersistentVolume 将具有它们在创建时分配的任何回收策略。
卷扩展
PersistentVolume 可以配置为可扩展。这允许您通过编辑相应的 PVC 对象来调整卷的大小,从而请求更大的存储量。
当底层 StorageClass 的 allowVolumeExpansion
字段设置为 true 时,以下类型的卷支持卷扩展。
卷类型 | 卷扩展所需的 Kubernetes 版本 |
---|---|
Azure 文件 | 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 驱动程序支持此功能
以下插件支持使用预创建的 PersistentVolume 绑定的 WaitForFirstConsumer
- 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.32 不包含 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 云提供程序 vSphere 配置文件中指定的数据存储上创建。Kubernetes 内的存储策略管理
使用现有的 vCenter SPBM 策略
vSphere 存储管理最重要的功能之一是基于策略的管理。存储策略基于管理 (SPBM) 是一个存储策略框架,它为各种数据服务和存储解决方案提供了一个统一的控制平面。SPBM 使 vSphere 管理员能够克服预先的存储配置难题,例如容量规划、差异化的服务级别和管理容量余量。
可以使用
storagePolicyName
参数在 StorageClass 中指定 SPBM 策略。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.32 不包含 azureDisk
卷类型。
azureDisk
内置存储驱动程序已在 Kubernetes v1.19 版本中弃用,然后在 v1.27 版本中完全删除。
Kubernetes 项目建议您改用 Azure 磁盘第三方存储驱动程序。
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-<accountName>-secret
readOnly
:一个标志,指示存储是否将以只读方式挂载。默认为 false,表示读/写挂载。此设置也将影响 VolumeMounts 中的ReadOnly
设置。
在存储配置期间,将创建一个名为 secretName
的 Secret,用于挂载凭据。如果集群同时启用了 RBAC 和 控制器角色,请为 clusterrole 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.32 中不支持动态配置;但是,仍应创建 StorageClass,以延迟卷绑定,直到 Pod 实际调度到相应的节点。这由 WaitForFirstConsumer
卷绑定模式指定。
延迟卷绑定允许调度程序在为 PersistentVolumeClaim 选择适当的 PersistentVolume 时考虑 Pod 的所有调度约束。