Merge pull request #43306 from timothysc/perf_e2e_split
Automatic merge from submit-queue (batch tested with PRs 43522, 43306) Sig-scalability test segregation to allow for assignment and cleaning… **What this PR does / why we need it**: e2e test segregation to allow for easier test assignment and general cleanliness. **Special notes for your reviewer**: cleaning per-conversation @gmarek **Release note**: ``` NONE ``` /cc @gmarek @wojtek-t @kubernetes/sig-scalability-pr-reviews
This commit is contained in:
		| @@ -26,7 +26,6 @@ go_library( | ||||
|         "daemon_restart.go", | ||||
|         "daemon_set.go", | ||||
|         "dashboard.go", | ||||
|         "density.go", | ||||
|         "deployment.go", | ||||
|         "disruption.go", | ||||
|         "dns.go", | ||||
| @@ -39,7 +38,6 @@ go_library( | ||||
|         "etcd_failure.go", | ||||
|         "events.go", | ||||
|         "example_cluster_dns.go", | ||||
|         "example_k8petstore.go", | ||||
|         "examples.go", | ||||
|         "firewall.go", | ||||
|         "garbage_collector.go", | ||||
| @@ -57,7 +55,6 @@ go_library( | ||||
|         "kubelet.go", | ||||
|         "kubelet_perf.go", | ||||
|         "limit_range.go", | ||||
|         "load.go", | ||||
|         "logging_soak.go", | ||||
|         "monitoring.go", | ||||
|         "namespace.go", | ||||
| @@ -151,6 +148,7 @@ go_library( | ||||
|         "//test/e2e/common:go_default_library", | ||||
|         "//test/e2e/framework:go_default_library", | ||||
|         "//test/e2e/generated:go_default_library", | ||||
|         "//test/e2e/perf:go_default_library", | ||||
|         "//test/e2e/scheduling:go_default_library", | ||||
|         "//test/e2e/upgrades:go_default_library", | ||||
|         "//test/e2e_federation:go_default_library", | ||||
| @@ -202,10 +200,8 @@ go_library( | ||||
|         "//vendor:k8s.io/client-go/pkg/apis/policy/v1beta1", | ||||
|         "//vendor:k8s.io/client-go/rest", | ||||
|         "//vendor:k8s.io/client-go/tools/cache", | ||||
|         "//vendor:k8s.io/client-go/transport", | ||||
|         "//vendor:k8s.io/client-go/util/flowcontrol", | ||||
|         "//vendor:k8s.io/client-go/util/integer", | ||||
|         "//vendor:k8s.io/client-go/util/workqueue", | ||||
|     ], | ||||
| ) | ||||
|  | ||||
| @@ -226,6 +222,7 @@ go_test( | ||||
|         "//pkg/client/clientset_generated/clientset:go_default_library", | ||||
|         "//pkg/metrics:go_default_library", | ||||
|         "//test/e2e/framework:go_default_library", | ||||
|         "//test/e2e/perf:go_default_library", | ||||
|         "//test/e2e/scheduling:go_default_library", | ||||
|         "//test/utils:go_default_library", | ||||
|         "//vendor:github.com/onsi/ginkgo", | ||||
| @@ -263,6 +260,7 @@ filegroup( | ||||
|         "//test/e2e/common:all-srcs", | ||||
|         "//test/e2e/framework:all-srcs", | ||||
|         "//test/e2e/generated:all-srcs", | ||||
|         "//test/e2e/perf:all-srcs", | ||||
|         "//test/e2e/perftype:all-srcs", | ||||
|         "//test/e2e/scheduling:all-srcs", | ||||
|         "//test/e2e/testing-manifests:all-srcs", | ||||
|   | ||||
| @@ -20,6 +20,7 @@ import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"k8s.io/kubernetes/test/e2e/framework" | ||||
| 	_ "k8s.io/kubernetes/test/e2e/perf" | ||||
| 	_ "k8s.io/kubernetes/test/e2e/scheduling" | ||||
| ) | ||||
|  | ||||
|   | ||||
| @@ -22,6 +22,7 @@ import ( | ||||
| 	"k8s.io/kubernetes/pkg/api" | ||||
| 	"k8s.io/kubernetes/pkg/api/v1" | ||||
| 	"k8s.io/kubernetes/test/e2e/framework" | ||||
| 	"k8s.io/kubernetes/test/e2e/perf" | ||||
|  | ||||
| 	. "github.com/onsi/ginkgo" | ||||
| ) | ||||
| @@ -42,7 +43,7 @@ var _ = framework.KubeDescribe("Empty [Feature:Empty]", func() { | ||||
| 	}) | ||||
|  | ||||
| 	It("starts a pod", func() { | ||||
| 		configs, _ := generateConfigsForGroup([]*v1.Namespace{f.Namespace}, "empty-pod", 1, 1, framework.GetPauseImageName(f.ClientSet), []string{}, api.Kind("ReplicationController"), 0) | ||||
| 		configs, _ := perf.GenerateConfigsForGroup([]*v1.Namespace{f.Namespace}, "empty-pod", 1, 1, framework.GetPauseImageName(f.ClientSet), []string{}, api.Kind("ReplicationController"), 0) | ||||
| 		if len(configs) != 1 { | ||||
| 			framework.Failf("generateConfigs should have generated single config") | ||||
| 		} | ||||
|   | ||||
| @@ -1,187 +0,0 @@ | ||||
| /* | ||||
| Copyright 2015 The Kubernetes Authors. | ||||
|  | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| */ | ||||
|  | ||||
| package e2e | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"path/filepath" | ||||
| 	"strconv" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
|  | ||||
| 	"k8s.io/kubernetes/pkg/client/clientset_generated/clientset" | ||||
| 	"k8s.io/kubernetes/test/e2e/framework" | ||||
|  | ||||
| 	. "github.com/onsi/ginkgo" | ||||
| 	. "github.com/onsi/gomega" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	k8bpsContainerVersion         = "r.2.8.19"       // Container version, see the examples/k8petstore dockerfiles for details. | ||||
| 	k8bpsThroughputDummy          = "0"              // Polling time = 0, since we framework.Poll in ginkgo rather than using the shell script tests. | ||||
| 	k8bpsRedisSlaves              = "1"              // Number of redis slaves. | ||||
| 	k8bpsDontRunTest              = "0"              // Don't bother embedded test. | ||||
| 	k8bpsStartupTimeout           = 30 * time.Second // Amount of elapsed time before petstore transactions are being stored. | ||||
| 	k8bpsMinTransactionsOnStartup = 3                // Amount of transactions we expect we should have before data generator starts. | ||||
|  | ||||
| 	// Constants for the first test. We can make this a hashmap once we add scale tests to it. | ||||
| 	k8bpsSmokeTestFinalTransactions = 50 | ||||
| 	k8bpsSmokeTestTimeout           = 60 * time.Second | ||||
| ) | ||||
|  | ||||
| // readTransactions reads # of transactions from the k8petstore web server endpoint. | ||||
| // for more details see the source of the k8petstore web server. | ||||
| func readTransactions(c clientset.Interface, ns string) (error, int) { | ||||
| 	proxyRequest, errProxy := framework.GetServicesProxyRequest(c, c.Core().RESTClient().Get()) | ||||
| 	if errProxy != nil { | ||||
| 		return errProxy, -1 | ||||
| 	} | ||||
|  | ||||
| 	ctx, cancel := context.WithTimeout(context.Background(), framework.SingleCallTimeout) | ||||
| 	defer cancel() | ||||
|  | ||||
| 	body, err := proxyRequest.Namespace(ns). | ||||
| 		Context(ctx). | ||||
| 		Name("frontend"). | ||||
| 		Suffix("llen"). | ||||
| 		DoRaw() | ||||
| 	if err != nil { | ||||
| 		if ctx.Err() != nil { | ||||
| 			framework.Failf("Failed to read petstore transactions: %v", err) | ||||
| 		} | ||||
| 		return err, -1 | ||||
| 	} | ||||
|  | ||||
| 	totalTrans, err := strconv.Atoi(string(body)) | ||||
| 	return err, totalTrans | ||||
|  | ||||
| } | ||||
|  | ||||
| // runK8petstore runs the k8petstore application, bound to external nodeport, and | ||||
| // polls until finalTransactionsExpected transactions are acquired, in a maximum of maxSeconds. | ||||
| func runK8petstore(restServers int, loadGenerators int, c clientset.Interface, ns string, finalTransactionsExpected int, maxTime time.Duration) { | ||||
|  | ||||
| 	var err error = nil | ||||
| 	k8bpsScriptLocation := filepath.Join(framework.TestContext.RepoRoot, "examples/k8petstore/k8petstore-nodeport.sh") | ||||
|  | ||||
| 	cmd := exec.Command( | ||||
| 		k8bpsScriptLocation, | ||||
| 		framework.TestContext.KubectlPath, | ||||
| 		k8bpsContainerVersion, | ||||
| 		k8bpsThroughputDummy, | ||||
| 		strconv.Itoa(restServers), | ||||
| 		strconv.Itoa(loadGenerators), | ||||
| 		k8bpsRedisSlaves, | ||||
| 		k8bpsDontRunTest, // Don't bother embedded test. | ||||
| 		ns, | ||||
| 	) | ||||
|  | ||||
| 	cmd.Stdout = os.Stdout | ||||
| 	cmd.Stderr = os.Stderr | ||||
|  | ||||
| 	framework.Logf("Starting k8petstore application....") | ||||
| 	// Run the k8petstore app, and log / fail if it returns any errors. | ||||
| 	// This should return quickly, assuming containers are downloaded. | ||||
| 	if err = cmd.Start(); err != nil { | ||||
| 		framework.Failf("%v", err) | ||||
| 	} | ||||
| 	// Make sure there are no command errors. | ||||
| 	if err = cmd.Wait(); err != nil { | ||||
| 		if exiterr, ok := err.(*exec.ExitError); ok { | ||||
| 			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok { | ||||
| 				framework.Logf("Exit Status: %d", status.ExitStatus()) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	Expect(err).NotTo(HaveOccurred()) | ||||
| 	framework.Logf("... Done starting k8petstore ") | ||||
|  | ||||
| 	totalTransactions := 0 | ||||
| 	framework.Logf("Start polling, timeout is %v seconds", maxTime) | ||||
|  | ||||
| 	// How long until the FIRST transactions are created. | ||||
| 	startupTimeout := time.After(time.Duration(k8bpsStartupTimeout)) | ||||
|  | ||||
| 	// Maximum time to wait until we reach the nth transaction. | ||||
| 	transactionsCompleteTimeout := time.After(time.Duration(maxTime)) | ||||
| 	tick := time.Tick(2 * time.Second) | ||||
| 	var ready = false | ||||
|  | ||||
| 	framework.Logf("Now waiting %v seconds to see progress (transactions  > 3)", k8bpsStartupTimeout) | ||||
| T: | ||||
| 	for { | ||||
| 		select { | ||||
| 		case <-transactionsCompleteTimeout: | ||||
| 			framework.Logf("Completion timeout %v reached, %v transactions not complete.  Breaking!", time.Duration(maxTime), finalTransactionsExpected) | ||||
| 			break T | ||||
| 		case <-tick: | ||||
| 			// Don't fail if there's an error.  We expect a few failures might happen in the cloud. | ||||
| 			err, totalTransactions = readTransactions(c, ns) | ||||
| 			if err == nil { | ||||
| 				framework.Logf("PetStore : Time: %v, %v = total petstore transactions stored into redis.", time.Now(), totalTransactions) | ||||
| 				if totalTransactions >= k8bpsMinTransactionsOnStartup { | ||||
| 					ready = true | ||||
| 				} | ||||
| 				if totalTransactions >= finalTransactionsExpected { | ||||
| 					break T | ||||
| 				} | ||||
| 			} else { | ||||
| 				if ready { | ||||
| 					framework.Logf("Blip: during polling: %v", err) | ||||
| 				} else { | ||||
| 					framework.Logf("Not ready yet: %v", err) | ||||
| 				} | ||||
| 			} | ||||
| 		case <-startupTimeout: | ||||
| 			if !ready { | ||||
| 				framework.Logf("Startup Timeout %v reached: Its been too long and we still haven't started accumulating %v transactions!", startupTimeout, k8bpsMinTransactionsOnStartup) | ||||
| 				break T | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// We should have exceeded the finalTransactionsExpected num of transactions. | ||||
| 	// If this fails, but there are transactions being created, we may need to recalibrate | ||||
| 	// the finalTransactionsExpected value - or else - your cluster is broken/slow ! | ||||
| 	Expect(totalTransactions).To(BeNumerically(">", finalTransactionsExpected)) | ||||
| } | ||||
|  | ||||
| var _ = framework.KubeDescribe("Pet Store [Feature:Example]", func() { | ||||
|  | ||||
| 	BeforeEach(func() { | ||||
| 		// The shell scripts in k8petstore break on jenkins... Pure golang rewrite is in progress. | ||||
| 		framework.SkipUnlessProviderIs("local") | ||||
| 	}) | ||||
|  | ||||
| 	// The number of nodes dictates total number of generators/transaction expectations. | ||||
| 	var nodeCount int | ||||
| 	f := framework.NewDefaultFramework("petstore") | ||||
|  | ||||
| 	It(fmt.Sprintf("should scale to persist a nominal number ( %v ) of transactions in %v seconds", k8bpsSmokeTestFinalTransactions, k8bpsSmokeTestTimeout), func() { | ||||
| 		nodes := framework.GetReadySchedulableNodesOrDie(f.ClientSet) | ||||
| 		nodeCount = len(nodes.Items) | ||||
|  | ||||
| 		loadGenerators := nodeCount | ||||
| 		restServers := nodeCount | ||||
| 		fmt.Printf("load generators / rest servers [ %v  /  %v ] ", loadGenerators, restServers) | ||||
| 		runK8petstore(restServers, loadGenerators, f.ClientSet, f.Namespace.Name, k8bpsSmokeTestFinalTransactions, k8bpsSmokeTestTimeout) | ||||
| 	}) | ||||
|  | ||||
| }) | ||||
							
								
								
									
										57
									
								
								test/e2e/perf/BUILD
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								test/e2e/perf/BUILD
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| package(default_visibility = ["//visibility:public"]) | ||||
|  | ||||
| licenses(["notice"]) | ||||
|  | ||||
| load( | ||||
|     "@io_bazel_rules_go//go:def.bzl", | ||||
|     "go_library", | ||||
| ) | ||||
|  | ||||
| go_library( | ||||
|     name = "go_default_library", | ||||
|     srcs = [ | ||||
|         "density.go", | ||||
|         "load.go", | ||||
|     ], | ||||
|     tags = ["automanaged"], | ||||
|     deps = [ | ||||
|         "//pkg/api:go_default_library", | ||||
|         "//pkg/api/v1:go_default_library", | ||||
|         "//pkg/apis/batch:go_default_library", | ||||
|         "//pkg/apis/extensions:go_default_library", | ||||
|         "//pkg/client/clientset_generated/clientset:go_default_library", | ||||
|         "//pkg/client/clientset_generated/internalclientset:go_default_library", | ||||
|         "//test/e2e/framework:go_default_library", | ||||
|         "//test/utils:go_default_library", | ||||
|         "//vendor:github.com/onsi/ginkgo", | ||||
|         "//vendor:github.com/onsi/gomega", | ||||
|         "//vendor:k8s.io/apimachinery/pkg/api/resource", | ||||
|         "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", | ||||
|         "//vendor:k8s.io/apimachinery/pkg/fields", | ||||
|         "//vendor:k8s.io/apimachinery/pkg/labels", | ||||
|         "//vendor:k8s.io/apimachinery/pkg/runtime", | ||||
|         "//vendor:k8s.io/apimachinery/pkg/runtime/schema", | ||||
|         "//vendor:k8s.io/apimachinery/pkg/util/intstr", | ||||
|         "//vendor:k8s.io/apimachinery/pkg/util/net", | ||||
|         "//vendor:k8s.io/apimachinery/pkg/util/sets", | ||||
|         "//vendor:k8s.io/apimachinery/pkg/util/uuid", | ||||
|         "//vendor:k8s.io/apimachinery/pkg/watch", | ||||
|         "//vendor:k8s.io/client-go/rest", | ||||
|         "//vendor:k8s.io/client-go/tools/cache", | ||||
|         "//vendor:k8s.io/client-go/transport", | ||||
|         "//vendor:k8s.io/client-go/util/workqueue", | ||||
|     ], | ||||
| ) | ||||
|  | ||||
| filegroup( | ||||
|     name = "package-srcs", | ||||
|     srcs = glob(["**"]), | ||||
|     tags = ["automanaged"], | ||||
|     visibility = ["//visibility:private"], | ||||
| ) | ||||
|  | ||||
| filegroup( | ||||
|     name = "all-srcs", | ||||
|     srcs = [":package-srcs"], | ||||
|     tags = ["automanaged"], | ||||
| ) | ||||
							
								
								
									
										7
									
								
								test/e2e/perf/OWNERS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								test/e2e/perf/OWNERS
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| approvers: | ||||
| - gmarek | ||||
| - wojtek-t | ||||
| reviewers: | ||||
| - gmarek | ||||
| - wojtek-t | ||||
| - timothysc | ||||
| @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| */ | ||||
| 
 | ||||
| package e2e | ||||
| package perf | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| */ | ||||
| 
 | ||||
| package e2e | ||||
| package perf | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| @@ -344,13 +344,13 @@ func generateConfigs( | ||||
| 	secretConfigs := make([]*testutils.SecretConfig, 0) | ||||
| 
 | ||||
| 	smallGroupCount, mediumGroupCount, bigGroupCount := computePodCounts(totalPods) | ||||
| 	newConfigs, newSecretConfigs := generateConfigsForGroup(nss, smallGroupName, smallGroupSize, smallGroupCount, image, command, kind, secretsPerPod) | ||||
| 	newConfigs, newSecretConfigs := GenerateConfigsForGroup(nss, smallGroupName, smallGroupSize, smallGroupCount, image, command, kind, secretsPerPod) | ||||
| 	configs = append(configs, newConfigs...) | ||||
| 	secretConfigs = append(secretConfigs, newSecretConfigs...) | ||||
| 	newConfigs, newSecretConfigs = generateConfigsForGroup(nss, mediumGroupName, mediumGroupSize, mediumGroupCount, image, command, kind, secretsPerPod) | ||||
| 	newConfigs, newSecretConfigs = GenerateConfigsForGroup(nss, mediumGroupName, mediumGroupSize, mediumGroupCount, image, command, kind, secretsPerPod) | ||||
| 	configs = append(configs, newConfigs...) | ||||
| 	secretConfigs = append(secretConfigs, newSecretConfigs...) | ||||
| 	newConfigs, newSecretConfigs = generateConfigsForGroup(nss, bigGroupName, bigGroupSize, bigGroupCount, image, command, kind, secretsPerPod) | ||||
| 	newConfigs, newSecretConfigs = GenerateConfigsForGroup(nss, bigGroupName, bigGroupSize, bigGroupCount, image, command, kind, secretsPerPod) | ||||
| 	configs = append(configs, newConfigs...) | ||||
| 	secretConfigs = append(secretConfigs, newSecretConfigs...) | ||||
| 
 | ||||
| @@ -371,7 +371,7 @@ func generateConfigs( | ||||
| 	return configs, secretConfigs | ||||
| } | ||||
| 
 | ||||
| func generateConfigsForGroup( | ||||
| func GenerateConfigsForGroup( | ||||
| 	nss []*v1.Namespace, | ||||
| 	groupName string, | ||||
| 	size, count int, | ||||
		Reference in New Issue
	
	Block a user
	 Kubernetes Submit Queue
					Kubernetes Submit Queue