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

external-attacher 组件观察到由上一步 AttachDetachController 创建的 VolumeAttachment 对象,如果其 .spec.Attacher 中的 Driver name 指定的是自己同一 Pod 内的 CSI Plugin,则调用 CSI Plugin 的ControllerPublish 接口进行 Volume Attach。

首先,通过标准的 cmd 方式获取命令行参数,执行 newController -> Run() 逻辑,相关代码如下:

// external-attacher/cmd/csi-attacher/main.go func main() { ... ctrl := controller.NewCSIAttachController( clientset, csiAttacher, handler, factory.Storage().V1().VolumeAttachments(), factory.Core().V1().PersistentVolumes(), workqueue.NewItemExponentialFailureRateLimiter(*retryIntervalStart, *retryIntervalMax), workqueue.NewItemExponentialFailureRateLimiter(*retryIntervalStart, *retryIntervalMax), supportsListVolumesPublishedNodes, *reconcileSync, ) run := func(ctx context.Context) { stopCh := ctx.Done() factory.Start(stopCh) ctrl.Run(int(*workerThreads), stopCh) } ... }

接着,调用 Volume 附着/分离逻辑:

Volume 附着(Attach):syncVA -> SyncNewOrUpdatedVolumeAttachment -> syncAttach -> csiAttach -> Attach -> ControllerPublishVolume
Volume 分离(Detach):syncVA -> SyncNewOrUpdatedVolumeAttachment -> syncDetach -> csiDetach -> Detach -> ControllerUnpublishVolume

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

kubelet 挂载/卸载 Volume

K8s 中持久卷 PV 的挂载(Mount)与卸载(Unmount),由 kubelet 组件实现。

kubelet 通过 VolumeManager 启动 reconcile loop,当观察到有新的使用 PersistentVolumeSource 为CSI 的 PV 的 Pod 调度到本节点上,于是调用 reconcile 函数进行 Attach/Detach/Mount/Unmount 相关逻辑处理。

// kubernetes/pkg/kubelet/volumemanager/reconciler/reconciler.go func (rc *reconciler) reconcile() { // 先进行 UnmountVolume,确保因 Pod 删除被重新 Attach 到其他 Pod 的 Volume 提前卸载(Unmount) rc.unmountVolumes() // 接着通过判断 controllerAttachDetachEnabled || PluginIsAttachable 及当前 Volume 状态 // 进行 AttachVolume / MountVolume / ExpandInUseVolume rc.mountAttachVolumes() // 卸载(Unmount) 或分离(Detach) 不再需要(Pod 删除)的 Volume rc.unmountDetachDevices() }

相关调用逻辑如下:

Volume 挂载(Mount):reconcile -> mountAttachVolumes -> MountVolume -> SetUp -> SetUpAt -> NodePublishVolume
Volume 卸载(Unmount):reconcile -> unmountVolumes -> UnmountVolume -> TearDown -> TearDownAt -> NodeUnpublishVolume

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

小结

本文通过分析 K8s 中持久卷 PV 的 创建(Create)、附着(Attach)、分离(Detach)、挂载(Mount)、卸载(Unmount)、删除(Delete) 等核心生命周期流程,对 CSI 实现机制进行了解析,通过源码、图文方式说明了相关流程逻辑,以期更好的理解 K8s CSI 运行流程。

可以看到,K8s 以 CSI Plugin(out-of-tree) 插件方式开放存储能力,一方面是为了将 K8s 核心主干代码与 Volume 相关代码解耦,便于更好的维护;另一方面在遵从 CSI 规范接口下,便于各大云厂商根据业务需求实现相关的接口,提供个性化的云存储能力,以期达到云存储生态圈的开放共赢。

PS: 更多内容请关注 k8s-club

相关资料

CSI 规范

Kubernetes 源码

kubernetes-csi 源码

kubernetes-sig-storage 源码

K8s CSI 概念

K8s CSI 介绍

关于我们

更多关于云原生的案例和知识,可关注同名【腾讯云原生】公众号~

福利:

①公众号后台回复【手册】,可获得《腾讯云原生路线图手册》&《腾讯云原生最佳实践》~ ②公众号后台回复【系列】,可获得《15个系列100+篇超实用云原生原创干货合集》,包含Kubernetes 降本增效、K8s 性能优化实践、最佳实践等系列。

【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!

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

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

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