摘要:本文分析了hostPath volume缺陷,而后对local persistent volume的使用场景、基本的工做机制进行了分析,介绍了使用时的注意事项,并简单介绍local volume manager如何帮助administrator进行local persistent volume的生命周期管理的。node
过去咱们常常会经过hostPath volume
让Pod可以使用本地存储,将Node文件系统中的文件或者目录挂载到容器内,可是hostPath volume
的使用是很难受的,并不适合在生产环境中使用。git
咱们先看看hostPath Type有哪些类型:github
Value | Behavior |
---|---|
Empty string (default) is for backward compatibility, which means that no checks will be performed before mounting the hostPath volume. | |
DirectoryOrCreate | If nothing exists at the given path, an empty directory will be created there as needed with permission set to 0755, having the same group and ownership with Kubelet. |
Directory | A directory must exist at the given path |
FileOrCreate | If nothing exists at the given path, an empty file will be created there as needed with permission set to 0644, having the same group and ownership with Kubelet. |
File | A file must exist at the given path |
Socket | A UNIX socket must exist at the given path |
CharDevice | A character device must exist at the given path |
BlockDevice | A block device must exist at the given path |
看起来支持这么多type仍是挺好的,但为何说不适合在生产环境中使用呢?api
因为集群内每一个节点的差别化,要使用hostPath Volume,咱们须要经过NodeSelector等方式进行精确调度,这种事情多了,你就会不耐烦了。网络
注意DirectoryOrCreate和FileOrCreate两种类型的hostPath,当Node上没有对应的File/Directory时,你须要保证kubelet有在Node上Create File/Directory的权限。socket
另外,若是Node上的文件或目录是由root建立的,挂载到容器内以后,你一般还要保证容器内进程有权限对该文件或者目录进行写入,好比你须要以root用户启动进程并运行于privileged容器,或者你须要事先修改好Node上的文件权限配置。分布式
Scheduler并不会考虑hostPath volume的大小,hostPath也不能申明须要的storage size,这样调度时存储的考虑,就须要人为检查并保证。源码分析
StatefulSet没法使用hostPath volume,已经写好的使用共享存储的Helm Chart不能兼容hostPath volume,须要修改的地方还很多,这也挺难受的。ui
FEATURE STATE: Kubernetes v1.11 Betacode
Local persistent volume就是用来解决hostPath volume面临的**portability, disk accounting, and scheduling
**的缺陷。PV Controller和Scheduler会对local PV作特殊的逻辑处理,以实现Pod使用本地存储时发生Pod re-schedule的状况下能再次调度到local volume所在的Node。
local pv在生产中使用,也是须要谨慎的,毕竟它本质上仍是使用的是节点上的本地存储,若是没有相应的存储副本机制,那意味着一旦节点或者磁盘异常,使用该volume的Pod也会异常,甚至出现数据丢失,除非你明确知道这个风险不会对你的应用形成很大影响或者容许数据丢失。
那么一般什么状况会使用Local PV呢?
Local volume容许挂载本地的disk, partition, directory到容器内某个挂载点。在Kuberentes 1.11仍然仅支持local pv的static provision,不支持dynamic provision。
Kubernetes使用PersistentVolume的.spec.nodeAffinity
field来描述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
使用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。
上面这么多事情须要人为的去作预处理的工做,咱们必需要有解决方案帮咱们自动完成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了。下面咱们专门介绍下这个Static Local Volume Provisioner。
后面我会单独写一个博文对local volume manager进行深度剖析。
本文对hostPath volume不能在生产环境中很好使用的缘由进行了阐述,而后对local persistent volume的使用场景、基本的工做机制进行了分析,介绍了使用时的注意事项,最后简单介绍了local volume manager如何帮助administrator进行local persistent volume的生命周期管理的。接下来,我会再写两篇博客,分别对scheduler和pv controller如何对local persistent volume的处理逻辑进行源码分析,对local volume manager进行深度剖析。