Merge pull request #87725 from alculquicondor/rm_affinity_weight

Add defaults to pod affinity args
This commit is contained in:
Kubernetes Prow Robot 2020-02-07 12:32:17 -08:00 committed by GitHub
commit 7cfa396e7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 321 additions and 318 deletions

View File

@ -68,6 +68,7 @@ go_test(
"//pkg/scheduler/core:go_default_library", "//pkg/scheduler/core: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/interpodaffinity: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",

View File

@ -30,7 +30,6 @@ go_library(
"//pkg/scheduler/framework/plugins/volumebinding:go_default_library", "//pkg/scheduler/framework/plugins/volumebinding:go_default_library",
"//pkg/scheduler/framework/plugins/volumerestrictions:go_default_library", "//pkg/scheduler/framework/plugins/volumerestrictions:go_default_library",
"//pkg/scheduler/framework/plugins/volumezone:go_default_library", "//pkg/scheduler/framework/plugins/volumezone:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
], ],
@ -60,7 +59,6 @@ go_test(
"//pkg/scheduler/framework/plugins/volumebinding:go_default_library", "//pkg/scheduler/framework/plugins/volumebinding:go_default_library",
"//pkg/scheduler/framework/plugins/volumerestrictions:go_default_library", "//pkg/scheduler/framework/plugins/volumerestrictions:go_default_library",
"//pkg/scheduler/framework/plugins/volumezone:go_default_library", "//pkg/scheduler/framework/plugins/volumezone:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library", "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
"//vendor/github.com/google/go-cmp/cmp:go_default_library", "//vendor/github.com/google/go-cmp/cmp:go_default_library",

View File

@ -17,11 +17,9 @@ limitations under the License.
package algorithmprovider package algorithmprovider
import ( import (
"fmt"
"sort" "sort"
"strings" "strings"
"k8s.io/apimachinery/pkg/runtime"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/klog" "k8s.io/klog"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
@ -48,21 +46,15 @@ import (
// ClusterAutoscalerProvider defines the default autoscaler provider // ClusterAutoscalerProvider defines the default autoscaler provider
const ClusterAutoscalerProvider = "ClusterAutoscalerProvider" const ClusterAutoscalerProvider = "ClusterAutoscalerProvider"
// Config the configuration of an algorithm provider.
type Config struct {
FrameworkPlugins *schedulerapi.Plugins
FrameworkPluginConfig []schedulerapi.PluginConfig
}
// Registry is a collection of all available algorithm providers. // Registry is a collection of all available algorithm providers.
type Registry map[string]*Config type Registry map[string]*schedulerapi.Plugins
// NewRegistry returns an algorithm provider registry instance. // NewRegistry returns an algorithm provider registry instance.
func NewRegistry(hardPodAffinityWeight int64) Registry { func NewRegistry() Registry {
defaultConfig := getDefaultConfig(hardPodAffinityWeight) defaultConfig := getDefaultConfig()
applyFeatureGates(defaultConfig) applyFeatureGates(defaultConfig)
caConfig := getClusterAutoscalerConfig(hardPodAffinityWeight) caConfig := getClusterAutoscalerConfig()
applyFeatureGates(caConfig) applyFeatureGates(caConfig)
return Registry{ return Registry{
@ -73,7 +65,7 @@ func NewRegistry(hardPodAffinityWeight int64) Registry {
// ListAlgorithmProviders lists registered algorithm providers. // ListAlgorithmProviders lists registered algorithm providers.
func ListAlgorithmProviders() string { func ListAlgorithmProviders() string {
r := NewRegistry(1) r := NewRegistry()
var providers []string var providers []string
for k := range r { for k := range r {
providers = append(providers, k) providers = append(providers, k)
@ -82,109 +74,94 @@ func ListAlgorithmProviders() string {
return strings.Join(providers, " | ") return strings.Join(providers, " | ")
} }
func getDefaultConfig(hardPodAffinityWeight int64) *Config { func getDefaultConfig() *schedulerapi.Plugins {
return &Config{ return &schedulerapi.Plugins{
FrameworkPlugins: &schedulerapi.Plugins{ QueueSort: &schedulerapi.PluginSet{
QueueSort: &schedulerapi.PluginSet{ Enabled: []schedulerapi.Plugin{
Enabled: []schedulerapi.Plugin{ {Name: queuesort.Name},
{Name: queuesort.Name},
},
},
PreFilter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: noderesources.FitName},
{Name: nodeports.Name},
{Name: interpodaffinity.Name},
},
},
Filter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: nodeunschedulable.Name},
{Name: noderesources.FitName},
{Name: nodename.Name},
{Name: nodeports.Name},
{Name: nodeaffinity.Name},
{Name: volumerestrictions.Name},
{Name: tainttoleration.Name},
{Name: nodevolumelimits.EBSName},
{Name: nodevolumelimits.GCEPDName},
{Name: nodevolumelimits.CSIName},
{Name: nodevolumelimits.AzureDiskName},
{Name: volumebinding.Name},
{Name: volumezone.Name},
{Name: interpodaffinity.Name},
},
},
PostFilter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: interpodaffinity.Name},
{Name: defaultpodtopologyspread.Name},
{Name: tainttoleration.Name},
},
},
Score: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: noderesources.BalancedAllocationName, Weight: 1},
{Name: imagelocality.Name, Weight: 1},
{Name: interpodaffinity.Name, Weight: 1},
{Name: noderesources.LeastAllocatedName, Weight: 1},
{Name: nodeaffinity.Name, Weight: 1},
{Name: nodepreferavoidpods.Name, Weight: 10000},
{Name: defaultpodtopologyspread.Name, Weight: 1},
{Name: tainttoleration.Name, Weight: 1},
},
},
Bind: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: defaultbinder.Name},
},
}, },
}, },
FrameworkPluginConfig: []schedulerapi.PluginConfig{ PreFilter: &schedulerapi.PluginSet{
{ Enabled: []schedulerapi.Plugin{
Name: interpodaffinity.Name, {Name: noderesources.FitName},
Args: runtime.Unknown{Raw: []byte(fmt.Sprintf(`{"hardPodAffinityWeight":%d}`, hardPodAffinityWeight))}, {Name: nodeports.Name},
{Name: interpodaffinity.Name},
},
},
Filter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: nodeunschedulable.Name},
{Name: noderesources.FitName},
{Name: nodename.Name},
{Name: nodeports.Name},
{Name: nodeaffinity.Name},
{Name: volumerestrictions.Name},
{Name: tainttoleration.Name},
{Name: nodevolumelimits.EBSName},
{Name: nodevolumelimits.GCEPDName},
{Name: nodevolumelimits.CSIName},
{Name: nodevolumelimits.AzureDiskName},
{Name: volumebinding.Name},
{Name: volumezone.Name},
{Name: interpodaffinity.Name},
},
},
PostFilter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: interpodaffinity.Name},
{Name: defaultpodtopologyspread.Name},
{Name: tainttoleration.Name},
},
},
Score: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: noderesources.BalancedAllocationName, Weight: 1},
{Name: imagelocality.Name, Weight: 1},
{Name: interpodaffinity.Name, Weight: 1},
{Name: noderesources.LeastAllocatedName, Weight: 1},
{Name: nodeaffinity.Name, Weight: 1},
{Name: nodepreferavoidpods.Name, Weight: 10000},
{Name: defaultpodtopologyspread.Name, Weight: 1},
{Name: tainttoleration.Name, Weight: 1},
},
},
Bind: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: defaultbinder.Name},
}, },
}, },
} }
} }
func getClusterAutoscalerConfig(hardPodAffinityWeight int64) *Config { func getClusterAutoscalerConfig() *schedulerapi.Plugins {
defaultConfig := getDefaultConfig(hardPodAffinityWeight) caConfig := getDefaultConfig()
caConfig := Config{
FrameworkPlugins: &schedulerapi.Plugins{},
}
defaultConfig.FrameworkPlugins.DeepCopyInto(caConfig.FrameworkPlugins)
caConfig.FrameworkPluginConfig = append([]schedulerapi.PluginConfig(nil), defaultConfig.FrameworkPluginConfig...)
// Replace least with most requested. // Replace least with most requested.
for i := range caConfig.FrameworkPlugins.Score.Enabled { for i := range caConfig.Score.Enabled {
if caConfig.FrameworkPlugins.Score.Enabled[i].Name == noderesources.LeastAllocatedName { if caConfig.Score.Enabled[i].Name == noderesources.LeastAllocatedName {
caConfig.FrameworkPlugins.Score.Enabled[i].Name = noderesources.MostAllocatedName caConfig.Score.Enabled[i].Name = noderesources.MostAllocatedName
} }
} }
return caConfig
return &caConfig
} }
func applyFeatureGates(config *Config) { func applyFeatureGates(config *schedulerapi.Plugins) {
// Only add EvenPodsSpread if the feature is enabled. // Only add EvenPodsSpread if the feature is enabled.
if utilfeature.DefaultFeatureGate.Enabled(features.EvenPodsSpread) { if utilfeature.DefaultFeatureGate.Enabled(features.EvenPodsSpread) {
klog.Infof("Registering EvenPodsSpread predicate and priority function") klog.Infof("Registering EvenPodsSpread predicate and priority function")
f := schedulerapi.Plugin{Name: podtopologyspread.Name} f := schedulerapi.Plugin{Name: podtopologyspread.Name}
config.FrameworkPlugins.PreFilter.Enabled = append(config.FrameworkPlugins.PreFilter.Enabled, f) config.PreFilter.Enabled = append(config.PreFilter.Enabled, f)
config.FrameworkPlugins.Filter.Enabled = append(config.FrameworkPlugins.Filter.Enabled, f) config.Filter.Enabled = append(config.Filter.Enabled, f)
config.FrameworkPlugins.PostFilter.Enabled = append(config.FrameworkPlugins.PostFilter.Enabled, f) config.PostFilter.Enabled = append(config.PostFilter.Enabled, f)
s := schedulerapi.Plugin{Name: podtopologyspread.Name, Weight: 1} s := schedulerapi.Plugin{Name: podtopologyspread.Name, Weight: 1}
config.FrameworkPlugins.Score.Enabled = append(config.FrameworkPlugins.Score.Enabled, s) config.Score.Enabled = append(config.Score.Enabled, s)
} }
// Prioritizes nodes that satisfy pod's resource limits // Prioritizes nodes that satisfy pod's resource limits
if utilfeature.DefaultFeatureGate.Enabled(features.ResourceLimitsPriorityFunction) { if utilfeature.DefaultFeatureGate.Enabled(features.ResourceLimitsPriorityFunction) {
klog.Infof("Registering resourcelimits priority function") klog.Infof("Registering resourcelimits priority function")
s := schedulerapi.Plugin{Name: noderesources.ResourceLimitsName} s := schedulerapi.Plugin{Name: noderesources.ResourceLimitsName}
config.FrameworkPlugins.PostFilter.Enabled = append(config.FrameworkPlugins.PostFilter.Enabled, s) config.PostFilter.Enabled = append(config.PostFilter.Enabled, s)
s = schedulerapi.Plugin{Name: noderesources.ResourceLimitsName, Weight: 1} s = schedulerapi.Plugin{Name: noderesources.ResourceLimitsName, Weight: 1}
config.FrameworkPlugins.Score.Enabled = append(config.FrameworkPlugins.Score.Enabled, s) config.Score.Enabled = append(config.Score.Enabled, s)
} }
} }

View File

@ -17,12 +17,10 @@ limitations under the License.
package algorithmprovider package algorithmprovider
import ( import (
"fmt"
"testing" "testing"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"k8s.io/apimachinery/pkg/runtime"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
featuregatetesting "k8s.io/component-base/featuregate/testing" featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
@ -47,73 +45,64 @@ import (
) )
func TestClusterAutoscalerProvider(t *testing.T) { func TestClusterAutoscalerProvider(t *testing.T) {
hardPodAffinityWeight := int64(1) wantConfig := &schedulerapi.Plugins{
wantConfig := &Config{ QueueSort: &schedulerapi.PluginSet{
FrameworkPlugins: &schedulerapi.Plugins{ Enabled: []schedulerapi.Plugin{
QueueSort: &schedulerapi.PluginSet{ {Name: queuesort.Name},
Enabled: []schedulerapi.Plugin{
{Name: queuesort.Name},
},
},
PreFilter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: noderesources.FitName},
{Name: nodeports.Name},
{Name: interpodaffinity.Name},
},
},
Filter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: nodeunschedulable.Name},
{Name: noderesources.FitName},
{Name: nodename.Name},
{Name: nodeports.Name},
{Name: nodeaffinity.Name},
{Name: volumerestrictions.Name},
{Name: tainttoleration.Name},
{Name: nodevolumelimits.EBSName},
{Name: nodevolumelimits.GCEPDName},
{Name: nodevolumelimits.CSIName},
{Name: nodevolumelimits.AzureDiskName},
{Name: volumebinding.Name},
{Name: volumezone.Name},
{Name: interpodaffinity.Name},
},
},
PostFilter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: interpodaffinity.Name},
{Name: defaultpodtopologyspread.Name},
{Name: tainttoleration.Name},
},
},
Score: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: noderesources.BalancedAllocationName, Weight: 1},
{Name: imagelocality.Name, Weight: 1},
{Name: interpodaffinity.Name, Weight: 1},
{Name: noderesources.MostAllocatedName, Weight: 1},
{Name: nodeaffinity.Name, Weight: 1},
{Name: nodepreferavoidpods.Name, Weight: 10000},
{Name: defaultpodtopologyspread.Name, Weight: 1},
{Name: tainttoleration.Name, Weight: 1},
},
},
Bind: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: defaultbinder.Name},
},
}, },
}, },
FrameworkPluginConfig: []schedulerapi.PluginConfig{ PreFilter: &schedulerapi.PluginSet{
{ Enabled: []schedulerapi.Plugin{
Name: interpodaffinity.Name, {Name: noderesources.FitName},
Args: runtime.Unknown{Raw: []byte(fmt.Sprintf(`{"hardPodAffinityWeight":%d}`, hardPodAffinityWeight))}, {Name: nodeports.Name},
{Name: interpodaffinity.Name},
},
},
Filter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: nodeunschedulable.Name},
{Name: noderesources.FitName},
{Name: nodename.Name},
{Name: nodeports.Name},
{Name: nodeaffinity.Name},
{Name: volumerestrictions.Name},
{Name: tainttoleration.Name},
{Name: nodevolumelimits.EBSName},
{Name: nodevolumelimits.GCEPDName},
{Name: nodevolumelimits.CSIName},
{Name: nodevolumelimits.AzureDiskName},
{Name: volumebinding.Name},
{Name: volumezone.Name},
{Name: interpodaffinity.Name},
},
},
PostFilter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: interpodaffinity.Name},
{Name: defaultpodtopologyspread.Name},
{Name: tainttoleration.Name},
},
},
Score: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: noderesources.BalancedAllocationName, Weight: 1},
{Name: imagelocality.Name, Weight: 1},
{Name: interpodaffinity.Name, Weight: 1},
{Name: noderesources.MostAllocatedName, Weight: 1},
{Name: nodeaffinity.Name, Weight: 1},
{Name: nodepreferavoidpods.Name, Weight: 10000},
{Name: defaultpodtopologyspread.Name, Weight: 1},
{Name: tainttoleration.Name, Weight: 1},
},
},
Bind: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: defaultbinder.Name},
}, },
}, },
} }
r := NewRegistry(hardPodAffinityWeight) r := NewRegistry()
gotConfig := r[ClusterAutoscalerProvider] gotConfig := r[ClusterAutoscalerProvider]
if diff := cmp.Diff(wantConfig, gotConfig); diff != "" { if diff := cmp.Diff(wantConfig, gotConfig); diff != "" {
t.Errorf("unexpected config diff (-want, +got): %s", diff) t.Errorf("unexpected config diff (-want, +got): %s", diff)
@ -121,76 +110,67 @@ func TestClusterAutoscalerProvider(t *testing.T) {
} }
func TestApplyFeatureGates(t *testing.T) { func TestApplyFeatureGates(t *testing.T) {
hardPodAffinityWeight := int64(1)
tests := []struct { tests := []struct {
name string name string
featuresEnabled bool featuresEnabled bool
wantConfig *Config wantConfig *schedulerapi.Plugins
}{ }{
{ {
name: "Feature gates disabled", name: "Feature gates disabled",
featuresEnabled: false, featuresEnabled: false,
wantConfig: &Config{ wantConfig: &schedulerapi.Plugins{
FrameworkPlugins: &schedulerapi.Plugins{ QueueSort: &schedulerapi.PluginSet{
QueueSort: &schedulerapi.PluginSet{ Enabled: []schedulerapi.Plugin{
Enabled: []schedulerapi.Plugin{ {Name: queuesort.Name},
{Name: queuesort.Name},
},
},
PreFilter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: noderesources.FitName},
{Name: nodeports.Name},
{Name: interpodaffinity.Name},
},
},
Filter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: nodeunschedulable.Name},
{Name: noderesources.FitName},
{Name: nodename.Name},
{Name: nodeports.Name},
{Name: nodeaffinity.Name},
{Name: volumerestrictions.Name},
{Name: tainttoleration.Name},
{Name: nodevolumelimits.EBSName},
{Name: nodevolumelimits.GCEPDName},
{Name: nodevolumelimits.CSIName},
{Name: nodevolumelimits.AzureDiskName},
{Name: volumebinding.Name},
{Name: volumezone.Name},
{Name: interpodaffinity.Name},
},
},
PostFilter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: interpodaffinity.Name},
{Name: defaultpodtopologyspread.Name},
{Name: tainttoleration.Name},
},
},
Score: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: noderesources.BalancedAllocationName, Weight: 1},
{Name: imagelocality.Name, Weight: 1},
{Name: interpodaffinity.Name, Weight: 1},
{Name: noderesources.LeastAllocatedName, Weight: 1},
{Name: nodeaffinity.Name, Weight: 1},
{Name: nodepreferavoidpods.Name, Weight: 10000},
{Name: defaultpodtopologyspread.Name, Weight: 1},
{Name: tainttoleration.Name, Weight: 1},
},
},
Bind: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: defaultbinder.Name},
},
}, },
}, },
FrameworkPluginConfig: []schedulerapi.PluginConfig{ PreFilter: &schedulerapi.PluginSet{
{ Enabled: []schedulerapi.Plugin{
Name: interpodaffinity.Name, {Name: noderesources.FitName},
Args: runtime.Unknown{Raw: []byte(fmt.Sprintf(`{"hardPodAffinityWeight":%d}`, hardPodAffinityWeight))}, {Name: nodeports.Name},
{Name: interpodaffinity.Name},
},
},
Filter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: nodeunschedulable.Name},
{Name: noderesources.FitName},
{Name: nodename.Name},
{Name: nodeports.Name},
{Name: nodeaffinity.Name},
{Name: volumerestrictions.Name},
{Name: tainttoleration.Name},
{Name: nodevolumelimits.EBSName},
{Name: nodevolumelimits.GCEPDName},
{Name: nodevolumelimits.CSIName},
{Name: nodevolumelimits.AzureDiskName},
{Name: volumebinding.Name},
{Name: volumezone.Name},
{Name: interpodaffinity.Name},
},
},
PostFilter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: interpodaffinity.Name},
{Name: defaultpodtopologyspread.Name},
{Name: tainttoleration.Name},
},
},
Score: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: noderesources.BalancedAllocationName, Weight: 1},
{Name: imagelocality.Name, Weight: 1},
{Name: interpodaffinity.Name, Weight: 1},
{Name: noderesources.LeastAllocatedName, Weight: 1},
{Name: nodeaffinity.Name, Weight: 1},
{Name: nodepreferavoidpods.Name, Weight: 10000},
{Name: defaultpodtopologyspread.Name, Weight: 1},
{Name: tainttoleration.Name, Weight: 1},
},
},
Bind: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: defaultbinder.Name},
}, },
}, },
}, },
@ -198,73 +178,65 @@ func TestApplyFeatureGates(t *testing.T) {
{ {
name: "Feature gates enabled", name: "Feature gates enabled",
featuresEnabled: true, featuresEnabled: true,
wantConfig: &Config{ wantConfig: &schedulerapi.Plugins{
FrameworkPlugins: &schedulerapi.Plugins{ QueueSort: &schedulerapi.PluginSet{
QueueSort: &schedulerapi.PluginSet{ Enabled: []schedulerapi.Plugin{
Enabled: []schedulerapi.Plugin{ {Name: queuesort.Name},
{Name: queuesort.Name},
},
},
PreFilter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: noderesources.FitName},
{Name: nodeports.Name},
{Name: interpodaffinity.Name},
{Name: podtopologyspread.Name},
},
},
Filter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: nodeunschedulable.Name},
{Name: noderesources.FitName},
{Name: nodename.Name},
{Name: nodeports.Name},
{Name: nodeaffinity.Name},
{Name: volumerestrictions.Name},
{Name: tainttoleration.Name},
{Name: nodevolumelimits.EBSName},
{Name: nodevolumelimits.GCEPDName},
{Name: nodevolumelimits.CSIName},
{Name: nodevolumelimits.AzureDiskName},
{Name: volumebinding.Name},
{Name: volumezone.Name},
{Name: interpodaffinity.Name},
{Name: podtopologyspread.Name},
},
},
PostFilter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: interpodaffinity.Name},
{Name: defaultpodtopologyspread.Name},
{Name: tainttoleration.Name},
{Name: podtopologyspread.Name},
{Name: noderesources.ResourceLimitsName},
},
},
Score: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: noderesources.BalancedAllocationName, Weight: 1},
{Name: imagelocality.Name, Weight: 1},
{Name: interpodaffinity.Name, Weight: 1},
{Name: noderesources.LeastAllocatedName, Weight: 1},
{Name: nodeaffinity.Name, Weight: 1},
{Name: nodepreferavoidpods.Name, Weight: 10000},
{Name: defaultpodtopologyspread.Name, Weight: 1},
{Name: tainttoleration.Name, Weight: 1},
{Name: podtopologyspread.Name, Weight: 1},
{Name: noderesources.ResourceLimitsName, Weight: 1},
},
},
Bind: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: defaultbinder.Name},
},
}, },
}, },
FrameworkPluginConfig: []schedulerapi.PluginConfig{ PreFilter: &schedulerapi.PluginSet{
{ Enabled: []schedulerapi.Plugin{
Name: interpodaffinity.Name, {Name: noderesources.FitName},
Args: runtime.Unknown{Raw: []byte(fmt.Sprintf(`{"hardPodAffinityWeight":%d}`, hardPodAffinityWeight))}, {Name: nodeports.Name},
{Name: interpodaffinity.Name},
{Name: podtopologyspread.Name},
},
},
Filter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: nodeunschedulable.Name},
{Name: noderesources.FitName},
{Name: nodename.Name},
{Name: nodeports.Name},
{Name: nodeaffinity.Name},
{Name: volumerestrictions.Name},
{Name: tainttoleration.Name},
{Name: nodevolumelimits.EBSName},
{Name: nodevolumelimits.GCEPDName},
{Name: nodevolumelimits.CSIName},
{Name: nodevolumelimits.AzureDiskName},
{Name: volumebinding.Name},
{Name: volumezone.Name},
{Name: interpodaffinity.Name},
{Name: podtopologyspread.Name},
},
},
PostFilter: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: interpodaffinity.Name},
{Name: defaultpodtopologyspread.Name},
{Name: tainttoleration.Name},
{Name: podtopologyspread.Name},
{Name: noderesources.ResourceLimitsName},
},
},
Score: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: noderesources.BalancedAllocationName, Weight: 1},
{Name: imagelocality.Name, Weight: 1},
{Name: interpodaffinity.Name, Weight: 1},
{Name: noderesources.LeastAllocatedName, Weight: 1},
{Name: nodeaffinity.Name, Weight: 1},
{Name: nodepreferavoidpods.Name, Weight: 10000},
{Name: defaultpodtopologyspread.Name, Weight: 1},
{Name: tainttoleration.Name, Weight: 1},
{Name: podtopologyspread.Name, Weight: 1},
{Name: noderesources.ResourceLimitsName, Weight: 1},
},
},
Bind: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: defaultbinder.Name},
}, },
}, },
}, },
@ -276,7 +248,7 @@ func TestApplyFeatureGates(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ResourceLimitsPriorityFunction, test.featuresEnabled)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ResourceLimitsPriorityFunction, test.featuresEnabled)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EvenPodsSpread, test.featuresEnabled)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EvenPodsSpread, test.featuresEnabled)()
r := NewRegistry(hardPodAffinityWeight) r := NewRegistry()
gotConfig := r[schedulerapi.SchedulerDefaultProviderName] gotConfig := r[schedulerapi.SchedulerDefaultProviderName]
if diff := cmp.Diff(test.wantConfig, gotConfig); diff != "" { if diff := cmp.Diff(test.wantConfig, gotConfig); diff != "" {
t.Errorf("unexpected config diff (-want, +got): %s", diff) t.Errorf("unexpected config diff (-want, +got): %s", diff)

View File

@ -25,8 +25,9 @@ import (
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
@ -169,20 +170,17 @@ func (c *Configurator) create(extenders []core.SchedulerExtender) (*Scheduler, e
// createFromProvider creates a scheduler from the name of a registered algorithm provider. // createFromProvider creates a scheduler from the name of a registered algorithm provider.
func (c *Configurator) createFromProvider(providerName string) (*Scheduler, error) { func (c *Configurator) createFromProvider(providerName string) (*Scheduler, error) {
klog.V(2).Infof("Creating scheduler from algorithm provider '%v'", providerName) klog.V(2).Infof("Creating scheduler from algorithm provider '%v'", providerName)
r := algorithmprovider.NewRegistry(int64(c.hardPodAffinitySymmetricWeight)) r := algorithmprovider.NewRegistry()
provider, exist := r[providerName] defaultPlugins, exist := r[providerName]
if !exist { if !exist {
return nil, fmt.Errorf("algorithm provider %q is not registered", providerName) return nil, fmt.Errorf("algorithm provider %q is not registered", providerName)
} }
// Combine the provided plugins with the ones from component config. // Combine the provided plugins with the ones from component config.
var defaultPlugins schedulerapi.Plugins
defaultPlugins.Append(provider.FrameworkPlugins)
defaultPlugins.Apply(c.plugins) defaultPlugins.Apply(c.plugins)
c.plugins = &defaultPlugins c.plugins = defaultPlugins
var pluginConfig []schedulerapi.PluginConfig pluginConfig := []schedulerapi.PluginConfig{c.interPodAffinityPluginConfig()}
pluginConfig = append(pluginConfig, provider.FrameworkPluginConfig...)
pluginConfig = append(pluginConfig, c.pluginConfig...) pluginConfig = append(pluginConfig, c.pluginConfig...)
c.pluginConfig = pluginConfig c.pluginConfig = pluginConfig
@ -268,12 +266,8 @@ func (c *Configurator) createFromConfig(policy schedulerapi.Policy) (*Scheduler,
klog.V(2).Infof("Creating scheduler with fit predicates '%v' and priority functions '%v'", predicateKeys, priorityKeys) klog.V(2).Infof("Creating scheduler with fit predicates '%v' and priority functions '%v'", predicateKeys, priorityKeys)
if c.hardPodAffinitySymmetricWeight < 1 || c.hardPodAffinitySymmetricWeight > 100 {
return nil, fmt.Errorf("invalid hardPodAffinitySymmetricWeight: %d, must be in the range 1-100", c.hardPodAffinitySymmetricWeight)
}
args.InterPodAffinityArgs = &interpodaffinity.Args{ args.InterPodAffinityArgs = &interpodaffinity.Args{
HardPodAffinityWeight: c.hardPodAffinitySymmetricWeight, HardPodAffinityWeight: &c.hardPodAffinitySymmetricWeight,
} }
pluginsForPredicates, pluginConfigForPredicates, err := getPredicateConfigs(predicateKeys, lr, args) pluginsForPredicates, pluginConfigForPredicates, err := getPredicateConfigs(predicateKeys, lr, args)
@ -312,6 +306,15 @@ func (c *Configurator) createFromConfig(policy schedulerapi.Policy) (*Scheduler,
return c.create(extenders) return c.create(extenders)
} }
func (c *Configurator) interPodAffinityPluginConfig() schedulerapi.PluginConfig {
return schedulerapi.PluginConfig{
Name: interpodaffinity.Name,
Args: runtime.Unknown{
Raw: []byte(fmt.Sprintf(`{"hardPodAffinityWeight":%d}`, c.hardPodAffinitySymmetricWeight)),
},
}
}
// getPriorityConfigs returns priorities configuration: ones that will run as priorities and ones that will run // getPriorityConfigs returns priorities configuration: ones that will run as priorities and ones that will run
// as framework plugins. Specifically, a priority will run as a framework plugin if a plugin config producer was // as framework plugins. Specifically, a priority will run as a framework plugin if a plugin config producer was
// registered for that priority. // registered for that priority.
@ -436,7 +439,7 @@ func MakeDefaultErrorFunc(client clientset.Interface, podQueue internalqueue.Sch
// Retry asynchronously. // Retry asynchronously.
// Note that this is extremely rudimentary and we need a more real error handling path. // Note that this is extremely rudimentary and we need a more real error handling path.
go func() { go func() {
defer runtime.HandleCrash() defer utilruntime.HandleCrash()
podID := types.NamespacedName{ podID := types.NamespacedName{
Namespace: pod.Namespace, Namespace: pod.Namespace,
Name: pod.Name, Name: pod.Name,

View File

@ -42,7 +42,9 @@ import (
extenderv1 "k8s.io/kubernetes/pkg/scheduler/apis/extender/v1" extenderv1 "k8s.io/kubernetes/pkg/scheduler/apis/extender/v1"
frameworkplugins "k8s.io/kubernetes/pkg/scheduler/framework/plugins" frameworkplugins "k8s.io/kubernetes/pkg/scheduler/framework/plugins"
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultbinder" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultbinder"
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/interpodaffinity"
"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/queuesort" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/queuesort"
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/serviceaffinity" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/serviceaffinity"
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1" framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
@ -190,17 +192,29 @@ func TestCreateFromConfigWithHardPodAffinitySymmetricWeight(t *testing.T) {
"priorities" : [ "priorities" : [
{"name" : "RackSpread", "weight" : 3, "argument" : {"serviceAntiAffinity" : {"label" : "rack"}}}, {"name" : "RackSpread", "weight" : 3, "argument" : {"serviceAntiAffinity" : {"label" : "rack"}}},
{"name" : "NodeAffinityPriority", "weight" : 2}, {"name" : "NodeAffinityPriority", "weight" : 2},
{"name" : "ImageLocalityPriority", "weight" : 1} {"name" : "ImageLocalityPriority", "weight" : 1},
{"name" : "InterPodAffinityPriority", "weight" : 1}
], ],
"hardPodAffinitySymmetricWeight" : 10 "hardPodAffinitySymmetricWeight" : 10
}`) }`)
if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), configData, &policy); err != nil { if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), configData, &policy); err != nil {
t.Errorf("Invalid configuration: %v", err) t.Fatalf("Invalid configuration: %v", err)
} }
factory.createFromConfig(policy) factory.createFromConfig(policy)
hpa := factory.hardPodAffinitySymmetricWeight // TODO(#87703): Verify that the entire pluginConfig is correct.
if hpa != 10 { foundAffinityCfg := false
t.Errorf("Wrong hardPodAffinitySymmetricWeight, ecpected: %d, got: %d", 10, hpa) for _, cfg := range factory.pluginConfig {
if cfg.Name == interpodaffinity.Name {
foundAffinityCfg = true
wantArgs := runtime.Unknown{Raw: []byte(`{"hardPodAffinityWeight":10}`)}
if diff := cmp.Diff(wantArgs, cfg.Args); diff != "" {
t.Errorf("wrong InterPodAffinity args (-want, +got): %s", diff)
}
}
}
if !foundAffinityCfg {
t.Errorf("args for InterPodAffinity were not found")
} }
} }
@ -219,6 +233,19 @@ func TestCreateFromEmptyConfig(t *testing.T) {
} }
factory.createFromConfig(policy) factory.createFromConfig(policy)
wantConfig := []schedulerapi.PluginConfig{
{
Name: noderesources.FitName,
Args: runtime.Unknown{Raw: []byte(`null`)},
},
{
Name: interpodaffinity.Name,
Args: runtime.Unknown{Raw: []byte(`{"hardPodAffinityWeight":1}`)},
},
}
if diff := cmp.Diff(wantConfig, factory.pluginConfig); diff != "" {
t.Errorf("wrong plugin config (-want, +got): %s", diff)
}
} }
// Test configures a scheduler from a policy that does not specify any // Test configures a scheduler from a policy that does not specify any

View File

@ -25,12 +25,18 @@ import (
schedulerlisters "k8s.io/kubernetes/pkg/scheduler/listers" schedulerlisters "k8s.io/kubernetes/pkg/scheduler/listers"
) )
// Name is the name of the plugin used in the plugin registry and configurations. const (
const Name = "InterPodAffinity" // Name is the name of the plugin used in the plugin registry and configurations.
Name = "InterPodAffinity"
defaultHardPodAffinityWeight int32 = 1
minHardPodAffinityWeight int32 = 0
maxHardPodAffinityWeight int32 = 100
)
// Args holds the args that are used to configure the plugin. // Args holds the args that are used to configure the plugin.
type Args struct { type Args struct {
HardPodAffinityWeight int32 `json:"hardPodAffinityWeight,omitempty"` HardPodAffinityWeight *int32 `json:"hardPodAffinityWeight,omitempty"`
} }
var _ framework.PreFilterPlugin = &InterPodAffinity{} var _ framework.PreFilterPlugin = &InterPodAffinity{}
@ -55,14 +61,31 @@ func New(plArgs *runtime.Unknown, h framework.FrameworkHandle) (framework.Plugin
if h.SnapshotSharedLister() == nil { if h.SnapshotSharedLister() == nil {
return nil, fmt.Errorf("SnapshotSharedlister is nil") return nil, fmt.Errorf("SnapshotSharedlister is nil")
} }
args := &Args{} args := &Args{}
if err := framework.DecodeInto(plArgs, args); err != nil { if err := framework.DecodeInto(plArgs, args); err != nil {
return nil, err return nil, err
} }
if err := validateArgs(args); err != nil {
return &InterPodAffinity{ return nil, err
}
pl := &InterPodAffinity{
sharedLister: h.SnapshotSharedLister(), sharedLister: h.SnapshotSharedLister(),
hardPodAffinityWeight: args.HardPodAffinityWeight, hardPodAffinityWeight: defaultHardPodAffinityWeight,
}, nil }
if args.HardPodAffinityWeight != nil {
pl.hardPodAffinityWeight = *args.HardPodAffinityWeight
}
return pl, nil
}
func validateArgs(args *Args) error {
if args.HardPodAffinityWeight == nil {
return nil
}
weight := *args.HardPodAffinityWeight
if weight < minHardPodAffinityWeight || weight > maxHardPodAffinityWeight {
return fmt.Errorf("invalid args.hardPodAffinityWeight: %d, must be in the range %d-%d", weight, minHardPodAffinityWeight, maxHardPodAffinityWeight)
}
return nil
} }

View File

@ -627,7 +627,10 @@ func TestPreferredAffinityWithHardPodAffinitySymmetricWeight(t *testing.T) {
fh, _ := framework.NewFramework(nil, nil, nil, framework.WithSnapshotSharedLister(snapshot)) fh, _ := framework.NewFramework(nil, nil, nil, framework.WithSnapshotSharedLister(snapshot))
args := &runtime.Unknown{Raw: []byte(fmt.Sprintf(`{"hardPodAffinityWeight":%d}`, test.hardPodAffinityWeight))} args := &runtime.Unknown{Raw: []byte(fmt.Sprintf(`{"hardPodAffinityWeight":%d}`, test.hardPodAffinityWeight))}
p, _ := New(args, fh) p, err := New(args, fh)
if err != nil {
t.Fatal(err)
}
status := p.(framework.PostFilterPlugin).PostFilter(context.Background(), state, test.pod, test.nodes, nil) status := p.(framework.PostFilterPlugin).PostFilter(context.Background(), state, test.pod, test.nodes, nil)
if !status.IsSuccess() { if !status.IsSuccess() {
t.Errorf("unexpected error: %v", status) t.Errorf("unexpected error: %v", status)

View File

@ -52,7 +52,7 @@ type Fit struct {
type FitArgs struct { type FitArgs struct {
// IgnoredResources is the list of resources that NodeResources fit filter // IgnoredResources is the list of resources that NodeResources fit filter
// should ignore. // should ignore.
IgnoredResources []string `json:"IgnoredResources,omitempty"` IgnoredResources []string `json:"ignoredResources,omitempty"`
} }
// preFilterState computed at PreFilter and used at Filter. // preFilterState computed at PreFilter and used at Filter.

View File

@ -165,13 +165,12 @@ func TestPriorityQueue_Add(t *testing.T) {
} }
func newDefaultFramework() framework.Framework { func newDefaultFramework() framework.Framework {
defaultCfg := algorithmprovider.NewRegistry(1)[schedulerapi.SchedulerDefaultProviderName] plugins := algorithmprovider.NewRegistry()[schedulerapi.SchedulerDefaultProviderName]
pl, pls := defaultCfg.FrameworkPlugins, defaultCfg.FrameworkPluginConfig
fakeClient := fake.NewSimpleClientset() fakeClient := fake.NewSimpleClientset()
fwk, err := framework.NewFramework( fwk, err := framework.NewFramework(
frameworkplugins.NewInTreeRegistry(), frameworkplugins.NewInTreeRegistry(),
pl, plugins,
pls, nil,
framework.WithClientSet(fakeClient), framework.WithClientSet(fakeClient),
framework.WithInformerFactory(informers.NewSharedInformerFactory(fakeClient, 0)), framework.WithInformerFactory(informers.NewSharedInformerFactory(fakeClient, 0)),
framework.WithSnapshotSharedLister(cache.NewEmptySnapshot()), framework.WithSnapshotSharedLister(cache.NewEmptySnapshot()),