From f6fb0bd308fff8810e46f2e52f617a73f9dbcfdd Mon Sep 17 00:00:00 2001 From: Aldo Culquicondor Date: Wed, 21 Oct 2020 18:06:03 -0400 Subject: [PATCH] Add integration test for Default PodTopologySpread Simulating a cluster with 500 nodes in 3 zones, deploying 3, 12 and 27 Pods belonging to the same service. Change-Id: I16425594012ea7bd24b888acedb12958360bff97 --- test/integration/scheduler/priorities_test.go | 98 ++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-) diff --git a/test/integration/scheduler/priorities_test.go b/test/integration/scheduler/priorities_test.go index ea0f1311a84..de16a480413 100644 --- a/test/integration/scheduler/priorities_test.go +++ b/test/integration/scheduler/priorities_test.go @@ -25,6 +25,7 @@ import ( v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubernetes/pkg/scheduler" schedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" @@ -254,8 +255,8 @@ func makeContainersWithImages(images []string) []v1.Container { return containers } -// TestEvenPodsSpreadPriority verifies that EvenPodsSpread priority functions well. -func TestEvenPodsSpreadPriority(t *testing.T) { +// TestPodTopologySpreadScore verifies that the PodTopologySpread Score plugin works. +func TestPodTopologySpreadScore(t *testing.T) { testCtx := initTestSchedulerForPriorityTest(t, podtopologyspread.Name) defer testutils.CleanupTest(t, testCtx) cs := testCtx.ClientSet @@ -361,3 +362,96 @@ func TestEvenPodsSpreadPriority(t *testing.T) { }) } } + +// TestDefaultPodTopologySpreadScore verifies that the PodTopologySpread Score plugin +// with the system default spreading spreads Pods belonging to a Service. +// The setup has 300 nodes over 3 zones. +func TestDefaultPodTopologySpreadScore(t *testing.T) { + testCtx := initTestSchedulerForPriorityTest(t, podtopologyspread.Name) + t.Cleanup(func() { + testutils.CleanupTest(t, testCtx) + }) + cs := testCtx.ClientSet + ns := testCtx.NS.Name + + zoneForNode := make(map[string]string) + for i := 0; i < 300; i++ { + nodeName := fmt.Sprintf("node-%d", i) + zone := fmt.Sprintf("zone-%d", i%3) + zoneForNode[nodeName] = zone + _, err := createNode(cs, st.MakeNode().Name(nodeName).Label(v1.LabelHostname, nodeName).Label(v1.LabelZoneFailureDomainStable, zone).Obj()) + if err != nil { + t.Fatalf("Cannot create node: %v", err) + } + } + + serviceName := "test-service" + svc := &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: serviceName, + Namespace: ns, + }, + Spec: v1.ServiceSpec{ + Selector: map[string]string{ + "service": serviceName, + }, + Ports: []v1.ServicePort{{ + Port: 80, + TargetPort: intstr.FromInt(80), + }}, + }, + } + _, err := cs.CoreV1().Services(ns).Create(testCtx.Ctx, svc, metav1.CreateOptions{}) + if err != nil { + t.Fatalf("Cannot create Service: %v", err) + } + + pause := imageutils.GetPauseImageName() + totalPodCnt := 0 + for _, nPods := range []int{3, 9, 15} { + // Append nPods each iteration. + t.Run(fmt.Sprintf("%d-pods", totalPodCnt+nPods), func(t *testing.T) { + for i := 0; i < nPods; i++ { + p := st.MakePod().Name(fmt.Sprintf("p-%d", totalPodCnt)).Label("service", serviceName).Container(pause).Obj() + _, err = cs.CoreV1().Pods(ns).Create(testCtx.Ctx, p, metav1.CreateOptions{}) + if err != nil { + t.Fatalf("Cannot create Pod: %v", err) + } + totalPodCnt++ + } + var pods []v1.Pod + // Wait for all Pods scheduled. + err = wait.Poll(pollInterval, wait.ForeverTestTimeout, func() (bool, error) { + podList, err := cs.CoreV1().Pods(ns).List(testCtx.Ctx, metav1.ListOptions{}) + if err != nil { + t.Fatalf("Cannot list pods to verify scheduling: %v", err) + } + for _, p := range podList.Items { + if p.Spec.NodeName == "" { + return false, nil + } + } + pods = podList.Items + return true, nil + }) + // Verify zone spreading. + zoneCnts := make(map[string]int) + for _, p := range pods { + zoneCnts[zoneForNode[p.Spec.NodeName]]++ + } + maxCnt := 0 + minCnt := len(pods) + for _, c := range zoneCnts { + if c > maxCnt { + maxCnt = c + } + if c < minCnt { + minCnt = c + } + } + if skew := maxCnt - minCnt; skew != 0 { + t.Errorf("Zone skew is %d, should be 0", skew) + } + }) + } +}