深究Kubernetes源碼-存儲-3 Volume Controller機(jī)制流程分析
分析基于kubernetes v1.26?
2.2.1 PVController
PVController運(yùn)行在kube-controller-manager中,主要類圖如下:

其核心邏輯是調(diào)諧PersistenVolume和PersistenVolumeClaim,對PVC如果是動(dòng)態(tài)創(chuàng)建PV,則創(chuàng)建對應(yīng)Volume,并生成PV,綁定PV和PVC。

關(guān)鍵啟動(dòng)流程如下,主要流程在resync/volumeWorker/claimWorker三個(gè)協(xié)程中。

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中對比,執(zhí)行updateVolume或deleteVolume。updateVolume核心是更新pv狀態(tài),PV五個(gè)狀態(tài)是Pending(創(chuàng)建默認(rèn)狀態(tài)),Available,Bound,Released,F(xiàn)ailed,syncVolume邏輯如下所示,根據(jù)volume.Spec.ClaimRef進(jìn)行一系列的判斷,執(zhí)行操作包括reclaimVolume/unbindVolume。

eclaimVolume邏輯即釋放PV,根據(jù)PersistenVolumeReclaimPolicy共定義了三種策略https://kubernetes.io/docs/concepts/storage/persistent-volumes/#reclaim-policy
Retain -- 不做任何動(dòng)作,由后續(xù)人為處理
Recycle -- 對PV進(jìn)行循環(huán)回收,通常是執(zhí)行rm -rf /thevolume/* 刪除volume目錄數(shù)據(jù),只有NFS支持
Delete -- 部分Intree Volume Plugin支持直接刪除PV
claimWorker主要處理PVC狀態(tài),PVC包括Pending/Bound/Lost三個(gè)狀態(tài),其中包含的核心操作是findBestMatchForClaim,即為PVC找到需要消費(fèi)的PV,bind更新PVC/PV到Bound狀態(tài)

provisionClaim是根據(jù)PVC StorageClass動(dòng)態(tài)創(chuàng)建PV流程,核心是根據(jù)findProvisionablePlugin是否找到VolumePlugin分為外部volume和內(nèi)部volume,內(nèi)部volume即intree VolumePlugin處理,外部基本為CSI流程處理(flexVolumePlugin已廢棄)。

findProvisionablePlugin根據(jù)PVC StorageClass其中的Provsion字段從VolumePluginMgr中找到對應(yīng)要處理的VolumePlugin,例如下面Cinder CSI StorageClass provision為cinder.csi.openstack.org,并不匹配intree VolumePlugin,會走provisionClaimOperationExternal,更新PVC的annotation volume.beta.kubernetes.io/storage-provisioner: cinder.csi.openstack.org ,后續(xù)走CSI Provision流程,見《1.2.3 ProvisionController》。如若是intree則走provisionClaimOperation,調(diào)用VolumePlugin Provision Volume,并創(chuàng)建PV。
最后看下PV如何與PVC匹配,源碼如下:
1)allPossibleMatchingAccessModes根據(jù)AccessMode匹配:PV AccessMode需要包含PVC AccessMode (https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes)
AccessMode包含4種
ReadWriteOnce -- 可以被一個(gè)節(jié)點(diǎn)掛載為讀寫模式,同一個(gè)節(jié)點(diǎn)上的Pod可以同時(shí)掛載此Volume,基礎(chǔ)能力,基本所有的Volume Plugin都支持
ReadOnlyMany -- 可以被多個(gè)節(jié)點(diǎn)掛載為只讀模式,大部分VolumePlugin都支持
ReadWriteMany -- 可以被多個(gè)節(jié)點(diǎn)掛載為讀寫模式
ReadWriteOncePod -- 只可以被一個(gè)Pod掛載為讀寫模式,只有k8s 1.22+ csi volume支持
2)FindMatchingVolume根據(jù)規(guī)則過濾
a) 已綁定的排除
b) pvc request storage > volume capacity storage排除
c) VolumeMode不同排除,默認(rèn)Filesystem,共包含Block和Filesystem兩種
d) 標(biāo)記刪除Volume 排除
e) Volume非Available排除
f) pvc label seletor不匹配pv label排除
g) StorageClass不同排除
h) node親和規(guī)則不匹配排除,調(diào)度階段使用
3)FindMatchingVolume匹配pvc request storage和pv capacity最接近的PV