k8s PvController绑定pvc和pv
k8s v1.19.0
结论
pv-controller创建pv,完成pvc与pv的绑定。
无论是WaitForFirstConsumer还是Immediate,挑选pv时都是选择满足vpc的accessMode和容量前提下最接近容量要求的pv。
1. 如果StorageClass中volumeBindingMode是WaitForFirstConsumer,那么pvc和pv绑定延迟到kube-scheduler的异步preBind,在异步bind之前。
异步preBind,具体是,kube-scheduler会触发预绑定即保存pv关联的pvc id,等待pv-controller完成绑定。完成绑定的标志是,pvc有关联的pv id,且有完成绑定的注解。
pv自身可能会有nodeAffinity要求,调度时需要满足。
2. 如果StorageClass中volumeBindingMode是Immediate(默认),那么pvc和pv满足条件就绑定,不延迟到调度时。
为什么kube-scheduler不自己完成pvc和pv的绑定?
因为pvc和pv的绑定是pv-controller的职责,kube-scheduler最多预绑定,触发pv-controller完成最终绑定。
pv-controller代码分析
pv controller每隔1s处理未绑定pv的pvc。
pkg/controller/volume/persistentvolume/pv_controller.go
syncUnboundClaim方法
同步未绑定的pvc
1. 获取pvc的绑定模式。
2. 找到最适合pvc的pv。
3. 如果没有找到pv,延迟绑定,pvc注解上没有kube-scheduler增加的节点id,那么结束。
4. 如果没有找到pv,支持动态创建pv,那么由pv-controller创建pv,对应底层存储系统卷。
5. 如果找到pv,那么pv-controller更新pvc和pv字段,互相关联,完成pvc和pv的绑定。
pkg/controller/volume/persistentvolume/util/util.go
FindMatchingVolume函数
遍历所有pv,找到最合适的。kube-scheduler使用该方法预选。
1. 如果pv已绑定pvc,但不是当前pvc,那么跳过。
2. 跳过容量不满足pvc要求的pv。
3. 跳过卷模式不满足pvc要求的pv。卷模式有格式化和非格式化。
4. 跳过正在删除中的pv。
5. pv-controller判断时,node是nil,pv已关联当前pvc,直接返回该pv,kube-scheduler预绑定触发该逻辑;kube-scheduler判断时,node需要满足pv的nodeAffinity,否则即使pv已关联当前pvc,不会选择该节点。
6. pv-controller跳过延迟绑定场景。
7. 跳过pv不可用、pv标签满足不了pvc要求、pv与pvc StorageClassName不匹配、节点满足不了pv的nodeAffinity的pv。
8. kube-scheduler跳过不匹配pvc accessMode的pv。accessMode包括只挂载到单台主机读写、可挂载到多台主机只读、可挂载到多台主机读写。
9. 更新最接近pvc容量的pv。
10. 选择容量最接近pvc的pv。
kube-scheduler代码分析
pkg/scheduler/scheduler.go
scheduleOne方法
作为调度入口,通过预选和优选找到最优节点,通过开协程的并行方式来加速。
pkg/scheduler/core/generic_scheduler.go
findNodesThatPassFilters方法
并行预选
pkg/scheduler/framework/runtime/framework.go
RunScorePlugins方法
并行优选
pkg/scheduler/algorithmprovider/registry.go
getDefaultConfig函数
预置的调度插件算法
预选过程中,volumebinding会调用上面提到的FindMatchingVolume函数。
预绑定过程中,volumebinding会通过bindAPIUpdate方法使选中的pv关联上pvc,并阻塞等待pv-controller绑定成功或者超时失败。
pkg/controller/volume/scheduling/scheduler_binder.go
bindAPIUpdate方法
kube-scheduler更新pv和pvc,触发pv-controller完成绑定。
pkg/controller/volume/scheduling/scheduler_binder.go
BindPodVolumes方法
阻塞等待pv-controller绑定成功或者超时失败。
pkg/controller/volume/scheduling/scheduler_binder.go
isPVCFullyBound方法
pvc有关联的pv id,且有完成绑定的注解,说明pvc和pv已完成绑定。