mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-10 12:32:03 +00:00
Return Skip in InterPodAffinity#PreScore under specific conditions
This commit updates the InterPodAffinity PreScore to return a Skip status when the following conditions are met: 1. There are no nodes to score. 2. The incoming pod has no inter-pod affinities && the `IgnorePreferredTermsOfExistingPods` option is enabled. Signed-off-by: utam0k <k0ma@utam0k.jp>
This commit is contained in:
parent
dea1312e03
commit
c0611b6bb3
@ -131,7 +131,7 @@ func (pl *InterPodAffinity) PreScore(
|
|||||||
) *framework.Status {
|
) *framework.Status {
|
||||||
if len(nodes) == 0 {
|
if len(nodes) == 0 {
|
||||||
// No nodes to score.
|
// No nodes to score.
|
||||||
return nil
|
return framework.NewStatus(framework.Skip)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pl.sharedLister == nil {
|
if pl.sharedLister == nil {
|
||||||
@ -145,10 +145,7 @@ func (pl *InterPodAffinity) PreScore(
|
|||||||
// Optionally ignore calculating preferences of existing pods' affinity rules
|
// Optionally ignore calculating preferences of existing pods' affinity rules
|
||||||
// if the incoming pod has no inter-pod affinities.
|
// if the incoming pod has no inter-pod affinities.
|
||||||
if pl.args.IgnorePreferredTermsOfExistingPods && !hasPreferredAffinityConstraints && !hasPreferredAntiAffinityConstraints {
|
if pl.args.IgnorePreferredTermsOfExistingPods && !hasPreferredAffinityConstraints && !hasPreferredAntiAffinityConstraints {
|
||||||
cycleState.Write(preScoreStateKey, &preScoreState{
|
return framework.NewStatus(framework.Skip)
|
||||||
topologyScore: make(map[string]map[string]int64),
|
|
||||||
})
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unless the pod being scheduled has preferred affinity terms, we only
|
// Unless the pod being scheduled has preferred affinity terms, we only
|
||||||
@ -213,6 +210,10 @@ func (pl *InterPodAffinity) PreScore(
|
|||||||
}
|
}
|
||||||
pl.parallelizer.Until(pCtx, len(allNodes), processNode, pl.Name())
|
pl.parallelizer.Until(pCtx, len(allNodes), processNode, pl.Name())
|
||||||
|
|
||||||
|
if index == -1 {
|
||||||
|
return framework.NewStatus(framework.Skip)
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i <= int(index); i++ {
|
for i := 0; i <= int(index); i++ {
|
||||||
state.topologyScore.append(topoScores[i])
|
state.topologyScore.append(topoScores[i])
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
@ -385,7 +386,7 @@ func TestPreferredAffinity(t *testing.T) {
|
|||||||
{ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
|
{ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
|
||||||
{ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
|
{ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
|
||||||
},
|
},
|
||||||
expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}, {Name: "node3", Score: 0}},
|
wantStatus: framework.NewStatus(framework.Skip),
|
||||||
},
|
},
|
||||||
// the node(node1) that have the label {"region": "China"} (match the topology key) and that have existing pods that match the labelSelector get high score
|
// the node(node1) that have the label {"region": "China"} (match the topology key) and that have existing pods that match the labelSelector get high score
|
||||||
// the node(node3) that don't have the label {"region": "whatever the value is"} (mismatch the topology key) but that have existing pods that match the labelSelector get low score
|
// the node(node3) that don't have the label {"region": "whatever the value is"} (mismatch the topology key) but that have existing pods that match the labelSelector get low score
|
||||||
@ -749,6 +750,7 @@ func TestPreferredAffinity(t *testing.T) {
|
|||||||
{ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
|
{ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
|
||||||
},
|
},
|
||||||
expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}},
|
expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}},
|
||||||
|
wantStatus: framework.NewStatus(framework.Skip),
|
||||||
ignorePreferredTermsOfExistingPods: true,
|
ignorePreferredTermsOfExistingPods: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -765,6 +767,13 @@ func TestPreferredAffinity(t *testing.T) {
|
|||||||
expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: framework.MaxNodeScore}},
|
expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: framework.MaxNodeScore}},
|
||||||
ignorePreferredTermsOfExistingPods: false,
|
ignorePreferredTermsOfExistingPods: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "No nodes to score",
|
||||||
|
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
|
||||||
|
pods: []*v1.Pod{},
|
||||||
|
nodes: []*v1.Node{},
|
||||||
|
wantStatus: framework.NewStatus(framework.Skip),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
@ -773,31 +782,36 @@ func TestPreferredAffinity(t *testing.T) {
|
|||||||
state := framework.NewCycleState()
|
state := framework.NewCycleState()
|
||||||
p := plugintesting.SetupPluginWithInformers(ctx, t, New, &config.InterPodAffinityArgs{HardPodAffinityWeight: 1, IgnorePreferredTermsOfExistingPods: test.ignorePreferredTermsOfExistingPods}, cache.NewSnapshot(test.pods, test.nodes), namespaces)
|
p := plugintesting.SetupPluginWithInformers(ctx, t, New, &config.InterPodAffinityArgs{HardPodAffinityWeight: 1, IgnorePreferredTermsOfExistingPods: test.ignorePreferredTermsOfExistingPods}, cache.NewSnapshot(test.pods, test.nodes), namespaces)
|
||||||
status := p.(framework.PreScorePlugin).PreScore(ctx, state, test.pod, test.nodes)
|
status := p.(framework.PreScorePlugin).PreScore(ctx, state, test.pod, test.nodes)
|
||||||
|
|
||||||
if !status.IsSuccess() {
|
if !status.IsSuccess() {
|
||||||
|
if status.Code() != test.wantStatus.Code() {
|
||||||
|
t.Errorf("InterPodAffinity#PreScore() returned unexpected status.Code got: %v, want: %v", status.Code(), test.wantStatus.Code())
|
||||||
|
}
|
||||||
|
|
||||||
if !strings.Contains(status.Message(), test.wantStatus.Message()) {
|
if !strings.Contains(status.Message(), test.wantStatus.Message()) {
|
||||||
t.Errorf("unexpected error: %v", status)
|
t.Errorf("InterPodAffinity#PreScore() returned unexpected status.Message got: %v, want: %v", status.Message(), test.wantStatus.Message())
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var gotList framework.NodeScoreList
|
|
||||||
for _, n := range test.nodes {
|
|
||||||
nodeName := n.ObjectMeta.Name
|
|
||||||
score, status := p.(framework.ScorePlugin).Score(ctx, state, test.pod, nodeName)
|
|
||||||
if !status.IsSuccess() {
|
|
||||||
t.Errorf("unexpected error: %v", status)
|
|
||||||
}
|
|
||||||
gotList = append(gotList, framework.NodeScore{Name: nodeName, Score: score})
|
|
||||||
}
|
|
||||||
|
|
||||||
status = p.(framework.ScorePlugin).ScoreExtensions().NormalizeScore(ctx, state, test.pod, gotList)
|
|
||||||
if !status.IsSuccess() {
|
|
||||||
t.Errorf("unexpected error: %v", status)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(test.expectedList, gotList) {
|
|
||||||
t.Errorf("expected:\n\t%+v,\ngot:\n\t%+v", test.expectedList, gotList)
|
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var gotList framework.NodeScoreList
|
||||||
|
for _, n := range test.nodes {
|
||||||
|
nodeName := n.ObjectMeta.Name
|
||||||
|
score, status := p.(framework.ScorePlugin).Score(ctx, state, test.pod, nodeName)
|
||||||
|
if !status.IsSuccess() {
|
||||||
|
t.Errorf("unexpected error from Score: %v", status)
|
||||||
|
}
|
||||||
|
gotList = append(gotList, framework.NodeScore{Name: nodeName, Score: score})
|
||||||
|
}
|
||||||
|
|
||||||
|
status = p.(framework.ScorePlugin).ScoreExtensions().NormalizeScore(ctx, state, test.pod, gotList)
|
||||||
|
if !status.IsSuccess() {
|
||||||
|
t.Errorf("unexpected error from NormalizeScore: %v", status)
|
||||||
|
}
|
||||||
|
|
||||||
|
if diff := cmp.Diff(test.expectedList, gotList); diff != "" {
|
||||||
|
t.Errorf("node score list doesn't match (-want,+got): \n %s", diff)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -850,6 +864,7 @@ func TestPreferredAffinityWithHardPodAffinitySymmetricWeight(t *testing.T) {
|
|||||||
hardPodAffinityWeight int32
|
hardPodAffinityWeight int32
|
||||||
expectedList framework.NodeScoreList
|
expectedList framework.NodeScoreList
|
||||||
name string
|
name string
|
||||||
|
wantStatus *framework.Status
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "with default weight",
|
name: "with default weight",
|
||||||
@ -879,7 +894,7 @@ func TestPreferredAffinityWithHardPodAffinitySymmetricWeight(t *testing.T) {
|
|||||||
{ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
|
{ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
|
||||||
},
|
},
|
||||||
hardPodAffinityWeight: 0,
|
hardPodAffinityWeight: 0,
|
||||||
expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}, {Name: "node3", Score: 0}},
|
wantStatus: framework.NewStatus(framework.Skip),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with no matching namespace",
|
name: "with no matching namespace",
|
||||||
@ -894,7 +909,7 @@ func TestPreferredAffinityWithHardPodAffinitySymmetricWeight(t *testing.T) {
|
|||||||
{ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
|
{ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
|
||||||
},
|
},
|
||||||
hardPodAffinityWeight: v1.DefaultHardPodAffinitySymmetricWeight,
|
hardPodAffinityWeight: v1.DefaultHardPodAffinitySymmetricWeight,
|
||||||
expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}, {Name: "node3", Score: 0}},
|
wantStatus: framework.NewStatus(framework.Skip),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with matching NamespaceSelector",
|
name: "with matching NamespaceSelector",
|
||||||
@ -934,9 +949,13 @@ func TestPreferredAffinityWithHardPodAffinitySymmetricWeight(t *testing.T) {
|
|||||||
state := framework.NewCycleState()
|
state := framework.NewCycleState()
|
||||||
p := plugintesting.SetupPluginWithInformers(ctx, t, New, &config.InterPodAffinityArgs{HardPodAffinityWeight: test.hardPodAffinityWeight}, cache.NewSnapshot(test.pods, test.nodes), namespaces)
|
p := plugintesting.SetupPluginWithInformers(ctx, t, New, &config.InterPodAffinityArgs{HardPodAffinityWeight: test.hardPodAffinityWeight}, cache.NewSnapshot(test.pods, test.nodes), namespaces)
|
||||||
status := p.(framework.PreScorePlugin).PreScore(ctx, state, test.pod, test.nodes)
|
status := p.(framework.PreScorePlugin).PreScore(ctx, state, test.pod, test.nodes)
|
||||||
if !status.IsSuccess() {
|
if !test.wantStatus.Equal(status) {
|
||||||
t.Errorf("unexpected error: %v", status)
|
t.Errorf("InterPodAffinity#PreScore() returned unexpected status.Code got: %v, want: %v", status.Code(), test.wantStatus.Code())
|
||||||
}
|
}
|
||||||
|
if !status.IsSuccess() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var gotList framework.NodeScoreList
|
var gotList framework.NodeScoreList
|
||||||
for _, n := range test.nodes {
|
for _, n := range test.nodes {
|
||||||
nodeName := n.ObjectMeta.Name
|
nodeName := n.ObjectMeta.Name
|
||||||
|
Loading…
Reference in New Issue
Block a user