mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-11-02 23:02:25 +00:00
EvenPodsSpread: integration test
This commit is contained in:
@@ -17,12 +17,21 @@ limitations under the License.
|
||||
package scheduler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/scheduler/algorithmprovider"
|
||||
st "k8s.io/kubernetes/pkg/scheduler/testing"
|
||||
testutils "k8s.io/kubernetes/test/utils"
|
||||
"strings"
|
||||
imageutils "k8s.io/kubernetes/test/utils/image"
|
||||
)
|
||||
|
||||
// This file tests the scheduler priority functions.
|
||||
@@ -234,3 +243,121 @@ func makeContainersWithImages(images []string) []v1.Container {
|
||||
}
|
||||
return containers
|
||||
}
|
||||
|
||||
// TestEvenPodsSpreadPriority verifies that EvenPodsSpread priority functions well.
|
||||
func TestEvenPodsSpreadPriority(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EvenPodsSpread, true)()
|
||||
// Apply feature gates to enable EvenPodsSpread
|
||||
defer algorithmprovider.ApplyFeatureGates()()
|
||||
|
||||
context := initTest(t, "eps-priority")
|
||||
cs := context.clientSet
|
||||
ns := context.ns.Name
|
||||
defer cleanupTest(t, context)
|
||||
// Add 4 nodes.
|
||||
nodes, err := createNodes(cs, "node", nil, 4)
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot create nodes: %v", err)
|
||||
}
|
||||
for i, node := range nodes {
|
||||
// Apply labels "zone: zone-{0,1}" and "node: <node name>" to each node.
|
||||
labels := map[string]string{
|
||||
"zone": fmt.Sprintf("zone-%d", i/2),
|
||||
"node": node.Name,
|
||||
}
|
||||
if err = testutils.AddLabelsToNode(cs, node.Name, labels); err != nil {
|
||||
t.Fatalf("Cannot add labels to node: %v", err)
|
||||
}
|
||||
if err = waitForNodeLabels(cs, node.Name, labels); err != nil {
|
||||
t.Fatalf("Adding labels to node failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Taint the 0th node
|
||||
taint := v1.Taint{
|
||||
Key: "k1",
|
||||
Value: "v1",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
}
|
||||
if err = addTaintToNode(cs, nodes[0].Name, taint); err != nil {
|
||||
t.Fatalf("Adding taint to node failed: %v", err)
|
||||
}
|
||||
if err = waitForNodeTaints(cs, nodes[0], []v1.Taint{taint}); err != nil {
|
||||
t.Fatalf("Taint not seen on node: %v", err)
|
||||
}
|
||||
|
||||
pause := imageutils.GetPauseImageName()
|
||||
tests := []struct {
|
||||
name string
|
||||
incomingPod *v1.Pod
|
||||
existingPods []*v1.Pod
|
||||
fits bool
|
||||
want []string // nodes expected to schedule onto
|
||||
}{
|
||||
// note: naming starts at index 0
|
||||
// the symbol ~X~ means that node is infeasible
|
||||
{
|
||||
name: "place pod on a ~0~/1/2/3 cluster with MaxSkew=1, node-1 is the preferred fit",
|
||||
incomingPod: st.MakePod().Namespace(ns).Name("p").Label("foo", "").Container(pause).
|
||||
SpreadConstraint(1, "node", softSpread, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Namespace(ns).Name("p1").Node("node-1").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Namespace(ns).Name("p2a").Node("node-2").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Namespace(ns).Name("p2b").Node("node-2").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Namespace(ns).Name("p3a").Node("node-3").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Namespace(ns).Name("p3b").Node("node-3").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Namespace(ns).Name("p3c").Node("node-3").Label("foo", "").Container(pause).Obj(),
|
||||
},
|
||||
fits: true,
|
||||
want: []string{"node-1"},
|
||||
},
|
||||
{
|
||||
name: "combined with hardSpread constraint on a ~4~/0/1/2 cluster",
|
||||
incomingPod: st.MakePod().Namespace(ns).Name("p").Label("foo", "").Container(pause).
|
||||
SpreadConstraint(1, "node", softSpread, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||
SpreadConstraint(1, "zone", hardSpread, st.MakeLabelSelector().Exists("foo").Obj()).
|
||||
Obj(),
|
||||
existingPods: []*v1.Pod{
|
||||
st.MakePod().Namespace(ns).Name("p0a").Node("node-0").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Namespace(ns).Name("p0b").Node("node-0").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Namespace(ns).Name("p0c").Node("node-0").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Namespace(ns).Name("p0d").Node("node-0").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Namespace(ns).Name("p2").Node("node-2").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Namespace(ns).Name("p3a").Node("node-3").Label("foo", "").Container(pause).Obj(),
|
||||
st.MakePod().Namespace(ns).Name("p3b").Node("node-3").Label("foo", "").Container(pause).Obj(),
|
||||
},
|
||||
fits: true,
|
||||
want: []string{"node-2"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
allPods := append(tt.existingPods, tt.incomingPod)
|
||||
defer cleanupPods(cs, t, allPods)
|
||||
for _, pod := range tt.existingPods {
|
||||
createdPod, err := cs.CoreV1().Pods(pod.Namespace).Create(pod)
|
||||
if err != nil {
|
||||
t.Fatalf("Test Failed: error while creating pod during test: %v", err)
|
||||
}
|
||||
err = wait.Poll(pollInterval, wait.ForeverTestTimeout, podScheduled(cs, createdPod.Namespace, createdPod.Name))
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed: error while waiting for pod during test: %v", err)
|
||||
}
|
||||
}
|
||||
testPod, err := cs.CoreV1().Pods(tt.incomingPod.Namespace).Create(tt.incomingPod)
|
||||
if err != nil && !errors.IsInvalid(err) {
|
||||
t.Fatalf("Test Failed: error while creating pod during test: %v", err)
|
||||
}
|
||||
|
||||
if tt.fits {
|
||||
err = wait.Poll(pollInterval, wait.ForeverTestTimeout, podScheduledIn(cs, testPod.Namespace, testPod.Name, tt.want))
|
||||
} else {
|
||||
err = wait.Poll(pollInterval, wait.ForeverTestTimeout, podUnschedulable(cs, testPod.Namespace, testPod.Name))
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user