Kubernetes-持久化存储卷PersistentVolume

1、持久化存储卷和声明介绍

PersistentVolume(PV)用于为用户和管理员提供如何提供和消费存储的API,PV由管理员在集群中提供的存储。它就像Node一样是集群中的一种资源。PersistentVolume 也是和存储卷一样的一种插件,但其有着自己独立的生命周期。PersistentVolumeClaim (PVC)是用户对存储的请求,类似于Pod消费Node资源,PVC消费PV资源。Pod能够请求特定的资源(CPU和内存),声明请求特定的存储大小和访问模式。PV是一个系统的资源,因此没有所属的命名空间。

2、持久化存储卷和声明的生命周期

在Kubernetes集群中,PV 作为存储资源存在。PVC 是对PV资源的请求和使用,也是对PV存储资源的”提取证”,而Pod通过PVC来使用PV。PV 和 PVC 之间的交互过程有着自己的生命周期,这个生命周期分为5个阶段:

  • 供应(Provisioning):即PV的创建,可以直接创建PV(静态方式),也可以使用StorageClass动态创建
  • 绑定(Binding):将PV分配给PVC
  • 使用(Using):Pod通过PVC使用该Volume
  • 释放(Releasing):Pod释放Volume并删除PVC
  • 回收(Reclaiming):回收PV,可以保留PV以便下次使用,也可以直接从云存储中删除

根据上述的5个阶段,存储卷的存在下面的4种状态:

  • Available:可用状态,处于此状态表明PV以及准备就绪了,可以被PVC使用了。
  • Bound:绑定状态,表明PV已被分配给了PVC。
  • Released:释放状态,表明PVC解绑PV,但还未执行回收策略。
  • Failed:错误状态,表明PV发生错误。

2.1 供应(Provisioning

供应是为集群提供可用的存储卷,在Kubernetes中有两种持久化存储卷的提供方式:静态或者动态。

2.1.1 静态(Static)

PV是由Kubernetes的集群管理员创建的,PV代表真实的存储,PV提供的这些存储对于集群中所有的用户都是可用的。它们存在于Kubernetes API中,并可被Pod作为真实存储使用。在静态供应的情况下,由集群管理员预先创建PV,开发者创建PVC和Pod,Pod通过PVC使用PV提供的存储。静态供应方式的过程如下图所示:

2.1.2 动态(Dynamic

对于动态的提供方式,当管理员创建的静态PV都不能够匹配用户的PVC时,集群会尝试自动为PVC提供一个存储卷,这种提供方式基于StorageClass。在动态提供方向,PVC需要请求一个存储类,但此存储类必须有管理员预先创建和配置。集群管理员需要在API Server中启用DefaultStorageClass的接入控制器。动态供应过程如下图所示:

 

2.2 绑定

在Kubernetes中,会动态的将PVC与可用的PV的进行绑定。在kubernetes的Master中有一个控制回路,它将监控新的PVC,并为其查找匹配的PV(如果有),并把PVC和PV绑定在一起。如果一个PV曾经动态供给到了一个新的PVC,那么这个回路会一直绑定这个PV和PVC。另外,用户总是能得到它们所要求的存储,但是volume可能超过它们的请求。一旦绑定了,PVC绑定就是专属的,无论它们的绑定模式是什么。

如果没有匹配的PV,那么PVC会无限期的处于未绑定状态,一旦存在匹配的PV,PVC绑定此PV。比如,就算集群中存在很多的50G的PV,需要100G容量的PVC也不会匹配满足需求的PV。直到集群中有100G的PV时,PVC才会被绑定。PVC基于下面的条件绑定PV,如果下面的条件同时存在,则选择符合所有要求的PV进行绑定:

1)如果PVC指定了存储类,则只会绑定指定了同样存储类的PV;

2)如果PVC设置了选择器,则选择器去匹配符合的PV;

3)如果没有指定存储类和设置选取器,PVC会根据存储空间容量大小和访问模式匹配符合的PV。

2.3 使用

Pod把PVC作为卷来使用,Kubernetes集群会通过PVC查找绑定的PV,并将其挂接至Pod。对于支持多种访问方式的卷,用户在使用 PVC 作为卷时,可以指定需要的访问方式。一旦用户拥有了一个已经绑定的PVC,被绑定的PV就归该用户所有。用户能够通过在Pod的存储卷中包含的PVC,从而访问所占有的PV。

2.4释放

当用户完成对卷的使用时,就可以利用API删除PVC对象了,而且还可以重新申请。删除PVC后,对应的持久化存储卷被视为“被释放”,但这时还不能给其他的PVC使用。之前的PVC数据还保存在卷中,要根据策略来进行后续处理。

2.5 回收

PV的回收策略向集群阐述了在PVC释放卷时,应如何进行后续工作。目前可以采用三种策略:保留,回收或者删除。保留策略允许重新申请这一资源。在PVC能够支持的情况下,删除策略会同时删除卷以及AWS EBS/GCE PD或者Cinder卷中的存储内容。如果插件能够支持,回收策略会执行基础的擦除操作(rm -rf /thevolume/*),这一卷就能被重新申请了。

2.5.1 保留

保留回收策略允许手工回收资源。当PVC被删除,PV将仍然存储,存储卷被认为处于已释放的状态。但是,它对于其他的PVC是不可用的,因为以前的数据仍然保留在数据中。管理员能够通过下面的步骤手工回收存储卷:

1)删除PV:在PV被删除后,在外部设施中相关的存储资产仍然还在;

2)手工删除遗留在外部存储中的数据;

3)手工删除存储资产,如果需要重用这些存储资产,则需要创建新的PV。

2.5.2 循环

警告:此策略将会被遗弃。建议后续使用动态供应的模式。

循环回收会在存储卷上执行基本擦除命令:rm -rf /thevolume/*,使数据对于新的PVC可用。

2.5.3 删除

对于支持删除回收策略的存储卷插件,删除即会从Kubernetes中移除PV,也会从相关的外部设施中删除存储资产,例如AWS EBS, GCE PD, Azure Disk或者Cinder存储卷。

3、持久化存储卷

在Kubernetes中,PV通过各种插件进行实现,当前支持下面这些类型的插件:

  • GCEPersistentDisk
  • AWSElasticBlockStore
  • AzureFile
  • AzureDisk
  • FC (Fibre Channel)
  • FlexVolume
  • Flocker
  • NFS
  • iSCSI
  • RBD (Ceph Block Device)
  • CephFS
  • Cinder (OpenStack block storage)
  • Glusterfs
  • VsphereVolume
  • Quobyte Volumes
  • HostPath (Single node testing only – local storage is not supported in any way and WILL NOT WORK in a multi-node cluster)
  • VMware Photon
  • Portworx Volumes
  • ScaleIO Volumes
  • StorageOS

持久化存储卷的可以通过YAML配置文件进行,并指定使用哪个插件类型,下面是一个持久化存储卷的YAML配置文件。在此配置文件中要求提供5Gi的存储空间,存储模式为Filesystem ,访问模式是ReadWriteOnce,通过Recycle回收策略进行持久化存储卷的回收,指定存储类为slow,使用nfs的插件类型。需要注意的是,nfs服务需要提供存在。

apiVersion:v1
kind:PersistentVolume
metadata:
  name:pv0003
spec:
  capacity: #容量
     storage:5Gi
  volumeMode:Filesystem #存储卷模式
  accessModes: #访问模式
  - ReadWriteOnce
  persistentVolumeReclaimPolicy:Recycle #持久化卷回收策略
  storageClassName:slow #存储类
  mountOptions: #挂接选项
   - hard
   - nfsvers=4.1
  nfs:
     path:/tmp
     server:172.17.0.2 

3.1 容量(Capacity

一般来说,PV会指定存储容量。这里通过使用PV的capcity属性进行设置。目前,capcity属性仅有storage(存储大小)这唯一一个资源需要被设置。

3.2 存储卷模式(Volume Mode

在kubernetes v1.9之前的版本,存储卷模式的默认值为filesystem,不需要指定。在v1.9版本,用户可以指定volumeMode的值,除了支持文件系统外(file system)也支持块设备(raw block devices)。volumeMode是一个可选的参数,如果不进行设定,则默认为Filesystem。

3.3 访问模式(Access Modes

只要资源提供者支持,持久卷能够通过任何方式加载到主机上。每种存储都会有不同的能力,每个PV的访问模式也会被设置成为该卷所支持的特定模式。例如NFS能够支持多个读写客户端,但某个NFS PV可能会在服务器上以只读方式使用。每个PV都有自己的一系列的访问模式,这些访问模式取决于PV的能力。

访问模式的可选范围如下:

  •   ReadWriteOnce:该卷能够以读写模式被加载到一个节点上。
  •   ReadOnlyMany:该卷能够以只读模式加载到多个节点上。
  •   ReadWriteMany:该卷能够以读写模式被多个节点同时加载。

在 CLI 下,访问模式缩写为:

  •   RWO:ReadWriteOnce
  •   ROX:ReadOnlyMany
  •   RWX:ReadWriteMany

一个卷不论支持多少种访问模式,同时只能以一种访问模式加载。例如一个 GCEPersistentDisk既能支持ReadWriteOnce,也能支持ReadOnlyMany。

存储卷插件

ReadWriteOnce

ReadOnlyMany

ReadWriteMany

AWSElasticBlockStore
AzureFile
AzureDisk
CephFS
Cinder
FC
FlexVolume
Flocker
GCEPersistentDisk
Glusterfs
HostPath
iSCSI
PhotonPersistentDisk
Quobyte
NFS
RBD
VsphereVolume – (works when pods are collocated)
PortworxVolume
ScaleIO
StorageOS

3.4 类(Class

在PV中可以指定存储类,通过设置storageClassName字段进行设置。如果设置了存储类,则此PV只能被绑定到也指定了此存储类的PVC。在以前的版本中,使用注释volume.beta.kubernetes.io/storage-class字段来指定存储类,而不是storageClassName字段来指定存储类。 此注释仍然可用,但是,在将来的版本中将会被废弃。

3.5 回收策略

当前的回收策略可选值包括:

  • Retain-持久化卷被释放后,需要手工进行回收操作。
  • Recycle-基础擦除(“rm-rf /thevolume/*”)
  • Delete-相关的存储资产,例如AWSEBS或GCE PD卷一并删除。

目前,只有NFS和HostPath支持Recycle策略,AWSEBS、GCE PD支持Delete策略。

3.6 挂接选项(Mount Options

当持久化卷被挂接至Pod上时,管理员能够指定额外的挂接选项。但不是所有的持久化卷类型都支持挂接选项,下面的存储卷类型支持挂接选项:

  • GCEPersistentDisk
  • AWSElasticBlockStore
  • AzureFile
  • AzureDisk
  • NFS
  • iSCSI
  • RBD (Ceph Block Device)
  • CephFS
  • Cinder (OpenStack block storage)
  • Glusterfs
  • VsphereVolume
  • Quobyte Volumes
  • VMware Photon

挂接选项不会进行验证,因此如果如果设置不正确,则会失败。在以前的版本中,使用volume.beta.kubernetes.io/mount-options注释指定挂接选项,而不是使用mountOptions字段。此注释仍然可用,但是在将来的版本中将会被废弃。

4、持久化卷声明

下面是一个名称为myclaim的PVC YAML配置文件,它的访问模式为ReadWriteOnce,存储卷模式是Filesystem,需要的存储空间大小为8Gi,指定的存储类为slow,并设置了标签选择器和匹配表达式。

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: myclaim
spec:
  accessModes: #访问模式
    - ReadWriteOnce
  volumeMode: Filesystem #存储卷模式
  resources: #资源
    requests:
      storage: 8Gi
  storageClassName: slow #存储类
  selector: #选择器
    matchLabels:
      release: "stable"
    matchExpressions: #匹配表达式
      - {key: environment, operator: In, values: [dev]}

4.1 选择器

在PVC中,可以通过标签选择器来进一步的过滤PV。仅仅与选择器匹配的PV才会被绑定到PVC中。选择器的组成如下:

  • matchLabels: 只有存在与此处的标签一样的PV才会被PVC选中;
  • matchExpressions :匹配表达式由键、值和操作符组成,操作符包括In, NotIn, Exists和DoesNotExist,只有符合表达式的PV才能被选择。

如果同时设置了matchLabels和matchExpressions,则会进行求与,即只有同时满足上述匹配要求的PV才会被选择。

4.2 存储

如果PVC使用storageClassName字段指定一个存储类,那么只有指定了同样的存储类的PV才能被绑定到PVC上。对于PVC来说,存储类并不是必须的。依赖于安装方法,可以在安装过程中使用add-on管理器将默认的StorageClass部署至Kubernetes集群中。当PVC指定了选择器,并且指定了StorageClass,则在匹配PV时,取两者之间的与:即仅仅同时满足存储类和带有要求标签值的PV才能被匹配上。

4.3 PVC作为存储卷

Pod通过使用PVC来访问存储,而PVC必须和使用它的Pod在同一个命名空间中。Pod会同一个命名空间中选择一个合适的PVC,并使用PVC为其获取存储卷,并将PV挂接到主机和Pod上。

kind:Pod
apiVersion:v1
metadata:
  name:mypod
spec:
  containers:
  - name:myfrontend
    image:dockerfile/nginx
     volumeMounts: #挂接存储卷
     - mountPath:"/var/www/html" #挂接的路径
       name:mypd #所要挂接的存储卷的名称
 volumes: #定义存储卷
 - name:mypd
   persistentVolumeClaim: #所使用的持久化存储卷声明
     claimName:myclaim

 

参考资料

1.《Configure a Pod to Use a PersistentVolume for Storage》地址:https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/

2.《Persistent Volumes》地址:https://kubernetes.io/docs/concepts/storage/persistent-volumes/

3.《Persistent Storage》地址:https://github.com/kubernetes/community/blob/master/contributors/design-proposals/storage/persistent-storage.md

4.《PersistentVolume v1 core》地址:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.10/#persistentvolume-v1-core

作者简介:
季向远,北京神舟航天软件技术有限公司产品经理。本文版权归原作者所有。

K8S中文社区微信公众号