diff --git a/pkg/scheduler/framework/plugins/imagelocality/image_locality.go b/pkg/scheduler/framework/plugins/imagelocality/image_locality.go index bdf3c6c62134e..3b0a772296034 100644 --- a/pkg/scheduler/framework/plugins/imagelocality/image_locality.go +++ b/pkg/scheduler/framework/plugins/imagelocality/image_locality.go @@ -63,7 +63,8 @@ func (pl *ImageLocality) Score(ctx context.Context, state *framework.CycleState, } totalNumNodes := len(nodeInfos) - score := calculatePriority(sumImageScores(nodeInfo, pod.Spec.Containers, totalNumNodes), len(pod.Spec.Containers)) + imageScores := sumImageScores(nodeInfo, pod, totalNumNodes) + score := calculatePriority(imageScores, len(pod.Spec.InitContainers)+len(pod.Spec.Containers)) return score, nil } @@ -88,15 +89,20 @@ func calculatePriority(sumScores int64, numContainers int) int64 { sumScores = maxThreshold } - return int64(framework.MaxNodeScore) * (sumScores - minThreshold) / (maxThreshold - minThreshold) + return framework.MaxNodeScore * (sumScores - minThreshold) / (maxThreshold - minThreshold) } // sumImageScores returns the sum of image scores of all the containers that are already 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. Note that the init containers are not considered for it's rare for users to deploy huge init containers. -func sumImageScores(nodeInfo *framework.NodeInfo, containers []v1.Container, totalNumNodes int) int64 { +// the final score. +func sumImageScores(nodeInfo *framework.NodeInfo, pod *v1.Pod, totalNumNodes int) int64 { var sum int64 - for _, container := range containers { + for _, container := range pod.Spec.InitContainers { + if state, ok := nodeInfo.ImageStates[normalizedImageName(container.Image)]; ok { + sum += scaledImageScore(state, totalNumNodes) + } + } + for _, container := range pod.Spec.Containers { if state, ok := nodeInfo.ImageStates[normalizedImageName(container.Image)]; ok { sum += scaledImageScore(state, totalNumNodes) } diff --git a/pkg/scheduler/framework/plugins/imagelocality/image_locality_test.go b/pkg/scheduler/framework/plugins/imagelocality/image_locality_test.go index 8e16df35f0ead..44a5de2a9b361 100644 --- a/pkg/scheduler/framework/plugins/imagelocality/image_locality_test.go +++ b/pkg/scheduler/framework/plugins/imagelocality/image_locality_test.go @@ -91,6 +91,17 @@ func TestImageLocalityPriority(t *testing.T) { }, } + test30Init300 := v1.PodSpec{ + Containers: []v1.Container{ + { + Image: "gcr.io/30", + }, + }, + InitContainers: []v1.Container{ + {Image: "gcr.io/300"}, + }, + } + node403002000 := v1.NodeStatus{ Images: []v1.ContainerImage{ { @@ -317,7 +328,7 @@ func TestImageLocalityPriority(t *testing.T) { // Pod: gcr.io/30 gcr.io/40 // Node1 - // Image: gcr.io/20:latest 20MB, gcr.io/30:latest 30MB gcr.io/40:latest 40MB + // Image: gcr.io/20:latest 20MB, gcr.io/30:latest 30MB, gcr.io/40:latest 40MB // Score: 100 * (30M + 40M * 1/2 - 23M) / (1000M * 2 - 23M) = 1 // Node2 @@ -328,6 +339,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/30 InitContainers: gcr.io/300 + + // Node1 + // Image: gcr.io/40:latest 40MB, gcr.io/300:latest 300MB, gcr.io/2000:latest 2000MB + // Score: 100 * (300M * 1/2 - 23M) / (1000M * 2 - 23M) = 6 + + // Node2 + // Image: gcr.io/20:latest 20MB, gcr.io/30:latest 30MB, gcr.io/40:latest 40MB + // Score: 100 * (30M * 1/2 - 23M) / (1000M * 2 - 23M) = 0 + pod: &v1.Pod{Spec: test30Init300}, + nodes: []*v1.Node{makeImageNode("node1", node403002000), makeImageNode("node2", node203040)}, + expectedList: []framework.NodeScore{{Name: "node1", Score: 6}, {Name: "node2", Score: 0}}, + name: "include InitContainers: two images spread on two nodes, prefer the larger image one", + }, } for _, test := range tests {