mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-02 08:17:26 +00:00
Merge pull request #96426 from damemi/print-scheduler-config
Log defaulted kube-scheduler component config at startup
This commit is contained in:
commit
ae95984e88
@ -19,6 +19,7 @@ package options
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
@ -48,8 +49,13 @@ func loadConfig(data []byte) (*kubeschedulerconfig.KubeSchedulerConfiguration, e
|
|||||||
return nil, fmt.Errorf("couldn't decode as KubeSchedulerConfiguration, got %s: ", gvk)
|
return nil, fmt.Errorf("couldn't decode as KubeSchedulerConfiguration, got %s: ", gvk)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteConfigFile writes the config into the given file name as YAML.
|
// LogOrWriteConfig logs the completed component config and writes it into the given file name as YAML, if either is enabled
|
||||||
func WriteConfigFile(fileName string, cfg *kubeschedulerconfig.KubeSchedulerConfiguration) error {
|
func LogOrWriteConfig(fileName string, cfg *kubeschedulerconfig.KubeSchedulerConfiguration, completedProfiles []kubeschedulerconfig.KubeSchedulerProfile) error {
|
||||||
|
if !(klog.V(2).Enabled() || len(fileName) > 0) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
cfg.Profiles = completedProfiles
|
||||||
|
|
||||||
const mediaType = runtime.ContentTypeYAML
|
const mediaType = runtime.ContentTypeYAML
|
||||||
info, ok := runtime.SerializerInfoForMediaType(kubeschedulerscheme.Codecs.SupportedMediaTypes(), mediaType)
|
info, ok := runtime.SerializerInfoForMediaType(kubeschedulerscheme.Codecs.SupportedMediaTypes(), mediaType)
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -57,15 +63,26 @@ func WriteConfigFile(fileName string, cfg *kubeschedulerconfig.KubeSchedulerConf
|
|||||||
}
|
}
|
||||||
|
|
||||||
encoder := kubeschedulerscheme.Codecs.EncoderForVersion(info.Serializer, kubeschedulerconfigv1beta1.SchemeGroupVersion)
|
encoder := kubeschedulerscheme.Codecs.EncoderForVersion(info.Serializer, kubeschedulerconfigv1beta1.SchemeGroupVersion)
|
||||||
|
if klog.V(2).Enabled() {
|
||||||
configFile, err := os.Create(fileName)
|
bytes, err := runtime.Encode(encoder, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer configFile.Close()
|
configString := string(bytes)
|
||||||
if err := encoder.Encode(cfg, configFile); err != nil {
|
klog.Infof("Using component config:\n%+v\n", configString)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(fileName) > 0 {
|
||||||
|
configFile, err := os.Create(fileName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer configFile.Close()
|
||||||
|
if err := encoder.Encode(cfg, configFile); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
klog.Infof("Wrote configuration to: %s\n", fileName)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -128,14 +128,6 @@ func runCommand(cmd *cobra.Command, opts *options.Options, registryOptions ...Op
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(opts.WriteConfigTo) > 0 {
|
|
||||||
if err := options.WriteConfigFile(opts.WriteConfigTo, &cc.ComponentConfig); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
klog.Infof("Wrote configuration to: %s\n", opts.WriteConfigTo)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return Run(ctx, cc, sched)
|
return Run(ctx, cc, sched)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,6 +302,7 @@ func Setup(ctx context.Context, opts *options.Options, outOfTreeRegistryOptions
|
|||||||
}
|
}
|
||||||
|
|
||||||
recorderFactory := getRecorderFactory(&cc)
|
recorderFactory := getRecorderFactory(&cc)
|
||||||
|
completedProfiles := make([]kubeschedulerconfig.KubeSchedulerProfile, 0)
|
||||||
// Create the scheduler.
|
// Create the scheduler.
|
||||||
sched, err := scheduler.New(cc.Client,
|
sched, err := scheduler.New(cc.Client,
|
||||||
cc.InformerFactory,
|
cc.InformerFactory,
|
||||||
@ -323,10 +316,17 @@ func Setup(ctx context.Context, opts *options.Options, outOfTreeRegistryOptions
|
|||||||
scheduler.WithPodInitialBackoffSeconds(cc.ComponentConfig.PodInitialBackoffSeconds),
|
scheduler.WithPodInitialBackoffSeconds(cc.ComponentConfig.PodInitialBackoffSeconds),
|
||||||
scheduler.WithExtenders(cc.ComponentConfig.Extenders...),
|
scheduler.WithExtenders(cc.ComponentConfig.Extenders...),
|
||||||
scheduler.WithParallelism(cc.ComponentConfig.Parallelism),
|
scheduler.WithParallelism(cc.ComponentConfig.Parallelism),
|
||||||
|
scheduler.WithBuildFrameworkCapturer(func(profile kubeschedulerconfig.KubeSchedulerProfile) {
|
||||||
|
// Profiles are processed during Framework instantiation to set default plugins and configurations. Capturing them for logging
|
||||||
|
completedProfiles = append(completedProfiles, profile)
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
if err := options.LogOrWriteConfig(opts.WriteConfigTo, &cc.ComponentConfig, completedProfiles); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &cc, sched, nil
|
return &cc, sched, nil
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,9 @@ go_test(
|
|||||||
"//pkg/scheduler/framework:go_default_library",
|
"//pkg/scheduler/framework:go_default_library",
|
||||||
"//pkg/scheduler/framework/plugins:go_default_library",
|
"//pkg/scheduler/framework/plugins:go_default_library",
|
||||||
"//pkg/scheduler/framework/plugins/defaultbinder:go_default_library",
|
"//pkg/scheduler/framework/plugins/defaultbinder:go_default_library",
|
||||||
|
"//pkg/scheduler/framework/plugins/defaultpreemption:go_default_library",
|
||||||
"//pkg/scheduler/framework/plugins/interpodaffinity:go_default_library",
|
"//pkg/scheduler/framework/plugins/interpodaffinity:go_default_library",
|
||||||
|
"//pkg/scheduler/framework/plugins/nodeaffinity:go_default_library",
|
||||||
"//pkg/scheduler/framework/plugins/nodelabel:go_default_library",
|
"//pkg/scheduler/framework/plugins/nodelabel:go_default_library",
|
||||||
"//pkg/scheduler/framework/plugins/nodeports:go_default_library",
|
"//pkg/scheduler/framework/plugins/nodeports:go_default_library",
|
||||||
"//pkg/scheduler/framework/plugins/noderesources:go_default_library",
|
"//pkg/scheduler/framework/plugins/noderesources:go_default_library",
|
||||||
|
@ -1593,6 +1593,48 @@ func TestPluginsConfigurationCompatibility(t *testing.T) {
|
|||||||
"PreBindPlugin": {{Name: "VolumeBinding"}},
|
"PreBindPlugin": {{Name: "VolumeBinding"}},
|
||||||
"BindPlugin": {{Name: "DefaultBinder"}},
|
"BindPlugin": {{Name: "DefaultBinder"}},
|
||||||
}
|
}
|
||||||
|
defaultPluginConfigs := []config.PluginConfig{
|
||||||
|
{
|
||||||
|
Name: "DefaultPreemption",
|
||||||
|
Args: &config.DefaultPreemptionArgs{
|
||||||
|
MinCandidateNodesPercentage: 10,
|
||||||
|
MinCandidateNodesAbsolute: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "InterPodAffinity",
|
||||||
|
Args: &config.InterPodAffinityArgs{
|
||||||
|
HardPodAffinityWeight: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "NodeAffinity",
|
||||||
|
Args: &config.NodeAffinityArgs{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "NodeResourcesFit",
|
||||||
|
Args: &config.NodeResourcesFitArgs{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "NodeResourcesLeastAllocated",
|
||||||
|
Args: &config.NodeResourcesLeastAllocatedArgs{
|
||||||
|
Resources: []config.ResourceSpec{
|
||||||
|
{Name: "cpu", Weight: 1},
|
||||||
|
{Name: "memory", Weight: 1},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "PodTopologySpread",
|
||||||
|
Args: &config.PodTopologySpreadArgs{DefaultingType: config.SystemDefaulting},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "VolumeBinding",
|
||||||
|
Args: &config.VolumeBindingArgs{
|
||||||
|
BindTimeoutSeconds: 600,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
testcases := []struct {
|
testcases := []struct {
|
||||||
name string
|
name string
|
||||||
@ -1604,11 +1646,76 @@ func TestPluginsConfigurationCompatibility(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "default plugins",
|
name: "default plugins",
|
||||||
wantPlugins: defaultPlugins,
|
wantPlugins: defaultPlugins,
|
||||||
wantPluginConfig: nil,
|
wantPluginConfig: defaultPluginConfigs,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "default plugins with customized plugin config",
|
name: "in-tree plugins with customized plugin config",
|
||||||
wantPlugins: defaultPlugins,
|
plugins: config.Plugins{
|
||||||
|
Filter: &config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: "NodeLabel"},
|
||||||
|
{Name: "ServiceAffinity"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Score: &config.PluginSet{
|
||||||
|
Enabled: []config.Plugin{
|
||||||
|
{Name: "RequestedToCapacityRatio"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantPlugins: map[string][]config.Plugin{
|
||||||
|
"QueueSortPlugin": {
|
||||||
|
{Name: "PrioritySort"},
|
||||||
|
},
|
||||||
|
"PreFilterPlugin": {
|
||||||
|
{Name: "NodeResourcesFit"},
|
||||||
|
{Name: "NodePorts"},
|
||||||
|
{Name: "PodTopologySpread"},
|
||||||
|
{Name: "InterPodAffinity"},
|
||||||
|
{Name: "VolumeBinding"},
|
||||||
|
},
|
||||||
|
"FilterPlugin": {
|
||||||
|
{Name: "NodeUnschedulable"},
|
||||||
|
{Name: "NodeName"},
|
||||||
|
{Name: "TaintToleration"},
|
||||||
|
{Name: "NodeAffinity"},
|
||||||
|
{Name: "NodePorts"},
|
||||||
|
{Name: "NodeResourcesFit"},
|
||||||
|
{Name: "VolumeRestrictions"},
|
||||||
|
{Name: "EBSLimits"},
|
||||||
|
{Name: "GCEPDLimits"},
|
||||||
|
{Name: "NodeVolumeLimits"},
|
||||||
|
{Name: "AzureDiskLimits"},
|
||||||
|
{Name: "VolumeBinding"},
|
||||||
|
{Name: "VolumeZone"},
|
||||||
|
{Name: "PodTopologySpread"},
|
||||||
|
{Name: "InterPodAffinity"},
|
||||||
|
{Name: "NodeLabel"},
|
||||||
|
{Name: "ServiceAffinity"},
|
||||||
|
},
|
||||||
|
"PostFilterPlugin": {
|
||||||
|
{Name: "DefaultPreemption"},
|
||||||
|
},
|
||||||
|
"PreScorePlugin": {
|
||||||
|
{Name: "InterPodAffinity"},
|
||||||
|
{Name: "PodTopologySpread"},
|
||||||
|
{Name: "TaintToleration"},
|
||||||
|
},
|
||||||
|
"ScorePlugin": {
|
||||||
|
{Name: "NodeResourcesBalancedAllocation", Weight: 1},
|
||||||
|
{Name: "ImageLocality", Weight: 1},
|
||||||
|
{Name: "InterPodAffinity", Weight: 1},
|
||||||
|
{Name: "NodeResourcesLeastAllocated", Weight: 1},
|
||||||
|
{Name: "NodeAffinity", Weight: 1},
|
||||||
|
{Name: "NodePreferAvoidPods", Weight: 10000},
|
||||||
|
{Name: "PodTopologySpread", Weight: 2},
|
||||||
|
{Name: "TaintToleration", Weight: 1},
|
||||||
|
{Name: "RequestedToCapacityRatio", Weight: 1},
|
||||||
|
},
|
||||||
|
"ReservePlugin": {{Name: "VolumeBinding"}},
|
||||||
|
"PreBindPlugin": {{Name: "VolumeBinding"}},
|
||||||
|
"BindPlugin": {{Name: "DefaultBinder"}},
|
||||||
|
},
|
||||||
pluginConfig: []config.PluginConfig{
|
pluginConfig: []config.PluginConfig{
|
||||||
{
|
{
|
||||||
Name: "NodeResourcesFit",
|
Name: "NodeResourcesFit",
|
||||||
@ -1675,12 +1782,47 @@ func TestPluginsConfigurationCompatibility(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantPluginConfig: []config.PluginConfig{
|
wantPluginConfig: []config.PluginConfig{
|
||||||
|
{
|
||||||
|
Name: "DefaultPreemption",
|
||||||
|
Args: &config.DefaultPreemptionArgs{
|
||||||
|
MinCandidateNodesPercentage: 10,
|
||||||
|
MinCandidateNodesAbsolute: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "InterPodAffinity",
|
||||||
|
Args: &config.InterPodAffinityArgs{
|
||||||
|
HardPodAffinityWeight: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "NodeAffinity",
|
||||||
|
Args: &config.NodeAffinityArgs{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "NodeLabel",
|
||||||
|
Args: &config.NodeLabelArgs{
|
||||||
|
PresentLabels: []string{"foo", "bar"},
|
||||||
|
AbsentLabels: []string{"apple"},
|
||||||
|
PresentLabelsPreference: []string{"dog"},
|
||||||
|
AbsentLabelsPreference: []string{"cat"},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "NodeResourcesFit",
|
Name: "NodeResourcesFit",
|
||||||
Args: &config.NodeResourcesFitArgs{
|
Args: &config.NodeResourcesFitArgs{
|
||||||
IgnoredResources: []string{"foo", "bar"},
|
IgnoredResources: []string{"foo", "bar"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "NodeResourcesLeastAllocated",
|
||||||
|
Args: &config.NodeResourcesLeastAllocatedArgs{
|
||||||
|
Resources: []config.ResourceSpec{
|
||||||
|
{Name: "cpu", Weight: 1},
|
||||||
|
{Name: "memory", Weight: 1},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "PodTopologySpread",
|
Name: "PodTopologySpread",
|
||||||
Args: &config.PodTopologySpreadArgs{
|
Args: &config.PodTopologySpreadArgs{
|
||||||
@ -1710,21 +1852,6 @@ func TestPluginsConfigurationCompatibility(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: "InterPodAffinity",
|
|
||||||
Args: &config.InterPodAffinityArgs{
|
|
||||||
HardPodAffinityWeight: 100,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "NodeLabel",
|
|
||||||
Args: &config.NodeLabelArgs{
|
|
||||||
PresentLabels: []string{"foo", "bar"},
|
|
||||||
AbsentLabels: []string{"apple"},
|
|
||||||
PresentLabelsPreference: []string{"dog"},
|
|
||||||
AbsentLabelsPreference: []string{"cat"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Name: "ServiceAffinity",
|
Name: "ServiceAffinity",
|
||||||
Args: &config.ServiceAffinityArgs{
|
Args: &config.ServiceAffinityArgs{
|
||||||
@ -1864,6 +1991,7 @@ func TestPluginsConfigurationCompatibility(t *testing.T) {
|
|||||||
},
|
},
|
||||||
PreScore: &config.PluginSet{
|
PreScore: &config.PluginSet{
|
||||||
Enabled: []config.Plugin{
|
Enabled: []config.Plugin{
|
||||||
|
{Name: "PodTopologySpread"},
|
||||||
{Name: "TaintToleration"},
|
{Name: "TaintToleration"},
|
||||||
{Name: "SelectorSpread"},
|
{Name: "SelectorSpread"},
|
||||||
{Name: "InterPodAffinity"},
|
{Name: "InterPodAffinity"},
|
||||||
@ -1874,6 +2002,7 @@ func TestPluginsConfigurationCompatibility(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Score: &config.PluginSet{
|
Score: &config.PluginSet{
|
||||||
Enabled: []config.Plugin{
|
Enabled: []config.Plugin{
|
||||||
|
{Name: "PodTopologySpread", Weight: 24},
|
||||||
{Name: "TaintToleration", Weight: 24},
|
{Name: "TaintToleration", Weight: 24},
|
||||||
{Name: "SelectorSpread", Weight: 24},
|
{Name: "SelectorSpread", Weight: 24},
|
||||||
{Name: "NodePreferAvoidPods", Weight: 24},
|
{Name: "NodePreferAvoidPods", Weight: 24},
|
||||||
@ -1921,11 +2050,13 @@ func TestPluginsConfigurationCompatibility(t *testing.T) {
|
|||||||
{Name: "DefaultPreemption"},
|
{Name: "DefaultPreemption"},
|
||||||
},
|
},
|
||||||
"PreScorePlugin": {
|
"PreScorePlugin": {
|
||||||
|
{Name: "PodTopologySpread"},
|
||||||
{Name: "TaintToleration"},
|
{Name: "TaintToleration"},
|
||||||
{Name: "SelectorSpread"},
|
{Name: "SelectorSpread"},
|
||||||
{Name: "InterPodAffinity"},
|
{Name: "InterPodAffinity"},
|
||||||
},
|
},
|
||||||
"ScorePlugin": {
|
"ScorePlugin": {
|
||||||
|
{Name: "PodTopologySpread", Weight: 24},
|
||||||
{Name: "TaintToleration", Weight: 24},
|
{Name: "TaintToleration", Weight: 24},
|
||||||
{Name: "SelectorSpread", Weight: 24},
|
{Name: "SelectorSpread", Weight: 24},
|
||||||
{Name: "NodePreferAvoidPods", Weight: 24},
|
{Name: "NodePreferAvoidPods", Weight: 24},
|
||||||
@ -1939,7 +2070,7 @@ func TestPluginsConfigurationCompatibility(t *testing.T) {
|
|||||||
"PreBindPlugin": {{Name: "VolumeBinding"}},
|
"PreBindPlugin": {{Name: "VolumeBinding"}},
|
||||||
"BindPlugin": {{Name: "DefaultBinder"}},
|
"BindPlugin": {{Name: "DefaultBinder"}},
|
||||||
},
|
},
|
||||||
wantPluginConfig: nil,
|
wantPluginConfig: defaultPluginConfigs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
|
@ -138,12 +138,8 @@ func (c *Configurator) create() (*Scheduler, error) {
|
|||||||
frameworkruntime.WithSnapshotSharedLister(c.nodeInfoSnapshot),
|
frameworkruntime.WithSnapshotSharedLister(c.nodeInfoSnapshot),
|
||||||
frameworkruntime.WithRunAllFilters(c.alwaysCheckAllPredicates),
|
frameworkruntime.WithRunAllFilters(c.alwaysCheckAllPredicates),
|
||||||
frameworkruntime.WithPodNominator(nominator),
|
frameworkruntime.WithPodNominator(nominator),
|
||||||
|
frameworkruntime.WithCaptureProfile(frameworkruntime.CaptureProfile(c.frameworkCapturer)),
|
||||||
)
|
)
|
||||||
for _, p := range c.profiles {
|
|
||||||
if c.frameworkCapturer != nil {
|
|
||||||
c.frameworkCapturer(p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("initializing profiles: %v", err)
|
return nil, fmt.Errorf("initializing profiles: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -38,11 +38,14 @@ import (
|
|||||||
schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config"
|
schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework"
|
"k8s.io/kubernetes/pkg/scheduler/framework"
|
||||||
frameworkplugins "k8s.io/kubernetes/pkg/scheduler/framework/plugins"
|
frameworkplugins "k8s.io/kubernetes/pkg/scheduler/framework/plugins"
|
||||||
|
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultpreemption"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/interpodaffinity"
|
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/interpodaffinity"
|
||||||
|
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeaffinity"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodelabel"
|
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodelabel"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources"
|
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/podtopologyspread"
|
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/podtopologyspread"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/serviceaffinity"
|
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/serviceaffinity"
|
||||||
|
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumebinding"
|
||||||
frameworkruntime "k8s.io/kubernetes/pkg/scheduler/framework/runtime"
|
frameworkruntime "k8s.io/kubernetes/pkg/scheduler/framework/runtime"
|
||||||
internalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache"
|
internalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache"
|
||||||
internalqueue "k8s.io/kubernetes/pkg/scheduler/internal/queue"
|
internalqueue "k8s.io/kubernetes/pkg/scheduler/internal/queue"
|
||||||
@ -105,10 +108,46 @@ func TestCreateFromConfig(t *testing.T) {
|
|||||||
"apiVersion" : "v1"
|
"apiVersion" : "v1"
|
||||||
}`),
|
}`),
|
||||||
wantPluginConfig: []schedulerapi.PluginConfig{
|
wantPluginConfig: []schedulerapi.PluginConfig{
|
||||||
|
{
|
||||||
|
Name: defaultpreemption.Name,
|
||||||
|
Args: &schedulerapi.DefaultPreemptionArgs{
|
||||||
|
MinCandidateNodesPercentage: 10,
|
||||||
|
MinCandidateNodesAbsolute: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: interpodaffinity.Name,
|
||||||
|
Args: &schedulerapi.InterPodAffinityArgs{
|
||||||
|
HardPodAffinityWeight: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: nodeaffinity.Name,
|
||||||
|
Args: &schedulerapi.NodeAffinityArgs{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: noderesources.FitName,
|
||||||
|
Args: &schedulerapi.NodeResourcesFitArgs{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: noderesources.LeastAllocatedName,
|
||||||
|
Args: &schedulerapi.NodeResourcesLeastAllocatedArgs{
|
||||||
|
Resources: []schedulerapi.ResourceSpec{
|
||||||
|
{Name: "cpu", Weight: 1},
|
||||||
|
{Name: "memory", Weight: 1},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: podtopologyspread.Name,
|
Name: podtopologyspread.Name,
|
||||||
Args: &schedulerapi.PodTopologySpreadArgs{DefaultingType: schedulerapi.SystemDefaulting},
|
Args: &schedulerapi.PodTopologySpreadArgs{DefaultingType: schedulerapi.SystemDefaulting},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: volumebinding.Name,
|
||||||
|
Args: &schedulerapi.VolumeBindingArgs{
|
||||||
|
BindTimeoutSeconds: 600,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
wantPlugins: &schedulerapi.Plugins{
|
wantPlugins: &schedulerapi.Plugins{
|
||||||
QueueSort: &schedulerapi.PluginSet{Enabled: []schedulerapi.Plugin{{Name: "PrioritySort"}}},
|
QueueSort: &schedulerapi.PluginSet{Enabled: []schedulerapi.Plugin{{Name: "PrioritySort"}}},
|
||||||
@ -200,6 +239,23 @@ func TestCreateFromConfig(t *testing.T) {
|
|||||||
]
|
]
|
||||||
}`),
|
}`),
|
||||||
wantPluginConfig: []schedulerapi.PluginConfig{
|
wantPluginConfig: []schedulerapi.PluginConfig{
|
||||||
|
{
|
||||||
|
Name: defaultpreemption.Name,
|
||||||
|
Args: &schedulerapi.DefaultPreemptionArgs{
|
||||||
|
MinCandidateNodesPercentage: 10,
|
||||||
|
MinCandidateNodesAbsolute: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: interpodaffinity.Name,
|
||||||
|
Args: &schedulerapi.InterPodAffinityArgs{
|
||||||
|
HardPodAffinityWeight: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: nodeaffinity.Name,
|
||||||
|
Args: &schedulerapi.NodeAffinityArgs{},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: nodelabel.Name,
|
Name: nodelabel.Name,
|
||||||
Args: &schedulerapi.NodeLabelArgs{
|
Args: &schedulerapi.NodeLabelArgs{
|
||||||
@ -209,13 +265,6 @@ func TestCreateFromConfig(t *testing.T) {
|
|||||||
AbsentLabelsPreference: []string{"l2"},
|
AbsentLabelsPreference: []string{"l2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: serviceaffinity.Name,
|
|
||||||
Args: &schedulerapi.ServiceAffinityArgs{
|
|
||||||
AffinityLabels: []string{"zone", "foo"},
|
|
||||||
AntiAffinityLabelsPreference: []string{"rack", "zone"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Name: noderesources.RequestedToCapacityRatioName,
|
Name: noderesources.RequestedToCapacityRatioName,
|
||||||
Args: &schedulerapi.RequestedToCapacityRatioArgs{
|
Args: &schedulerapi.RequestedToCapacityRatioArgs{
|
||||||
@ -226,6 +275,13 @@ func TestCreateFromConfig(t *testing.T) {
|
|||||||
Resources: []schedulerapi.ResourceSpec{},
|
Resources: []schedulerapi.ResourceSpec{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: serviceaffinity.Name,
|
||||||
|
Args: &schedulerapi.ServiceAffinityArgs{
|
||||||
|
AffinityLabels: []string{"zone", "foo"},
|
||||||
|
AntiAffinityLabelsPreference: []string{"rack", "zone"},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
wantPlugins: &schedulerapi.Plugins{
|
wantPlugins: &schedulerapi.Plugins{
|
||||||
QueueSort: &schedulerapi.PluginSet{Enabled: []schedulerapi.Plugin{{Name: "PrioritySort"}}},
|
QueueSort: &schedulerapi.PluginSet{Enabled: []schedulerapi.Plugin{{Name: "PrioritySort"}}},
|
||||||
@ -262,31 +318,20 @@ func TestCreateFromConfig(t *testing.T) {
|
|||||||
"kind" : "Policy",
|
"kind" : "Policy",
|
||||||
"apiVersion" : "v1",
|
"apiVersion" : "v1",
|
||||||
"predicates" : [
|
"predicates" : [
|
||||||
{"name" : "TestZoneAffinity", "argument" : {"serviceAffinity" : {"labels" : ["zone"]}}},
|
|
||||||
{"name" : "TestRequireZone", "argument" : {"labelsPresence" : {"labels" : ["zone"], "presence" : true}}},
|
|
||||||
{"name" : "PodFitsResources"},
|
{"name" : "PodFitsResources"},
|
||||||
{"name" : "PodFitsHostPorts"}
|
{"name" : "PodFitsHostPorts"}
|
||||||
],
|
],
|
||||||
"priorities" : [
|
"priorities" : [
|
||||||
{"name" : "RackSpread", "weight" : 3, "argument" : {"serviceAntiAffinity" : {"label" : "rack"}}},
|
|
||||||
{"name" : "NodeAffinityPriority", "weight" : 2},
|
|
||||||
{"name" : "ImageLocalityPriority", "weight" : 1},
|
|
||||||
{"name" : "InterPodAffinityPriority", "weight" : 1}
|
{"name" : "InterPodAffinityPriority", "weight" : 1}
|
||||||
],
|
],
|
||||||
"hardPodAffinitySymmetricWeight" : 10
|
"hardPodAffinitySymmetricWeight" : 10
|
||||||
}`),
|
}`),
|
||||||
wantPluginConfig: []schedulerapi.PluginConfig{
|
wantPluginConfig: []schedulerapi.PluginConfig{
|
||||||
{
|
{
|
||||||
Name: nodelabel.Name,
|
Name: defaultpreemption.Name,
|
||||||
Args: &schedulerapi.NodeLabelArgs{
|
Args: &schedulerapi.DefaultPreemptionArgs{
|
||||||
PresentLabels: []string{"zone"},
|
MinCandidateNodesPercentage: 10,
|
||||||
},
|
MinCandidateNodesAbsolute: 100,
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: serviceaffinity.Name,
|
|
||||||
Args: &schedulerapi.ServiceAffinityArgs{
|
|
||||||
AffinityLabels: []string{"zone"},
|
|
||||||
AntiAffinityLabelsPreference: []string{"rack"},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -295,13 +340,16 @@ func TestCreateFromConfig(t *testing.T) {
|
|||||||
HardPodAffinityWeight: 10,
|
HardPodAffinityWeight: 10,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "NodeResourcesFit",
|
||||||
|
Args: &schedulerapi.NodeResourcesFitArgs{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
wantPlugins: &schedulerapi.Plugins{
|
wantPlugins: &schedulerapi.Plugins{
|
||||||
QueueSort: &schedulerapi.PluginSet{Enabled: []schedulerapi.Plugin{{Name: "PrioritySort"}}},
|
QueueSort: &schedulerapi.PluginSet{Enabled: []schedulerapi.Plugin{{Name: "PrioritySort"}}},
|
||||||
PreFilter: &schedulerapi.PluginSet{Enabled: []schedulerapi.Plugin{
|
PreFilter: &schedulerapi.PluginSet{Enabled: []schedulerapi.Plugin{
|
||||||
{Name: "NodePorts"},
|
{Name: "NodePorts"},
|
||||||
{Name: "NodeResourcesFit"},
|
{Name: "NodeResourcesFit"},
|
||||||
{Name: "ServiceAffinity"},
|
|
||||||
}},
|
}},
|
||||||
Filter: &schedulerapi.PluginSet{
|
Filter: &schedulerapi.PluginSet{
|
||||||
Enabled: []schedulerapi.Plugin{
|
Enabled: []schedulerapi.Plugin{
|
||||||
@ -309,18 +357,13 @@ func TestCreateFromConfig(t *testing.T) {
|
|||||||
{Name: "NodePorts"},
|
{Name: "NodePorts"},
|
||||||
{Name: "NodeResourcesFit"},
|
{Name: "NodeResourcesFit"},
|
||||||
{Name: "TaintToleration"},
|
{Name: "TaintToleration"},
|
||||||
{Name: "NodeLabel"},
|
|
||||||
{Name: "ServiceAffinity"},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PostFilter: &schedulerapi.PluginSet{Enabled: []schedulerapi.Plugin{{Name: "DefaultPreemption"}}},
|
PostFilter: &schedulerapi.PluginSet{Enabled: []schedulerapi.Plugin{{Name: "DefaultPreemption"}}},
|
||||||
PreScore: &schedulerapi.PluginSet{Enabled: []schedulerapi.Plugin{{Name: "InterPodAffinity"}}},
|
PreScore: &schedulerapi.PluginSet{Enabled: []schedulerapi.Plugin{{Name: "InterPodAffinity"}}},
|
||||||
Score: &schedulerapi.PluginSet{
|
Score: &schedulerapi.PluginSet{
|
||||||
Enabled: []schedulerapi.Plugin{
|
Enabled: []schedulerapi.Plugin{
|
||||||
{Name: "ImageLocality", Weight: 1},
|
|
||||||
{Name: "InterPodAffinity", Weight: 1},
|
{Name: "InterPodAffinity", Weight: 1},
|
||||||
{Name: "NodeAffinity", Weight: 2},
|
|
||||||
{Name: "ServiceAffinity", Weight: 3},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Reserve: &schedulerapi.PluginSet{},
|
Reserve: &schedulerapi.PluginSet{},
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
@ -130,6 +131,7 @@ type frameworkOptions struct {
|
|||||||
podNominator framework.PodNominator
|
podNominator framework.PodNominator
|
||||||
extenders []framework.Extender
|
extenders []framework.Extender
|
||||||
runAllFilters bool
|
runAllFilters bool
|
||||||
|
captureProfile CaptureProfile
|
||||||
}
|
}
|
||||||
|
|
||||||
// Option for the frameworkImpl.
|
// Option for the frameworkImpl.
|
||||||
@ -199,6 +201,16 @@ func WithExtenders(extenders []framework.Extender) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CaptureProfile is a callback to capture a finalized profile.
|
||||||
|
type CaptureProfile func(config.KubeSchedulerProfile)
|
||||||
|
|
||||||
|
// WithCaptureProfile sets a callback to capture the finalized profile.
|
||||||
|
func WithCaptureProfile(c CaptureProfile) Option {
|
||||||
|
return func(o *frameworkOptions) {
|
||||||
|
o.captureProfile = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var defaultFrameworkOptions = frameworkOptions{
|
var defaultFrameworkOptions = frameworkOptions{
|
||||||
metricsRecorder: newMetricsRecorder(1000, time.Second),
|
metricsRecorder: newMetricsRecorder(1000, time.Second),
|
||||||
}
|
}
|
||||||
@ -258,6 +270,11 @@ func NewFramework(r Registry, plugins *config.Plugins, args []config.PluginConfi
|
|||||||
}
|
}
|
||||||
pluginConfig[name] = args[i].Args
|
pluginConfig[name] = args[i].Args
|
||||||
}
|
}
|
||||||
|
outputProfile := config.KubeSchedulerProfile{
|
||||||
|
SchedulerName: f.profileName,
|
||||||
|
Plugins: plugins,
|
||||||
|
PluginConfig: make([]config.PluginConfig, 0, len(pg)),
|
||||||
|
}
|
||||||
|
|
||||||
pluginsMap := make(map[string]framework.Plugin)
|
pluginsMap := make(map[string]framework.Plugin)
|
||||||
var totalPriority int64
|
var totalPriority int64
|
||||||
@ -271,6 +288,12 @@ func NewFramework(r Registry, plugins *config.Plugins, args []config.PluginConfi
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("getting args for Plugin %q: %w", name, err)
|
return nil, fmt.Errorf("getting args for Plugin %q: %w", name, err)
|
||||||
}
|
}
|
||||||
|
if args != nil {
|
||||||
|
outputProfile.PluginConfig = append(outputProfile.PluginConfig, config.PluginConfig{
|
||||||
|
Name: name,
|
||||||
|
Args: args,
|
||||||
|
})
|
||||||
|
}
|
||||||
p, err := factory(args, f)
|
p, err := factory(args, f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("initializing plugin %q: %w", name, err)
|
return nil, fmt.Errorf("initializing plugin %q: %w", name, err)
|
||||||
@ -314,6 +337,17 @@ func NewFramework(r Registry, plugins *config.Plugins, args []config.PluginConfi
|
|||||||
return nil, fmt.Errorf("at least one bind plugin is needed")
|
return nil, fmt.Errorf("at least one bind plugin is needed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if options.captureProfile != nil {
|
||||||
|
if len(outputProfile.PluginConfig) != 0 {
|
||||||
|
sort.Slice(outputProfile.PluginConfig, func(i, j int) bool {
|
||||||
|
return outputProfile.PluginConfig[i].Name < outputProfile.PluginConfig[j].Name
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
outputProfile.PluginConfig = nil
|
||||||
|
}
|
||||||
|
options.captureProfile(outputProfile)
|
||||||
|
}
|
||||||
|
|
||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user