Update imageLocality plugin

to account for ImageVolume images when scoring
and prioritizing nodes with required pod images

Signed-off-by: bmordeha <bmordeha@redhat.com>
This commit is contained in:
bmordeha 2025-02-18 10:35:24 +02:00
parent 53b29512ec
commit 6f57f1e95b
2 changed files with 43 additions and 1 deletions

View file

@ -103,7 +103,8 @@ func calculatePriority(sumScores int64, numContainers int) int64 {
return fwk.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 {
@ -118,6 +119,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
}

View file

@ -93,6 +93,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{
{
@ -341,6 +359,21 @@ func TestImageLocalityPriority(t *testing.T) {
expectedList: []fwk.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: []fwk.NodeScore{{Name: "node1", Score: 12}, {Name: "node2", Score: 0}},
name: "pod with ImageVolume",
},
{
// Pod: gcr.io/30 InitContainers: gcr.io/300