mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 10:20:51 +00:00
Enable scheduler_perf to support scheduler config file
Signed-off-by: Dave Chen <dave.chen@arm.com>
This commit is contained in:
parent
23d4b3b4f0
commit
d50c0aeb5f
@ -19,10 +19,10 @@ package options
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"k8s.io/klog/v2"
|
||||
"os"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/klog/v2"
|
||||
kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||
kubeschedulerscheme "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme"
|
||||
kubeschedulerconfigv1beta1 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta1"
|
||||
|
@ -442,7 +442,7 @@ func benchmarkScheduling(numExistingPods, minPods int,
|
||||
//lint:ignore SA3001 Set a minimum for b.N to get more meaningful results
|
||||
b.N = minPods
|
||||
}
|
||||
finalFunc, podInformer, clientset, _ := mustSetupScheduler()
|
||||
finalFunc, podInformer, clientset, _ := mustSetupScheduler(nil)
|
||||
defer finalFunc()
|
||||
|
||||
nodePreparer := framework.NewIntegrationTestNodePreparer(
|
||||
|
@ -43,6 +43,9 @@ import (
|
||||
"k8s.io/component-base/featuregate"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||
"k8s.io/kubernetes/pkg/scheduler/apis/config/scheme"
|
||||
"k8s.io/kubernetes/pkg/scheduler/apis/config/validation"
|
||||
"k8s.io/kubernetes/test/integration/framework"
|
||||
testutils "k8s.io/kubernetes/test/utils"
|
||||
"sigs.k8s.io/yaml"
|
||||
@ -91,6 +94,8 @@ type testCase struct {
|
||||
WorkloadTemplate []op
|
||||
// List of workloads to run under this testCase.
|
||||
Workloads []*workload
|
||||
// SchedulerConfigFile is the path of scheduler configuration
|
||||
SchedulerConfigFile string
|
||||
// TODO(#93792): reduce config toil by having a default pod and node spec per
|
||||
// testCase? CreatePods and CreateNodes ops will inherit these unless
|
||||
// manually overridden.
|
||||
@ -372,11 +377,38 @@ func BenchmarkPerfScheduling(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func loadSchedulerConfig(file string) (*config.KubeSchedulerConfiguration, error) {
|
||||
data, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// The UniversalDecoder runs defaulting and returns the internal type by default.
|
||||
obj, gvk, err := scheme.Codecs.UniversalDecoder().Decode(data, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cfgObj, ok := obj.(*config.KubeSchedulerConfiguration); ok {
|
||||
return cfgObj, nil
|
||||
}
|
||||
return nil, fmt.Errorf("couldn't decode as KubeSchedulerConfiguration, got %s: ", gvk)
|
||||
}
|
||||
|
||||
func runWorkload(b *testing.B, tc *testCase, w *workload) []DataItem {
|
||||
// 30 minutes should be plenty enough even for the 5000-node tests.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute)
|
||||
defer cancel()
|
||||
finalFunc, podInformer, client, dynClient := mustSetupScheduler()
|
||||
var cfg *config.KubeSchedulerConfiguration
|
||||
var err error
|
||||
if len(tc.SchedulerConfigFile) != 0 {
|
||||
cfg, err = loadSchedulerConfig(tc.SchedulerConfigFile)
|
||||
if err != nil {
|
||||
b.Fatalf("error loading scheduler config file: %v", err)
|
||||
}
|
||||
if err = validation.ValidateKubeSchedulerConfiguration(cfg).ToAggregate(); err != nil {
|
||||
b.Fatalf("validate scheduler config file failed: %v", err)
|
||||
}
|
||||
}
|
||||
finalFunc, podInformer, client, dynClient := mustSetupScheduler(cfg)
|
||||
b.Cleanup(finalFunc)
|
||||
|
||||
var mu sync.Mutex
|
||||
|
@ -116,7 +116,7 @@ type testConfig struct {
|
||||
|
||||
// getBaseConfig returns baseConfig after initializing number of nodes and pods.
|
||||
func getBaseConfig(nodes int, pods int) *testConfig {
|
||||
destroyFunc, podInformer, clientset, _ := mustSetupScheduler()
|
||||
destroyFunc, podInformer, clientset, _ := mustSetupScheduler(nil)
|
||||
return &testConfig{
|
||||
clientset: clientset,
|
||||
destroyFunc: destroyFunc,
|
||||
|
@ -40,6 +40,9 @@ import (
|
||||
"k8s.io/component-base/metrics/legacyregistry"
|
||||
"k8s.io/component-base/metrics/testutil"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/kube-scheduler/config/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||
kubeschedulerscheme "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme"
|
||||
"k8s.io/kubernetes/test/integration/util"
|
||||
testutils "k8s.io/kubernetes/test/utils"
|
||||
)
|
||||
@ -53,6 +56,16 @@ const (
|
||||
|
||||
var dataItemsDir = flag.String("data-items-dir", "", "destination directory for storing generated data items for perf dashboard")
|
||||
|
||||
func newDefaultComponentConfig() (*config.KubeSchedulerConfiguration, error) {
|
||||
gvk := v1beta1.SchemeGroupVersion.WithKind("KubeSchedulerConfiguration")
|
||||
cfg := config.KubeSchedulerConfiguration{}
|
||||
_, _, err := kubeschedulerscheme.Codecs.UniversalDecoder().Decode(nil, &gvk, &cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cfg, nil
|
||||
}
|
||||
|
||||
// mustSetupScheduler starts the following components:
|
||||
// - k8s api server (a.k.a. master)
|
||||
// - scheduler
|
||||
@ -60,9 +73,12 @@ var dataItemsDir = flag.String("data-items-dir", "", "destination directory for
|
||||
// remove resources after finished.
|
||||
// Notes on rate limiter:
|
||||
// - client rate limit is set to 5000.
|
||||
func mustSetupScheduler() (util.ShutdownFunc, coreinformers.PodInformer, clientset.Interface, dynamic.Interface) {
|
||||
func mustSetupScheduler(config *config.KubeSchedulerConfiguration) (util.ShutdownFunc, coreinformers.PodInformer, clientset.Interface, dynamic.Interface) {
|
||||
apiURL, apiShutdown := util.StartApiserver()
|
||||
var err error
|
||||
|
||||
// TODO: client connection configuration, such as QPS or Burst is configurable in theory, this could be derived from the `config`, need to
|
||||
// support this when there is any testcase that depends on such configuration.
|
||||
cfg := &restclient.Config{
|
||||
Host: apiURL,
|
||||
ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}},
|
||||
@ -70,10 +86,20 @@ func mustSetupScheduler() (util.ShutdownFunc, coreinformers.PodInformer, clients
|
||||
Burst: 5000,
|
||||
}
|
||||
|
||||
// use default component config if config here is nil
|
||||
if config == nil {
|
||||
config, err = newDefaultComponentConfig()
|
||||
if err != nil {
|
||||
klog.Fatalf("Error creating default component config: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
client := clientset.NewForConfigOrDie(cfg)
|
||||
dynClient := dynamic.NewForConfigOrDie(cfg)
|
||||
|
||||
_, podInformer, schedulerShutdown := util.StartScheduler(client)
|
||||
// Not all config options will be effective but only those mostly related with scheduler performance will
|
||||
// be applied to start a scheduler, most of them are defined in `scheduler.schedulerOptions`.
|
||||
_, podInformer, schedulerShutdown := util.StartScheduler(client, config)
|
||||
fakePVControllerShutdown := util.StartFakePVController(client)
|
||||
|
||||
shutdownFunc := func() {
|
||||
|
@ -42,6 +42,7 @@ import (
|
||||
"k8s.io/klog/v2"
|
||||
pvutil "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/util"
|
||||
"k8s.io/kubernetes/pkg/scheduler"
|
||||
kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||
schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||
"k8s.io/kubernetes/pkg/scheduler/apis/config/scheme"
|
||||
schedulerapiv1 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1"
|
||||
@ -74,7 +75,7 @@ func StartApiserver() (string, ShutdownFunc) {
|
||||
|
||||
// StartScheduler configures and starts a scheduler given a handle to the clientSet interface
|
||||
// and event broadcaster. It returns the running scheduler, podInformer and the shutdown function to stop it.
|
||||
func StartScheduler(clientSet clientset.Interface) (*scheduler.Scheduler, coreinformers.PodInformer, ShutdownFunc) {
|
||||
func StartScheduler(clientSet clientset.Interface, cfg *kubeschedulerconfig.KubeSchedulerConfiguration) (*scheduler.Scheduler, coreinformers.PodInformer, ShutdownFunc) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
informerFactory := scheduler.NewInformerFactory(clientSet, 0)
|
||||
@ -87,7 +88,14 @@ func StartScheduler(clientSet clientset.Interface) (*scheduler.Scheduler, corein
|
||||
clientSet,
|
||||
informerFactory,
|
||||
profile.NewRecorderFactory(evtBroadcaster),
|
||||
ctx.Done())
|
||||
ctx.Done(),
|
||||
scheduler.WithProfiles(cfg.Profiles...),
|
||||
scheduler.WithAlgorithmSource(cfg.AlgorithmSource),
|
||||
scheduler.WithPercentageOfNodesToScore(cfg.PercentageOfNodesToScore),
|
||||
scheduler.WithPodMaxBackoffSeconds(cfg.PodMaxBackoffSeconds),
|
||||
scheduler.WithPodInitialBackoffSeconds(cfg.PodInitialBackoffSeconds),
|
||||
scheduler.WithExtenders(cfg.Extenders...),
|
||||
scheduler.WithParallelism(cfg.Parallelism))
|
||||
if err != nil {
|
||||
klog.Fatalf("Error creating scheduler: %v", err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user