Change:
when kubelet restart,all images which notused cleaned. but there is a flag in kubelet,,explainMinimum age for an unused image before it is garbage collected. Examples: '300ms', '10s' or '2h45m'. i set to ,it's means if a image not used,it will live 20m and then clean by kubeletif has disk pressure.if kubelet not restart, it work,but if restart ther is a bug, not work,image will be cleaneven if it's no enough time. work, image even if not used,it will live 20m and then clean by kubelet. 1make node trigger disk pressure. 2pull some image which not used by pod 3restart kubelet 4image cleaned by kubelet after around 10s i see the source code, and maybe there is a bug. in func,well detect image and update firstdetect time for every image. and in func,well check images livetime by firstDetected. if kubelet running normal,it work,because there is a func. in this line,,in first time,ts is zero. so image's firstDetected time is zero,and in freeSpace this check is always false,so image will be cleaned. maybe we can change to ,can fix this bug. <details</details<detailsNone </details<details</details<details</details<details</details<details</details
/sig node
/assign
/triage accepted /priority backlog initial assessment of priority, subject to change

Discussion:
defer f.Unlock() f.CalledFunctions = append(f.CalledFunctions, "ListImages") <del> return f.ImageList, f.Err </del> <ins> return snapshot(f.ImageList), f.Err } func snapshot(imageList []kubecontainer.Image) []kubecontainer.Image { result := make([]kubecontainer.Image, len(imageList)) copy(result, imageList) return result </ins> } func (f *FakeRuntime) RemoveImage(_ context.Context, image kubecontainer.ImageSpec) error {

// Reference to this node. nodeRef *v1.ObjectReference <del> // Track initialization initialized bool </del> // imageCache is the cache of latest image list. imageCache imageCache

statsProvider: statsProvider, recorder:      recorder, nodeRef:       nodeRef, <del> initialized:   false, </del> tracer:        tracer, }

func (im *realImageGCManager) Start() { ctx := context.Background() go wait.Until(func() { <del> // Initial detection make detected time "unknown" in the past. var ts time.Time if im.initialized { ts = time.Now() } _, err := im.detectImages(ctx, ts) </del> <ins> _, err := im.detectImages(ctx, time.Now()) </ins> if err != nil { klog.InfoS("Failed to monitor images", "err", err) <del> } else { im.initialized = true </del> } }, 5*time.Minute, wait.NeverStop)

assert.Len(fakeRuntime.ImageList, 1) } <ins> func TestDeleteUnusedImagesLimitByImageLiveTime(t *testing.T) { ctx := context.Background() mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() mockStatsProvider := statstest.NewMockProvider(mockCtrl) manager, fakeRuntime := newRealImageGCManager(ImageGCPolicy{ MinAge: time.Second * 3, // set minAge to 3 seconds, }, mockStatsProvider) fakeRuntime.ImageList = []container.Image{ makeImage(0, 1024), makeImage(1, 2048), makeImage(2, 2048), } fakeRuntime.AllPodList = []*containertest.FakePod{ {Pod: &container.Pod{ Containers: []*container.Container{ makeContainer(2), }, }}, } // start to detect images manager.Start() // try to delete images, but images are not old enough,so no image will be deleted err := manager.DeleteUnusedImages(ctx) assert := assert.New(t) require.NoError(t, err) assert.Len(fakeRuntime.ImageList, 3) // sleep 3 seconds, then images will be old enough to be deleted time.Sleep(time.Second * 3) err = manager.DeleteUnusedImages(ctx) require.NoError(t, err) assert.Len(fakeRuntime.ImageList, 1) } </ins> func TestFreeSpaceRemoveByLeastRecentlyUsed(t *testing.T) { ctx := context.Background() mockCtrl := gomock.NewController(t)