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