存储基础知识
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社区推荐的存储插件实现方案。everest是CCE基于CSI开发的自研存储插件,能够为容器提供不同类型的持久化存储功能。
存储卷访问模式
存储卷只能以底层存储资源所支持的方式挂载到宿主系统上。例如,文件存储可以支持多个节点读写,云硬盘只能被一个节点读写。
- ReadWriteOnce:存储卷可以被一个节点以读写方式挂载。
- ReadWriteMany:存储卷可以被多个节点以读写方式挂载。
存储类型 |
ReadWriteOnce |
ReadWriteMany |
---|---|---|
云硬盘EVS |
√ |
× |
文件存储SFS |
× |
√ |
对象存储OBS |
× |
√ |
极速文件存储SFS Turbo |
× |
√ |
存储卷挂载方式
通常在使用存储卷时,可以通过以下方式挂载:
可以使用PV描述已有的存储资源,然后通过创建PVC在Pod中使用存储资源。也可以使用动态创建的方式,在PVC中指定存储类(StorageClass),利用StorageClass中的Provisioner自动创建PV来绑定PVC。
挂载方式 |
说明 |
支持的存储卷类型 |
其他限制 |
---|---|---|---|
静态创建存储卷(使用已有存储) |
即使用已有的存储(例如云硬盘、文件存储等)创建好PV,并通过PVC在工作负载中挂载。Kubernetes会将PVC和匹配的PV进行绑定,这样就实现了工作负载访问存储服务的能力。 |
所有存储卷均支持 |
无 |
动态创建存储卷(自动创建存储) |
即在PVC中指定存储类(StorageClass),由存储Provisioner根据需求创建底层存储介质,实现PV的自动化创建并直接绑定至PVC。 |
云硬盘存储、对象存储、文件存储、本地持久卷 |
无 |
动态挂载(VolumeClaimTemplate) |
动态挂载能力通过卷申领模板(volumeClaimTemplates字段)实现,并依赖于StorageClass的动态创建PV能力。动态挂载可以为每一个Pod关联一个独有的PVC及PV,当Pod被重新调度后,仍然能够根据该PVC名称挂载原有的数据。 |
仅云硬盘存储、本地持久卷支持 |
仅有状态工作负载支持 |
PV回收策略
PV回收策略用于指定删除PVC时,底层卷的回收策略,支持设定Delete、Retain回收策略。
- Delete:删除PVC的动作会将PV对象从Kubernetes中移除,同时也会从外部基础设施中移除所关联的底层存储资产。
- 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