很多人对hostPath volume和local persistent volume的使用场景还存在很多困惑。下面对这两种volume的使用场景、基本的工作机制进行了分析,介绍了使用时的注意事项,并简单介绍local volume manager如何帮助administrator进行local persistent volume的生命周期管理的
1、hostPath volume存在的问题
过去我们经常会通过hostPath volume让Pod能够使用本地存储,将Node文件系统中的文件或者目录挂载到容器内,但是hostPath volume的使用是很难受的,并不适合在生产环境中使用。
我们先看看hostPath Type有哪些类型:
| 取值 | 行为 |
|---|---|
| 空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。 | |
| DirectoryOrCreate | 在给定路径上必须存在的目录。 |
| FileOrCreate | 如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 Kubelet 相同的组和所有权。 |
| File | 在给定路径上必须存在的文件。 |
| Socket | 在给定路径上必须存在的 UNIX 套接字。 |
| CharDevice | 在给定路径上必须存在的字符设备。 |
| BlockDevice | 在给定路径上必须存在的块设备。 |
看起来支持这么多type还是挺好的,但为什么说不适合在生产环境中使用呢?
-
由于集群内每个节点的差异化,要使用
hostPath Volume,我们需要通过NodeSelector等方式进行精确调度,这种事情多了,你就会不耐烦了。 -
注意
DirectoryOrCreate和FileOrCreate两种类型的hostPath,当Node上没有对应的File/Directory时,你需要保证kubelet有在Node上Create File/Directory的权限。 -
另外,如果
Node上的文件或目录是由root创建的,挂载到容器内之后,你通常还要保证容器内进程有权限对该文件或者目录进行写入,比如你需要以root用户启动进程并运行于privileged容器,或者你需要事先修改好Node上的文件权限配置。 -
Scheduler并不会考虑hostPath volume的大小,hostPath也不能申明需要的storagesize,这样调度时存储的考虑,就需要人为检查并保证。
2、local persistent volume工作机制
Local persistent volume就是用来解决 hostPath volume面临的portability,disk accounting, and scheduling的缺陷。PV Controller和Scheduler会对local PV做特殊的逻辑处理,以实现Pod使用本地存储时发生Pod re-schedule的情况下能再次调度到ocal volume所在的Node。
local pv在生产中使用,也是需要谨慎的,毕竟它本质上还是使用的是节点上的本地存储,如果没有相应的存储副本机制,那意味着一旦节点或者磁盘异常,使用该volume的Pod也会异常,甚至出现数据丢失,除非你明确知道这个风险不会对你的应用造成很大影响或者允许数据丢失。
那么通常什么情况会使用Local PV呢?
-
比如节点上的目录数据是从远程的网络存储上挂载或者预先读取到本地的,为了能加速
Pod读取这些数据的速度,相当于起Cache作用,这种情况下因为只读,不存在惧怕数据丢失。这种AI训练中存在需要重复利用并且训练数据巨大的时候可能会采取的方式。 -
如果本地节点上目录/磁盘实际是具有副本/分片机制的分布式存储(比如
gluster,ceph等)挂载过来的,这种情况也可以使用local pv。
Local volume允许挂载本地的disk,partition,directory到容器内某个挂载点。在Kuberentes 1.11仍然仅支持local pv的static provision,不支持dynamic provision。
-
Kubernetes使用PersistentVolume的.spec.nodeAffinityfield来描述local volume与Node的绑定关系。 -
使用
volumeBindingMode: WaitForFirstConsumer的local-storage StorageClass来实现PVC的延迟绑定,使得PV Controller并不会立刻PVC做Bound,而是等待某个需要使用该local pv的Pod完成调度后,才去做Bound。
下面是定义local pv的Sample:
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
spec:
capacity:
storage: 100Gi
# volumeMode field requires BlockVolume Alpha feature gate to be enabled.
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-storage
local:
path: /mnt/disks/ssd1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- example-node
对应的local-storage storageClass定义如下:
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
3、使用local persistent volume注意事项
-
使用
local pv时必须定义nodeAffinity,Kubernetes Scheduler需要使用PV的nodeAffinity描述信息来保证Pod能够调度到有对应local volume的Node上。 -
volumeMode可以是FileSystem(Default)和 Block,并且需要enable BlockVolume Alpha feature gate。 -
创建
local PV之前,你需要先保证有对应的storageClass已经创建。并且该storageClass的volumeBindingMode必须是WaitForFirstConsumer以标识延迟Volume Binding。WaitForFirstConsumer可以保证正常的Pod调度要求(resource requirements, node selectors, Pod affinity, and Pod anti-affinity等),又能保证Pod需要的Local PV 的 nodeAffinity得到满足,实际上,一共有以下两种volumeBindingMode:
// VolumeBindingImmediate indicates that PersistentVolumeClaims should be
// immediately provisioned and bound.
VolumeBindingImmediate VolumeBindingMode = "Immediate"
// VolumeBindingWaitForFirstConsumer indicates that PersistentVolumeClaims
// should not be provisioned and bound until the first Pod is created that
// references the PeristentVolumeClaim. The volume provisioning and
// binding will occur during Pod scheduing.
VolumeBindingWaitForFirstConsumer VolumeBindingMode = "WaitForFirstConsumer"
- 节点上
local volume的初始化需要我们人为去完成(比如local disk需要pre-partitioned,formatted,and mounted. 共享存储对应的Directories也需要pre-created),并且人工创建这个local PV,当Pod结束,我们还需要手动的清理local volume,然后手动删除该local PV对象。因此,persistentVolumeReclaimPolicy只能是Retain。
4、local volume manager
上面这么多事情需要人为的去做预处理的工作,我们必须要有解决方案帮我们自动完成local volume的 create和cleanup的工作。官方给出了一个简单的 local volume manager,注意它仍然只是一个 static provisioner,目前主要帮我们做两件事:
-
local volume manager监控配置好的discovery directory的新的挂载点,并为每个挂载点根据对应的storageClassName,path,nodeAffinity,and capacity创建PersistentVolume object。 -
当
Pod结束并删除了使用local volume的PVC,local volume manager将自动清理该local mount上的所有文件, 然后删除对应的PersistentVolume object。
因此,除了需要人为的完成local volume的mount 操作,local PV的生命周期管理就全部交给local volume manager了。
5、总结
本文对hostPath volume不能在生产环境中很好使用的原因进行了阐述,然后对local persistent volume的使用场景、基本的工作机制进行了分析,介绍了使用时的注意事项,最后简单介绍了local volume manager如何帮助administrator进行local persistent volume的生命周期管理的。