Graduate PodSchedulingReadiness to beta

This commit is contained in:
Wei Huang 2023-02-15 15:04:59 -08:00
parent ccaa730805
commit 72863f65d6
No known key found for this signature in database
GPG Key ID: 17AFE05D01EA77B2
13 changed files with 160 additions and 181 deletions

View File

@ -1438,37 +1438,23 @@ profiles:
Profiles: []kubeschedulerconfig.KubeSchedulerProfile{ Profiles: []kubeschedulerconfig.KubeSchedulerProfile{
{ {
SchedulerName: "foo-profile", SchedulerName: "foo-profile",
Plugins: &kubeschedulerconfig.Plugins{ Plugins: func() *kubeschedulerconfig.Plugins {
QueueSort: defaults.PluginsV1beta2.QueueSort, plugins := defaults.PluginsV1beta2.DeepCopy()
PreFilter: defaults.PluginsV1beta2.PreFilter, plugins.Reserve.Enabled = []kubeschedulerconfig.Plugin{
Filter: defaults.PluginsV1beta2.Filter, {Name: "foo"},
PostFilter: defaults.PluginsV1beta2.PostFilter, {Name: names.VolumeBinding},
PreScore: defaults.PluginsV1beta2.PreScore, }
Score: defaults.PluginsV1beta2.Score, return plugins
Bind: defaults.PluginsV1beta2.Bind, }(),
PreBind: defaults.PluginsV1beta2.PreBind,
Reserve: kubeschedulerconfig.PluginSet{
Enabled: []kubeschedulerconfig.Plugin{
{Name: "foo"},
{Name: names.VolumeBinding},
},
},
},
PluginConfig: defaults.PluginConfigsV1beta2, PluginConfig: defaults.PluginConfigsV1beta2,
}, },
{ {
SchedulerName: "bar-profile", SchedulerName: "bar-profile",
Plugins: &kubeschedulerconfig.Plugins{ Plugins: func() *kubeschedulerconfig.Plugins {
PreEnqueue: defaults.PluginsV1beta2.PreEnqueue, plugins := defaults.PluginsV1beta2.DeepCopy()
QueueSort: defaults.PluginsV1beta2.QueueSort, plugins.PreBind.Enabled = nil
PreFilter: defaults.PluginsV1beta2.PreFilter, return plugins
Filter: defaults.PluginsV1beta2.Filter, }(),
PostFilter: defaults.PluginsV1beta2.PostFilter,
PreScore: defaults.PluginsV1beta2.PreScore,
Score: defaults.PluginsV1beta2.Score,
Bind: defaults.PluginsV1beta2.Bind,
Reserve: defaults.PluginsV1beta2.Reserve,
},
PluginConfig: []kubeschedulerconfig.PluginConfig{ PluginConfig: []kubeschedulerconfig.PluginConfig{
{ {
Name: "foo", Name: "foo",

View File

@ -42,7 +42,6 @@ import (
"k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/apis/config"
"k8s.io/kubernetes/pkg/scheduler/apis/config/testing/defaults" "k8s.io/kubernetes/pkg/scheduler/apis/config/testing/defaults"
"k8s.io/kubernetes/pkg/scheduler/framework" "k8s.io/kubernetes/pkg/scheduler/framework"
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/names"
) )
func TestSetup(t *testing.T) { func TestSetup(t *testing.T) {
@ -318,21 +317,33 @@ leaderElection:
wantLeaderElection *componentbaseconfig.LeaderElectionConfiguration wantLeaderElection *componentbaseconfig.LeaderElectionConfiguration
}{ }{
{ {
name: "default config with two alpha features enabled", name: "default config with an alpha feature enabled",
flags: []string{ flags: []string{
"--kubeconfig", configKubeconfig, "--kubeconfig", configKubeconfig,
"--feature-gates=VolumeCapacityPriority=true,PodSchedulingReadiness=true", "--feature-gates=VolumeCapacityPriority=true",
},
wantPlugins: map[string]*config.Plugins{
"default-scheduler": defaults.ExpandedPluginsV1,
},
restoreFeatures: map[featuregate.Feature]bool{
features.VolumeCapacityPriority: false,
},
},
{
name: "default config with a beta feature disabled",
flags: []string{
"--kubeconfig", configKubeconfig,
"--feature-gates=PodSchedulingReadiness=false",
}, },
wantPlugins: map[string]*config.Plugins{ wantPlugins: map[string]*config.Plugins{
"default-scheduler": func() *config.Plugins { "default-scheduler": func() *config.Plugins {
plugins := defaults.ExpandedPluginsV1.DeepCopy() plugins := defaults.ExpandedPluginsV1.DeepCopy()
plugins.PreEnqueue.Enabled = append(plugins.PreEnqueue.Enabled, config.Plugin{Name: names.SchedulingGates}) plugins.PreEnqueue = config.PluginSet{}
return plugins return plugins
}(), }(),
}, },
restoreFeatures: map[featuregate.Feature]bool{ restoreFeatures: map[featuregate.Feature]bool{
features.VolumeCapacityPriority: false, features.PodSchedulingReadiness: true,
features.PodSchedulingReadiness: false,
}, },
}, },
{ {
@ -351,37 +362,26 @@ leaderElection:
"--kubeconfig", configKubeconfig, "--kubeconfig", configKubeconfig,
}, },
wantPlugins: map[string]*config.Plugins{ wantPlugins: map[string]*config.Plugins{
"default-scheduler": { "default-scheduler": func() *config.Plugins {
Bind: config.PluginSet{Enabled: []config.Plugin{{Name: "DefaultBinder"}}}, plugins := defaults.PluginsV1beta2.DeepCopy()
Filter: config.PluginSet{ plugins.Filter.Enabled = []config.Plugin{
Enabled: []config.Plugin{ {Name: "NodeResourcesFit"},
{Name: "NodeResourcesFit"}, {Name: "NodePorts"},
{Name: "NodePorts"}, }
}, plugins.PreFilter.Enabled = []config.Plugin{
}, {Name: "NodeResourcesFit"},
PreFilter: config.PluginSet{ {Name: "NodePorts"},
Enabled: []config.Plugin{ }
{Name: "NodeResourcesFit"}, plugins.PreScore.Enabled = []config.Plugin{
{Name: "NodePorts"}, {Name: "InterPodAffinity"},
}, {Name: "TaintToleration"},
}, }
PostFilter: config.PluginSet{Enabled: []config.Plugin{{Name: "DefaultPreemption"}}}, plugins.Score.Enabled = []config.Plugin{
PreScore: config.PluginSet{ {Name: "InterPodAffinity", Weight: 1},
Enabled: []config.Plugin{ {Name: "TaintToleration", Weight: 1},
{Name: "InterPodAffinity"}, }
{Name: "TaintToleration"}, return plugins
}, }(),
},
QueueSort: config.PluginSet{Enabled: []config.Plugin{{Name: "PrioritySort"}}},
Score: config.PluginSet{
Enabled: []config.Plugin{
{Name: "InterPodAffinity", Weight: 1},
{Name: "TaintToleration", Weight: 1},
},
},
Reserve: config.PluginSet{Enabled: []config.Plugin{{Name: "VolumeBinding"}}},
PreBind: config.PluginSet{Enabled: []config.Plugin{{Name: "VolumeBinding"}}},
},
}, },
}, },
{ {
@ -391,38 +391,26 @@ leaderElection:
"--kubeconfig", configKubeconfig, "--kubeconfig", configKubeconfig,
}, },
wantPlugins: map[string]*config.Plugins{ wantPlugins: map[string]*config.Plugins{
"default-scheduler": { "default-scheduler": func() *config.Plugins {
PreEnqueue: config.PluginSet{Enabled: []config.Plugin{{Name: "SchedulingGates"}}}, plugins := defaults.ExpandedPluginsV1beta3.DeepCopy()
Bind: config.PluginSet{Enabled: []config.Plugin{{Name: "DefaultBinder"}}}, plugins.Filter.Enabled = []config.Plugin{
Filter: config.PluginSet{ {Name: "NodeResourcesFit"},
Enabled: []config.Plugin{ {Name: "NodePorts"},
{Name: "NodeResourcesFit"}, }
{Name: "NodePorts"}, plugins.PreFilter.Enabled = []config.Plugin{
}, {Name: "NodeResourcesFit"},
}, {Name: "NodePorts"},
PreFilter: config.PluginSet{ }
Enabled: []config.Plugin{ plugins.PreScore.Enabled = []config.Plugin{
{Name: "NodeResourcesFit"}, {Name: "InterPodAffinity"},
{Name: "NodePorts"}, {Name: "TaintToleration"},
}, }
}, plugins.Score.Enabled = []config.Plugin{
PostFilter: config.PluginSet{Enabled: []config.Plugin{{Name: "DefaultPreemption"}}}, {Name: "InterPodAffinity", Weight: 1},
PreScore: config.PluginSet{ {Name: "TaintToleration", Weight: 1},
Enabled: []config.Plugin{ }
{Name: "InterPodAffinity"}, return plugins
{Name: "TaintToleration"}, }(),
},
},
QueueSort: config.PluginSet{Enabled: []config.Plugin{{Name: "PrioritySort"}}},
Score: config.PluginSet{
Enabled: []config.Plugin{
{Name: "InterPodAffinity", Weight: 1},
{Name: "TaintToleration", Weight: 1},
},
},
Reserve: config.PluginSet{Enabled: []config.Plugin{{Name: "VolumeBinding"}}},
PreBind: config.PluginSet{Enabled: []config.Plugin{{Name: "VolumeBinding"}}},
},
}, },
}, },
{ {
@ -432,38 +420,26 @@ leaderElection:
"--kubeconfig", configKubeconfig, "--kubeconfig", configKubeconfig,
}, },
wantPlugins: map[string]*config.Plugins{ wantPlugins: map[string]*config.Plugins{
"default-scheduler": { "default-scheduler": func() *config.Plugins {
PreEnqueue: config.PluginSet{Enabled: []config.Plugin{{Name: "SchedulingGates"}}}, plugins := defaults.ExpandedPluginsV1.DeepCopy()
Bind: config.PluginSet{Enabled: []config.Plugin{{Name: "DefaultBinder"}}}, plugins.Filter.Enabled = []config.Plugin{
Filter: config.PluginSet{ {Name: "NodeResourcesFit"},
Enabled: []config.Plugin{ {Name: "NodePorts"},
{Name: "NodeResourcesFit"}, }
{Name: "NodePorts"}, plugins.PreFilter.Enabled = []config.Plugin{
}, {Name: "NodeResourcesFit"},
}, {Name: "NodePorts"},
PreFilter: config.PluginSet{ }
Enabled: []config.Plugin{ plugins.PreScore.Enabled = []config.Plugin{
{Name: "NodeResourcesFit"}, {Name: "InterPodAffinity"},
{Name: "NodePorts"}, {Name: "TaintToleration"},
}, }
}, plugins.Score.Enabled = []config.Plugin{
PostFilter: config.PluginSet{Enabled: []config.Plugin{{Name: "DefaultPreemption"}}}, {Name: "InterPodAffinity", Weight: 1},
PreScore: config.PluginSet{ {Name: "TaintToleration", Weight: 1},
Enabled: []config.Plugin{ }
{Name: "InterPodAffinity"}, return plugins
{Name: "TaintToleration"}, }(),
},
},
QueueSort: config.PluginSet{Enabled: []config.Plugin{{Name: "PrioritySort"}}},
Score: config.PluginSet{
Enabled: []config.Plugin{
{Name: "InterPodAffinity", Weight: 1},
{Name: "TaintToleration", Weight: 1},
},
},
Reserve: config.PluginSet{Enabled: []config.Plugin{{Name: "VolumeBinding"}}},
PreBind: config.PluginSet{Enabled: []config.Plugin{{Name: "VolumeBinding"}}},
},
}, },
}, },
{ {
@ -474,21 +450,12 @@ leaderElection:
}, },
registryOptions: []Option{WithPlugin("Foo", newFoo)}, registryOptions: []Option{WithPlugin("Foo", newFoo)},
wantPlugins: map[string]*config.Plugins{ wantPlugins: map[string]*config.Plugins{
"default-scheduler": { "default-scheduler": func() *config.Plugins {
Bind: defaults.PluginsV1beta2.Bind, plugins := defaults.PluginsV1beta2.DeepCopy()
Filter: config.PluginSet{ plugins.PreFilter.Enabled = append(plugins.PreFilter.Enabled, config.Plugin{Name: "Foo"})
Enabled: append(defaults.PluginsV1beta2.Filter.Enabled, config.Plugin{Name: "Foo"}), plugins.Filter.Enabled = append(plugins.Filter.Enabled, config.Plugin{Name: "Foo"})
}, return plugins
PreFilter: config.PluginSet{ }(),
Enabled: append(defaults.PluginsV1beta2.PreFilter.Enabled, config.Plugin{Name: "Foo"}),
},
PostFilter: defaults.PluginsV1beta2.PostFilter,
PreScore: defaults.PluginsV1beta2.PreScore,
QueueSort: defaults.PluginsV1beta2.QueueSort,
Score: defaults.PluginsV1beta2.Score,
Reserve: defaults.PluginsV1beta2.Reserve,
PreBind: defaults.PluginsV1beta2.PreBind,
},
}, },
}, },
{ {
@ -499,21 +466,12 @@ leaderElection:
}, },
registryOptions: []Option{WithPlugin("Foo", newFoo)}, registryOptions: []Option{WithPlugin("Foo", newFoo)},
wantPlugins: map[string]*config.Plugins{ wantPlugins: map[string]*config.Plugins{
"default-scheduler": { "default-scheduler": func() *config.Plugins {
Bind: defaults.ExpandedPluginsV1beta3.Bind, plugins := defaults.ExpandedPluginsV1beta3.DeepCopy()
Filter: config.PluginSet{ plugins.PreFilter.Enabled = append(plugins.PreFilter.Enabled, config.Plugin{Name: "Foo"})
Enabled: append(defaults.ExpandedPluginsV1beta3.Filter.Enabled, config.Plugin{Name: "Foo"}), plugins.Filter.Enabled = append(plugins.Filter.Enabled, config.Plugin{Name: "Foo"})
}, return plugins
PreFilter: config.PluginSet{ }(),
Enabled: append(defaults.ExpandedPluginsV1beta3.PreFilter.Enabled, config.Plugin{Name: "Foo"}),
},
PostFilter: defaults.ExpandedPluginsV1beta3.PostFilter,
PreScore: defaults.ExpandedPluginsV1beta3.PreScore,
QueueSort: defaults.ExpandedPluginsV1beta3.QueueSort,
Score: defaults.ExpandedPluginsV1beta3.Score,
Reserve: defaults.ExpandedPluginsV1beta3.Reserve,
PreBind: defaults.ExpandedPluginsV1beta3.PreBind,
},
}, },
}, },
{ {
@ -524,22 +482,12 @@ leaderElection:
}, },
registryOptions: []Option{WithPlugin("Foo", newFoo)}, registryOptions: []Option{WithPlugin("Foo", newFoo)},
wantPlugins: map[string]*config.Plugins{ wantPlugins: map[string]*config.Plugins{
"default-scheduler": { "default-scheduler": func() *config.Plugins {
PreEnqueue: defaults.ExpandedPluginsV1.PreEnqueue, plugins := defaults.ExpandedPluginsV1.DeepCopy()
Bind: defaults.ExpandedPluginsV1.Bind, plugins.PreFilter.Enabled = append(plugins.PreFilter.Enabled, config.Plugin{Name: "Foo"})
Filter: config.PluginSet{ plugins.Filter.Enabled = append(plugins.Filter.Enabled, config.Plugin{Name: "Foo"})
Enabled: append(defaults.ExpandedPluginsV1.Filter.Enabled, config.Plugin{Name: "Foo"}), return plugins
}, }(),
PreFilter: config.PluginSet{
Enabled: append(defaults.ExpandedPluginsV1.PreFilter.Enabled, config.Plugin{Name: "Foo"}),
},
PostFilter: defaults.ExpandedPluginsV1.PostFilter,
PreScore: defaults.ExpandedPluginsV1.PreScore,
QueueSort: defaults.ExpandedPluginsV1.QueueSort,
Score: defaults.ExpandedPluginsV1.Score,
Reserve: defaults.ExpandedPluginsV1.Reserve,
PreBind: defaults.ExpandedPluginsV1.PreBind,
},
}, },
}, },
{ {

View File

@ -3044,9 +3044,14 @@ type PodSpec struct {
OS *PodOS OS *PodOS
// SchedulingGates is an opaque list of values that if specified will block scheduling the pod. // SchedulingGates is an opaque list of values that if specified will block scheduling the pod.
// More info: https://git.k8s.io/enhancements/keps/sig-scheduling/3521-pod-scheduling-readiness. // If schedulingGates is not empty, the pod will stay in the SchedulingGated state and the
// scheduler will not attempt to schedule the pod.
// //
// This is an alpha-level feature enabled by PodSchedulingReadiness feature gate. // SchedulingGates can only be set at pod creation time, and be removed only afterwards.
//
// This is a beta feature enabled by the PodSchedulingReadiness feature gate.
//
// +featureGate=PodSchedulingReadiness
// +optional // +optional
SchedulingGates []PodSchedulingGate SchedulingGates []PodSchedulingGate
// ResourceClaims defines which ResourceClaims must be allocated // ResourceClaims defines which ResourceClaims must be allocated

View File

@ -611,6 +611,7 @@ const (
// owner: @Huang-Wei // owner: @Huang-Wei
// kep: https://kep.k8s.io/3521 // kep: https://kep.k8s.io/3521
// alpha: v1.26 // alpha: v1.26
// beta: v1.27
// //
// Enable users to specify when a Pod is ready for scheduling. // Enable users to specify when a Pod is ready for scheduling.
PodSchedulingReadiness featuregate.Feature = "PodSchedulingReadiness" PodSchedulingReadiness featuregate.Feature = "PodSchedulingReadiness"
@ -999,7 +1000,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
PodHasNetworkCondition: {Default: false, PreRelease: featuregate.Alpha}, PodHasNetworkCondition: {Default: false, PreRelease: featuregate.Alpha},
PodSchedulingReadiness: {Default: false, PreRelease: featuregate.Alpha}, PodSchedulingReadiness: {Default: true, PreRelease: featuregate.Beta},
PodSecurity: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, PodSecurity: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},

View File

@ -23,6 +23,11 @@ import (
// PluginsV1beta2 default set of v1beta2 plugins. // PluginsV1beta2 default set of v1beta2 plugins.
var PluginsV1beta2 = &config.Plugins{ var PluginsV1beta2 = &config.Plugins{
PreEnqueue: config.PluginSet{
Enabled: []config.Plugin{
{Name: names.SchedulingGates},
},
},
QueueSort: config.PluginSet{ QueueSort: config.PluginSet{
Enabled: []config.Plugin{ Enabled: []config.Plugin{
{Name: names.PrioritySort}, {Name: names.PrioritySort},
@ -176,12 +181,18 @@ var PluginsV1beta3 = &config.Plugins{
{Name: names.NodeResourcesBalancedAllocation, Weight: 1}, {Name: names.NodeResourcesBalancedAllocation, Weight: 1},
{Name: names.ImageLocality, Weight: 1}, {Name: names.ImageLocality, Weight: 1},
{Name: names.DefaultBinder}, {Name: names.DefaultBinder},
{Name: names.SchedulingGates},
}, },
}, },
} }
// ExpandedPluginsV1beta3 default set of v1beta3 plugins after MultiPoint expansion // ExpandedPluginsV1beta3 default set of v1beta3 plugins after MultiPoint expansion
var ExpandedPluginsV1beta3 = &config.Plugins{ var ExpandedPluginsV1beta3 = &config.Plugins{
PreEnqueue: config.PluginSet{
Enabled: []config.Plugin{
{Name: names.SchedulingGates},
},
},
QueueSort: config.PluginSet{ QueueSort: config.PluginSet{
Enabled: []config.Plugin{ Enabled: []config.Plugin{
{Name: names.PrioritySort}, {Name: names.PrioritySort},
@ -347,12 +358,18 @@ var PluginsV1 = &config.Plugins{
{Name: names.NodeResourcesBalancedAllocation, Weight: 1}, {Name: names.NodeResourcesBalancedAllocation, Weight: 1},
{Name: names.ImageLocality, Weight: 1}, {Name: names.ImageLocality, Weight: 1},
{Name: names.DefaultBinder}, {Name: names.DefaultBinder},
{Name: names.SchedulingGates},
}, },
}, },
} }
// ExpandedPluginsV1 default set of v1 plugins after MultiPoint expansion // ExpandedPluginsV1 default set of v1 plugins after MultiPoint expansion
var ExpandedPluginsV1 = &config.Plugins{ var ExpandedPluginsV1 = &config.Plugins{
PreEnqueue: config.PluginSet{
Enabled: []config.Plugin{
{Name: names.SchedulingGates},
},
},
QueueSort: config.PluginSet{ QueueSort: config.PluginSet{
Enabled: []config.Plugin{ Enabled: []config.Plugin{
{Name: names.PrioritySort}, {Name: names.PrioritySort},

View File

@ -38,6 +38,9 @@ func TestApplyFeatureGates(t *testing.T) {
}{ }{
{ {
name: "Feature gates disabled", name: "Feature gates disabled",
features: map[featuregate.Feature]bool{
features.PodSchedulingReadiness: false,
},
wantConfig: &v1.Plugins{ wantConfig: &v1.Plugins{
MultiPoint: v1.PluginSet{ MultiPoint: v1.PluginSet{
Enabled: []v1.Plugin{ Enabled: []v1.Plugin{
@ -127,6 +130,7 @@ func TestApplyFeatureGates(t *testing.T) {
{Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32(1)}, {Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32(1)},
{Name: names.ImageLocality, Weight: pointer.Int32(1)}, {Name: names.ImageLocality, Weight: pointer.Int32(1)},
{Name: names.DefaultBinder}, {Name: names.DefaultBinder},
{Name: names.SchedulingGates},
}, },
}, },
}, },

View File

@ -348,6 +348,7 @@ func TestSchedulerDefaults(t *testing.T) {
{Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32(1)}, {Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32(1)},
{Name: names.ImageLocality, Weight: pointer.Int32(1)}, {Name: names.ImageLocality, Weight: pointer.Int32(1)},
{Name: names.DefaultBinder}, {Name: names.DefaultBinder},
{Name: names.SchedulingGates},
}, },
}, },
Bind: configv1.PluginSet{ Bind: configv1.PluginSet{

View File

@ -37,6 +37,9 @@ func TestApplyFeatureGates(t *testing.T) {
}{ }{
{ {
name: "Feature gates disabled", name: "Feature gates disabled",
features: map[featuregate.Feature]bool{
features.PodSchedulingReadiness: false,
},
wantConfig: &v1beta2.Plugins{ wantConfig: &v1beta2.Plugins{
QueueSort: v1beta2.PluginSet{ QueueSort: v1beta2.PluginSet{
Enabled: []v1beta2.Plugin{ Enabled: []v1beta2.Plugin{

View File

@ -326,6 +326,11 @@ func TestSchedulerDefaults(t *testing.T) {
{ {
SchedulerName: pointer.String("custom-scheduler"), SchedulerName: pointer.String("custom-scheduler"),
Plugins: &v1beta2.Plugins{ Plugins: &v1beta2.Plugins{
PreEnqueue: v1beta2.PluginSet{
Enabled: []v1beta2.Plugin{
{Name: "SchedulingGates"},
},
},
QueueSort: v1beta2.PluginSet{ QueueSort: v1beta2.PluginSet{
Enabled: []v1beta2.Plugin{ Enabled: []v1beta2.Plugin{
{Name: names.PrioritySort}, {Name: names.PrioritySort},

View File

@ -37,6 +37,9 @@ func TestApplyFeatureGates(t *testing.T) {
}{ }{
{ {
name: "Feature gates disabled", name: "Feature gates disabled",
features: map[featuregate.Feature]bool{
features.PodSchedulingReadiness: false,
},
wantConfig: &v1beta3.Plugins{ wantConfig: &v1beta3.Plugins{
MultiPoint: v1beta3.PluginSet{ MultiPoint: v1beta3.PluginSet{
Enabled: []v1beta3.Plugin{ Enabled: []v1beta3.Plugin{

View File

@ -348,6 +348,7 @@ func TestSchedulerDefaults(t *testing.T) {
{Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32(1)}, {Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32(1)},
{Name: names.ImageLocality, Weight: pointer.Int32(1)}, {Name: names.ImageLocality, Weight: pointer.Int32(1)},
{Name: names.DefaultBinder}, {Name: names.DefaultBinder},
{Name: names.SchedulingGates},
}, },
}, },
Bind: v1beta3.PluginSet{ Bind: v1beta3.PluginSet{

View File

@ -3386,14 +3386,19 @@ type PodSpec struct {
HostUsers *bool `json:"hostUsers,omitempty" protobuf:"bytes,37,opt,name=hostUsers"` HostUsers *bool `json:"hostUsers,omitempty" protobuf:"bytes,37,opt,name=hostUsers"`
// SchedulingGates is an opaque list of values that if specified will block scheduling the pod. // SchedulingGates is an opaque list of values that if specified will block scheduling the pod.
// More info: https://git.k8s.io/enhancements/keps/sig-scheduling/3521-pod-scheduling-readiness. // If schedulingGates is not empty, the pod will stay in the SchedulingGated state and the
// scheduler will not attempt to schedule the pod.
//
// SchedulingGates can only be set at pod creation time, and be removed only afterwards.
//
// This is a beta feature enabled by the PodSchedulingReadiness feature gate.
// //
// This is an alpha-level feature enabled by PodSchedulingReadiness feature gate.
// +optional
// +patchMergeKey=name // +patchMergeKey=name
// +patchStrategy=merge // +patchStrategy=merge
// +listType=map // +listType=map
// +listMapKey=name // +listMapKey=name
// +featureGate=PodSchedulingReadiness
// +optional
SchedulingGates []PodSchedulingGate `json:"schedulingGates,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,38,opt,name=schedulingGates"` SchedulingGates []PodSchedulingGate `json:"schedulingGates,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,38,opt,name=schedulingGates"`
// ResourceClaims defines which ResourceClaims must be allocated // ResourceClaims defines which ResourceClaims must be allocated
// and reserved before the Pod is allowed to start. The resources // and reserved before the Pod is allowed to start. The resources

View File

@ -806,7 +806,7 @@ var _ = SIGDescribe("SchedulerPredicates [Serial]", func() {
}) })
}) })
ginkgo.It("validates Pods with non-empty schedulingGates are blocked on scheduling [Feature:PodSchedulingReadiness] [alpha]", func(ctx context.Context) { ginkgo.It("validates Pods with non-empty schedulingGates are blocked on scheduling", func(ctx context.Context) {
podLabel := "e2e-scheduling-gates" podLabel := "e2e-scheduling-gates"
replicas := 3 replicas := 3
ginkgo.By(fmt.Sprintf("Creating a ReplicaSet with replicas=%v, carrying scheduling gates [foo bar]", replicas)) ginkgo.By(fmt.Sprintf("Creating a ReplicaSet with replicas=%v, carrying scheduling gates [foo bar]", replicas))