01 引言
声明:本文为《Kubernetes权威指南:从Docker到Kubernetes实践全接触(第5版)》的读书笔记
在Kubernetes中,对存储资源的管理方式与计算资源(CPU
/内存)截然不同。为了能够屏蔽底层存储实现的细节,让用户方便使用及管理员方便管理, Kubernetes
从1.0版本开始就引入了 Persistent Volume ( PV)
和Persistent Volume Claim(PVC)
两个资源对象来实现存储管理子系统。
在本文开始前,先简单了解几个概念:
概念 | 描述 |
PV(持久卷) | 是对存储资源的抽象,将存储定义为一种容器应用可以使用的资源。它与存储提供商的具体实现直接相关,例如 GlusterFS 或AWS 公有云提供的共享存储,通过插件式的机制进行管理,供应用访问和使用 |
PVC | 是用户对存储资源的一个申请,就像Pod 消耗Node 的资源一样,PVC 消耗PV 资源,PVC 可以申请存储空间的大小(size )和访问模式(例如 ReadWriteOnce 、 ReadOnlyMany 或ReadWriteMany ) |
StorageClass | 用于标记存储资源的特性和性能,根据PVC 的需求动态供给合适的 PV 资源,根据StorageClass 的描述就可以直观地得知各种存储资源的特性,根据应用对存储资源的需求去申请存储资源了 |
Container Storage Interface (CSI)机制 | 目标是在Kubernetes和外部存储系统之间建立一套标准的存储管理接口,具体的存储驱动程序由存储提供商在Kubernetes之外提供,并通过该标准接口为容器提供存储服务,类似于CRI (容器运行时接口)和CNI (容器网络接口),目的是将Kubernetes 代码与存储相关代码解耦 |
02 PV和PVC的工作原理
我们可以将PV
看作可用的存储资源,PVC
则是对存储资源的需求。
PV
和PVC
的生命周期如图所示:
2.1 资源供应
Kubernetes 支持两种资源供应模式:静态模式(Static)和动态模式 (Dynamic),资源供应的结果就是将适合的PV与PVC成功绑定。
模式 | 描述 |
静态模式 | 集群管理员预先创建许多PV ,在PV 的定义中能够体现存储资源的特性 |
动态模式 | 集群管理员无须预先创建PV ,而是通过StorageClass 的设置对后端存储资源进行描述,标记存储的类型和特性 |
用户通过创建
PVC
对存储类型进行申请,系统将自动完成PV
的创建及与PVC
的绑定。如果PVC
声明的Class
为空,则说明PVC
不使用动态模式。另外,Kubernetes
支持设置集群范围内默认的StorageClass
设置,通过kube-apiserver
开启准入控制器DefaultStorageClass
,可以为用户创建的PVC
设置一个默认的存储类StorageClass
。
2.1.1 静态资源供应模式
下图描述了静态资源供应模式下,通过PV
和PVC
完成绑定并供Pod
使用的原理:
2.1.2 动态资源供应模式
下图描述了动态资源供应模式下,通过StorageClass
和PVC
完成资源动态绑定(系统自动生成PV
),并供Pod
使用的原理:
2.2 资源绑定
在用户定义好PVC
之后,系统将根据PVC
对存储资源的请求(存储空间和访问模式)在已存在的PV
中选择一个满足PVC
要求的PV
,一旦找到,就将该PV
与用户定义的PVC
绑定,用户的应用就可以使用这个PVC
了。
注意:
- 如果在系统中没有满足
PVC
要求的PV
,PVC
则会无限期处于Pending
状态,直到系统管理员创建了一个符合其要求的PV
; PV
一旦与某个PVC
上完成绑定,就会被这个PVC
独占,不能再与其他PVC
绑定了。PVC
与PV
的绑定关系是一对一的,不会存在一对多的情况。- 如果
PVC
申请的存储空间比PV
拥有的空间少,则整个PV
的空间都能为PVC
所用,可能造成资源的浪费。 - 如果资源供应使用的是动态模式,则系统在为
PVC
找到合适的StorageClass
后,将自动创建一个PV
并完成与PVC
的绑定。
2.3 资源使用
Pod需要使用存储资源时,需要在Volume的定义中引用PVC类型的存储卷, 将 PVC挂载到容器内的某个路径下进行使用,Volume 的类型字段为 “persistentVolumeClaim”。同一个PVC还可以被多个Pod同时挂载使用,在这种情况下,应用程序需要处理好多个进程访问同一个存储的问题。
存储对象的保护机制(Storage Object in Use Protection):存储资源(PV、PVC)相对于容器应用(Pod)是独立管理的资源,可以单独删除。在做删除操作的时候,系统会检测存储资源当前是否正在被使用,如果仍被使用,则对相关资源对象的删除操作将被推迟,直到没被使用才会执行删除操作,这样可以确保资源仍被使用的情况下不会被直接删除而导致数据丢失。这个机制被称为对使用中的存储对象的保护机制(Storage Object in Use Protection)。
该保护机制适用于PVC
和PV
两种资源:
- ① 对PVC的删除操作将等到使用它的Pod被删除之后再执行:举例来说,当用户删除一个正在被Pod使用的PVC时,PVC对象不会被立刻删除,查看PVC对象的状态,可以看到其状态为“Terminating”,以及系统为其设置的Finalizer为“kubernetes.io/pvc-protection”:
- ② 对PV的删除操作将等到绑定它的PVC被删除之后再执行:举例来说,当用户删除一个仍被PVC绑定的PV时,PV对象不会被立刻删除, 查看PV对象的状态,可以看到其状态为“Terminating”,以及系统为其设置的 Finalizer为“kubernetes.io/pvc-protection”:
2.4 资源回收
用户在使用存储资源完毕后,可以删除PVC。与该PVC绑定的PV将被标记为 “已释放”,但还不能立刻与其他PVC绑定。通过之前PVC写入的数据可能还被留在存储设备上,只有在清除这些数据之后,该PV才能再次使用。
管理员可以对PV设置资源回收策略(Reclaim Policy),可以设置3种回收策略:Retain、 Delete和Recycle:
回收策略 | 描述 |
Retain(保留数据) | Retain策略表示在删除PVC之后,与之绑定的PV不会被删除,仅被标记为已释放(released)。PV中的数据仍然存在,在清空之前不能被新的PVC使用,需要管理员手工清理之后才能继续使用,清理步骤如下: ① 删除PV资源对象,此时与该PV关联的某些外部存储提供商(例如 AWSElasticBlockStore、 GCEPersistentDisk、 AzureDisk、 Cinder等)的后端存储资产(asset)中的数据仍然存在。 ② 手工清理PV后端存储资产 (asset)中的数据。 ③ 手工删除后端存储资产。如果希望重用该存储资产,则可以创建一个新的PV与之关联。 |
Delete(删除数据) | Delete策略表示自动删除PV资源对象和相关后端存储资产,并不是所有类型的存储提供商都支持Delete 策略,目前支持 Delete 策略的存储提供商包括 AWSElasticBlockStore、 GCEPersistentDisk、 Azure Disk、 Cinder等。通过动态供应机制创建的PV将继承StorageClass的回收策略,默认为Delete策略。管理员应该基于用户的需求设置StorageClass的回收策略,或者在创建出PV 后手工更新其回收策略。 |
Recycle(弃用) | 目前只有HostPort和NFS类型的Volume支持Recycle策略,其实现机制为运行 Im-rf/thevolume/*命令,删除Volume目录下的全部文件,使得PV可以被新的 PVC使用。 |
2.5 PVC资源扩容
PVC在首次创建成功之后,还应该能够在使用过程中实现空间的扩容,如需扩容 PVC,则首先需要在PVC对应的 StorageClass 定义中设置 allowVolumeExpansion=true
,例如:
apiVersion: storage.k8s.io/v1 kind: Storageclass metadata: name: gluster-vol-default provisioner: kubernetes.io/glusterfs parameters: resturl: "http: //192.168.10.100:8080" restuser: "" secretNamespace: "" SecretName: "" allowVolumeExpansion: true
对PVC进行扩容操作时,只需修改PVC的定义,将resources.requests.storage 设置为一个更大的值即可,例如通过以下设置,系统将会基于PVC新设置的存储空间触发后端PV的扩容操作,而不会创建一个新的PV资源对象:
resources: requests: Storage: 16Gi
03 文末
本文主要讲解持久卷的一些概念及工作原理,希望能帮助到大家,谢谢大家的阅读,本文完!