存储类
本文档描述了 Kubernetes 中 StorageClass 的概念。建议您熟悉 卷 和 持久卷.
StorageClass 为管理员提供了一种描述他们提供的存储类别的方法。不同的类别可能映射到服务质量级别、备份策略或由集群管理员决定的任意策略。Kubernetes 本身对类别代表什么没有偏好。
Kubernetes 中的 StorageClass 概念类似于其他一些存储系统设计中的“配置文件”。
StorageClass 对象
每个 StorageClass 包含字段provisioner
、parameters
和reclaimPolicy
,这些字段在需要动态配置属于该类别的持久卷以满足持久卷声明 (PVC) 时使用。
StorageClass 对象的名称很重要,它也是用户请求特定类别的方式。管理员在首次创建 StorageClass 对象时设置类别的名称和其他参数。
作为管理员,您可以指定一个默认的 StorageClass,该 StorageClass 适用于未请求特定类别的任何 PVC。有关更多详细信息,请参见 持久卷声明概念.
以下是一个 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.kubernetes.io/is-default-class
注释设置为集群中多个 StorageClass 的 true,并且您随后创建了未设置storageClassName
的持久卷声明,Kubernetes 将使用最近创建的默认 StorageClass。
注意
您应该尝试在集群中只拥有一个标记为默认值的 StorageClass。Kubernetes 允许您拥有多个默认 StorageClass 的原因是为了允许无缝迁移。您可以在不指定新 PVC 的storageClassName
的情况下创建持久卷声明,即使您的集群中不存在默认的 StorageClass 也是如此。在这种情况下,新的 PVC 会按照您的定义创建,并且该 PVC 的storageClassName
将保持未设置状态,直到默认值可用。
您可以创建一个没有任何默认 StorageClass 的集群。如果您不标记任何 StorageClass 作为默认值(并且例如云提供商没有为您设置任何默认值),则 Kubernetes 无法为需要该默认值的持久卷声明应用该默认值。
如果或当默认的 StorageClass 可用时,控制平面将识别所有没有storageClassName
的现有 PVC。对于storageClassName
为空值或没有此键的 PVC,控制平面随后会更新这些 PVC 以将storageClassName
设置为与新的默认 StorageClass 相匹配。如果您有一个storageClassName
为""
的现有 PVC,并且您配置了一个默认的 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 动态创建的持久卷将具有在类的reclaimPolicy
字段中指定的 回收策略,该策略可以是Delete
或Retain
。如果在创建 StorageClass 对象时未指定reclaimPolicy
,它将默认为Delete
。
手动创建并通过 StorageClass 管理的持久卷将具有在创建时分配的任何回收策略。
卷扩展
持久卷可以配置为可扩展的。这允许您通过编辑相应的 PVC 对象来调整卷的大小,请求更大的存储空间。
当底层 StorageClass 的字段allowVolumeExpansion
设置为 true 时,以下类型的卷支持卷扩展。
卷类型 | 卷扩展所需的 Kubernetes 版本 |
---|---|
Azure 文件 | 1.11 |
CSI | 1.24 |
FlexVolume | 1.13 |
Portworx | 1.11 |
rbd | 1.11 |
注意
您只能使用卷扩展功能来扩展卷,而不能缩小卷。安装选项
由 StorageClass 动态创建的持久卷将具有在类的mountOptions
字段中指定的安装选项。
如果卷插件不支持安装选项但指定了安装选项,则配置将失败。安装选项不会在类或 PV 上进行验证。如果安装选项无效,则 PV 安装将失败。
卷绑定模式
volumeBindingMode
字段控制何时 卷绑定和动态配置 应该发生。当未设置时,默认情况下使用Immediate
模式。
Immediate
模式表示卷绑定和动态配置将在创建持久卷声明后立即发生。对于拓扑受限且无法从集群中所有节点全局访问的存储后端,将绑定或配置持久卷,而不会了解 Pod 的调度要求。这可能会导致无法调度的 Pod。
集群管理员可以通过指定WaitForFirstConsumer
模式来解决此问题,该模式将延迟持久卷的绑定和配置,直到使用持久卷声明的 Pod 创建。持久卷将根据 Pod 的调度约束中指定的拓扑进行选择或配置。这些约束包括但不限于 资源要求、节点选择器、Pod 亲和性和反亲和性 以及 污点和容忍度。
以下插件支持使用动态配置的WaitForFirstConsumer
- CSI 卷,前提是特定的 CSI 驱动程序支持此功能
以下插件支持使用预创建持久卷绑定的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: kubernetes.io/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 个。包括其键和值的 parameters 对象的总长度不能超过 256 KiB。
AWS EBS
Kubernetes 1.31 不包含awsElasticBlockStore
卷类型。
Kubernetes v1.19 版本弃用了 AWSElasticBlockStore 内置存储驱动程序,然后在 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"
allowedTopologies:
- matchLabelExpressions:
- key: topology.ebs.csi.aws.com/zone
values:
- us-east-2c
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 创建存储类。以下是一些示例
vSphere
vSphere 存储类有两种类型的配置程序
树内配置程序已 弃用。有关 CSI 配置程序的更多信息,请参见 Kubernetes vSphere CSI 驱动程序 和 vSphereVolume CSI 迁移。
CSI 配置程序
vSphere CSI 存储类配置程序与 Tanzu Kubernetes 集群一起使用。有关示例,请参阅 vSphere CSI 代码库。
vCP 配置程序
以下示例使用 VMware Cloud Provider (vCP) 存储类配置程序。
使用用户指定的磁盘格式创建存储类。
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast provisioner: kubernetes.io/vsphere-volume parameters: diskformat: zeroedthick
diskformat
:thin
、zeroedthick
和eagerzeroedthick
。默认值:"thin"
。在用户指定的存储库上创建具有磁盘格式的存储类。
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast provisioner: kubernetes.io/vsphere-volume parameters: diskformat: zeroedthick datastore: VSANDatastore
datastore
:用户也可以在存储类中指定存储库。卷将在存储类中指定的存储库上创建,在本例中为VSANDatastore
。此字段是可选的。如果未指定存储库,则卷将在用于初始化 vSphere Cloud Provider 的 vSphere 配置文件中指定的存储库上创建。Kubernetes 中的存储策略管理
使用现有的 vCenter SPBM 策略
vSphere 用于存储管理的最重要功能之一是基于策略的管理。基于存储策略的管理 (SPBM) 是一个存储策略框架,它为广泛的数据服务和存储解决方案提供了一个统一的控制平面。SPBM 使 vSphere 管理员能够克服容量规划、差异化服务级别和管理容量裕量等前期存储配置挑战。
SPBM 策略可以在存储类中使用
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
parameters:
monitors: 10.16.153.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
的密钥名称。此参数是必需的。提供的密钥必须具有类型“kubernetes.io/rbd”。adminSecretNamespace
:adminSecretName
的命名空间。默认值为“default”。pool
:Ceph RBD 池。默认值为“rbd”。userId
:用于映射 RBD 映像的 Ceph 客户端 ID。默认值与adminId
相同。userSecretName
:用于映射 RBD 映像的userId
的 Ceph 密钥名称。它必须存在于与 PVC 相同的命名空间中。此参数是必需的。提供的密钥必须具有类型“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.31 不包含 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
skuName
:Azure 存储帐户 SKU 层级。默认值为空。location
:Azure 存储帐户位置。默认值为空。storageAccount
:Azure 存储帐户名称。默认值为空。如果没有提供存储帐户,将搜索与资源组关联的所有存储帐户,以查找与skuName
和location
匹配的存储帐户。如果提供了存储帐户,它必须驻留在与集群相同的资源组中,并且skuName
和location
将被忽略。secretNamespace
:包含 Azure 存储帐户名称和密钥的密钥的命名空间。默认值与 Pod 相同。secretName
:包含 Azure 存储帐户名称和密钥的密钥的名称。默认值为azure-storage-account-<accountName>-secret
readOnly
:一个标志,指示存储是否将以只读方式挂载。默认为 false,这意味着读写挂载。此设置也会影响 VolumeMounts 中的ReadOnly
设置。
在存储配置期间,将为挂载凭据创建名为 secretName
的密钥。如果集群启用了 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
parameters:
repl: "1"
snap_interval: "70"
priority_io: "high"
fs
:要布局的文件系统:none/xfs/ext4
(默认值:ext4
)。block_size
:块大小(以 KB 为单位)(默认值: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
volumeBindingMode: WaitForFirstConsumer
本地卷在 Kubernetes 1.31 中不支持动态配置;但是,仍然应该创建存储类以延迟卷绑定,直到 Pod 实际调度到相应的节点为止。这是由 WaitForFirstConsumer
卷绑定模式指定的。
延迟卷绑定允许调度程序在选择持久卷以满足持久卷声明时考虑 Pod 的所有调度约束。