Change:
Currently the scheduler may add an assumed pod back to the queue if the update didn't include specific fields (see ). There doesn't seem to be a reason why we can't simply ignore all updates of assumed pods. Assumed pods are waiting to be bound, if binding succeeded then the pod is scheduled. If binding fails, the pod's latest version will be put back into the unschedulable queue anyways. Performance: we save on unnecessary scheduling attempts. This is a followup on the discussion we had in /sig scheduling /triage accepted /help
This request has been marked as needing help from a contributor. Please ensure the request meets the requirements listed . If this request no longer meets these requirements, the label can be removed by commenting with the command. <detailsIn response to : #### What would you like to be : /triage accepted /help Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
What we basically need to do is: 1) remove function 2) in the places where we call , we should simply call
/assign

Discussion:
if oldPod.ResourceVersion == newPod.ResourceVersion { return } <del> if sched.skipPodUpdate(newPod) { </del> <ins> isAssumed, err := sched.SchedulerCache.IsAssumedPod(newPod) if err != nil { utilruntime.HandleError(fmt.Errorf("failed to check whether pod %s/%s is assumed: %v", newPod.Namespace, newPod.Name, err)) } if isAssumed { </ins> return } if err := sched.SchedulingQueue.Update(oldPod, newPod); err != nil { utilruntime.HandleError(fmt.Errorf("unable to update %T: %v", newObj, err)) }

return profiles.HandlesSchedulerName(pod.Spec.SchedulerName) } <del> // skipPodUpdate checks whether the specified pod update should be ignored. // This function will return true if //   - The pod has already been assumed, AND //   - The pod has only its ResourceVersion, Spec.NodeName, Annotations, //     ManagedFields, Finalizers and/or Conditions updated. func (sched *Scheduler) skipPodUpdate(pod *v1.Pod) bool { // Non-assumed pods should never be skipped. isAssumed, err := sched.SchedulerCache.IsAssumedPod(pod) if err != nil { utilruntime.HandleError(fmt.Errorf("failed to check whether pod %s/%s is assumed: %v", pod.Namespace, pod.Name, err)) return false } if !isAssumed { return false } // Gets the assumed pod from the cache. assumedPod, err := sched.SchedulerCache.GetPod(pod) if err != nil { utilruntime.HandleError(fmt.Errorf("failed to get assumed pod %s/%s from cache: %v", pod.Namespace, pod.Name, err)) return false } // Compares the assumed pod in the cache with the pod update. If they are // equal (with certain fields excluded), this pod update will be skipped. f := func(pod *v1.Pod) *v1.Pod { p := pod.DeepCopy() // ResourceVersion must be excluded because each object update will // have a new resource version. p.ResourceVersion = "" // Spec.NodeName must be excluded because the pod assumed in the cache // is expected to have a node assigned while the pod update may nor may // not have this field set. p.Spec.NodeName = "" // Annotations must be excluded for the reasons described in // https://github.com/kubernetes/kubernetes/issues/52914. p.Annotations = nil // Same as above, when annotations are modified with ServerSideApply, // ManagedFields may also change and must be excluded p.ManagedFields = nil // The following might be changed by external controllers, but they don't // affect scheduling decisions. p.Finalizers = nil p.Status.Conditions = nil return p } assumedPodCopy, podCopy := f(assumedPod), f(pod) if !reflect.DeepEqual(assumedPodCopy, podCopy) { return false } klog.V(3).InfoS("Pod update ignored because changes won't affect scheduling", "pod", klog.KObj(pod)) return true } </del> // addAllEventHandlers is a helper function used in tests and in Scheduler // to add event handlers for various informers. func addAllEventHandlers(

"k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/scheduler/internal/cache" <del> fakecache "k8s.io/kubernetes/pkg/scheduler/internal/cache/fake" </del> "k8s.io/kubernetes/pkg/scheduler/internal/queue" ) <del> func TestSkipPodUpdate(t *testing.T) { for _, test := range []struct { pod              *v1.Pod isAssumedPodFunc func(*v1.Pod) bool getPodFunc       func(*v1.Pod) *v1.Pod expected         bool name             string }{ { name: "Non-assumed pod", pod: &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "pod-0", }, }, isAssumedPodFunc: func(*v1.Pod) bool { return false }, getPodFunc: func(*v1.Pod) *v1.Pod { return &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "pod-0", }, } }, expected: false, }, { name: "with changes on ResourceVersion, Spec.NodeName and/or Annotations", pod: &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name:            "pod-0", Annotations:     map[string]string{"a": "b"}, ResourceVersion: "0", }, Spec: v1.PodSpec{ NodeName: "node-0", }, }, isAssumedPodFunc: func(*v1.Pod) bool { return true }, getPodFunc: func(*v1.Pod) *v1.Pod { return &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name:            "pod-0", Annotations:     map[string]string{"c": "d"}, ResourceVersion: "1", }, Spec: v1.PodSpec{ NodeName: "node-1", }, } }, expected: true, }, { name: "with ServerSideApply changes on Annotations", pod: &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name:            "pod-0", Annotations:     map[string]string{"a": "b"}, ResourceVersion: "0", ManagedFields: []metav1.ManagedFieldsEntry{ { Manager:    "some-actor", Operation:  metav1.ManagedFieldsOperationApply, APIVersion: "v1", FieldsType: "FieldsV1", FieldsV1: &metav1.FieldsV1{ Raw: []byte(` "f:metadata": { "f:annotations": { "f:a: {} } } `), }, }, }, }, Spec: v1.PodSpec{ NodeName: "node-0", }, }, isAssumedPodFunc: func(*v1.Pod) bool { return true }, getPodFunc: func(*v1.Pod) *v1.Pod { return &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name:            "pod-0", Annotations:     map[string]string{"a": "c", "d": "e"}, ResourceVersion: "1", ManagedFields: []metav1.ManagedFieldsEntry{ { Manager:    "some-actor", Operation:  metav1.ManagedFieldsOperationApply, APIVersion: "v1", FieldsType: "FieldsV1", FieldsV1: &metav1.FieldsV1{ Raw: []byte(` "f:metadata": { "f:annotations": { "f:a: {} "f:d: {} } } `), }, }, { Manager:    "some-actor", Operation:  metav1.ManagedFieldsOperationApply, APIVersion: "v1", FieldsType: "FieldsV1", FieldsV1: &metav1.FieldsV1{ Raw: []byte(` "f:metadata": { "f:annotations": { "f:a: {} } } `), }, }, }, }, Spec: v1.PodSpec{ NodeName: "node-1", }, } }, expected: true, }, { name: "with changes on Labels", pod: &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name:   "pod-0", Labels: map[string]string{"a": "b"}, }, }, isAssumedPodFunc: func(*v1.Pod) bool { return true }, getPodFunc: func(*v1.Pod) *v1.Pod { return &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name:   "pod-0", Labels: map[string]string{"c": "d"}, }, } }, expected: false, }, { name: "with changes on Finalizers", pod: &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name:       "pod-0", Finalizers: []string{"a", "b"}, }, }, isAssumedPodFunc: func(*v1.Pod) bool { return true }, getPodFunc: func(*v1.Pod) *v1.Pod { return &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name:       "pod-0", Finalizers: []string{"c", "d"}, }, } }, expected: true, }, { name: "with changes on Conditions", pod: &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "pod-0", }, Status: v1.PodStatus{ Conditions: []v1.PodCondition{ {Type: "foo"}, }, }, }, isAssumedPodFunc: func(*v1.Pod) bool { return true }, getPodFunc: func(*v1.Pod) *v1.Pod { return &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "pod-0", }, } }, expected: true, }, } { t.Run(test.name, func(t *testing.T) { c := &Scheduler{ SchedulerCache: &fakecache.Cache{ IsAssumedPodFunc: test.isAssumedPodFunc, GetPodFunc:       test.getPodFunc, }, } got := c.skipPodUpdate(test.pod) if got != test.expected { t.Errorf("skipPodUpdate() = %t, expected = %t", got, test.expected) } }) } } </del> func TestNodeAllocatableChanged(t *testing.T) { newQuantity := func(value int64) resource.Quantity { return *resource.NewQuantity(value, resource.BinarySI)

p.ResourceVersion = "" p.Generation = 0 p.Status = v1.PodStatus{} <ins> p.ManagedFields = nil p.Finalizers = nil </ins> return p } return !reflect.DeepEqual(strip(oldPod), strip(newPod))

v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" <ins> utilruntime "k8s.io/apimachinery/pkg/util/runtime" </ins> "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/informers" coreinformers "k8s.io/client-go/informers/core/v1"

return true } <del> // Case 2: pod has been assumed and pod updates could be skipped. </del> <ins> // Case 2: pod has been assumed could be skipped. </ins> // An assumed pod can be added again to the scheduling queue if it got an update event // during its previous scheduling cycle but before getting assumed. <del> if sched.skipPodUpdate(pod) { return true </del> <ins> isAssumed, err := sched.SchedulerCache.IsAssumedPod(pod) if err != nil { utilruntime.HandleError(fmt.Errorf("failed to check whether pod %s/%s is assumed: %v", pod.Namespace, pod.Name, err)) return false </ins> } <del> return false </del> <ins> return isAssumed </ins> } func defaultAlgorithmSourceProviderName() *string {