如何接入 K8s 持久化存储?K8s CSI 实现机制浅析 (3)

PV 创建:runClaimWorker -> syncClaimHandler -> syncClaim -> provisionClaimOperation -> Provision -> CreateVolume
PV 删除:runVolumeWorker -> syncVolumeHandler -> syncVolume -> deleteVolumeOperation -> Delete -> DeleteVolume

如何接入 K8s 持久化存储?K8s CSI 实现机制浅析

由 sigs.k8s.io/sig-storage-lib-external-provisioner 抽象了相关接口:

// 通过 vendor 方式引入 sigs.k8s.io/sig-storage-lib-external-provisioner // external-provisioner/vendor/sigs.k8s.io/sig-storage-lib-external-provisioner/v7/controller/volume.go type Provisioner interface { // 调用 PRC CreateVolume 接口实现 PV 创建 Provision(context.Context, ProvisionOptions) (*v1.PersistentVolume, ProvisioningState, error) // 调用 PRC DeleteVolume 接口实现 PV 删除 Delete(context.Context, *v1.PersistentVolume) error } Controller 调谐

K8s 中与 PV 相关的控制器有 PVController、AttachDetachController。

PVController

PVController 通过在 PVC 添加相关 Annotation(如 pv.kubernetes.io/provisioned-by),由 external-provisioner 组件负责完成对应 PV 的创建/删除,然后 PVController 监测到 PV 创建成功的状态,完成与 PVC 的绑定(Bound),调谐(reconcile)任务完成。然后交给 AttachDetachController 控制器进行下一步逻辑处理。

值得一提的是,PVController 内部通过使用 local cache,高效实现了 PVC 与 PV 的状态更新与绑定事件处理,相当于在 K8s informer 机制之外,又自己维护了一个 local store 进行 Add/Update/Delete 事件处理。

首先,通过标准的 newController -> Run() 逻辑:

// kubernetes/pkg/controller/volume/persistentvolume/pv_controller_base.go func NewController(p ControllerParameters) (*PersistentVolumeController, error) { ... // 初始化 PVController controller := &PersistentVolumeController{ volumes: newPersistentVolumeOrderedIndex(), claims: cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc), kubeClient: p.KubeClient, eventRecorder: eventRecorder, runningOperations: goroutinemap.NewGoRoutineMap(true /* exponentialBackOffOnError */), cloud: p.Cloud, enableDynamicProvisioning: p.EnableDynamicProvisioning, clusterName: p.ClusterName, createProvisionedPVRetryCount: createProvisionedPVRetryCount, createProvisionedPVInterval: createProvisionedPVInterval, claimQueue: workqueue.NewNamed("claims"), volumeQueue: workqueue.NewNamed("volumes"), resyncPeriod: p.SyncPeriod, operationTimestamps: metrics.NewOperationStartTimeCache(), } ... // PV 增删改事件监听 p.VolumeInformer.Informer().AddEventHandler( cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { controller.enqueueWork(controller.volumeQueue, obj) }, UpdateFunc: func(oldObj, newObj interface{}) { controller.enqueueWork(controller.volumeQueue, newObj) }, DeleteFunc: func(obj interface{}) { controller.enqueueWork(controller.volumeQueue, obj) }, }, ) ... // PVC 增删改事件监听 p.ClaimInformer.Informer().AddEventHandler( cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { controller.enqueueWork(controller.claimQueue, obj) }, UpdateFunc: func(oldObj, newObj interface{}) { controller.enqueueWork(controller.claimQueue, newObj) }, DeleteFunc: func(obj interface{}) { controller.enqueueWork(controller.claimQueue, obj) }, }, ) ... return controller, nil }

接着,调用 PVC/PV 绑定/解绑逻辑:

PVC/PV 绑定:claimWorker -> updateClaim -> syncClaim -> syncBoundClaim -> bind
PVC/PV 解绑:volumeWorker -> updateVolume -> syncVolume -> unbindVolume

AttachDetachController

AttachDetachController 将已经绑定(Bound) 成功的 PVC/PV,内部经过 InTreeToCSITranslator 转换器,实现由 in-tree 方式管理的 Volume 向 out-of-tree 方式管理的 CSI 插件模式转换。

接着,由 CSIPlugin 内部逻辑实现 VolumeAttachment 资源类型的创建/删除,调谐(reconcile) 任务完成。然后交给 external-attacher 组件进行下一步逻辑处理。

相关核心代码在 reconciler.Run() 中实现如下:

// kubernetes/pkg/controller/volume/attachdetach/reconciler/reconciler.go func (rc *reconciler) reconcile() { // 先进行 DetachVolume,确保因 Pod 重新调度到其他节点的 Volume 提前分离(Detach) for _, attachedVolume := range rc.actualStateOfWorld.GetAttachedVolumes() { // 如果不在期望状态的 Volume,则调用 DetachVolume 删除 VolumeAttachment 资源对象 if !rc.desiredStateOfWorld.VolumeExists( attachedVolume.VolumeName, attachedVolume.NodeName) { ... err = rc.attacherDetacher.DetachVolume(attachedVolume.AttachedVolume, verifySafeToDetach, rc.actualStateOfWorld) ... } } // 调用 AttachVolume 创建 VolumeAttachment 资源对象 rc.attachDesiredVolumes() ... } 附着/分离 Volume

K8s 中持久卷 PV 的附着(Attach)与分离(Detach),由 external-attacher 组件实现,相关工程代码在:【https://github.com/kubernetes-csi/external-attacher】

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgzjdg.html