很多人对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
也不能申明需要的storage
size,这样调度时存储的考虑,就需要人为检查并保证。
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
的生命周期管理的。