本节全部的代码基于1.13.4版本。缓存
在kubernetes中,与存储相关的controller主要由三种:
一、AttachDetachController,简称AD Controller,主要处理真实的与volume相关的操做;
二、PersistentVolumeBinderController,其实就是PV Controller,主要负责pv和pvc的生命周期以及状态的切换;
三、VolumeExpandController,主要负责volume的扩容操做。
oop
首先追踪PersistentVolumeBinderController方法,直接进入其Run方法。 插件
进入resync,代码很简单,以下: code
volumeWorker经过for循环,不停获取resync缓冲的队列信息,对pv,即volume作相应的更新操做。主要实现方法updateVolume
cdn
updateVolume
方法,主要调用
syncVolume
方法,这个方法是整个volumeWorker的核心。工做流程以下:
Available
;
Available
;Released
且不为Failed
,更新PV状态为Released
,按照配置的回收策略执行pv的回收(调用reclaimVolume
方法);Bound
;claimWorker的工做流程和volumeWorker相似,核心调用方法为updateClaim-->syncClaim
,主要处理的是pvc生命周期中的各类状态:Pending、Bound以及Lost。不作过多赘述。
blog
PersistentVolumeBinderController的执行流程很清晰,依赖三个goroutine的协做,分别处理数据的获取、pv的生命周期的状态更新和pvc的生命周期的状态更新。整个逻辑中,没有对具体的volume作操做,更新的仅仅是kubernetes中定义的pv和pvc资源的信息,说白了就是etcd中的数据。具体干活的主要仍是AttachDetachController,即AD Controller。接口
首先由Run
方法进入AD Controller的启动方法,以下: 生命周期
populateActualStateOfWorld
方法获取Node上Volume的信息;
populateDesiredStateOfWorld
方法获取Pod须要对应的Volume信息;
reconciler.Run
负责检查挂载状态,判断是否须要挂载或卸载(真正干活的);
desiredStateOfWorldPopulator.Run
同步Pod与Volume的挂载信息,相应信息输送给
reconciler.Run
使用;
pvcWorker
控制pvc的流控;
metrics
中,供Prometheus采集数据使用。
populateActualStateOfWorld
方法主要处理的是Node与Volume之间的关系,主要做用是将Node Volume当前的状态存入到actualStateOfWorld
中。主要方法以下: 队列
attached
的Volume,分别置于已经attached状态和
in-user
状态,将Volume信息添加到
actualStateOfWorld
中,并将Node添加到
desiredStateOfWorld
中。
actualStateOfWorld
和
desiredStateOfWorld
的数据会在
reconciler.Run
使用。
populateDesiredStateOfWorld
方法主要处理的是Pod与Volume之间的关系,主要做用是将Pod Volume指望的状态添加到desiredStateOfWorld
中去。和populateActualStateOfWorld
相似,主要就是针对Volume作标记操做,并将相应的Pod信息缓存到desiredStateOfWorld
中或者从desiredStateOfWorld
中剔除不匹配的Pod信息。事件
desiredStateOfWorldPopulator.Run
方法经过不停的循环,调用findAndAddActivePods
方法,经过获取全部的Pod,判断是否须要添加到desiredStateOfWorld
中去。
前面几步主要的目的是为了获取Node Volume和Pod Volume的状态。其中,Node上的Volume是已经存在的,故称做为actualStateOfWorld
,而Pod Volume是最终须要生效的资源,故称之为desiredStateOfWorld
。reconciler.Run
的做用就是经过不停获取actualStateOfWorld
和desiredStateOfWorld
状态,将Pod与Volume置于相对应的状态,保证磁盘的最终挂载成功或者卸载成功。主要方法以下:
reconciliationLoopFunc
方法。
reconcile
方法,这是真正干活的地方。
reconcile
使用了三个大的for循环,处理三类事件:
UnmountVolume
方法最终调用后台存储的解绑接口;
/dev/xx
等。Mount操做包含了MountDevice和Mount两部分,其中,MountDevice将生成的卷标挂载成Node的路径,通常在
/var/lib/kubelet/xx/kubernetes.io/xx
下,依赖于不一样的存储,Mount最终将MountDevice生成的路径和Pod须要使用的路径Mount起来,通常路径为
/var/lib/kubelet/pods/xx/volumes/xx
。
sync
方法主要完成Volume的后续操做。若是Volume未被成功绑定,将Volume进行重建或者解绑操做。
Kubernetes在1.8开始支持卷的扩容操做,1.11功能已经处于Beta阶段。主要代码以下:
pvcPopulator.Run
监听PVC的变化,只要PVC中Request字段的Storage值比Status中的大,即表示PVC容量发生了变化,须要扩容。此时,将相应的PV和PVC的信息缓存到
resizeMap
中去。以下:
syncResize
则是不停获取
resizeMap
中的数据,若是有变化,则调用
ExpandVolume
方法生成扩展动做,完成磁盘的扩容和PV、PVC的状态更新操做。代码以下:
Kubernetes的存储主要针对Node、Pod、PV以及PVC四类资源。经过获取Node上Volume状态,将其与Pod中的Volume进行绑定,完成卷的加载。最终的绑定或者解绑等操做依赖的是后台的存储,包括内置的开源存储插件或者本身实现的插件(FlexVolume或者CSI)。
在kubelet中,同时存在VolumeManager
去管理其节点上的Volume资源信息,基本功能与AD Controller一致。能够经过kube-controller-manager的--disable-attach-detach-reconcile-sync
参数或者kubelet的--enable-controller-attach-detach
参数控制是由kube-controller-manager执行volume的attach/detach操做仍是kubelet执行相应的操做。