Skip to content

Commit cf97dae

Browse files
Merge pull request kubernetes#18189 from sjenning/pick-58229
Automatic merge from submit-queue (batch tested with PRs 18189, 18010). UPSTREAM: 58229: kubelet: imagegc: exempt sandbox image kubernetes#58229 Prevents the imageGC from removing the locally built origin-pod sandbox image @derekwaynecarr @bparees @stevekuznetsov @pweil- @jupierce Origin-commit: ffab5c9958893ab0faa606fd8949176f970d8fe4
2 parents 6fa604d + 0848f48 commit cf97dae

File tree

5 files changed

+34
-11
lines changed

5 files changed

+34
-11
lines changed

pkg/kubelet/images/image_gc_manager.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ type realImageGCManager struct {
101101

102102
// imageCache is the cache of latest image list.
103103
imageCache imageCache
104+
105+
// sandbox image exempted from GC
106+
sandboxImage string
104107
}
105108

106109
// imageCache caches latest result of ListImages.
@@ -137,7 +140,7 @@ type imageRecord struct {
137140
size int64
138141
}
139142

140-
func NewImageGCManager(runtime container.Runtime, statsProvider StatsProvider, recorder record.EventRecorder, nodeRef *v1.ObjectReference, policy ImageGCPolicy) (ImageGCManager, error) {
143+
func NewImageGCManager(runtime container.Runtime, statsProvider StatsProvider, recorder record.EventRecorder, nodeRef *v1.ObjectReference, policy ImageGCPolicy, sandboxImage string) (ImageGCManager, error) {
141144
// Validate policy.
142145
if policy.HighThresholdPercent < 0 || policy.HighThresholdPercent > 100 {
143146
return nil, fmt.Errorf("invalid HighThresholdPercent %d, must be in range [0-100]", policy.HighThresholdPercent)
@@ -156,6 +159,7 @@ func NewImageGCManager(runtime container.Runtime, statsProvider StatsProvider, r
156159
recorder: recorder,
157160
nodeRef: nodeRef,
158161
initialized: false,
162+
sandboxImage: sandboxImage,
159163
}
160164

161165
return im, nil
@@ -206,6 +210,13 @@ func (im *realImageGCManager) detectImages(detectTime time.Time) error {
206210

207211
// Make a set of images in use by containers.
208212
imagesInUse := sets.NewString()
213+
214+
// Always consider the container runtime pod sandbox image in use
215+
imageRef, err := im.runtime.GetImageRef(container.ImageSpec{Image: im.sandboxImage})
216+
if err == nil && imageRef != "" {
217+
imagesInUse.Insert(imageRef)
218+
}
219+
209220
for _, pod := range pods {
210221
for _, container := range pod.Containers {
211222
glog.V(5).Infof("Pod %s/%s, container %s uses image %s(%s)", pod.Namespace, pod.Name, container.Name, container.Image, container.ImageID)

pkg/kubelet/images/image_gc_manager_test.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
)
3434

3535
var zero time.Time
36+
var sandboxImage = "gcr.io/google_containers/pause-amd64:latest"
3637

3738
func newRealImageGCManager(policy ImageGCPolicy) (*realImageGCManager, *containertest.FakeRuntime, *statstest.StatsProvider) {
3839
fakeRuntime := &containertest.FakeRuntime{}
@@ -43,6 +44,7 @@ func newRealImageGCManager(policy ImageGCPolicy) (*realImageGCManager, *containe
4344
imageRecords: make(map[string]*imageRecord),
4445
statsProvider: mockStatsProvider,
4546
recorder: &record.FakeRecorder{},
47+
sandboxImage: sandboxImage,
4648
}, fakeRuntime, mockStatsProvider
4749
}
4850

@@ -176,6 +178,21 @@ func TestDetectImagesWithNewImage(t *testing.T) {
176178
assert.Equal(zero, noContainer.lastUsed)
177179
}
178180

181+
func TestDeleteUnusedImagesExemptSandboxImage(t *testing.T) {
182+
manager, fakeRuntime, _ := newRealImageGCManager(ImageGCPolicy{})
183+
fakeRuntime.ImageList = []container.Image{
184+
{
185+
ID: sandboxImage,
186+
Size: 1024,
187+
},
188+
}
189+
190+
spaceFreed, err := manager.DeleteUnusedImages()
191+
assert := assert.New(t)
192+
require.NoError(t, err)
193+
assert.EqualValues(0, spaceFreed)
194+
}
195+
179196
func TestDetectImagesContainerStopped(t *testing.T) {
180197
manager, fakeRuntime, _ := newRealImageGCManager(ImageGCPolicy{})
181198
fakeRuntime.ImageList = []container.Image{
@@ -517,7 +534,7 @@ func TestValidateImageGCPolicy(t *testing.T) {
517534
}
518535

519536
for _, tc := range testCases {
520-
if _, err := NewImageGCManager(nil, nil, nil, nil, tc.imageGCPolicy); err != nil {
537+
if _, err := NewImageGCManager(nil, nil, nil, nil, tc.imageGCPolicy, ""); err != nil {
521538
if err.Error() != tc.expectErr {
522539
t.Errorf("[%s:]Expected err:%v, but got:%v", tc.name, tc.expectErr, err.Error())
523540
}

pkg/kubelet/kubelet.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
767767
klet.containerDeletor = newPodContainerDeletor(klet.containerRuntime, integer.IntMax(containerGCPolicy.MaxPerPodContainer, minDeadContainerInPod))
768768

769769
// setup imageManager
770-
imageManager, err := images.NewImageGCManager(klet.containerRuntime, klet.StatsProvider, kubeDeps.Recorder, nodeRef, imageGCPolicy)
770+
imageManager, err := images.NewImageGCManager(klet.containerRuntime, klet.StatsProvider, kubeDeps.Recorder, nodeRef, imageGCPolicy, crOptions.PodSandboxImage)
771771
if err != nil {
772772
return nil, fmt.Errorf("failed to initialize image manager: %v", err)
773773
}

pkg/kubelet/kubelet_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ func newTestKubeletWithImageList(
256256
HighThresholdPercent: 90,
257257
LowThresholdPercent: 80,
258258
}
259-
imageGCManager, err := images.NewImageGCManager(fakeRuntime, kubelet.StatsProvider, fakeRecorder, fakeNodeRef, fakeImageGCPolicy)
259+
imageGCManager, err := images.NewImageGCManager(fakeRuntime, kubelet.StatsProvider, fakeRecorder, fakeNodeRef, fakeImageGCPolicy, "")
260260
assert.NoError(t, err)
261261
kubelet.imageManager = &fakeImageGCManager{
262262
fakeImageService: fakeRuntime,

pkg/kubelet/kuberuntime/kuberuntime_image.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func (m *kubeGenericRuntimeManager) PullImage(image kubecontainer.ImageSpec, pul
7878
return "", utilerrors.NewAggregate(pullErrs)
7979
}
8080

81-
// GetImageRef gets the reference (digest or ID) of the image which has already been in
81+
// GetImageRef gets the ID of the image which has already been in
8282
// the local storage. It returns ("", nil) if the image isn't in the local storage.
8383
func (m *kubeGenericRuntimeManager) GetImageRef(image kubecontainer.ImageSpec) (string, error) {
8484
status, err := m.imageService.ImageStatus(&runtimeapi.ImageSpec{Image: image.Image})
@@ -89,12 +89,7 @@ func (m *kubeGenericRuntimeManager) GetImageRef(image kubecontainer.ImageSpec) (
8989
if status == nil {
9090
return "", nil
9191
}
92-
93-
imageRef := status.Id
94-
if len(status.RepoDigests) > 0 {
95-
imageRef = status.RepoDigests[0]
96-
}
97-
return imageRef, nil
92+
return status.Id, nil
9893
}
9994

10095
// ListImages gets all images currently on the machine.

0 commit comments

Comments
 (0)