基于tag v2.1.1
https://github.com/kubernetes-csi/external-attacher/releases/tag/v2.1.1
external-attacher
external-attacher属于external plugin中的一个。下面我们先来回顾一下external plugin以及csi系统结构。
external plugin
external plugin包括了external-provisioner、external-attacher、external-resizer、external-snapshotter等,external plugin辅助csi plugin组件,共同完成了存储相关操作。external plugin负责watch pvc、volumeAttachment等对象,然后调用volume plugin来完成存储的相关操作。如external-provisioner watch pvc对象,然后调用csi plugin来创建存储,最后创建pv对象;external-attacher watch volumeAttachment对象,然后调用csi plugin来做attach/dettach操作,并修改volumeAttachment对象与pv对象;external-resizer watch pvc对象,然后调用csi plugin来做存储的扩容操作等。
csi系统结构
external-attacher作用分析
根据CSI plugin是否支持ControllerPublish/ControllerUnpublish操作,external-attacher的作用分为如下两种:
(1)当CSI plugin不支持ControllerPublish/ControllerUnpublish操作时,AD controller(或kubelet的volume manager)创建VolumeAttachment对象后,external-attacher仅参与VolumeAttachment对象的修改,将attached属性值patch为true;而external-attacher对pv对象无任何同步处理操作。
(2)当CSI plugin支持ControllerPublish/ControllerUnpublish操作时,external-attacher调用csi plugin(ControllerPublishVolume)进行存储的attach操作,然后更改VolumeAttachment对象,将attached属性值patch为true,并patch pv对象,增加该external-attacher相关的finalizer;对于pv对象,external-attacher负责处理pv对象的finalizer,patch pv对象,去除该external-attacher相关的finalizer(该external-attacher执行attach操作时添加的finalizer)。
源码分析
external-attacher的源码分析将分为两部分:
(1)main方法以及启动参数分析;
(2)核心处理逻辑分析。
前面一篇博客已经对external-attacher的main方法以及启动参数做了分析,这篇博客将对external-attacher的核心处理逻辑进行源码分析。
Run
核心逻辑为跑goroutine不停的调用ctrl.syncVA与ctrl.syncPV对VolumeAttachment对象以及PV对象进行同步处理。
//external-attcher/pkg/controller/controller.go
// Run starts CSI attacher and listens on channel events
func (ctrl *CSIAttachController) Run(workers int, stopCh <-chan struct{}) {
defer ctrl.vaQueue.ShutDown()
defer ctrl.pvQueue.ShutDown()
klog.Infof("Starting CSI attacher")
defer klog.Infof("Shutting CSI attacher")
if !cache.WaitForCacheSync(stopCh, ctrl.vaListerSynced, ctrl.pvListerSynced) {
klog.Errorf("Cannot sync caches")
return
}
for i := 0; i < workers; i++ {
go wait.Until(ctrl.syncVA, 0, stopCh)
go wait.Until(ctrl.syncPV, 0, stopCh)
}
if ctrl.shouldReconcileVolumeAttachment {
go wait.Until(func() {
err := ctrl.handler.ReconcileVA()
if err != nil {
klog.Errorf("Failed to reconcile volume attachments: %v", err)
}
}, ctrl.reconcileSync, stopCh)
}
<-stopCh
}
1.syncVA
syncVA负责VolumeAttachment对象的处理,核心逻辑为:
(1)判断VolumeAttachment对象的.Spec.Attacher
属性值,判断是否由本attacher组件来负责VolumeAttachment对象的同步处理;
(2)调用ctrl.handler.SyncNewOrUpdatedVolumeAttachment(va)。
//external-attcher/pkg/controller/controller.go
func (ctrl *CSIAttachController) syncVA() {
key, quit := ctrl.vaQueue.Get()
if quit