Skip to content

Commit 7766e65

Browse files
authored
Merge pull request kubernetes#91955 from Huang-Wei/preemption-e2e-flake
Fix an e2e flake on updating node status
2 parents 983395f + 43da0ff commit 7766e65

File tree

2 files changed

+39
-21
lines changed

2 files changed

+39
-21
lines changed

test/e2e/scheduling/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ go_library(
3131
"//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library",
3232
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
3333
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
34+
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
3435
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
3536
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
37+
"//staging/src/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library",
3638
"//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
3739
"//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
3840
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",

test/e2e/scheduling/preemption.go

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package scheduling
1818

1919
import (
2020
"context"
21+
"encoding/json"
2122
"fmt"
2223
"strings"
2324
"sync/atomic"
@@ -30,7 +31,9 @@ import (
3031
"k8s.io/apimachinery/pkg/api/resource"
3132
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3233
"k8s.io/apimachinery/pkg/runtime"
34+
"k8s.io/apimachinery/pkg/types"
3335
"k8s.io/apimachinery/pkg/util/sets"
36+
"k8s.io/apimachinery/pkg/util/strategicpatch"
3437
"k8s.io/apimachinery/pkg/util/wait"
3538
"k8s.io/apimachinery/pkg/watch"
3639
clientset "k8s.io/client-go/kubernetes"
@@ -40,7 +43,6 @@ import (
4043
e2enode "k8s.io/kubernetes/test/e2e/framework/node"
4144
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
4245
e2ereplicaset "k8s.io/kubernetes/test/e2e/framework/replicaset"
43-
e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
4446

4547
"github.com/onsi/ginkgo"
4648
"github.com/onsi/gomega"
@@ -77,8 +79,10 @@ var _ = SIGDescribe("SchedulerPreemption [Serial]", func() {
7779
cs.SchedulingV1().PriorityClasses().Delete(context.TODO(), pair.name, *metav1.NewDeleteOptions(0))
7880
}
7981
for _, node := range nodeList.Items {
80-
delete(node.Status.Capacity, testExtendedResource)
81-
cs.CoreV1().Nodes().UpdateStatus(context.TODO(), &node, metav1.UpdateOptions{})
82+
nodeCopy := node.DeepCopy()
83+
delete(nodeCopy.Status.Capacity, testExtendedResource)
84+
err := patchNode(cs, &node, nodeCopy)
85+
framework.ExpectNoError(err)
8286
}
8387
})
8488

@@ -119,8 +123,9 @@ var _ = SIGDescribe("SchedulerPreemption [Serial]", func() {
119123
// Now create victim pods on each of the node with lower priority
120124
for i, node := range nodeList.Items {
121125
// Update each node to advertise 3 available extended resources
122-
node.Status.Capacity[testExtendedResource] = resource.MustParse("3")
123-
node, err := cs.CoreV1().Nodes().UpdateStatus(context.TODO(), &node, metav1.UpdateOptions{})
126+
nodeCopy := node.DeepCopy()
127+
nodeCopy.Status.Capacity[testExtendedResource] = resource.MustParse("3")
128+
err := patchNode(cs, &node, nodeCopy)
124129
framework.ExpectNoError(err)
125130

126131
// Request 2 of the available resources for the victim pods
@@ -204,8 +209,9 @@ var _ = SIGDescribe("SchedulerPreemption [Serial]", func() {
204209
pods := make([]*v1.Pod, 0, len(nodeList.Items))
205210
for i, node := range nodeList.Items {
206211
// Update each node to advertise 3 available extended resources
207-
node.Status.Capacity[testExtendedResource] = resource.MustParse("3")
208-
node, err := cs.CoreV1().Nodes().UpdateStatus(context.TODO(), &node, metav1.UpdateOptions{})
212+
nodeCopy := node.DeepCopy()
213+
nodeCopy.Status.Capacity[testExtendedResource] = resource.MustParse("3")
214+
err := patchNode(cs, &node, nodeCopy)
209215
framework.ExpectNoError(err)
210216

211217
// Request 2 of the available resources for the victim pods
@@ -241,7 +247,7 @@ var _ = SIGDescribe("SchedulerPreemption [Serial]", func() {
241247
framework.Logf("Created pod: %v", pods[i].Name)
242248
}
243249
if len(pods) < 2 {
244-
e2eskipper.Skipf("We need at least two pods to be created but" +
250+
framework.Failf("We need at least two pods to be created but" +
245251
"all nodes are already heavily utilized, so preemption tests cannot be run")
246252
}
247253
ginkgo.By("Wait for pods to be scheduled.")
@@ -305,12 +311,10 @@ var _ = SIGDescribe("SchedulerPreemption [Serial]", func() {
305311
node, err := cs.CoreV1().Nodes().Get(context.TODO(), nodeName, metav1.GetOptions{})
306312
framework.ExpectNoError(err)
307313
// update Node API object with a fake resource
308-
nodeCopy := node.DeepCopy()
309-
// force it to update
310-
nodeCopy.ResourceVersion = "0"
311314
ginkgo.By(fmt.Sprintf("Apply 10 fake resource to node %v.", node.Name))
315+
nodeCopy := node.DeepCopy()
312316
nodeCopy.Status.Capacity[fakeRes] = resource.MustParse("10")
313-
node, err = cs.CoreV1().Nodes().UpdateStatus(context.TODO(), nodeCopy, metav1.UpdateOptions{})
317+
err = patchNode(cs, node, nodeCopy)
314318
framework.ExpectNoError(err)
315319
nodes = append(nodes, node)
316320
}
@@ -321,10 +325,8 @@ var _ = SIGDescribe("SchedulerPreemption [Serial]", func() {
321325
}
322326
for _, node := range nodes {
323327
nodeCopy := node.DeepCopy()
324-
// force it to update
325-
nodeCopy.ResourceVersion = "0"
326328
delete(nodeCopy.Status.Capacity, fakeRes)
327-
_, err := cs.CoreV1().Nodes().UpdateStatus(context.TODO(), nodeCopy, metav1.UpdateOptions{})
329+
err := patchNode(cs, node, nodeCopy)
328330
framework.ExpectNoError(err)
329331
}
330332
})
@@ -470,10 +472,8 @@ var _ = SIGDescribe("SchedulerPreemption [Serial]", func() {
470472

471473
if node != nil {
472474
nodeCopy := node.DeepCopy()
473-
// force it to update
474-
nodeCopy.ResourceVersion = "0"
475475
delete(nodeCopy.Status.Capacity, fakecpu)
476-
_, err := cs.CoreV1().Nodes().UpdateStatus(context.TODO(), nodeCopy, metav1.UpdateOptions{})
476+
err := patchNode(cs, node, nodeCopy)
477477
framework.ExpectNoError(err)
478478
}
479479
for _, pair := range priorityPairs {
@@ -504,10 +504,8 @@ var _ = SIGDescribe("SchedulerPreemption [Serial]", func() {
504504

505505
// update Node API object with a fake resource
506506
nodeCopy := node.DeepCopy()
507-
// force it to update
508-
nodeCopy.ResourceVersion = "0"
509507
nodeCopy.Status.Capacity[fakecpu] = resource.MustParse("1000")
510-
node, err = cs.CoreV1().Nodes().UpdateStatus(context.TODO(), nodeCopy, metav1.UpdateOptions{})
508+
err = patchNode(cs, node, nodeCopy)
511509
framework.ExpectNoError(err)
512510

513511
// create four PriorityClass: p1, p2, p3, p4
@@ -737,3 +735,21 @@ func waitForPreemptingWithTimeout(f *framework.Framework, pod *v1.Pod, timeout t
737735
})
738736
framework.ExpectNoError(err, "pod %v/%v failed to preempt other pods", pod.Namespace, pod.Name)
739737
}
738+
739+
func patchNode(client clientset.Interface, old *v1.Node, new *v1.Node) error {
740+
oldData, err := json.Marshal(old)
741+
if err != nil {
742+
return err
743+
}
744+
745+
newData, err := json.Marshal(new)
746+
if err != nil {
747+
return err
748+
}
749+
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, &v1.Node{})
750+
if err != nil {
751+
return fmt.Errorf("failed to create merge patch for node %q: %v", old.Name, err)
752+
}
753+
_, err = client.CoreV1().Nodes().Patch(context.TODO(), old.Name, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{}, "status")
754+
return err
755+
}

0 commit comments

Comments
 (0)