From 7dbbef8bd40b12576785d65552f2aaba998c376a Mon Sep 17 00:00:00 2001 From: bmordeha Date: Tue, 18 Feb 2025 10:35:24 +0200 Subject: [PATCH] Update imageLocality plugin to account for ImageVolume images when scoring and prioritizing nodes with required pod images Signed-off-by: bmordeha --- .../plugins/imagelocality/image_locality.go | 11 ++++++- .../imagelocality/image_locality_test.go | 33 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/pkg/scheduler/framework/plugins/imagelocality/image_locality.go b/pkg/scheduler/framework/plugins/imagelocality/image_locality.go index 3aa678856d925..a33fb35ade938 100644 --- a/pkg/scheduler/framework/plugins/imagelocality/image_locality.go +++ b/pkg/scheduler/framework/plugins/imagelocality/image_locality.go @@ -87,7 +87,8 @@ func calculatePriority(sumScores int64, numContainers int) int64 { return framework.MaxNodeScore * (sumScores - minThreshold) / (maxThreshold - minThreshold) } -// sumImageScores returns the sum of image scores of all the containers that are already on the node. +// sumImageScores returns the total image score for all container images in the Pod spec, +// including regular containers, init containers, and image volumes, that already exist on the node. // Each image receives a raw score of its size, scaled by scaledImageScore. The raw scores are later used to calculate // the final score. func sumImageScores(nodeInfo fwk.NodeInfo, pod *v1.Pod, totalNumNodes int) int64 { @@ -102,6 +103,14 @@ func sumImageScores(nodeInfo fwk.NodeInfo, pod *v1.Pod, totalNumNodes int) int64 sum += scaledImageScore(state, totalNumNodes) } } + for _, volume := range pod.Spec.Volumes { + if volume.Image == nil { + continue + } + if state, ok := nodeInfo.GetImageStates()[normalizedImageName(volume.Image.Reference)]; ok { + sum += scaledImageScore(state, totalNumNodes) + } + } return sum } diff --git a/pkg/scheduler/framework/plugins/imagelocality/image_locality_test.go b/pkg/scheduler/framework/plugins/imagelocality/image_locality_test.go index 8813c20c8feaf..1c9d65f8fb7d3 100644 --- a/pkg/scheduler/framework/plugins/imagelocality/image_locality_test.go +++ b/pkg/scheduler/framework/plugins/imagelocality/image_locality_test.go @@ -92,6 +92,24 @@ func TestImageLocalityPriority(t *testing.T) { }, } + testImageVolume := v1.PodSpec{ + Containers: []v1.Container{ + { + Image: "gcr.io/30", + }, + }, + Volumes: []v1.Volume{ + { + Name: "imageVolume", + VolumeSource: v1.VolumeSource{ + Image: &v1.ImageVolumeSource{ + Reference: "gcr.io/300", + }, + }, + }, + }, + } + test30Init300 := v1.PodSpec{ Containers: []v1.Container{ { @@ -340,6 +358,21 @@ func TestImageLocalityPriority(t *testing.T) { expectedList: []framework.NodeScore{{Name: "node1", Score: 1}, {Name: "node2", Score: 0}}, name: "pod with multiple small images", }, + { + // Pod: gcr.io/300 gcr.io/30 + + // Node1 + // Image: gcr.io/300:latest 300MB + // Score: 100 * (300M * 1/2 - 23M) / (1000M - 23M) = 12 + + // Node2 + // Image: gcr.io/30:latest 30MB + // Score: 100 * (30M - 23M) / (1000M - 23M) = 0 + pod: &v1.Pod{Spec: testImageVolume}, + nodes: []*v1.Node{makeImageNode("node1", node300600900), makeImageNode("node2", node400030)}, + expectedList: []framework.NodeScore{{Name: "node1", Score: 12}, {Name: "node2", Score: 0}}, + name: "pod with ImageVolume", + }, { // Pod: gcr.io/30 InitContainers: gcr.io/300