深究Kubernetes源码-存储-3 Volume Controller机制流程分析
分析基于kubernetes v1.26
2.2.1 PVController
PVController运行在kube-controller-manager中,主要类图如下:

其核心逻辑是调谐PersistenVolume和PersistenVolumeClaim,对PVC如果是动态创建PV,则创建对应Volume,并生成PV,绑定PV和PVC。

关键启动流程如下,主要流程在resync/volumeWorker/claimWorker三个协程中。

resync逻辑为定期resync pv/pvc informer,将pv/pvc放入到WorkQueue。
k8s.io/kubernetes/pkg/controller/volume/pv_controller_base.go
volumeWorker为从volumes WorkQueue 中取出pv,并与 pv informer和 volumes cache.Store中对比,执行updateVolume或deleteVolume。updateVolume核心是更新pv状态,PV五个状态是Pending(创建默认状态),Available,Bound,Released,Failed,syncVolume逻辑如下所示,根据volume.Spec.ClaimRef进行一系列的判断,执行操作包括reclaimVolume/unbindVolume。

eclaimVolume逻辑即释放PV,根据PersistenVolumeReclaimPolicy共定义了三种策略https://kubernetes.io/docs/concepts/storage/persistent-volumes/#reclaim-policy
Retain -- 不做任何动作,由后续人为处理
Recycle -- 对PV进行循环回收,通常是执行rm -rf /thevolume/* 删除volume目录数据,只有NFS支持
Delete -- 部分Intree Volume Plugin支持直接删除PV
claimWorker主要处理PVC状态,PVC包括Pending/Bound/Lost三个状态,其中包含的核心操作是findBestMatchForClaim,即为PVC找到需要消费的PV,bind更新PVC/PV到Bound状态

provisionClaim是根据PVC StorageClass动态创建PV流程,核心是根据findProvisionablePlugin是否找到VolumePlugin分为外部volume和内部volume,内部volume即intree VolumePlugin处理,外部基本为CSI流程处理(flexVolumePlugin已废弃)。

findProvisionablePlugin根据PVC StorageClass其中的Provsion字段从VolumePluginMgr中找到对应要处理的VolumePlugin,例如下面Cinder CSI StorageClass provision为cinder.csi.openstack.org,并不匹配intree VolumePlugin,会走provisionClaimOperationExternal,更新PVC的annotation volume.beta.kubernetes.io/storage-provisioner: cinder.csi.openstack.org ,后续走CSI Provision流程,见《1.2.3 ProvisionController》。如若是intree则走provisionClaimOperation,调用VolumePlugin Provision Volume,并创建PV。
最后看下PV如何与PVC匹配,源码如下:
1)allPossibleMatchingAccessModes根据AccessMode匹配:PV AccessMode需要包含PVC AccessMode (https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes)
AccessMode包含4种
ReadWriteOnce -- 可以被一个节点挂载为读写模式,同一个节点上的Pod可以同时挂载此Volume,基础能力,基本所有的Volume Plugin都支持
ReadOnlyMany -- 可以被多个节点挂载为只读模式,大部分VolumePlugin都支持
ReadWriteMany -- 可以被多个节点挂载为读写模式
ReadWriteOncePod -- 只可以被一个Pod挂载为读写模式,只有k8s 1.22+ csi volume支持
2)FindMatchingVolume根据规则过滤
a) 已绑定的排除
b) pvc request storage > volume capacity storage排除
c) VolumeMode不同排除,默认Filesystem,共包含Block和Filesystem两种
d) 标记删除Volume 排除
e) Volume非Available排除
f) pvc label seletor不匹配pv label排除
g) StorageClass不同排除
h) node亲和规则不匹配排除,调度阶段使用
3)FindMatchingVolume匹配pvc request storage和pv capacity最接近的PV