基于tag v0.5.0
https://github.com/kubernetes-csi/external-resizer/releases/tag/v0.5.0
存储扩容过程
存储扩容分为controller端和node端两步,先进行controller端(external-resizer触发)的扩容,然后再进行node端(kubelet触发)扩容(当volumemode是block,则不用进行node端扩容操作),存储的扩容操作才算完成。
controller端存储扩容作用
将底层存储扩容,如ceph rbd扩容,则会让ceph集群中的rbd image扩容。
node端存储扩容作用
在pod所在的node上做相应的操作,让node感知该存储已经扩容,如ceph rbd filesystem扩容,则会调用node上的文件系统扩容命令让文件系统扩容。
某些存储无需进行node端扩容操作如cephfs。
存储扩容大致过程
(1)更改pvc.Spec.Resources.Requests.storgage,触发扩容
(2)controller端存储扩容:external-resizer watch pvc对象,当发现pvc.Spec.Resources.Requests.storgage比pvc.Status.Capacity.storgage大,于是调csi plugin的ControllerExpandVolume方法进行 controller端扩容,进行底层存储扩容,并更新pv.Spec.Capacity.storgage。
(3)node端存储扩容:kubelet发现pv.Spec.Capacity.storage大于pvc.Status.Capacity.storage,于是调csi node端扩容,对dnode上文件系统扩容,成功后kubelet更新pvc.Status.Capacity.storage。
存储扩容详细过程
下面以ceph rbd存储扩容为例,对详细的存储扩容过程进行分析。
(1)修改pvc对象,修改申请存储大小(pvc.spec.resources.requests.storage);
(2)修改成功后,external-resizer监听到该pvc的update事件,发现pvc.Spec.Resources.Requests.storgage比pvc.Status.Capacity.storgage大,于是调ceph-csi组件进行 controller端扩容;
(3)ceph-csi组件调用ceph存储,进行底层存储扩容;
(4)底层存储扩容完成后,external-resizer组件更新pv对象的.Spec.Capacity.storgage的值为扩容后的存储大小;
(5)kubelet的volume manager在reconcile()调谐过程中发现pv.Spec.Capacity.storage大于pvc.Status.Capacity.storage,于是调ceph-csi组件进行 node端扩容;
(6)ceph-csi组件对node上存储对应的文件系统扩容;
(7)扩容完成后,kubelet更新pvc.Status.Capacity.storage的值为扩容后的存储大小。
本节将对controller端存储扩容进行分析,node端存储扩容已经在之前有分析过了,可以看kubelet pvc存储扩容相关代码分析
controller端存储扩容
当pvc.Spec.Resources.Requests大小比pvc.Status.Capacity.storgage大时,会触发到controller端(external-resizer)的扩容逻辑。
controller端(external-resizer)的扩容操作包括:
(1)调用csi plugin的ControllerExpandVolume方法进行存储扩容;
(2)更新pv对象的.spec.capacity.storage为扩容后的存储大小;
(3)更新pvc对象的.Status.Conditions,追加键值对"FileSystemResizePending":“true”,表明该pvc的controller端扩容已经完成,接下来将由kubelet完成node端的存储扩容操作。
源码分析
Run
主要逻辑:根据workers的数量,起数量相等的goroutine不断的跑ctrl.syncPVCs来处理pvc变更事件,筛选出需要扩容的pvc,触发扩容操作。
// pkg/controller/controller.go
// Run starts the controller.
func (ctrl *resizeController) Run(
workers int, ctx context.Context) {
defer ctrl.claimQueue.ShutDown()
klog.Infof("Starting external resizer %s", ctrl.name)
defer klog.Infof("Shutting down external resizer %s", ctrl.name)
stopCh := ctx.Done()
if !cache.WaitForCacheSync(stopCh, ctrl.pvSynced, ctrl.pvcSynced) {
klog.Errorf("Can