Skip to content
This repository has been archived by the owner on Oct 6, 2023. It is now read-only.

Commit

Permalink
Merge pull request #38 from everpeace/stress-test
Browse files Browse the repository at this point in the history
stress test in e2e
  • Loading branch information
everpeace authored Oct 16, 2021
2 parents 9513fa8 + 0d09da3 commit e6fda14
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 11 deletions.
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,14 @@ dev-run-debug: dev-scheduler-conf
#
# E2E test
#
export E2E_GOMEGA_DEFAULT_EVENTUALLY_TIMEOUT=10s
export E2E_GOMEGA_DEFAULT_EVENTUALLY_TIMEOUT=1m
export E2E_GOMEGA_DEFAULT_CONSISTENTLY_DURATION=2s
E2E_PAUSE_IMAGE=k8s.gcr.io/pause:3.2
E2E_KIND_KUBECNOFIG = $(DEV_TOOL_PREFIX)/.kubeconfig
E2E_KIND_CONF=./hack/e2e/kind.conf
e2e-setup:
$(KIND) get clusters | grep kube-throttler-e2e 2>&1 >/dev/null \
|| $(KIND) create cluster --name=kube-throttler-e2e --kubeconfig=$(E2E_KIND_KUBECNOFIG)
|| $(KIND) create cluster --name=kube-throttler-e2e --kubeconfig=$(E2E_KIND_KUBECNOFIG) --config=$(E2E_KIND_CONF)
kubectl --kubeconfig=$(E2E_KIND_KUBECNOFIG) apply -f ./deploy/crd.yaml
docker pull $(E2E_PAUSE_IMAGE)
$(KIND) load docker-image $(E2E_PAUSE_IMAGE) --name=kube-throttler-e2e
Expand Down
15 changes: 15 additions & 0 deletions hack/e2e/kind.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: ClusterConfiguration
controllerManager:
extraArgs:
node-cidr-mask-size: "23"
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
max-pods: "300"
88 changes: 88 additions & 0 deletions test/integration/clusterthrottle_stress_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Licensed to Shingo Omura under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Shingo Omura licenses this file to you 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 integration

import (
"context"
"fmt"

"github.com/everpeace/kube-throttler/pkg/apis/schedule/v1alpha1"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
)

var _ = Describe("Clusterthrottle Stress Test", func() {
ctx := context.Background()

var nClThr = 50
var nNs = 10
var nPodsInNs = 10
var totalCpuReq = fmt.Sprintf("%dm", nNs*nPodsInNs)
thrName := func(i int) string { return fmt.Sprintf("clthr-%d", i) }
nsName := func(i int) string { return fmt.Sprintf("ns-%d", i) }
podName := func(i int) string { return fmt.Sprintf("pod-%d", i) }

Context(fmt.Sprintf("%d clusterthrottle x (%d pod x %d namespace)", nClThr, nPodsInNs, nNs), func() {
nsKey, nsVal := "targetns", "true"
thrKey, thrVal := "clthr-target", "true"

clthrs := make([]*v1alpha1.ClusterThrottle, nClThr)
nss := make([]*corev1.Namespace, nNs)
pods := make([]*corev1.Pod, nNs*nPodsInNs)

AfterEach(func() {
MustDeleteAllClusterThrottlesInNs(ctx)
for _, ns := range nss {
MustDeleteAllPodsInNs(ctx, ns.Name)
MustDeleteNs(ctx, ns.Name)
}
})

BeforeEach(func() {
for i := range clthrs {
clthrs[i] = MustCreateClusterThrottle(ctx,
MakeClusterThrottle(thrName(i)).Selectors(nsKey, nsVal, thrKey, thrVal).
ThresholdPod(nNs*nPodsInNs).
ThresholdCpu(totalCpuReq).
Obj(),
)
}
for i := range nss {
nss[i] = MustCreateNamespace(ctx, MakeNamespace(nsName(i)).Label(nsKey, nsVal).Obj())
for j := 0; j < nPodsInNs; j++ {
pods[i*nPodsInNs+j] = MustCreatePod(ctx, MakePod(nss[i].Name, podName(j), "1m").Label(thrKey, thrVal).Obj())
}
}
})
It("works correctly", func() {
Eventually(AsyncAll(
WakeupBackoffPod(ctx),
AsyncPods(pods, func(p *corev1.Pod) func(g Gomega) { return PodIsScheduled(ctx, p.Namespace, p.Name) }),
AsyncClusterThrottles(clthrs, func(thr *v1alpha1.ClusterThrottle) func(g Gomega) {
return ClusterThottleHasStatus(ctx, thr.Name,
ClthrOpts.WithCalculatedThreshold(thr.Spec.Threshold),
ClthrOpts.WithUsedPod(nNs*nPodsInNs),
ClthrOpts.WithUsedCpuReq(totalCpuReq),
ClthrOpts.WithPodThrottled(true), ClthrOpts.WithCpuThrottled(true),
)
}),
)).Should(Succeed())
})
})
})
8 changes: 3 additions & 5 deletions test/integration/integration_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,11 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

"github.com/onsi/gomega/format"

. "github.com/MakeNowJust/heredoc/dot"
kthrclient "github.com/everpeace/kube-throttler/pkg/generated/clientset/versioned"
kubethrottler "github.com/everpeace/kube-throttler/pkg/scheduler_plugin"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/component-base/logs"
scheduler "k8s.io/kubernetes/cmd/kube-scheduler/app"
"k8s.io/kubernetes/cmd/kube-scheduler/app/options"

Expand Down Expand Up @@ -65,7 +62,6 @@ func init() {
}

func TestIntegration(t *testing.T) {
format.MaxLength = 0
RegisterFailHandler(Fail)
RunSpecs(t, "Integration Suite")
}
Expand Down Expand Up @@ -119,6 +115,8 @@ func mustStartKubeThrottler() {
name: %s
targetSchedulerName: %s
kubeconfig: %s
controllerThrediness: 64
numKeyMutex: 128
`,
kubeConfigPath, // clientConnection.kubeconfig
SchedulerName, // prifiles[0].scedulerName
Expand All @@ -141,5 +139,5 @@ func mustStartKubeThrottler() {
go func() {
_ = scheduler.Run(schedulerContext, cc, sched)
}()
logs.GlogSetter("4")
// logs.GlogSetter("2")
}
21 changes: 19 additions & 2 deletions test/integration/util_clusterthrottle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package integration

import (
"context"
"time"

"github.com/everpeace/kube-throttler/pkg/apis/schedule/v1alpha1"
. "github.com/onsi/gomega"
Expand Down Expand Up @@ -88,6 +87,16 @@ func (w *clusterThrottleWrapper) Selector(ns, podKey, podVal string) *clusterThr
return w
}

func (w *clusterThrottleWrapper) Selectors(nsKey, nsVal, podKey, podVal string) *clusterThrottleWrapper {
w.Spec.Selector.SelecterTerms = []v1alpha1.ClusterThrottleSelectorTerm{{
NamespaceSelector: metav1.LabelSelector{MatchLabels: map[string]string{nsKey: nsVal}},
ThrottleSelectorTerm: v1alpha1.ThrottleSelectorTerm{
PodSelector: metav1.LabelSelector{MatchLabels: map[string]string{podKey: podVal}},
},
}}
return w
}

type ClusterThrottleStatusMatcher struct {
name string
calculatedThreshold *v1alpha1.ResourceAmount
Expand Down Expand Up @@ -179,11 +188,19 @@ func MustDeleteAllClusterThrottlesInNs(ctx context.Context) {
thrs, err := kthrCli.ScheduleV1alpha1().ClusterThrottles().List(ctx, metav1.ListOptions{LabelSelector: labels.Everything().String()})
g.Expect(err).NotTo(HaveOccurred())
g.Expect(thrs.Items).Should(HaveLen(0))
}, 10*time.Second).Should(Succeed())
}).Should(Succeed())
}

func MustCreateClusterThrottle(ctx context.Context, thr *v1alpha1.ClusterThrottle) *v1alpha1.ClusterThrottle {
created, err := kthrCli.ScheduleV1alpha1().ClusterThrottles().Create(ctx, thr, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
return created
}

func AsyncClusterThrottles(thrs []*v1alpha1.ClusterThrottle, f func(*v1alpha1.ClusterThrottle) func(g Gomega)) func(g Gomega) {
return func(g Gomega) {
for _, thr := range thrs {
f(thr)(g)
}
}
}
65 changes: 65 additions & 0 deletions test/integration/util_namespace_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Licensed to Shingo Omura under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Shingo Omura licenses this file to you 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 integration

import (
"context"
"time"

. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func MustCreateNamespace(ctx context.Context, ns *corev1.Namespace) *corev1.Namespace {
var err error
created, err := k8sCli.CoreV1().Namespaces().Create(ctx, ns, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
return created
}

func MustDeleteNs(ctx context.Context, ns string) {
Expect(
k8sCli.CoreV1().Namespaces().Delete(ctx, ns, metav1.DeleteOptions{}),
).NotTo(HaveOccurred())
Eventually(func(g Gomega) {
_, err := k8sCli.CoreV1().Namespaces().Get(ctx, ns, metav1.GetOptions{})
g.Expect(err).To(HaveOccurred())
g.Expect(apierrors.IsNotFound(err)).Should(BeTrue())
}, 10*time.Second).Should(Succeed())
}

type namespaceWrapper struct {
corev1.Namespace
}

func MakeNamespace(name string) *namespaceWrapper {
return &namespaceWrapper{
Namespace: corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: name, Labels: map[string]string{}}},
}
}

func (w *namespaceWrapper) Label(key, val string) *namespaceWrapper {
w.Labels[key] = val
return w
}

func (w *namespaceWrapper) Obj() *corev1.Namespace {
return &w.Namespace
}
8 changes: 6 additions & 2 deletions test/integration/util_pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ package integration
import (
"context"
"fmt"
"time"

"github.com/everpeace/kube-throttler/pkg/apis/schedule/v1alpha1"
. "github.com/onsi/gomega"
Expand All @@ -38,6 +37,11 @@ func MakePod(namespace, name string, cpuReq string) *st.PodWrapper {
"cpu": resource.MustParse(cpuReq),
}
w.Spec.TerminationGracePeriodSeconds = pointer.Int64Ptr(0)
w.Spec.Tolerations = []corev1.Toleration{{
Key: "node-role.kubernetes.io/master",
Operator: corev1.TolerationOpExists,
Effect: corev1.TaintEffectNoSchedule,
}}
return w
}

Expand All @@ -58,7 +62,7 @@ func MustDeleteAllPodsInNs(ctx context.Context, ns string) {
pods, err := k8sCli.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{LabelSelector: labels.Everything().String()})
g.Expect(err).NotTo(HaveOccurred())
g.Expect(pods.Items).Should(HaveLen(0))
}, 10*time.Second).Should(Succeed())
}).Should(Succeed())
}

func MustPodFailedScheduling(ctx context.Context, ns, n string, throttleStatus v1alpha1.CheckThrottleStatus) func(g Gomega) {
Expand Down

0 comments on commit e6fda14

Please sign in to comment.