一:初始化
1.adc调用InitPlugins()初始化volumeplugins。
1.1初始化dynamicplugins(Currentlyonly Flexvolume plugins are dynamicallydiscoverable.Flexvolume允许用户编写自己的驱动程序,并在Kubernetes中添加对其Volume的支持)
1.2初始化kubernetes已经含有的volumeplugins:aws,gce,cinder等等
2.创建两个缓存desiredStateOfWorld(存放volume期望的状态)actualStateOfWorld
(存放volume当前的状态)
3.初始化对象attacherDetacher(用于挂载卸载volume)nodeStatusUpdater(更新node的状态)reconciler(循环进行attachdetach操作)desiredStateOfWorldPopulator(处理volume达到desiredStateOfWorld的状态)
二:启动
1.通过informer同步podnode pv pvc的状态到缓存
2.调用populateActualStateOfWorld()将nodevolume当前的对应状态存入actualStateOfWorld
3.调用populateDesiredStateOfWorld()将podvolume期望的对应状态存入desiredStateOfWorld
4.reconciler.Run()循环执行挂载卸载操作,处理desiredStateOfWorld达到actualStateOfWorld,并定期检查actualStateOfWorld的状态是真实挂载的,否则将volume从actualStateOfWorld删除。
5.desiredStateOfWorldPopulator.Run()循环获取新的pod的挂载信息,生成desiredStateOfWorld对应的状态
三:populateActualStateOfWorld
type actualStateOfWorld struct {
所有已经挂载的volume信息,key是volume unique name(volume plugin + volume id)用来记录volume的挂载状态
attachedVolumes map[v1.UniqueVolumeName]attachedVolume
volume挂载到某个node上的对应(node --> volume ) 用来跟踪volume的挂载状态(确认被标记为已被挂载到该节点的volume被挂载了)
nodesToUpdateStatusFor map[types.NodeName]nodeToUpdateStatusFor
volumePluginMgr *volume.VolumePluginMgr
sync.RWMutex
}
type attachedVolume struct {
// 唯一的volume名
volumeName v1.UniqueVolumeName
volume的详细信息
spec *volume.Spec
volume的挂载信息,key是node名,nodeAttachedTo包含简单的node信息
nodesAttachedTo map[types.NodeName]nodeAttachedTo
volume在node上的挂载路径
devicePath string
}
type nodeAttachedTo struct {
nodeName types.NodeName
是否被挂载,默认时挂载的状态,会轮询验证这个volume确实是被挂载的
mountedByNode bool
// number of times SetVolumeMountedByNode has been called to set the value
// of mountedByNode to true. This is used to prevent mountedByNode from
// being reset during the period between attach and mount when volumesInUse
// status for the node may not be set.
mountedByNodeSetCount uint
// detachRequestedTime used to capture the desire to detach this volume
detachRequestedTime time.Time
}
type nodeToUpdateStatusFor struct {
nodeName types.NodeName
当volume的挂载状态有变化时,需及时更新node的status,当volume被detach了,需要删除node中attachedvolume对应volume的值
statusUpdateNeeded bool
标记volume是attached
volumesToReportAsAttached map[v1.UniqueVolumeName]v1.UniqueVolumeName
}
1.获取所有node,并根据node.Status.VolumesAttached(已经挂载的volume)将volume标记为已被挂载。
1.1调用AddVolumeNode(uniqueName,volumeSpec, nodeName, devicePath)将volume的挂载状态存起来
1.1.1存入attachedVolumes(volume--> detail)
1.1.2调用addVolumeToReportAsAttached()存入nodesToUpdateStatusFor(node--> volume)
1.2调用processVolumesInUse()处理in-use状态的volume
1.2.1调用GetAttachedVolumesForNode获取所有挂载到该node上的volume
1.2.2当volume的确挂载到node上且状态是in-use时,调用SetVolumeMountedByNode将mountedByNode设置为true
1.3调用addNodeToDswp将node存入desiredStateOfWorld,如果node含有“停止挂载volume”的标签,adc需要将node上的volume期望状态设置为detached,进而再根据volume性为去detachvolume
四:populateDesiredStateOfWorld ==》nodesManaged
type desiredStateOfWorld struct {
node -> pod -> volume
nodesManaged map[k8stypes.NodeName]nodeManaged
volumePluginMgr *volume.VolumePluginMgr
sync.RWMutex
}
type nodeManaged struct {
nodeName k8stypes.NodeName
//volumesToAttach是一个map包含一系列volume,key是volume value是volume与pod的信息
volumesToAttach map[v1.UniqueVolumeName]volumeToAttach
对于删除了的pod,是否需要删除pod对应的volume
keepTerminatedPodVolumes bool
}
type volumeToAttach struct {
//多节点挂载报错
multiAttachErrorReported bool
volumeName v1.UniqueVolumeName
volume的详情
spec *volume.Spec
volume所挂载pod的详情
scheduledPods map[types.UniquePodName]pod
}
1.获取所有的pod,调用podAdd将pod的volume加入到desiredStateOfWorld
1.1如果pod所在的node不在desiredStateOfWorld中,就将这样的pod过滤过,不处理这样的podvolume
1.2假如pod的node被标记“删除pod”,调用desiredStateOfWorld.DeletePod从desiredStateOfWorld中删除pod,没有就直接返回
1.3否则将pod添加到desiredStateOfWorld中,等待挂载
1.4依次遍历pod的volume,判断volume是否挂载了,如果挂载就将volumemark为attached,否则报错(这段代码有问题,不需要在这里遍历vlume进而去修改actualStateOfWorld)
五:goadc.reconciler.Run(stopCh)循环执行挂载卸载操作
1.reconcile()
1.1(Ensurevolumes that should be detached aredetached.)遍历actualStateOfWorld中已经挂载的volume,假如该volume不在desiredStateOfWorld中并且挂载的时间超过maxWaitForUnmountDuration,将该volume从actualStateOfWorld删除,即markdetached,也调用UpdateNodeStatuses()更新volume在node的detach信息.最后调用attacherDetacher.DetachVolume()detachvolume,即调用volume插件去detach。
1.2(Ensurevolumes that should be attached are attached)
1.2.1遍历desiredStateOfWorld中期望被挂载的volume,假如该volume在actualStateOfWorld中,则ResetDetachRequestTime重新设置detach时间(待续),否则挂载他
1.2.2调用isMultiAttachForbidden判断该volume是否禁止多点挂载,如果是,判断该volume挂载到多个节点了报错,
1.2.3调用attacherDetacher.AttachVolume挂载期望被挂载但还没挂载的volume
1.3调用rc.nodeStatusUpdater.UpdateNodeStatuses()更新node的volume挂载状态
2.disableReconciliationSync为true时,如果adc已经挂载过的volume被别人通过命令行detach了,adc不会去再次挂载。否则执行sync()去同步volume的挂载状态
2.1调用GetAttachedVolumesPerNode从actualStateOfWorld获取所有已经挂载的volume及vlume所挂载的node信息,GetAttachedVolumesPerNode从attachedVolumes获取信息:map[types.NodeName][]operationexecutor.AttachedVolume
2.2调用VerifyVolumesAreAttached确保volume已经挂载到node上了
2.2.1将需要确保被挂载的volume及其node存入map,node-->volume
2.2.2假如volumeplugin支持BulkVerifyVolumes(plugin含有获取volume真实挂载信息的函数,该函数能获取到集群中所有node上挂载的volume信息,node--> volume),
就调用BulkVerifyVolumes()获取到node上挂载的volume信息,根据2.2.1的map,检测map中node对应的volume是否确实被挂载了,假如map中volume没有被真实挂载则调用MarkVolumeAsDetached标记actualStateOfWorld中该volume是detached的,即从actualStateOfWorld中将该volume删除
2.2.3否则调用VerifyVolumesAreAttachedPerNode依次检查node上的volume是否被真实挂载
2.2.3.1调用VolumesAreAttached去判断map中volume是否被挂载到node上(例如openstackcinder:如果volume被挂载到某个node上,volume的详情中能查到挂载的nodeid,如果nodeid是相同,则认为是被真实挂载到该node上了),假如map中volume没有被真实挂载则调用MarkVolumeAsDetached标记actualStateOfWorld中该volume是detached的,即从actualStateOfWorld中将该volume删除
六:goadc.desiredStateOfWorldPopulator.Run(stopCh)
1调用findAndRemoveDeletedPods将nodesManaged中不再存在的pod删除
1.1调用GetPodToAdd从nodesManaged获取所有pod及pod的volume挂载信息
1.2判断pod是否存在podinformer缓存中,不存在就调用DeletePod将该pod从nodesManaged中删除
2调用findAndAddActivePods将新的active的pod及pod上的volume信息加入nodesManaged中。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)