欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

kubernetes版本v1.5.0 diskSpaceManager源码分析

程序员文章站 2022-05-23 08:18:10
kubernetes版本v1.5.0 diskSpaceManager在结构体kubelet // Kubelet is the main kubelet implementation...

kubernetes版本v1.5.0

diskSpaceManager在结构体kubelet

// Kubelet is the main kubelet implementation.
type Kubelet struct {
    ...
    // Diskspace manager.
    diskSpaceManager diskSpaceManager

    // Cached MachineInfo returned by cadvisor.
    machineInfo *cadvisorapi.MachineInfo

    // Syncs pods statuses with apiserver; also used as a cache of statuses.
    statusManager status.Manager

    // VolumeManager runs a set of asynchronous loops that figure out which
    // volumes need to be attached/mounted/unmounted/detached based on the pods
    // scheduled on this node and makes it so.
    volumeManager volumemanager.VolumeManager

    // Cloud provider interface.
    cloud                   cloudprovider.Interface
    autoDetectCloudProvider bool

    // Reference to this node.
    nodeRef *api.ObjectReference

    // Container runtime.
    containerRuntime kubecontainer.Runtime

    // reasonCache caches the failure reason of the last creation of all containers, which is
    // used for generating ContainerStatus.
    reasonCache *ReasonCache

    ...
    experimentalHostUserNamespaceDefaulting bool
}

diskSpaceManager的声明以及初始化
声明

// Implementation is thread-safe.
type diskSpaceManager interface {
    // Checks the available disk space
    IsRootDiskSpaceAvailable() (bool, error)
    IsRuntimeDiskSpaceAvailable() (bool, error)
}

type DiskSpacePolicy struct {
    // free disk space threshold for filesystem holding docker images.
    DockerFreeDiskMB int
    // free disk space threshold for root filesystem. Host volumes are created on root fs.
    RootFreeDiskMB int
}

初始化
k8s.io/kubernetes/pkg/kubelet/kubelet.go 初始化在NewMainKubelet 函数

diskSpaceManager, err := newDiskSpaceManager(kubeDeps.CAdvisorInterface, diskSpacePolicy)
    if err != nil {
        return nil, fmt.Errorf("failed to initialize disk manager: %v", err)
    }

func newDiskSpaceManager(cadvisorInterface cadvisor.Interface, policy DiskSpacePolicy) (diskSpaceManager, error) {
    // validate policy
    err := validatePolicy(policy)
    if err != nil {
        return nil, err
    }

    dm := &realDiskSpaceManager{
        cadvisor:   cadvisorInterface,
        policy:     policy,
        cachedInfo: map[string]fsInfo{},
    }

    return dm, nil
}
LowDiskSpaceThresholdMB默认是256M
fs.Int32Var(&s.LowDiskSpaceThresholdMB, "low-diskspace-threshold-mb", s.LowDiskSpaceThresholdMB, "The absolute free disk space, in MB, to maintain. When disk space falls below this threshold, new pods would be rejected. Default: 256")

该接口的返回值是diskSpaceManager,而实际返回是realDiskSpaceManager结构体。
所以所有diskSpaceManager的接口实现需要根据realDiskSpaceManager进行查看。
realDiskSpaceManager结构如下:

type realDiskSpaceManager struct {
    cadvisor   cadvisor.Interface
    cachedInfo map[string]fsInfo // cache of filesystem info.
    lock       sync.Mutex        // protecting cachedInfo.
    policy     DiskSpacePolicy   // thresholds. Set at creation time.
}

查看下realDiskSpaceManager结构实现的diskSpaceManager接口:

func (dm *realDiskSpaceManager) IsRuntimeDiskSpaceAvailable() (bool, error) {
    return dm.isSpaceAvailable("runtime", dm.policy.DockerFreeDiskMB, dm.cadvisor.ImagesFsInfo)
}

func (dm *realDiskSpaceManager) IsRootDiskSpaceAvailable() (bool, error) {
    return dm.isSpaceAvailable("root", dm.policy.RootFreeDiskMB, dm.cadvisor.RootFsInfo)
}

上面两个方法最终都调用了dm.isSpaceAvailable(),该接口使用了3个参数:

文件系统类型

磁盘保留空间大小,用于判断是否有效

cAdvisor的接口,用于获取RootFS和ImagesFs使用的磁盘情况

而该接口返回的是一个Bool值,true or false。

func (dm *realDiskSpaceManager) isSpaceAvailable(fsType string, threshold int, f func() (cadvisorapi.FsInfo, error)) (bool, error) {
    fsInfo, err := dm.getFsInfo(fsType, f)
    if err != nil {
        return true, fmt.Errorf("failed to get fs info for %q: %v", fsType, err)
    }
    if fsInfo.Capacity == 0 {
        return true, fmt.Errorf("could not determine capacity for %q fs. Info: %+v", fsType, fsInfo)
    }
    if fsInfo.Available < 0 {
        return true, fmt.Errorf("wrong available space for %q: %+v", fsType, fsInfo)
    }

    if fsInfo.Available < int64(threshold)*mb {
        glog.Infof("Running out of space on disk for %q: available %d MB, threshold %d MB", fsType, fsInfo.Available/mb, threshold)
        return false, nil
    }
    return true, nil
}

继续看dm.getFsInfo()接口:

func (dm *realDiskSpaceManager) getFsInfo(fsType string, f func() (cadvisorapi.FsInfo, error)) (fsInfo, error) {
    dm.lock.Lock()
    defer dm.lock.Unlock()
    fsi := fsInfo{}
    if info, ok := dm.cachedInfo[fsType]; ok {
        timeLimit := time.Now().Add(-2 * time.Second)
        if info.Timestamp.After(timeLimit) {
            fsi = info
        }
    }
    if fsi.Timestamp.IsZero() {
        fs, err := f()
        if err != nil {
            return fsInfo{}, err
        }
        fsi.Timestamp = time.Now()
        fsi.Usage = int64(fs.Usage)
        fsi.Capacity = int64(fs.Capacity)
        fsi.Available = int64(fs.Available)
        dm.cachedInfo[fsType] = fsi
    }
    return fsi, nil
}

diskSpaceManager使用

// handleOutOfDisk detects if pods can't fit due to lack of disk space.
func (kl *Kubelet) isOutOfDisk() bool {
    // Check disk space once globally and reject or accept all new pods.
    withinBounds, err := kl.diskSpaceManager.IsRuntimeDiskSpaceAvailable()
    // Assume enough space in case of errors.
    if err != nil {
        glog.Errorf("Failed to check if disk space is available for the runtime: %v", err)
    } else if !withinBounds {
        return true
    }

    withinBounds, err = kl.diskSpaceManager.IsRootDiskSpaceAvailable()
    // Assume enough space in case of errors.
    if err != nil {
        glog.Errorf("Failed to check if disk space is available on the root partition: %v", err)
    } else if !withinBounds {
        return true
    }
    return false
}