k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/scheduler/apis/config/v1/defaults.go (about)

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package v1
    18  
    19  import (
    20  	v1 "k8s.io/api/core/v1"
    21  	"k8s.io/apimachinery/pkg/runtime"
    22  	"k8s.io/apimachinery/pkg/util/sets"
    23  	"k8s.io/apiserver/pkg/util/feature"
    24  	componentbaseconfigv1alpha1 "k8s.io/component-base/config/v1alpha1"
    25  	"k8s.io/klog/v2"
    26  	configv1 "k8s.io/kube-scheduler/config/v1"
    27  	"k8s.io/kubernetes/pkg/features"
    28  	"k8s.io/kubernetes/pkg/scheduler/apis/config"
    29  	"k8s.io/utils/ptr"
    30  )
    31  
    32  var defaultResourceSpec = []configv1.ResourceSpec{
    33  	{Name: string(v1.ResourceCPU), Weight: 1},
    34  	{Name: string(v1.ResourceMemory), Weight: 1},
    35  }
    36  
    37  func addDefaultingFuncs(scheme *runtime.Scheme) error {
    38  	return RegisterDefaults(scheme)
    39  }
    40  
    41  func pluginsNames(p *configv1.Plugins) []string {
    42  	if p == nil {
    43  		return nil
    44  	}
    45  	extensions := []configv1.PluginSet{
    46  		p.MultiPoint,
    47  		p.PreFilter,
    48  		p.Filter,
    49  		p.PostFilter,
    50  		p.Reserve,
    51  		p.PreScore,
    52  		p.Score,
    53  		p.PreBind,
    54  		p.Bind,
    55  		p.PostBind,
    56  		p.Permit,
    57  		p.PreEnqueue,
    58  		p.QueueSort,
    59  	}
    60  	n := sets.New[string]()
    61  	for _, e := range extensions {
    62  		for _, pg := range e.Enabled {
    63  			n.Insert(pg.Name)
    64  		}
    65  	}
    66  	return sets.List(n)
    67  }
    68  
    69  func setDefaults_KubeSchedulerProfile(logger klog.Logger, prof *configv1.KubeSchedulerProfile) {
    70  	// Set default plugins.
    71  	prof.Plugins = mergePlugins(logger, getDefaultPlugins(), prof.Plugins)
    72  	// Set default plugin configs.
    73  	scheme := GetPluginArgConversionScheme()
    74  	existingConfigs := sets.New[string]()
    75  	for j := range prof.PluginConfig {
    76  		existingConfigs.Insert(prof.PluginConfig[j].Name)
    77  		args := prof.PluginConfig[j].Args.Object
    78  		if _, isUnknown := args.(*runtime.Unknown); isUnknown {
    79  			continue
    80  		}
    81  		scheme.Default(args)
    82  	}
    83  
    84  	// Append default configs for plugins that didn't have one explicitly set.
    85  	for _, name := range pluginsNames(prof.Plugins) {
    86  		if existingConfigs.Has(name) {
    87  			continue
    88  		}
    89  		gvk := configv1.SchemeGroupVersion.WithKind(name + "Args")
    90  		args, err := scheme.New(gvk)
    91  		if err != nil {
    92  			// This plugin is out-of-tree or doesn't require configuration.
    93  			continue
    94  		}
    95  		scheme.Default(args)
    96  		args.GetObjectKind().SetGroupVersionKind(gvk)
    97  		prof.PluginConfig = append(prof.PluginConfig, configv1.PluginConfig{
    98  			Name: name,
    99  			Args: runtime.RawExtension{Object: args},
   100  		})
   101  	}
   102  }
   103  
   104  // SetDefaults_KubeSchedulerConfiguration sets additional defaults
   105  func SetDefaults_KubeSchedulerConfiguration(obj *configv1.KubeSchedulerConfiguration) {
   106  	logger := klog.TODO() // called by generated code that doesn't pass a logger. See #115724
   107  	if obj.Parallelism == nil {
   108  		obj.Parallelism = ptr.To[int32](16)
   109  	}
   110  
   111  	if len(obj.Profiles) == 0 {
   112  		obj.Profiles = append(obj.Profiles, configv1.KubeSchedulerProfile{})
   113  	}
   114  	// Only apply a default scheduler name when there is a single profile.
   115  	// Validation will ensure that every profile has a non-empty unique name.
   116  	if len(obj.Profiles) == 1 && obj.Profiles[0].SchedulerName == nil {
   117  		obj.Profiles[0].SchedulerName = ptr.To(v1.DefaultSchedulerName)
   118  	}
   119  
   120  	// Add the default set of plugins and apply the configuration.
   121  	for i := range obj.Profiles {
   122  		prof := &obj.Profiles[i]
   123  		setDefaults_KubeSchedulerProfile(logger, prof)
   124  	}
   125  
   126  	if obj.PercentageOfNodesToScore == nil {
   127  		obj.PercentageOfNodesToScore = ptr.To[int32](config.DefaultPercentageOfNodesToScore)
   128  	}
   129  
   130  	if len(obj.LeaderElection.ResourceLock) == 0 {
   131  		// Use lease-based leader election to reduce cost.
   132  		// We migrated for EndpointsLease lock in 1.17 and starting in 1.20 we
   133  		// migrated to Lease lock.
   134  		obj.LeaderElection.ResourceLock = "leases"
   135  	}
   136  	if len(obj.LeaderElection.ResourceNamespace) == 0 {
   137  		obj.LeaderElection.ResourceNamespace = configv1.SchedulerDefaultLockObjectNamespace
   138  	}
   139  	if len(obj.LeaderElection.ResourceName) == 0 {
   140  		obj.LeaderElection.ResourceName = configv1.SchedulerDefaultLockObjectName
   141  	}
   142  
   143  	if len(obj.ClientConnection.ContentType) == 0 {
   144  		obj.ClientConnection.ContentType = "application/vnd.kubernetes.protobuf"
   145  	}
   146  	// Scheduler has an opinion about QPS/Burst, setting specific defaults for itself, instead of generic settings.
   147  	if obj.ClientConnection.QPS == 0.0 {
   148  		obj.ClientConnection.QPS = 50.0
   149  	}
   150  	if obj.ClientConnection.Burst == 0 {
   151  		obj.ClientConnection.Burst = 100
   152  	}
   153  
   154  	// Use the default LeaderElectionConfiguration options
   155  	componentbaseconfigv1alpha1.RecommendedDefaultLeaderElectionConfiguration(&obj.LeaderElection)
   156  
   157  	if obj.PodInitialBackoffSeconds == nil {
   158  		obj.PodInitialBackoffSeconds = ptr.To[int64](1)
   159  	}
   160  
   161  	if obj.PodMaxBackoffSeconds == nil {
   162  		obj.PodMaxBackoffSeconds = ptr.To[int64](10)
   163  	}
   164  
   165  	// Enable profiling by default in the scheduler
   166  	if obj.EnableProfiling == nil {
   167  		obj.EnableProfiling = ptr.To(true)
   168  	}
   169  
   170  	// Enable contention profiling by default if profiling is enabled
   171  	if *obj.EnableProfiling && obj.EnableContentionProfiling == nil {
   172  		obj.EnableContentionProfiling = ptr.To(true)
   173  	}
   174  }
   175  
   176  func SetDefaults_DefaultPreemptionArgs(obj *configv1.DefaultPreemptionArgs) {
   177  	if obj.MinCandidateNodesPercentage == nil {
   178  		obj.MinCandidateNodesPercentage = ptr.To[int32](10)
   179  	}
   180  	if obj.MinCandidateNodesAbsolute == nil {
   181  		obj.MinCandidateNodesAbsolute = ptr.To[int32](100)
   182  	}
   183  }
   184  
   185  func SetDefaults_InterPodAffinityArgs(obj *configv1.InterPodAffinityArgs) {
   186  	if obj.HardPodAffinityWeight == nil {
   187  		obj.HardPodAffinityWeight = ptr.To[int32](1)
   188  	}
   189  }
   190  
   191  func SetDefaults_VolumeBindingArgs(obj *configv1.VolumeBindingArgs) {
   192  	if obj.BindTimeoutSeconds == nil {
   193  		obj.BindTimeoutSeconds = ptr.To[int64](600)
   194  	}
   195  	if len(obj.Shape) == 0 && feature.DefaultFeatureGate.Enabled(features.VolumeCapacityPriority) {
   196  		obj.Shape = []configv1.UtilizationShapePoint{
   197  			{
   198  				Utilization: 0,
   199  				Score:       0,
   200  			},
   201  			{
   202  				Utilization: 100,
   203  				Score:       int32(config.MaxCustomPriorityScore),
   204  			},
   205  		}
   206  	}
   207  }
   208  
   209  func SetDefaults_NodeResourcesBalancedAllocationArgs(obj *configv1.NodeResourcesBalancedAllocationArgs) {
   210  	if len(obj.Resources) == 0 {
   211  		obj.Resources = defaultResourceSpec
   212  		return
   213  	}
   214  	// If the weight is not set or it is explicitly set to 0, then apply the default weight(1) instead.
   215  	for i := range obj.Resources {
   216  		if obj.Resources[i].Weight == 0 {
   217  			obj.Resources[i].Weight = 1
   218  		}
   219  	}
   220  }
   221  
   222  func SetDefaults_PodTopologySpreadArgs(obj *configv1.PodTopologySpreadArgs) {
   223  	if obj.DefaultingType == "" {
   224  		obj.DefaultingType = configv1.SystemDefaulting
   225  	}
   226  }
   227  
   228  func SetDefaults_NodeResourcesFitArgs(obj *configv1.NodeResourcesFitArgs) {
   229  	if obj.ScoringStrategy == nil {
   230  		obj.ScoringStrategy = &configv1.ScoringStrategy{
   231  			Type:      configv1.ScoringStrategyType(config.LeastAllocated),
   232  			Resources: defaultResourceSpec,
   233  		}
   234  	}
   235  	if len(obj.ScoringStrategy.Resources) == 0 {
   236  		// If no resources specified, use the default set.
   237  		obj.ScoringStrategy.Resources = append(obj.ScoringStrategy.Resources, defaultResourceSpec...)
   238  	}
   239  	for i := range obj.ScoringStrategy.Resources {
   240  		if obj.ScoringStrategy.Resources[i].Weight == 0 {
   241  			obj.ScoringStrategy.Resources[i].Weight = 1
   242  		}
   243  	}
   244  }