|
| 1 | +/* |
| 2 | +Copyright 2014 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 algorithmprovider |
| 18 | + |
| 19 | +import ( |
| 20 | + "fmt" |
| 21 | + |
| 22 | + "k8s.io/apimachinery/pkg/runtime" |
| 23 | + utilfeature "k8s.io/apiserver/pkg/util/feature" |
| 24 | + "k8s.io/klog" |
| 25 | + "k8s.io/kubernetes/pkg/features" |
| 26 | + schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config" |
| 27 | + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultpodtopologyspread" |
| 28 | + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/imagelocality" |
| 29 | + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/interpodaffinity" |
| 30 | + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeaffinity" |
| 31 | + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodename" |
| 32 | + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeports" |
| 33 | + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodepreferavoidpods" |
| 34 | + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources" |
| 35 | + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeunschedulable" |
| 36 | + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodevolumelimits" |
| 37 | + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/podtopologyspread" |
| 38 | + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/tainttoleration" |
| 39 | + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumebinding" |
| 40 | + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumerestrictions" |
| 41 | + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumezone" |
| 42 | +) |
| 43 | + |
| 44 | +// ClusterAutoscalerProvider defines the default autoscaler provider |
| 45 | +const ClusterAutoscalerProvider = "ClusterAutoscalerProvider" |
| 46 | + |
| 47 | +// Config the configuration of an algorithm provider. |
| 48 | +type Config struct { |
| 49 | + FrameworkPlugins *schedulerapi.Plugins |
| 50 | + FrameworkPluginConfig []schedulerapi.PluginConfig |
| 51 | +} |
| 52 | + |
| 53 | +// Registry is a collection of all available algorithm providers. |
| 54 | +type Registry map[string]*Config |
| 55 | + |
| 56 | +// NewRegistry returns an algorithm provider registry instance. |
| 57 | +func NewRegistry(hardPodAffinityWeight int64) Registry { |
| 58 | + defaultConfig := getDefaultConfig(hardPodAffinityWeight) |
| 59 | + applyFeatureGates(defaultConfig) |
| 60 | + |
| 61 | + caConfig := getClusterAutoscalerConfig(hardPodAffinityWeight) |
| 62 | + applyFeatureGates(caConfig) |
| 63 | + |
| 64 | + return Registry{ |
| 65 | + schedulerapi.SchedulerDefaultProviderName: defaultConfig, |
| 66 | + ClusterAutoscalerProvider: caConfig, |
| 67 | + } |
| 68 | +} |
| 69 | + |
| 70 | +func getDefaultConfig(hardPodAffinityWeight int64) *Config { |
| 71 | + return &Config{ |
| 72 | + FrameworkPlugins: &schedulerapi.Plugins{ |
| 73 | + PreFilter: &schedulerapi.PluginSet{ |
| 74 | + Enabled: []schedulerapi.Plugin{ |
| 75 | + {Name: noderesources.FitName}, |
| 76 | + {Name: nodeports.Name}, |
| 77 | + {Name: interpodaffinity.Name}, |
| 78 | + }, |
| 79 | + }, |
| 80 | + Filter: &schedulerapi.PluginSet{ |
| 81 | + Enabled: []schedulerapi.Plugin{ |
| 82 | + {Name: nodeunschedulable.Name}, |
| 83 | + {Name: noderesources.FitName}, |
| 84 | + {Name: nodename.Name}, |
| 85 | + {Name: nodeports.Name}, |
| 86 | + {Name: nodeaffinity.Name}, |
| 87 | + {Name: volumerestrictions.Name}, |
| 88 | + {Name: tainttoleration.Name}, |
| 89 | + {Name: nodevolumelimits.EBSName}, |
| 90 | + {Name: nodevolumelimits.GCEPDName}, |
| 91 | + {Name: nodevolumelimits.CSIName}, |
| 92 | + {Name: nodevolumelimits.AzureDiskName}, |
| 93 | + {Name: volumebinding.Name}, |
| 94 | + {Name: volumezone.Name}, |
| 95 | + {Name: interpodaffinity.Name}, |
| 96 | + }, |
| 97 | + }, |
| 98 | + PostFilter: &schedulerapi.PluginSet{ |
| 99 | + Enabled: []schedulerapi.Plugin{ |
| 100 | + {Name: interpodaffinity.Name}, |
| 101 | + {Name: tainttoleration.Name}, |
| 102 | + }, |
| 103 | + }, |
| 104 | + Score: &schedulerapi.PluginSet{ |
| 105 | + Enabled: []schedulerapi.Plugin{ |
| 106 | + {Name: noderesources.BalancedAllocationName, Weight: 1}, |
| 107 | + {Name: imagelocality.Name, Weight: 1}, |
| 108 | + {Name: interpodaffinity.Name, Weight: 1}, |
| 109 | + {Name: noderesources.LeastAllocatedName, Weight: 1}, |
| 110 | + {Name: nodeaffinity.Name, Weight: 1}, |
| 111 | + {Name: nodepreferavoidpods.Name, Weight: 10000}, |
| 112 | + {Name: defaultpodtopologyspread.Name, Weight: 1}, |
| 113 | + {Name: tainttoleration.Name, Weight: 1}, |
| 114 | + }, |
| 115 | + }, |
| 116 | + }, |
| 117 | + FrameworkPluginConfig: []schedulerapi.PluginConfig{ |
| 118 | + { |
| 119 | + Name: interpodaffinity.Name, |
| 120 | + Args: runtime.Unknown{Raw: []byte(fmt.Sprintf(`{"hardPodAffinityWeight":%d}`, hardPodAffinityWeight))}, |
| 121 | + }, |
| 122 | + }, |
| 123 | + } |
| 124 | +} |
| 125 | + |
| 126 | +func getClusterAutoscalerConfig(hardPodAffinityWeight int64) *Config { |
| 127 | + defaultConfig := getDefaultConfig(hardPodAffinityWeight) |
| 128 | + caConfig := Config{ |
| 129 | + FrameworkPlugins: &schedulerapi.Plugins{}, |
| 130 | + } |
| 131 | + defaultConfig.FrameworkPlugins.DeepCopyInto(caConfig.FrameworkPlugins) |
| 132 | + caConfig.FrameworkPluginConfig = append([]schedulerapi.PluginConfig(nil), defaultConfig.FrameworkPluginConfig...) |
| 133 | + |
| 134 | + // Replace least with most requested. |
| 135 | + for i := range caConfig.FrameworkPlugins.Score.Enabled { |
| 136 | + if caConfig.FrameworkPlugins.Score.Enabled[i].Name == noderesources.LeastAllocatedName { |
| 137 | + caConfig.FrameworkPlugins.Score.Enabled[i].Name = noderesources.MostAllocatedName |
| 138 | + } |
| 139 | + } |
| 140 | + |
| 141 | + return &caConfig |
| 142 | +} |
| 143 | + |
| 144 | +func applyFeatureGates(config *Config) { |
| 145 | + // Only add EvenPodsSpread if the feature is enabled. |
| 146 | + if utilfeature.DefaultFeatureGate.Enabled(features.EvenPodsSpread) { |
| 147 | + klog.Infof("Registering EvenPodsSpread predicate and priority function") |
| 148 | + f := schedulerapi.Plugin{Name: podtopologyspread.Name} |
| 149 | + config.FrameworkPlugins.PreFilter.Enabled = append(config.FrameworkPlugins.PreFilter.Enabled, f) |
| 150 | + config.FrameworkPlugins.Filter.Enabled = append(config.FrameworkPlugins.Filter.Enabled, f) |
| 151 | + s := schedulerapi.Plugin{Name: podtopologyspread.Name, Weight: 1} |
| 152 | + config.FrameworkPlugins.Score.Enabled = append(config.FrameworkPlugins.Score.Enabled, s) |
| 153 | + } |
| 154 | + |
| 155 | + // Prioritizes nodes that satisfy pod's resource limits |
| 156 | + if utilfeature.DefaultFeatureGate.Enabled(features.ResourceLimitsPriorityFunction) { |
| 157 | + klog.Infof("Registering resourcelimits priority function") |
| 158 | + // TODO(ahg-g): append to config.FrameworkPlugins.Score.Enabled when available. |
| 159 | + } |
| 160 | +} |
0 commit comments