Skip to content

Commit

Permalink
Merge pull request kubernetes#103278 from marwanad/automated-cherry-p…
Browse files Browse the repository at this point in the history
…ick-of-#103133-upstream-release-1.20

Automated cherry pick of kubernetes#103133 on 1.20: switch scheduler to generate the merge patch on pod status instead of the full pod
  • Loading branch information
k8s-ci-robot authored Jul 10, 2021
2 parents 449b931 + bd5c548 commit 2e94d90
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 11 deletions.
8 changes: 4 additions & 4 deletions pkg/scheduler/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -353,17 +353,17 @@ func truncateMessage(message string) string {

func updatePod(client clientset.Interface, pod *v1.Pod, condition *v1.PodCondition, nominatedNode string) error {
klog.V(3).Infof("Updating pod condition for %s/%s to (%s==%s, Reason=%s)", pod.Namespace, pod.Name, condition.Type, condition.Status, condition.Reason)
podCopy := pod.DeepCopy()
podStatusCopy := pod.Status.DeepCopy()
// NominatedNodeName is updated only if we are trying to set it, and the value is
// different from the existing one.
if !podutil.UpdatePodCondition(&podCopy.Status, condition) &&
if !podutil.UpdatePodCondition(podStatusCopy, condition) &&
(len(nominatedNode) == 0 || pod.Status.NominatedNodeName == nominatedNode) {
return nil
}
if nominatedNode != "" {
podCopy.Status.NominatedNodeName = nominatedNode
podStatusCopy.NominatedNodeName = nominatedNode
}
return util.PatchPod(client, pod, podCopy)
return util.PatchPodStatus(client, pod, podStatusCopy)
}

// assume signals to the cache that a pod is already in the cache, so that binding can be asynchronous.
Expand Down
1 change: 1 addition & 0 deletions pkg/scheduler/util/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ go_test(
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
"//staging/src/k8s.io/client-go/testing:go_default_library",
"//staging/src/k8s.io/kube-scheduler/extender/v1:go_default_library",
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
],
)
Expand Down
18 changes: 11 additions & 7 deletions pkg/scheduler/util/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,19 @@ func GetPodAntiAffinityTerms(affinity *v1.Affinity) (terms []v1.PodAffinityTerm)
return terms
}

// PatchPod calculates the delta bytes change from <old> to <new>,
// PatchPodStatus calculates the delta bytes change from <old.Status> to <newStatus>,
// and then submit a request to API server to patch the pod changes.
func PatchPod(cs kubernetes.Interface, old *v1.Pod, new *v1.Pod) error {
oldData, err := json.Marshal(old)
func PatchPodStatus(cs kubernetes.Interface, old *v1.Pod, newStatus *v1.PodStatus) error {
if newStatus == nil {
return nil
}

oldData, err := json.Marshal(v1.Pod{Status: old.Status})
if err != nil {
return err
}

newData, err := json.Marshal(new)
newData, err := json.Marshal(v1.Pod{Status: *newStatus})
if err != nil {
return err
}
Expand Down Expand Up @@ -156,9 +160,9 @@ func ClearNominatedNodeName(cs kubernetes.Interface, pods ...*v1.Pod) utilerrors
if len(p.Status.NominatedNodeName) == 0 {
continue
}
podCopy := p.DeepCopy()
podCopy.Status.NominatedNodeName = ""
if err := PatchPod(cs, p, podCopy); err != nil {
podStatusCopy := p.Status.DeepCopy()
podStatusCopy.NominatedNodeName = ""
if err := PatchPodStatus(cs, p, podStatusCopy); err != nil {
errs = append(errs, err)
}
}
Expand Down
79 changes: 79 additions & 0 deletions pkg/scheduler/util/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ limitations under the License.
package util

import (
"context"
"fmt"
"github.com/google/go-cmp/cmp"
"testing"
"time"

Expand Down Expand Up @@ -171,3 +173,80 @@ func TestRemoveNominatedNodeName(t *testing.T) {
})
}
}

func TestPatchPodStatus(t *testing.T) {
tests := []struct {
name string
pod v1.Pod
statusToUpdate v1.PodStatus
}{
{
name: "Should update pod conditions successfully",
pod: v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Namespace: "ns",
Name: "pod1",
},
Spec: v1.PodSpec{
ImagePullSecrets: []v1.LocalObjectReference{{Name: "foo"}},
},
},
statusToUpdate: v1.PodStatus{
Conditions: []v1.PodCondition{
{
Type: v1.PodScheduled,
Status: v1.ConditionFalse,
},
},
},
},
{
// ref: #101697, #94626 - ImagePullSecrets are allowed to have empty secret names
// which would fail the 2-way merge patch generation on Pod patches
// due to the mergeKey being the name field
name: "Should update pod conditions successfully on a pod Spec with secrets with empty name",
pod: v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Namespace: "ns",
Name: "pod2",
},
Spec: v1.PodSpec{
// this will serialize to imagePullSecrets:[{}]
ImagePullSecrets: make([]v1.LocalObjectReference, 1),
},
},
statusToUpdate: v1.PodStatus{
Conditions: []v1.PodCondition{
{
Type: v1.PodScheduled,
Status: v1.ConditionFalse,
},
},
},
},
}

client := clientsetfake.NewSimpleClientset()
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
_, err := client.CoreV1().Pods(tc.pod.Namespace).Create(context.TODO(), &tc.pod, metav1.CreateOptions{})
if err != nil {
t.Fatal(err)
}

err = PatchPodStatus(client, &tc.pod, &tc.statusToUpdate)
if err != nil {
t.Fatal(err)
}

retrievedPod, err := client.CoreV1().Pods(tc.pod.Namespace).Get(context.TODO(), tc.pod.Name, metav1.GetOptions{})
if err != nil {
t.Fatal(err)
}

if diff := cmp.Diff(tc.statusToUpdate, retrievedPod.Status); diff != "" {
t.Errorf("unexpected pod status (-want,+got):\n%s", diff)
}
})
}
}

0 comments on commit 2e94d90

Please sign in to comment.