mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-14 21:53:52 +00:00
Handle image digests in node status and image GC
Start including Docker image digests in the node status and consider image digests during image garbage collection.
This commit is contained in:
@@ -108,7 +108,7 @@ func TestPuller(t *testing.T) {
|
||||
fakeRecorder := &record.FakeRecorder{}
|
||||
puller := NewImagePuller(fakeRecorder, fakeRuntime, backOff)
|
||||
|
||||
fakeRuntime.ImageList = []Image{{"present_image", nil, 0}}
|
||||
fakeRuntime.ImageList = []Image{{"present_image", nil, nil, 1}}
|
||||
fakeRuntime.Err = c.pullerErr
|
||||
fakeRuntime.InspectErr = c.inspectErr
|
||||
|
||||
|
@@ -319,6 +319,8 @@ type Image struct {
|
||||
ID string
|
||||
// Other names by which this image is known.
|
||||
RepoTags []string
|
||||
// Digests by which this image is known.
|
||||
RepoDigests []string
|
||||
// The size of the image in bytes.
|
||||
Size int64
|
||||
}
|
||||
|
@@ -108,7 +108,7 @@ func TestSerializedPuller(t *testing.T) {
|
||||
fakeRecorder := &record.FakeRecorder{}
|
||||
puller := NewSerializedImagePuller(fakeRecorder, fakeRuntime, backOff)
|
||||
|
||||
fakeRuntime.ImageList = []Image{{"present_image", nil, 0}}
|
||||
fakeRuntime.ImageList = []Image{{"present_image", nil, nil, 0}}
|
||||
fakeRuntime.Err = c.pullerErr
|
||||
fakeRuntime.InspectErr = c.inspectErr
|
||||
|
||||
|
@@ -78,6 +78,7 @@ func toRuntimeImage(image *dockertypes.Image) (*kubecontainer.Image, error) {
|
||||
return &kubecontainer.Image{
|
||||
ID: image.ID,
|
||||
RepoTags: image.RepoTags,
|
||||
RepoDigests: image.RepoDigests,
|
||||
Size: image.VirtualSize,
|
||||
}, nil
|
||||
}
|
||||
|
@@ -72,11 +72,13 @@ func TestToRuntimeImage(t *testing.T) {
|
||||
original := &dockertypes.Image{
|
||||
ID: "aeeea",
|
||||
RepoTags: []string{"abc", "def"},
|
||||
RepoDigests: []string{"123", "456"},
|
||||
VirtualSize: 1234,
|
||||
}
|
||||
expected := &kubecontainer.Image{
|
||||
ID: "aeeea",
|
||||
RepoTags: []string{"abc", "def"},
|
||||
RepoDigests: []string{"123", "456"},
|
||||
Size: 1234,
|
||||
}
|
||||
|
||||
|
@@ -164,6 +164,7 @@ func (im *realImageManager) detectImages(detectTime time.Time) error {
|
||||
imagesInUse := sets.NewString()
|
||||
for _, pod := range pods {
|
||||
for _, container := range pod.Containers {
|
||||
glog.V(5).Infof("Pod %s/%s, container %s uses image %s", pod.Namespace, pod.Name, container.Name, container.Image)
|
||||
imagesInUse.Insert(container.Image)
|
||||
}
|
||||
}
|
||||
@@ -174,10 +175,12 @@ func (im *realImageManager) detectImages(detectTime time.Time) error {
|
||||
im.imageRecordsLock.Lock()
|
||||
defer im.imageRecordsLock.Unlock()
|
||||
for _, image := range images {
|
||||
glog.V(5).Infof("Adding image ID %s to currentImages", image.ID)
|
||||
currentImages.Insert(image.ID)
|
||||
|
||||
// New image, set it as detected now.
|
||||
if _, ok := im.imageRecords[image.ID]; !ok {
|
||||
glog.V(5).Infof("Image ID %s is new", image.ID)
|
||||
im.imageRecords[image.ID] = &imageRecord{
|
||||
firstDetected: detectTime,
|
||||
}
|
||||
@@ -185,15 +188,18 @@ func (im *realImageManager) detectImages(detectTime time.Time) error {
|
||||
|
||||
// Set last used time to now if the image is being used.
|
||||
if isImageUsed(image, imagesInUse) {
|
||||
glog.V(5).Infof("Setting Image ID %s lastUsed to %v", image.ID, now)
|
||||
im.imageRecords[image.ID].lastUsed = now
|
||||
}
|
||||
|
||||
glog.V(5).Infof("Image ID %s has size %d", image.ID, image.Size)
|
||||
im.imageRecords[image.ID].size = image.Size
|
||||
}
|
||||
|
||||
// Remove old images from our records.
|
||||
for image := range im.imageRecords {
|
||||
if !currentImages.Has(image) {
|
||||
glog.V(5).Infof("Image ID %s is no longer present; removing from imageRecords", image)
|
||||
delete(im.imageRecords, image)
|
||||
}
|
||||
}
|
||||
@@ -266,8 +272,10 @@ func (im *realImageManager) freeSpace(bytesToFree int64, freeTime time.Time) (in
|
||||
var lastErr error
|
||||
spaceFreed := int64(0)
|
||||
for _, image := range images {
|
||||
glog.V(5).Infof("Evaluating image ID %s for possible garbage collection", image.id)
|
||||
// Images that are currently in used were given a newer lastUsed.
|
||||
if image.lastUsed.Equal(freeTime) || image.lastUsed.After(freeTime) {
|
||||
glog.V(5).Infof("Image ID %s has lastUsed=%v which is >= freeTime=%v, not eligible for garbage collection", image.id, image.lastUsed, freeTime)
|
||||
break
|
||||
}
|
||||
|
||||
@@ -275,6 +283,7 @@ func (im *realImageManager) freeSpace(bytesToFree int64, freeTime time.Time) (in
|
||||
// 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 {
|
||||
glog.V(5).Infof("Image ID %s has age %v which is less than the policy's minAge of %v, not eligible for garbage collection", image.id, freeTime.Sub(image.firstDetected), im.policy.MinAge)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -315,11 +324,11 @@ func (ev byLastUsedAndDetected) Less(i, j int) bool {
|
||||
}
|
||||
|
||||
func isImageUsed(image container.Image, imagesInUse sets.String) bool {
|
||||
// Check the image ID and all the RepoTags.
|
||||
// Check the image ID and all the RepoTags and RepoDigests.
|
||||
if _, ok := imagesInUse[image.ID]; ok {
|
||||
return true
|
||||
}
|
||||
for _, tag := range image.RepoTags {
|
||||
for _, tag := range append(image.RepoTags, image.RepoDigests...) {
|
||||
if _, ok := imagesInUse[tag]; ok {
|
||||
return true
|
||||
}
|
||||
|
@@ -337,6 +337,34 @@ func TestFreeSpaceImagesAlsoDoesLookupByRepoTags(t *testing.T) {
|
||||
assert.Len(fakeRuntime.ImageList, 1)
|
||||
}
|
||||
|
||||
func TestFreeSpaceImagesAlsoDoesLookupByRepoDigests(t *testing.T) {
|
||||
manager, fakeRuntime, _ := newRealImageManager(ImageGCPolicy{})
|
||||
fakeRuntime.ImageList = []container.Image{
|
||||
makeImage(0, 1024),
|
||||
{
|
||||
ID: "5678",
|
||||
RepoDigests: []string{"potato", "salad"},
|
||||
Size: 2048,
|
||||
},
|
||||
}
|
||||
fakeRuntime.AllPodList = []*container.Pod{
|
||||
{
|
||||
Containers: []*container.Container{
|
||||
{
|
||||
ID: container.ContainerID{Type: "test", ID: "c5678"},
|
||||
Image: "salad",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
spaceFreed, err := manager.freeSpace(1024, time.Now())
|
||||
assert := assert.New(t)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(1024, spaceFreed)
|
||||
assert.Len(fakeRuntime.ImageList, 1)
|
||||
}
|
||||
|
||||
func TestGarbageCollectBelowLowThreshold(t *testing.T) {
|
||||
policy := ImageGCPolicy{
|
||||
HighThresholdPercent: 90,
|
||||
|
@@ -3009,7 +3009,7 @@ func (kl *Kubelet) setNodeStatusImages(node *api.Node) {
|
||||
} else {
|
||||
for _, image := range containerImages {
|
||||
imagesOnNode = append(imagesOnNode, api.ContainerImage{
|
||||
Names: image.RepoTags,
|
||||
Names: append(image.RepoTags, image.RepoDigests...),
|
||||
SizeBytes: image.Size,
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user