更新时间:2024-01-24 GMT+08:00

存储基础知识

Volume(卷)

容器中的文件在磁盘上是临时存放的,这给容器中运行的较重要的应用程序带来如下两个问题:

  1. 当容器重建时,容器中的文件将会丢失。
  2. 当在一个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使用到存储资源,它们之间的关系如下图所示。

图1 PVC绑定PV

CSI

CSI(Container Storage Interface,容器存储接口)是容器标准存储接口规范,也是Kubernetes社区推荐的存储插件实现方案。everest是CCE基于CSI开发的自研存储插件,能够为容器提供不同类型的持久化存储功能。

存储卷访问模式

存储卷只能以底层存储资源所支持的方式挂载到宿主系统上。例如,文件存储可以支持多个节点读写,云硬盘只能被一个节点读写。

  • ReadWriteOnce:存储卷可以被一个节点以读写方式挂载。
  • ReadWriteMany:存储卷可以被多个节点以读写方式挂载。
表1 存储卷支持的访问模式

存储类型

ReadWriteOnce

ReadWriteMany

云硬盘EVS

×

对象存储OBS

×

极速文件存储SFS Turbo

×

本地持久卷LocalPV

×

存储卷挂载方式

通常在使用存储卷时,可以通过以下方式挂载:

可以使用PV描述已有的存储资源,然后通过创建PVC在Pod中使用存储资源。也可以使用动态创建的方式,在PVC中指定存储类(StorageClass),利用StorageClass中的Provisioner自动创建PV来绑定PVC。

表2 挂载存储卷的方式

挂载方式

说明

支持的存储卷类型

其他限制

静态创建存储卷(使用已有存储)

即使用已有的存储(例如云硬盘、文件存储等)创建好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绑定使用。

    您可以通过以下步骤来手动删除回收:

    1. 手动删除PersistentVolume对象。
    2. 根据情况,手动清除所关联的底层存储资源上的数据。
    3. 手动删除所关联的底层存储资源。

    如果您希望重用该底层存储资源,可以重新创建新的PersistentVolume对象。

CCE还支持一种删除PVC时不删除底层存储资源的使用方法,当前仅支持使用YAML创建:PV回收策略设置为Delete,并添加annotations“everest.io/reclaim-policy: retain-volume-only”。这样在删除PVC时,PV会被删除,但底层存储资源会保留。

以云硬盘为例,YAML示例如下:
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

相关文档

  • 更多关于Kubernetes存储的信息,请参见Storage
  • 更多关于CCE容器存储的信息,请参见存储概述