深入分析kubelet(4)—— ImageGC

深入分析kubelet(4)—— ImageGC

接着上一篇,继续介绍ImageGC过程

code

new

k8s.io\kubernetes\pkg\kubelet\kubelet.go

imageGCPolicy := images.ImageGCPolicy{
    MinAge:               kubeCfg.ImageMinimumGCAge.Duration,
    HighThresholdPercent: int(kubeCfg.ImageGCHighThresholdPercent),
    LowThresholdPercent:  int(kubeCfg.ImageGCLowThresholdPercent),
}
    
images.NewImageGCManager(klet.containerRuntime, klet.StatsProvider, kubeDeps.Recorder, nodeRef, imageGCPolicy, crOptions.PodSandboxImage)

参数说明:
k8s.io\kubernetes\pkg\kubelet\apis\kubeletconfig\types.go

  • imageGCHighThresholdPercent is the percent of disk usage after which image garbage collection is always run. The percent is calculated as this field value out of 100.
  • imageGCLowThresholdPercent is the percent of disk usage before which image garbage collection is never run. Lowest disk usage to garbage collect to. The percent is calculated as this field value out of 100.

start

// ImageGCPeriod is the period for performing image garbage collection.
    ImageGCPeriod = 5 * time.Minute

// StartGarbageCollection starts garbage collection threads.
func (kl *Kubelet) StartGarbageCollection() {
    go wait.Until(func() {
        kl.imageManager.GarbageCollect()
    }, ImageGCPeriod, wait.NeverStop)
}

每5分钟执行一次image gc

gc

k8s.io\kubernetes\pkg\kubelet\images\image_gc_manager.go

func (im *realImageGCManager) GarbageCollect() error {
    // Get disk usage on disk holding images.
    fsStats, err := im.statsProvider.ImageFsStats()
    
    var capacity, available int64
    if fsStats.CapacityBytes != nil {
        capacity = int64(*fsStats.CapacityBytes)
    }
    if fsStats.AvailableBytes != nil {
        available = int64(*fsStats.AvailableBytes)
    }
    
    // If over the max threshold, free enough to place us at the lower threshold.
    usagePercent := 100 - int(available*100/capacity)
    if usagePercent >= im.policy.HighThresholdPercent {
        amountToFree := capacity*int64(100-im.policy.LowThresholdPercent)/100 - available
        im.freeSpace(amountToFree, time.Now())
    }
}

获取镜像盘信息,根据策略算出需要释放多少磁盘空间。

// Tries to free bytesToFree worth of images on the disk.
//
// Returns the number of bytes free and an error if any occurred. The number of
// bytes freed is always returned.
// Note that error may be nil and the number of bytes free may be less
// than bytesToFree.
func (im *realImageGCManager) freeSpace(bytesToFree int64, freeTime time.Time) (int64, error) {
    imagesInUse, err := im.detectImages(freeTime)

    // Get all images in eviction order.
    images := make([]evictionInfo, 0, len(im.imageRecords))
    for image, record := range im.imageRecords {
        if isImageUsed(image, imagesInUse) {
            continue
        }
        images = append(images, evictionInfo{
            id:          image,
            imageRecord: *record,
        })
    }
    sort.Sort(byLastUsedAndDetected(images))

    // Delete unused images until we've freed up enough space.
    var deletionErrors []error
    spaceFreed := int64(0)
    for _, image := range images {
        // Images that are currently in used were given a newer lastUsed.
        if image.lastUsed.Equal(freeTime) || image.lastUsed.After(freeTime) {
            continue
        }

        // Avoid garbage collect the image if the image is not old enough.
        // In such a case, the image may have just been pulled down, and will be used by a container right away.
        if freeTime.Sub(image.firstDetected) < im.policy.MinAge {
            continue
        }

        // Remove image. Continue despite errors.
        im.runtime.RemoveImage(container.ImageSpec{Image: image.id})
        
        spaceFreed += image.size

        if spaceFreed >= bytesToFree {
            break
        }
}

找到没有正在使用的镜像,按照上次使用时间排序,删除最久没有使用过的镜像。上次使用时间差必须大于MinAge,最后通过CRI删除镜像。

如果释放资源不满足要求,会返回错误。

你可能感兴趣的:(深入分析kubelet(4)—— ImageGC)