存储基础知识
Volume(卷)
容器中的文件在磁盘上是临时存放的,这给容器中运行的较重要的应用程序带来如下两个问题:
- 当容器重建时,容器中的文件将会丢失。
- 当在一个Pod中同时运行多个容器时,容器间需要共享文件。
Kubernetes抽象出了Volume(卷)来解决以上两个问题。Kubernetes的Volume是Pod的一部分,Volume不是单独的对象,不能独立创建,只能在Pod中定义。Pod中的所有容器都可以使用Volume,但需要将Volume挂载到容器中的目录下。
实际中使用容器存储如下图所示,可将同一个Volume挂载到不同的容器中,实现不同容器间的存储共享。
存储卷的基本使用原则如下:
- 一个Pod可以挂载多个Volume。虽然单Pod可以挂载多个Volume,但是并不建议给一个Pod挂载过多卷。
- 一个Pod可以挂载多种类型的Volume。
- 每个被Pod挂载的Volume卷,可以在不同的容器间共享。
- Kubernetes环境推荐使用PVC和PV方式挂载Volume。

卷(Volume)的生命周期与挂载它的Pod相同,即Pod被删除的时候,Volume也一起被删除。但是Volume里面的文件可能在Volume消失后仍然存在,这取决于Volume的类型。
Kubernetes提供了非常丰富的Volume类型,主要可分为In-Tree和Out-of-Tree两个大类:
卷(Volume)分类 |
描述 |
---|---|
In-Tree |
In-Tree卷是通过Kubernetes代码仓库维护的,与Kubernetes二进制文件一起构建、编译、发布,当前Kubernetes已不再接受这种模式的卷类型。 例如HostPath、EmptyDir、Secret和ConfigMap等Kubernetes原生支持的卷都属于这个类型。 而PVC(PersistentVolumeClaim)可以说是一种特殊的In-Tree卷,Kubernetes使用这种类型的卷从In-Tree模式向Out-of-Tree模式进行转换,这种类型的卷允许使用者在不同的存储供应商环境中“申请”使用底层存储创建的PV(PersistentVolume)。 |
Out-of-Tree |
Out-of-Tree卷包括容器存储接口(CSI)和FlexVolume(已弃用),存储供应商只需遵循一定的规范即可创建自定义存储插件,创建可供Kubernetes使用的PV,而无需将插件源码添加到Kubernetes代码仓库。例如SFS、OBS等云存储都是通过在集群中安装存储驱动的形式使用的,需要在集群中创建对应的PV,然后使用PVC挂载到Pod中。 |
PV与PVC
Kubernetes抽象了PV(PersistentVolume)和PVC(PersistentVolumeClaim)来定义和使用存储,从而让使用者不用关心具体的基础设施,当需要存储资源的时候,只要像CPU和内存一样,声明要多少即可。
- PV:PV是PersistentVolume的缩写,译为持久化存储卷,描述的是一个集群里的持久化存储卷,它和节点一样,属于集群级别资源,其对象作用范围是整个Kubernetes集群。PV可以有自己的独立生命周期,不依附于Pod。
- PVC:PVC是PersistentVolumeClaim的缩写,译为持久化存储卷声明,描述的是负载对存储的申领。为应用配置存储时,需要声明一个存储需求(即PVC),Kubernetes会通过最佳匹配的方式选择一个满足需求的PV,并与PVC绑定。PVC与PV是一一对应关系,在创建PVC时,需描述请求的持久化存储的属性,比如,存储的大小、可读写权限等等。
在Pod中可以使用Volume关联PVC,即可让Pod使用到存储资源,它们之间的关系如下图所示。

CSI
CSI(Container Storage Interface,容器存储接口)是容器标准存储接口规范,也是Kubernetes社区推荐的存储插件实现方案。CCE容器存储(Everest)是CCE基于CSI开发的存储插件,能够为容器提供不同类型的持久化存储功能。
存储卷访问模式
存储卷只能以底层存储资源所支持的方式挂载到宿主系统上。例如,文件存储可以支持多个节点读写,云硬盘只能被一个节点读写。
- ReadWriteOnce:存储卷可以被一个节点以读写方式挂载。
- ReadWriteMany:存储卷可以被多个节点以读写方式挂载。
存储类型 |
ReadWriteOnce |
ReadWriteMany |
---|---|---|
云硬盘EVS |
√ |
× |
文件存储SFS |
× |
√ |
对象存储OBS |
× |
√ |
极速文件存储SFS Turbo |
× |
√ |
本地持久卷LocalPV |
√ |
× |
专属存储DSS |
√ |
× |
存储卷挂载方式
通常在使用存储卷时,可以通过以下方式挂载:
可以使用PV描述已有的存储资源,然后通过创建PVC在Pod中使用存储资源。也可以使用动态创建的方式,在PVC中指定存储类(StorageClass),利用StorageClass中的Provisioner自动创建PV来绑定PVC。
挂载方式 |
说明 |
支持的存储卷类型 |
其他限制 |
---|---|---|---|
静态创建存储卷(使用已有存储) |
指基于已有的存储资源(例如云硬盘、文件存储等),手动创建PV和PVC。Kubernetes会根据PVC的资源需求,自动将其与匹配的PV绑定。绑定完成后,PVC可挂载至工作负载,使工作负载获得访问存储资源的能力,进而实现业务数据的持久化存储。 若存储卷的访问模式为ReadWriteOnce,则创建工作负载时,工作负载的Pod实例数量只能设置为1。 |
所有存储卷均支持 |
无 |
动态创建存储卷(自动创建存储) |
指在PVC中指定存储类(StorageClass),由存储Provisioner根据PVC中声明的资源需求动态创建底层存储资源和对应的PV,并自动完成该PV与PVC的绑定,从而实现存储资源的自动化供给。 若存储卷的访问模式为ReadWriteOnce,则创建工作负载时,工作负载的Pod实例数量只能设置为1。 |
云硬盘存储、对象存储、文件存储、本地持久卷、专属存储 |
无 |
动态挂载(VolumeClaimTemplate) |
动态挂载能力通过卷申领模板(volumeClaimTemplates字段)实现,并依赖于StorageClass的动态创建PV能力。动态挂载可以为每一个Pod关联一个独有的PVC及PV,当Pod被重新调度后,仍然能够根据该PVC名称挂载原有的数据。 即使存储卷的访问模式为ReadWriteOnce,工作负载的Pod实例数量也可以设置为多个。 |
仅云硬盘存储、本地持久卷、专属存储支持 |
仅有状态工作负载支持 |
PV回收策略
PV回收策略用于指定删除PVC时,底层卷的回收策略,支持设定Delete、Retain回收策略。
- Delete:删除PVC的动作会将PV对象从Kubernetes中移除,同时也会从外部基础设施中移除所关联的底层存储资产。
包周期云硬盘资源支持通过Delete回收策略进行级联删除,而其他类型的包周期资源则无法通过Delete回收策略实现级联删除。
- Retain:当PVC对象被删除时,PV对象与底层存储资源均不会被删除,需要手动删除回收。PVC删除后PV资源状态为“已释放(Released)”,且不能直接再次被PVC绑定使用。
- 手动删除PersistentVolume对象。
- 根据情况,手动清除所关联的底层存储资源上的数据。
- 手动删除所关联的底层存储资源。
如果您希望重用该底层存储资源,可以重新创建新的PersistentVolume对象。
CCE还支持一种删除PVC时不删除底层存储资源的使用方法,当前仅支持使用YAML创建:PV回收策略设置为Delete,并添加annotations“everest.io/reclaim-policy: retain-volume-only”。这样在删除PVC时,PV会被删除,但底层存储资源会保留。
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: test namespace: default annotations: volume.beta.kubernetes.io/storage-provisioner: everest-csi-provisioner everest.io/disk-volume-type: SAS labels: failure-domain.beta.kubernetes.io/region: <your_region> # 替换为您待部署应用的节点所在的区域 failure-domain.beta.kubernetes.io/zone: <your_zone> # 替换为您待部署应用的节点所在的可用区 spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: csi-disk volumeName: pv-evs-test --- apiVersion: v1 kind: PersistentVolume metadata: annotations: pv.kubernetes.io/provisioned-by: everest-csi-provisioner everest.io/reclaim-policy: retain-volume-only name: pv-evs-test labels: failure-domain.beta.kubernetes.io/region: <your_region> # 替换为您待部署应用的节点所在的区域 failure-domain.beta.kubernetes.io/zone: <your_zone> # 替换为您待部署应用的节点所在的可用区 spec: accessModes: - ReadWriteOnce capacity: storage: 10Gi csi: driver: disk.csi.everest.io fsType: ext4 volumeHandle: 2af98016-6082-4ad6-bedc-1a9c673aef20 volumeAttributes: storage.kubernetes.io/csiProvisionerIdentity: everest-csi-provisioner everest.io/disk-mode: SCSI everest.io/disk-volume-type: SAS persistentVolumeReclaimPolicy: Delete storageClassName: csi-disk
存储类(StorageClass)
StorageClass是Kubernetes中用于定义存储类别的资源对象,提供动态分配存储卷的能力。通过设置不同的参数,StorageClass能够根据业务需求自动供应和调整存储资源。在PVC中指定StorageClassName字段后,若在集群中未找到匹配的PV,Kubernetes将根据所引用的StorageClass调用对应的Provisioner动态创建符合要求的PV及底层存储资源,从而简化了手动创建和维护PV的流程。StorageClass中的参数作为默认配置项使用,当PVC中存在与之冲突的配置时,以PVC中的设置为准。
CCE集群中默认提供以下StorageClass供您使用,默认StorageClass不支持修改。如果默认的StorageClass无法满足业务需求,您可以自定义创建新的StorageClass,设置回收策略、绑定模式等参数,具体请参见自定义存储类(StorageClass)。
StorageClass名称 |
对应存储类型 |
Provisioner |
回收策略 |
绑定模式 |
是否支持扩容 |
---|---|---|---|---|---|
csi-disk |
云硬盘 |
everest-csi-provisioner |
Delete |
Immediate |
支持 |
csi-disk-topology |
延迟创建的云硬盘 |
everest-csi-provisioner |
Delete |
WaitForFirstConsumer |
支持 |
csi-nas |
SFS容量型文件存储 |
everest-csi-provisioner |
Delete |
Immediate |
支持 |
csi-sfs |
通用文件系统(原SFS 3.0 容量型) |
everest-csi-provisioner |
Delete |
Immediate |
不支持 |
csi-sfsturbo |
极速文件存储 |
everest-csi-provisioner |
Delete |
Immediate |
支持 |
csi-obs |
对象存储 |
everest-csi-provisioner |
Delete |
Immediate |
不支持 |
csi-disk-dss |
专属存储 |
everest-csi-provisioner |
Delete |
Immediate |
支持 |
csi-local |
本地持久卷 |
everest-csi-provisioner |
Delete |
Immediate |
不支持 |
csi-local-topology |
延时创建的本地持久卷 |
everest-csi-provisioner |
Delete |
WaitForFirstConsumer |
支持 |
表3 默认存储类中参数介绍如下:
- 对应存储类型:表示该存储类创建的底层存储类型。
- Provisioner:表示存储资源提供商。
- 回收策略:用于指定删除PVC时底层存储的回收策略,详情请参见PV回收策略。
- 绑定模式:表示卷绑定模式,即动态创建PV的时间,分为立即创建(Immediate)和延迟创建(WaitForFirstConsumer)。
- Immediate:PVC创建后,会立即创建底层存储资源及存储卷PV,并与PVC绑定。
- WaitForFirstConsumer:PVC创建后,不会立即与存储卷PV绑定,而是等需要挂载该PVC的Pod被调度后,再创建底层存储资源及存储卷PV,并与PVC绑定。
- 是否支持扩容:表示由该存储类创建的PV是否支持动态扩容。
如果需要了解默认StorageClass的更多信息,请通过kubectl连接集群,并执行kubectl describe sc <storageclass-name>命令查询详细信息。