diff --git a/pkg/coscheduling/coscheduling.go b/pkg/coscheduling/coscheduling.go index 1dcf8705a..fff7ff292 100644 --- a/pkg/coscheduling/coscheduling.go +++ b/pkg/coscheduling/coscheduling.go @@ -28,6 +28,7 @@ import ( "k8s.io/client-go/tools/cache" corev1helpers "k8s.io/component-helpers/scheduling/corev1" "k8s.io/klog/v2" + v1qos "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos" "k8s.io/kubernetes/pkg/scheduler/framework" "sigs.k8s.io/controller-runtime/pkg/client" @@ -124,14 +125,26 @@ func (cs *Coscheduling) Name() string { // Less is used to sort pods in the scheduling queue in the following order. // 1. Compare the priorities of Pods. -// 2. Compare the initialization timestamps of PodGroups or Pods. -// 3. Compare the keys of PodGroups/Pods: /. +// 2. Compare the Qos of Pods. +// 3. Compare the initialization timestamps of PodGroups or Pods. +// 4. Compare the keys of PodGroups/Pods: /. func (cs *Coscheduling) Less(podInfo1, podInfo2 *framework.QueuedPodInfo) bool { prio1 := corev1helpers.PodPriority(podInfo1.Pod) prio2 := corev1helpers.PodPriority(podInfo2.Pod) if prio1 != prio2 { return prio1 > prio2 } + + if v1qos.GetPodQOS(podInfo1.Pod) != v1qos.GetPodQOS(podInfo2.Pod) { + if v1qos.GetPodQOS(podInfo1.Pod) == v1.PodQOSBestEffort { + return false + } + if v1qos.GetPodQOS(podInfo1.Pod) == v1.PodQOSBurstable && v1qos.GetPodQOS(podInfo2.Pod) == v1.PodQOSGuaranteed { + return false + } + return true + } + creationTime1 := cs.pgMgr.GetCreationTimestamp(context.TODO(), podInfo1.Pod, *podInfo1.InitialAttemptTimestamp) creationTime2 := cs.pgMgr.GetCreationTimestamp(context.TODO(), podInfo2.Pod, *podInfo2.InitialAttemptTimestamp) if creationTime1.Equal(creationTime2) { diff --git a/pkg/coscheduling/coscheduling_test.go b/pkg/coscheduling/coscheduling_test.go index f0ade5f10..29ab685b9 100644 --- a/pkg/coscheduling/coscheduling_test.go +++ b/pkg/coscheduling/coscheduling_test.go @@ -187,6 +187,11 @@ func TestLess(t *testing.T) { lowPriority, highPriority := int32(10), int32(100) now := time.Now() + capacity := map[v1.ResourceName]string{ + v1.ResourceCPU: "25m", + v1.ResourceMemory: "100Mi", + } + tests := []struct { name string p1 *framework.QueuedPodInfo @@ -400,6 +405,56 @@ func TestLess(t *testing.T) { }, want: true, }, + { + name: "equal priority, p1.Qos greater than p2.Qos and p2 belong to pg2", + p1: &framework.QueuedPodInfo{ + PodInfo: tu.MustNewPodInfo(t, st.MakePod().Name("p1").Namespace("ns1").Priority(highPriority). + Containers( + []v1.Container{ + st.MakeContainer().Name("p1").ResourceRequests(capacity).ResourceLimits(capacity).Obj(), + }, + ).Obj()), + InitialAttemptTimestamp: ptrTime(now.Add(time.Second * 1)), + }, + p2: &framework.QueuedPodInfo{ + PodInfo: tu.MustNewPodInfo(t, st.MakePod().Name("p2").Namespace("ns2").Priority(highPriority). + Label(v1alpha1.PodGroupLabel, "pg2").Containers( + []v1.Container{ + st.MakeContainer().Name("p1").ResourceRequests(capacity).Obj(), + }, + ).Obj()), + InitialAttemptTimestamp: ptrTime(now.Add(time.Second * 1)), + }, + pgs: []*v1alpha1.PodGroup{ + tu.MakePodGroup().Name("pg2").Namespace("ns2").Time(now.Add(time.Second * 2)).Obj(), + }, + want: true, + }, + { + name: "equal priority, p1.Qos greater than p2.Qos and p1 belongs pg1 and p2 belong to pg2", + p1: &framework.QueuedPodInfo{ + PodInfo: tu.MustNewPodInfo(t, st.MakePod().Name("p1").Namespace("ns1").Priority(highPriority). + Label(v1alpha1.PodGroupLabel, "pg1").Containers( + []v1.Container{ + st.MakeContainer().Name("p1").ResourceRequests(capacity).ResourceLimits(capacity).Obj(), + }, + ).Obj()), + InitialAttemptTimestamp: ptrTime(now.Add(time.Second * 1)), + }, + p2: &framework.QueuedPodInfo{ + PodInfo: tu.MustNewPodInfo(t, st.MakePod().Name("p2").Namespace("ns2").Priority(highPriority). + Label(v1alpha1.PodGroupLabel, "pg2").Containers( + []v1.Container{ + st.MakeContainer().Name("p2").Obj(), + }, + ).Obj()), + InitialAttemptTimestamp: ptrTime(now.Add(time.Second * 1)), + }, + pgs: []*v1alpha1.PodGroup{ + tu.MakePodGroup().Name("pg1").Namespace("ns1").Time(now.Add(time.Second * 1)).Obj(), + tu.MakePodGroup().Name("pg2").Namespace("ns2").Time(now.Add(time.Second * 2)).Obj()}, + want: true, + }, } for _, tt := range tests {