kubernetes添加第三方存储(一)

kubernetes发展到1.7以后,就朝着平台去开发了,上一个讨论的点是kubernetes把metrics单独出去,成为一个kubernetes的监控标准,这个我们以后再慢慢说,先看存储这个孵化的项目。github.com/kubernetes-incubator/external-storage第三方存储对接。
它和上一篇介绍的custom-metrics-apiserver项目一样都是孵化的项目,我们先看看他是如何工作的。
核心在lib/controller/controller.go

//启动了pvc的listwatch
controller.claimSource = &cache.ListWatch{
        ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
            return client.Core().PersistentVolumeClaims(v1.NamespaceAll).List(options)
        },
        WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
            return client.Core().PersistentVolumeClaims(v1.NamespaceAll).Watch(options)
        },
    }
    controller.claims, controller.claimController = cache.NewInformer(
        controller.claimSource,
        &v1.PersistentVolumeClaim{},
        controller.resyncPeriod,
        cache.ResourceEventHandlerFuncs{
            AddFunc:    controller.addClaim,
            UpdateFunc: controller.updateClaim,
            DeleteFunc: nil,
        },
    )
//启动了pv的listwatch
    controller.volumeSource = &cache.ListWatch{
        ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
            return client.Core().PersistentVolumes().List(options)
        },
        WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
            return client.Core().PersistentVolumes().Watch(options)
        },
    }
    controller.volumes, controller.volumeController = cache.NewInformer(
        controller.volumeSource,
        &v1.PersistentVolume{},
        controller.resyncPeriod,
        cache.ResourceEventHandlerFuncs{
            AddFunc:    nil,
            UpdateFunc: controller.updateVolume,
            DeleteFunc: nil,
        },
    )
//启动了storageclass的listwatch
controller.classSource = &cache.ListWatch{
            ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
                return client.StorageV1().StorageClasses().List(options)
            },
            WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
                return client.StorageV1().StorageClasses().Watch(options)
            },
        }
        controller.classReflector = cache.NewReflector(
            controller.classSource,
            &storage.StorageClass{},
            controller.classes,
            controller.resyncPeriod,
        )

上面启动服务主要是watch k8s对存储管理的各种事件,只要是pvc、pv和storageclass的事件的监听。

先看如果pvc创建了改如何处理

func (ctrl *ProvisionController) addClaim(obj interface{}) {
    claim, ok := obj.(*v1.PersistentVolumeClaim)
    if !ok {
        glog.Errorf("Expected PersistentVolumeClaim but addClaim received %+v", obj)
        return
    }

    if ctrl.shouldProvision(claim) {
        ctrl.leaderElectorsMutex.Lock()
        le, ok := ctrl.leaderElectors[claim.UID]
        ctrl.leaderElectorsMutex.Unlock()
        if ok && le.IsLeader() {
            opName := fmt.Sprintf("provision-%s[%s]", claimToClaimKey(claim), string(claim.UID))
            ctrl.scheduleOperation(opName, func() error {
                err := ctrl.provisionClaimOperation(claim)
                ctrl.updateProvisionStats(claim, err)
                return err
            })
        } else {
            opName := fmt.Sprintf("lock-provision-%s[%s]", claimToClaimKey(claim), string(claim.UID))
            ctrl.scheduleOperation(opName, func() error {
                ctrl.lockProvisionClaimOperation(claim)
                return nil
            })
        }
    }
}

关于选主的方法在此先跳过,主要看看,如何执行的

err := ctrl.provisionClaimOperation(claim)
ctrl.updateProvisionStats(claim, err)

先看provisionClaimOperation这个方法,这个方法比较长,挑选核心介绍

先获取到pv的名称通过pvc+pvc的uid拼接而成
pvName := ctrl.getProvisionedVolumeNameForClaim(claim)
获取pv是否存在,存在则跳过
volume, err := ctrl.client.Core().PersistentVolumes().Get(pvName, metav1.GetOptions{})
如果不存在则执行Provision,创建pv对象
volume, err = ctrl.provisioner.Provision(options)
调用k8s创建pv
ctrl.client.Core().PersistentVolumes().Create(volume)

核心是上面的Provision,它是通过pvc创建pv的入口。
它是一个接口

type Provisioner interface {
    //创建pv对象
    Provision(VolumeOptions) (*v1.PersistentVolume, error)
    // 删除pv
    Delete(*v1.PersistentVolume) error
}

这个就是让第三方去实现的接口,去创建自己的pv对象。这样存储就创建好了。
如果是pv被删除呢?当然按照一开始listwatch方式也是监听到这个消息,会执行

func (ctrl *ProvisionController) updateVolume(oldObj, newObj interface{}) {
    volume, ok := newObj.(*v1.PersistentVolume)
    if !ok {
        glog.Errorf("Expected PersistentVolume but handler received %#v", newObj)
        return
    }

    if ctrl.shouldDelete(volume) {
        opName := fmt.Sprintf("delete-%s[%s]", volume.Name, string(volume.UID))
        ctrl.scheduleOperation(opName, func() error {
            err := ctrl.deleteVolumeOperation(volume)
            ctrl.updateDeleteStats(volume, err)
            return err
        })
    }
}

deleteVolumeOperation这个方法原理和之前的一样会调用删除接口

err = ctrl.provisioner.Delete(volume)

释放存储。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柳清风09

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值