Merge pull request #139520 from macsko/merge_featuregates

Merge GangScheduling and WorkloadAwarePreemption feature gates into GenericWorkload
This commit is contained in:
Kubernetes Prow Robot 2026-06-17 12:33:35 +05:30 committed by GitHub
commit 05f19de8ed
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
49 changed files with 314 additions and 1018 deletions

View file

@ -20001,19 +20001,19 @@
"properties": {
"disruptionMode": {
"$ref": "#/definitions/io.k8s.api.scheduling.v1alpha3.DisruptionMode",
"description": "DisruptionMode defines the mode in which a given PodGroup can be disrupted. Controllers are expected to fill this field by copying it from a PodGroupTemplate. One of Single, All. Defaults to Single if unset. This field is immutable. This field is available only when the WorkloadAwarePreemption feature gate is enabled."
"description": "DisruptionMode defines the mode in which a given PodGroup can be disrupted. Controllers are expected to fill this field by copying it from a PodGroupTemplate. One of Single, All. Defaults to Single if unset. This field is immutable."
},
"podGroupTemplateRef": {
"$ref": "#/definitions/io.k8s.api.scheduling.v1alpha3.PodGroupTemplateReference",
"description": "PodGroupTemplateRef references an optional PodGroup template within other object (e.g. Workload) that was used to create the PodGroup. This field is immutable."
},
"priority": {
"description": "Priority is the value of priority of this pod group. Various system components use this field to find the priority of the pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
"description": "Priority is the value of priority of this pod group. Various system components use this field to find the priority of the pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable.",
"format": "int32",
"type": "integer"
},
"priorityClassName": {
"description": "PriorityClassName defines the priority that should be considered when scheduling this pod group. Controllers are expected to fill this field by copying it from a PodGroupTemplate. Otherwise, it is validated and resolved similarly to the PriorityClassName on PodGroupTemplate (i.e. if no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, the pod group's priority will be zero). This field is immutable. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
"description": "PriorityClassName defines the priority that should be considered when scheduling this pod group. Controllers are expected to fill this field by copying it from a PodGroupTemplate. Otherwise, it is validated and resolved similarly to the PriorityClassName on PodGroupTemplate (i.e. if no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, the pod group's priority will be zero). This field is immutable.",
"type": "string"
},
"resourceClaims": {
@ -20080,19 +20080,19 @@
"properties": {
"disruptionMode": {
"$ref": "#/definitions/io.k8s.api.scheduling.v1alpha3.DisruptionMode",
"description": "DisruptionMode defines the mode in which a given PodGroup can be disrupted. One of Single, All. This field is available only when the WorkloadAwarePreemption feature gate is enabled."
"description": "DisruptionMode defines the mode in which a given PodGroup can be disrupted. One of Single, All."
},
"name": {
"description": "Name is a unique identifier for the PodGroupTemplate within the Workload. It must be a DNS label. This field is immutable.",
"type": "string"
},
"priority": {
"description": "Priority is the value of priority of pod groups created from this template. Various system components use this field to find the priority of the pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
"description": "Priority is the value of priority of pod groups created from this template. Various system components use this field to find the priority of the pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority.",
"format": "int32",
"type": "integer"
},
"priorityClassName": {
"description": "PriorityClassName indicates the priority that should be considered when scheduling a pod group created from this template. If no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, pod groups created from this template will have the priority set to zero. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
"description": "PriorityClassName indicates the priority that should be considered when scheduling a pod group created from this template. If no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, pod groups created from this template will have the priority set to zero.",
"type": "string"
},
"resourceClaims": {

View file

@ -241,7 +241,7 @@
"default": {
"single": {}
},
"description": "DisruptionMode defines the mode in which a given PodGroup can be disrupted. Controllers are expected to fill this field by copying it from a PodGroupTemplate. One of Single, All. Defaults to Single if unset. This field is immutable. This field is available only when the WorkloadAwarePreemption feature gate is enabled."
"description": "DisruptionMode defines the mode in which a given PodGroup can be disrupted. Controllers are expected to fill this field by copying it from a PodGroupTemplate. One of Single, All. Defaults to Single if unset. This field is immutable."
},
"podGroupTemplateRef": {
"allOf": [
@ -252,12 +252,12 @@
"description": "PodGroupTemplateRef references an optional PodGroup template within other object (e.g. Workload) that was used to create the PodGroup. This field is immutable."
},
"priority": {
"description": "Priority is the value of priority of this pod group. Various system components use this field to find the priority of the pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
"description": "Priority is the value of priority of this pod group. Various system components use this field to find the priority of the pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable.",
"format": "int32",
"type": "integer"
},
"priorityClassName": {
"description": "PriorityClassName defines the priority that should be considered when scheduling this pod group. Controllers are expected to fill this field by copying it from a PodGroupTemplate. Otherwise, it is validated and resolved similarly to the PriorityClassName on PodGroupTemplate (i.e. if no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, the pod group's priority will be zero). This field is immutable. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
"description": "PriorityClassName defines the priority that should be considered when scheduling this pod group. Controllers are expected to fill this field by copying it from a PodGroupTemplate. Otherwise, it is validated and resolved similarly to the PriorityClassName on PodGroupTemplate (i.e. if no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, the pod group's priority will be zero). This field is immutable.",
"type": "string"
},
"resourceClaims": {
@ -337,7 +337,7 @@
"$ref": "#/components/schemas/io.k8s.api.scheduling.v1alpha3.DisruptionMode"
}
],
"description": "DisruptionMode defines the mode in which a given PodGroup can be disrupted. One of Single, All. This field is available only when the WorkloadAwarePreemption feature gate is enabled."
"description": "DisruptionMode defines the mode in which a given PodGroup can be disrupted. One of Single, All."
},
"name": {
"default": "",
@ -345,12 +345,12 @@
"type": "string"
},
"priority": {
"description": "Priority is the value of priority of pod groups created from this template. Various system components use this field to find the priority of the pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
"description": "Priority is the value of priority of pod groups created from this template. Various system components use this field to find the priority of the pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority.",
"format": "int32",
"type": "integer"
},
"priorityClassName": {
"description": "PriorityClassName indicates the priority that should be considered when scheduling a pod group created from this template. If no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, pod groups created from this template will have the priority set to zero. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
"description": "PriorityClassName indicates the priority that should be considered when scheduling a pod group created from this template. If no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, pod groups created from this template will have the priority set to zero.",
"type": "string"
},
"resourceClaims": {

View file

@ -215,10 +215,7 @@ type PodGroupTemplate struct {
// DisruptionMode defines the mode in which a given PodGroup can be disrupted.
// One of Single, All.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +optional
DisruptionMode *DisruptionMode
@ -226,10 +223,7 @@ type PodGroupTemplate struct {
// a pod group created from this template. If no priority class is specified, admission
// control can set this to the global default priority class if it exists. Otherwise,
// pod groups created from this template will have the priority set to zero.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +optional
PriorityClassName string
@ -238,10 +232,7 @@ type PodGroupTemplate struct {
// Priority Admission Controller is enabled, it prevents users from setting this field.
// The admission controller populates this field from PriorityClassName.
// The higher the value, the higher the priority.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +optional
Priority *int32
}
@ -437,10 +428,7 @@ type PodGroupSpec struct {
// Controllers are expected to fill this field by copying it from a PodGroupTemplate.
// One of Single, All. Defaults to Single if unset.
// This field is immutable.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +optional
DisruptionMode *DisruptionMode
@ -450,10 +438,7 @@ type PodGroupSpec struct {
// (i.e. if no priority class is specified, admission control can set this to the global default
// priority class if it exists. Otherwise, the pod group's priority will be zero).
// This field is immutable.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +optional
PriorityClassName string
@ -463,10 +448,7 @@ type PodGroupSpec struct {
// controller populates this field from PriorityClassName.
// The higher the value, the higher the priority.
// This field is immutable.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +optional
Priority *int32
}

View file

@ -722,19 +722,12 @@ func Validate_PodGroupSpec(
}
// call field-attached validations
earlyReturn := false
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", false, validate.ForbiddenPointer).MarkShortCircuit(); len(e) != 0 {
if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 {
errs = append(errs, e...)
earlyReturn = true
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", false, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 {
earlyReturn = true
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", true, // optional fields with default values are effectively required
validate.RequiredPointer).MarkShortCircuit(); len(e) != 0 {
errs = append(errs, e...)
earlyReturn = true
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", true, validate.Immutable).MarkShortCircuit(); len(e) != 0 {
// optional fields with default values are effectively required
if e := validate.RequiredPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 {
errs = append(errs, e...)
earlyReturn = true
}
@ -765,24 +758,17 @@ func Validate_PodGroupSpec(
}
// call field-attached validations
earlyReturn := false
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", false, validate.ForbiddenValue).MarkShortCircuit(); len(e) != 0 {
if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 {
errs = append(errs, e...)
earlyReturn = true
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", false, validate.OptionalValue).MarkShortCircuit(); len(e) != 0 {
earlyReturn = true
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", true, validate.OptionalValue).MarkShortCircuit(); len(e) != 0 {
earlyReturn = true
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", true, validate.Immutable).MarkShortCircuit(); len(e) != 0 {
errs = append(errs, e...)
if e := validate.OptionalValue(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", true, validate.LongName); len(e) != 0 {
if e := validate.LongName(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
errs = append(errs, e...)
}
return
@ -807,27 +793,17 @@ func Validate_PodGroupSpec(
}
// call field-attached validations
earlyReturn := false
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", false, validate.ForbiddenPointer).MarkShortCircuit(); len(e) != 0 {
if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 {
errs = append(errs, e...)
earlyReturn = true
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", false, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 {
earlyReturn = true
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", true, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 {
earlyReturn = true
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", true, validate.Immutable).MarkShortCircuit(); len(e) != 0 {
errs = append(errs, e...)
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", true,
func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *int32) field.ErrorList {
return validate.Maximum(ctx, op, fldPath, obj, oldObj, 1000000000)
}); len(e) != 0 {
if e := validate.Maximum(ctx, op, fldPath, obj, oldObj, 1000000000); len(e) != 0 {
errs = append(errs, e...)
}
return
@ -1091,14 +1067,7 @@ func Validate_PodGroupTemplate(
}
// call field-attached validations
earlyReturn := false
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", false, validate.ForbiddenPointer).MarkShortCircuit(); len(e) != 0 {
errs = append(errs, e...)
earlyReturn = true
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", false, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 {
earlyReturn = true
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", true, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 {
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
@ -1128,20 +1097,13 @@ func Validate_PodGroupTemplate(
}
// call field-attached validations
earlyReturn := false
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", false, validate.ForbiddenValue).MarkShortCircuit(); len(e) != 0 {
errs = append(errs, e...)
earlyReturn = true
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", false, validate.OptionalValue).MarkShortCircuit(); len(e) != 0 {
earlyReturn = true
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", true, validate.OptionalValue).MarkShortCircuit(); len(e) != 0 {
if e := validate.OptionalValue(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", true, validate.LongName); len(e) != 0 {
if e := validate.LongName(ctx, op, fldPath, obj, oldObj); len(e) != 0 {
errs = append(errs, e...)
}
return
@ -1166,23 +1128,13 @@ func Validate_PodGroupTemplate(
}
// call field-attached validations
earlyReturn := false
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", false, validate.ForbiddenPointer).MarkShortCircuit(); len(e) != 0 {
errs = append(errs, e...)
earlyReturn = true
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", false, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 {
earlyReturn = true
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", true, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 {
if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 {
earlyReturn = true
}
if earlyReturn {
return // do not proceed
}
if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "WorkloadAwarePreemption", true,
func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *int32) field.ErrorList {
return validate.Maximum(ctx, op, fldPath, obj, oldObj, 1000000000)
}); len(e) != 0 {
if e := validate.Maximum(ctx, op, fldPath, obj, oldObj, 1000000000); len(e) != 0 {
errs = append(errs, e...)
}
return

View file

@ -374,11 +374,6 @@ const (
// If enabled, it allows passing --service-account-signing-endpoint flag to configure external signer.
ExternalServiceAccountTokenSigner featuregate.Feature = "ExternalServiceAccountTokenSigner"
// owner: @erictune @wojtek-t
//
// Enables support for gang scheduling in kube-scheduler.
GangScheduling featuregate.Feature = "GangScheduling"
// owner: @erictune @wojtek-t
//
// Enables support for generic Workload API.
@ -1169,13 +1164,6 @@ const (
// Enables support for joining Windows containers to a hosts' network namespace.
WindowsHostNetwork featuregate.Feature = "WindowsHostNetwork"
// owner: @wojtek-t
// kep: https://kep.k8s.io/5710
//
// Enables support for workload-aware preemption in pod group scheduling cycle
// and related PodGroup and Workload API fields.
WorkloadAwarePreemption featuregate.Feature = "WorkloadAwarePreemption"
// owner: @helayoty @mm4tt @wojtek-t
// kep: https://kep.k8s.io/5547
//
@ -1422,10 +1410,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate
{Version: version.MustParse("1.36"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
},
GangScheduling: {
{Version: version.MustParse("1.35"), Default: false, PreRelease: featuregate.Alpha},
},
GenericWorkload: {
{Version: version.MustParse("1.35"), Default: false, PreRelease: featuregate.Alpha},
},
@ -2046,10 +2030,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate
{Version: version.MustParse("1.33"), Default: false, PreRelease: featuregate.Deprecated},
},
WorkloadAwarePreemption: {
{Version: version.MustParse("1.36"), Default: false, PreRelease: featuregate.Alpha},
},
WorkloadWithJob: {
{Version: version.MustParse("1.36"), Default: false, PreRelease: featuregate.Alpha},
},
@ -2358,8 +2338,6 @@ var defaultKubernetesFeatureGateDependencies = map[featuregate.Feature][]feature
ExternalServiceAccountTokenSigner: {},
GangScheduling: {GenericWorkload},
GenericWorkload: {},
GitRepoVolumeDriver: {},
@ -2606,8 +2584,6 @@ var defaultKubernetesFeatureGateDependencies = map[featuregate.Feature][]feature
WindowsHostNetwork: {},
WorkloadAwarePreemption: {GangScheduling},
WorkloadWithJob: {GenericWorkload},
apiextensionsfeatures.CRDObservedGenerationTracking: {},

View file

@ -54303,21 +54303,21 @@ func schema_k8sio_api_scheduling_v1alpha3_PodGroupSpec(ref common.ReferenceCallb
},
"disruptionMode": {
SchemaProps: spec.SchemaProps{
Description: "DisruptionMode defines the mode in which a given PodGroup can be disrupted. Controllers are expected to fill this field by copying it from a PodGroupTemplate. One of Single, All. Defaults to Single if unset. This field is immutable. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
Description: "DisruptionMode defines the mode in which a given PodGroup can be disrupted. Controllers are expected to fill this field by copying it from a PodGroupTemplate. One of Single, All. Defaults to Single if unset. This field is immutable.",
Default: map[string]interface{}{"single": map[string]interface{}{}},
Ref: ref(schedulingv1alpha3.DisruptionMode{}.OpenAPIModelName()),
},
},
"priorityClassName": {
SchemaProps: spec.SchemaProps{
Description: "PriorityClassName defines the priority that should be considered when scheduling this pod group. Controllers are expected to fill this field by copying it from a PodGroupTemplate. Otherwise, it is validated and resolved similarly to the PriorityClassName on PodGroupTemplate (i.e. if no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, the pod group's priority will be zero). This field is immutable. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
Description: "PriorityClassName defines the priority that should be considered when scheduling this pod group. Controllers are expected to fill this field by copying it from a PodGroupTemplate. Otherwise, it is validated and resolved similarly to the PriorityClassName on PodGroupTemplate (i.e. if no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, the pod group's priority will be zero). This field is immutable.",
Type: []string{"string"},
Format: "",
},
},
"priority": {
SchemaProps: spec.SchemaProps{
Description: "Priority is the value of priority of this pod group. Various system components use this field to find the priority of the pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
Description: "Priority is the value of priority of this pod group. Various system components use this field to find the priority of the pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable.",
Type: []string{"integer"},
Format: "int32",
},
@ -54445,20 +54445,20 @@ func schema_k8sio_api_scheduling_v1alpha3_PodGroupTemplate(ref common.ReferenceC
},
"disruptionMode": {
SchemaProps: spec.SchemaProps{
Description: "DisruptionMode defines the mode in which a given PodGroup can be disrupted. One of Single, All. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
Description: "DisruptionMode defines the mode in which a given PodGroup can be disrupted. One of Single, All.",
Ref: ref(schedulingv1alpha3.DisruptionMode{}.OpenAPIModelName()),
},
},
"priorityClassName": {
SchemaProps: spec.SchemaProps{
Description: "PriorityClassName indicates the priority that should be considered when scheduling a pod group created from this template. If no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, pod groups created from this template will have the priority set to zero. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
Description: "PriorityClassName indicates the priority that should be considered when scheduling a pod group created from this template. If no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, pod groups created from this template will have the priority set to zero.",
Type: []string{"string"},
Format: "",
},
},
"priority": {
SchemaProps: spec.SchemaProps{
Description: "Priority is the value of priority of pod groups created from this template. Various system components use this field to find the priority of the pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
Description: "Priority is the value of priority of pod groups created from this template. Various system components use this field to find the priority of the pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority.",
Type: []string{"integer"},
Format: "int32",
},

View file

@ -71,6 +71,9 @@ func validNewPodGroup() *scheduling.PodGroup {
MinCount: 5,
},
},
DisruptionMode: &scheduling.DisruptionMode{
Single: &scheduling.SingleDisruptionMode{},
},
},
}
}

View file

@ -83,9 +83,6 @@ func (*podGroupStrategy) DeclarativeValidationConfig(ctx context.Context, obj, o
if utilfeature.DefaultFeatureGate.Enabled(features.DRAWorkloadResourceClaims) {
opts = append(opts, string(features.DRAWorkloadResourceClaims))
}
if utilfeature.DefaultFeatureGate.Enabled(features.WorkloadAwarePreemption) {
opts = append(opts, string(features.WorkloadAwarePreemption))
}
return rest.DeclarativeValidationConfig{Options: opts}
}
@ -176,9 +173,6 @@ func dropDisabledPodGroupFields(podGroup, oldPodGroup *scheduling.PodGroup) {
func dropDisabledPodGroupSpecFields(podGroupSpec, oldPodGroupSpec *scheduling.PodGroupSpec) {
dropDisabledSchedulingConstraintsFields(podGroupSpec, oldPodGroupSpec)
dropDisabledDRAWorkloadResourceClaimsFields(podGroupSpec, oldPodGroupSpec)
dropDisabledDisruptionModeField(podGroupSpec, oldPodGroupSpec)
dropDisabledPriorityClassNameField(podGroupSpec, oldPodGroupSpec)
dropDisabledPriorityField(podGroupSpec, oldPodGroupSpec)
}
func dropDisabledPodGroupStatusFields(newPodGroup, oldPodGroup *scheduling.PodGroup) {
@ -214,36 +208,6 @@ func dropDisabledDRAWorkloadResourceClaimsFields(podGroupSpec, oldPodGroupSpec *
podGroupSpec.ResourceClaims = nil
}
// dropDisabledDisruptionModeField removes the DisruptionMode field unless it is
// already used in the old PodGroup spec.
func dropDisabledDisruptionModeField(podGroupSpec, oldPodGroupSpec *scheduling.PodGroupSpec) {
if utilfeature.DefaultFeatureGate.Enabled(features.WorkloadAwarePreemption) || disruptionModeInUse(oldPodGroupSpec) {
// No need to drop anything.
return
}
podGroupSpec.DisruptionMode = nil
}
// dropDisabledPriorityClassNameField removes the PriorityClassName field unless
// it is already used in the old PodGroup spec.
func dropDisabledPriorityClassNameField(podGroupSpec, oldPodGroupSpec *scheduling.PodGroupSpec) {
if utilfeature.DefaultFeatureGate.Enabled(features.WorkloadAwarePreemption) || priorityClassNameInUse(oldPodGroupSpec) {
// No need to drop anything.
return
}
podGroupSpec.PriorityClassName = ""
}
// dropDisabledPriorityField removes the Priority field unless it is already used
// in the old PodGroup spec.
func dropDisabledPriorityField(podGroupSpec, oldPodGroupSpec *scheduling.PodGroupSpec) {
if utilfeature.DefaultFeatureGate.Enabled(features.WorkloadAwarePreemption) || priorityInUse(oldPodGroupSpec) {
// No need to drop anything.
return
}
podGroupSpec.Priority = nil
}
func schedulingConstraintsInUse(podGroupSpec *scheduling.PodGroupSpec) bool {
return podGroupSpec != nil && podGroupSpec.SchedulingConstraints != nil
}
@ -251,15 +215,3 @@ func schedulingConstraintsInUse(podGroupSpec *scheduling.PodGroupSpec) bool {
func draWorkloadResourceClaimsInUse(podGroupSpec *scheduling.PodGroupSpec) bool {
return podGroupSpec != nil && len(podGroupSpec.ResourceClaims) > 0
}
func disruptionModeInUse(podGroupSpec *scheduling.PodGroupSpec) bool {
return podGroupSpec != nil && podGroupSpec.DisruptionMode != nil
}
func priorityClassNameInUse(podGroupSpec *scheduling.PodGroupSpec) bool {
return podGroupSpec != nil && podGroupSpec.PriorityClassName != ""
}
func priorityInUse(podGroupSpec *scheduling.PodGroupSpec) bool {
return podGroupSpec != nil && podGroupSpec.Priority != nil
}

View file

@ -52,6 +52,9 @@ var podGroup = &scheduling.PodGroup{
MinCount: 5,
},
},
DisruptionMode: &scheduling.DisruptionMode{
Single: &scheduling.SingleDisruptionMode{},
},
},
}
@ -67,14 +70,6 @@ func podGroupWithSchedulingConstraints(keys ...string) *scheduling.PodGroup {
return pg
}
func podGroupWithDisruptionModeSingle() *scheduling.PodGroup {
pg := podGroup.DeepCopy()
pg.Spec.DisruptionMode = &scheduling.DisruptionMode{
Single: &scheduling.SingleDisruptionMode{},
}
return pg
}
func podGroupWithDisruptionModeAll() *scheduling.PodGroup {
pg := podGroup.DeepCopy()
pg.Spec.DisruptionMode = &scheduling.DisruptionMode{
@ -129,7 +124,6 @@ func TestStrategyCreate(t *testing.T) {
obj *scheduling.PodGroup
expectObj *scheduling.PodGroup
enableTopologyAwareScheduling bool
enableWorkloadAwarePreemption bool
expectValidationError string
}{
"simple": {
@ -198,84 +192,53 @@ func TestStrategyCreate(t *testing.T) {
obj: podGroupWithSchedulingConstraints("foo-"),
expectObj: podGroup,
},
"workload aware preemption disabled - drop disruption mode": {
obj: podGroupWithDisruptionModeSingle(),
expectObj: podGroup,
"disruption mode all": {
obj: podGroupWithDisruptionModeAll(),
expectObj: podGroupWithDisruptionModeAll(),
},
"workload aware preemption enabled - preserve disruption mode (pod)": {
obj: podGroupWithDisruptionModeSingle(),
expectObj: podGroupWithDisruptionModeSingle(),
enableWorkloadAwarePreemption: true,
"both disruption modes set": {
obj: podGroupWithDisruptionModeBoth(),
expectValidationError: "must specify exactly one of",
},
"workload aware preemption enabled - preserve disruption mode (pod group)": {
obj: podGroupWithDisruptionModeAll(),
expectObj: podGroupWithDisruptionModeAll(),
enableWorkloadAwarePreemption: true,
},
"workload aware preemption enabled - both disruption modes set": {
obj: podGroupWithDisruptionModeBoth(),
enableWorkloadAwarePreemption: true,
expectValidationError: "must specify exactly one of",
},
"workload aware preemption disabled - drop priorityClassName": {
"invalid priorityClassName": {
obj: func() *scheduling.PodGroup {
pg := podGroupWithDisruptionModeSingle()
pg.Spec.PriorityClassName = "high-priority"
return pg
}(),
expectObj: podGroup,
},
"workload aware preemption enabled - invalid priorityClassName": {
obj: func() *scheduling.PodGroup {
pg := podGroupWithDisruptionModeSingle()
pg := podGroup.DeepCopy()
pg.Spec.PriorityClassName = "invalid/priority/class/name"
return pg
}(),
enableWorkloadAwarePreemption: true,
expectValidationError: subdomainNameError,
expectValidationError: subdomainNameError,
},
"workload aware preemption enabled - preserve priorityClassName": {
"priorityClassName set": {
obj: func() *scheduling.PodGroup {
pg := podGroupWithDisruptionModeSingle()
pg := podGroup.DeepCopy()
pg.Spec.PriorityClassName = "high-priority"
return pg
}(),
expectObj: func() *scheduling.PodGroup {
pg := podGroupWithDisruptionModeSingle()
pg := podGroup.DeepCopy()
pg.Spec.PriorityClassName = "high-priority"
return pg
}(),
enableWorkloadAwarePreemption: true,
},
"workload aware preemption disabled - drop priority": {
"priority set": {
obj: func() *scheduling.PodGroup {
pg := podGroupWithDisruptionModeSingle()
pg.Spec.Priority = new(int32(1000))
return pg
}(),
expectObj: podGroup,
},
"workload aware preemption enabled - preserve priority": {
obj: func() *scheduling.PodGroup {
pg := podGroupWithDisruptionModeSingle()
pg := podGroup.DeepCopy()
pg.Spec.Priority = new(int32(1000))
return pg
}(),
expectObj: func() *scheduling.PodGroup {
pg := podGroupWithDisruptionModeSingle()
pg := podGroup.DeepCopy()
pg.Spec.Priority = new(int32(1000))
return pg
}(),
enableWorkloadAwarePreemption: true,
},
"workload aware preemption enabled - too high priority": {
"too high priority": {
obj: func() *scheduling.PodGroup {
pg := podGroupWithDisruptionModeSingle()
pg := podGroup.DeepCopy()
pg.Spec.Priority = new(int32(scheduling.HighestUserDefinablePriority + 1))
return pg
}(),
enableWorkloadAwarePreemption: true,
expectValidationError: maximumError,
expectValidationError: maximumError,
},
}
@ -284,8 +247,6 @@ func TestStrategyCreate(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.TopologyAwareWorkloadScheduling: tc.enableTopologyAwareScheduling,
features.GangScheduling: tc.enableWorkloadAwarePreemption,
features.WorkloadAwarePreemption: tc.enableWorkloadAwarePreemption,
})
podGroup := tc.obj.DeepCopy()
@ -327,7 +288,6 @@ func TestStrategyUpdate(t *testing.T) {
oldObj *scheduling.PodGroup
newObj *scheduling.PodGroup
enableTopologyAwareScheduling bool
enableWorkloadAwarePreemption bool
expectValidationError string
}{
"no changes": {
@ -410,62 +370,28 @@ func TestStrategyUpdate(t *testing.T) {
newObj: podGroupWithSchedulingConstraints("foobar"),
expectValidationError: forbiddenError,
},
"disruption mode update, workload aware preemption disabled": {
oldObj: podGroupWithDisruptionModeSingle(),
"changing disruption mode not allowed": {
oldObj: podGroup,
newObj: podGroupWithDisruptionModeAll(),
expectValidationError: forbiddenError,
expectValidationError: fieldImmutableError,
},
"disruption mode update, workload aware preemption enabled": {
oldObj: podGroupWithDisruptionModeSingle(),
newObj: podGroupWithDisruptionModeAll(),
enableWorkloadAwarePreemption: true,
expectValidationError: fieldImmutableError,
},
"priority class name update, workload aware preemption disabled": {
oldObj: func() *scheduling.PodGroup {
pg := podGroupWithDisruptionModeSingle()
pg.Spec.PriorityClassName = "low-priority"
return pg
}(),
"changing priority class name not allowed": {
oldObj: podGroup,
newObj: func() *scheduling.PodGroup {
pg := podGroupWithDisruptionModeSingle()
pg := podGroup.DeepCopy()
pg.Spec.PriorityClassName = "high-priority"
return pg
}(),
expectValidationError: forbiddenError,
expectValidationError: fieldImmutableError,
},
"priority class name update, workload aware preemption enabled": {
oldObj: podGroupWithDisruptionModeSingle(),
"changing priority not allowed": {
oldObj: podGroup,
newObj: func() *scheduling.PodGroup {
pg := podGroupWithDisruptionModeSingle()
pg.Spec.PriorityClassName = "high-priority"
return pg
}(),
enableWorkloadAwarePreemption: true,
expectValidationError: fieldImmutableError,
},
"priority update, workload aware preemption disabled": {
oldObj: func() *scheduling.PodGroup {
pg := podGroupWithDisruptionModeSingle()
pg.Spec.Priority = new(int32(1000))
return pg
}(),
newObj: func() *scheduling.PodGroup {
pg := podGroupWithDisruptionModeSingle()
pg := podGroup.DeepCopy()
pg.Spec.Priority = new(int32(2000))
return pg
}(),
expectValidationError: forbiddenError,
},
"priority update, workload aware preemption enabled": {
oldObj: podGroupWithDisruptionModeSingle(),
newObj: func() *scheduling.PodGroup {
pg := podGroupWithDisruptionModeSingle()
pg.Spec.Priority = new(int32(2000))
return pg
}(),
enableWorkloadAwarePreemption: true,
expectValidationError: fieldImmutableError,
expectValidationError: fieldImmutableError,
},
}
@ -474,8 +400,6 @@ func TestStrategyUpdate(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.TopologyAwareWorkloadScheduling: tc.enableTopologyAwareScheduling,
features.GangScheduling: tc.enableWorkloadAwarePreemption,
features.WorkloadAwarePreemption: tc.enableWorkloadAwarePreemption,
})
podGroup := tc.oldObj.DeepCopy()
newPodGroup := tc.newObj.DeepCopy()

View file

@ -62,9 +62,6 @@ func (workloadStrategy) DeclarativeValidationConfig(ctx context.Context, obj, ol
if utilfeature.DefaultFeatureGate.Enabled(features.DRAWorkloadResourceClaims) {
opts = append(opts, string(features.DRAWorkloadResourceClaims))
}
if utilfeature.DefaultFeatureGate.Enabled(features.WorkloadAwarePreemption) {
opts = append(opts, string(features.WorkloadAwarePreemption))
}
return rest.DeclarativeValidationConfig{Options: opts}
}
@ -127,9 +124,6 @@ func dropDisabledPodGroupTemplatesFields(templates, oldTemplates []scheduling.Po
template := &templates[i]
dropDisabledSchedulingConstraintsFields(template, oldTemplate)
dropDisabledDRAWorkloadResourceClaimsFields(template, oldTemplate)
dropDisabledDisruptionModeField(template, oldTemplate)
dropDisabledPriorityClassNameField(template, oldTemplate)
dropDisabledPriorityField(template, oldTemplate)
}
}
@ -151,36 +145,6 @@ func dropDisabledDRAWorkloadResourceClaimsFields(template, oldTemplate *scheduli
template.ResourceClaims = nil
}
// dropDisabledDisruptionModeField removes the DisruptionMode field from a template
// unless it is already used in the old template.
func dropDisabledDisruptionModeField(template, oldTemplate *scheduling.PodGroupTemplate) {
if utilfeature.DefaultFeatureGate.Enabled(features.WorkloadAwarePreemption) || disruptionModeInUse(oldTemplate) {
// No need to drop anything.
return
}
template.DisruptionMode = nil
}
// dropDisabledPriorityClassNameField removes the PriorityClassName field from a template
// unless it is already used in the old template.
func dropDisabledPriorityClassNameField(template, oldTemplate *scheduling.PodGroupTemplate) {
if utilfeature.DefaultFeatureGate.Enabled(features.WorkloadAwarePreemption) || priorityClassNameInUse(oldTemplate) {
// No need to drop anything.
return
}
template.PriorityClassName = ""
}
// dropDisabledPriorityField removes the Priority field from a template unless it is
// already used in the old template.
func dropDisabledPriorityField(template, oldTemplate *scheduling.PodGroupTemplate) {
if utilfeature.DefaultFeatureGate.Enabled(features.WorkloadAwarePreemption) || priorityInUse(oldTemplate) {
// No need to drop anything.
return
}
template.Priority = nil
}
func schedulingConstraintsInUse(pgt *scheduling.PodGroupTemplate) bool {
return pgt != nil && pgt.SchedulingConstraints != nil
}
@ -188,15 +152,3 @@ func schedulingConstraintsInUse(pgt *scheduling.PodGroupTemplate) bool {
func draWorkloadResourceClaimsInUse(pgt *scheduling.PodGroupTemplate) bool {
return pgt != nil && len(pgt.ResourceClaims) > 0
}
func disruptionModeInUse(pgt *scheduling.PodGroupTemplate) bool {
return pgt != nil && pgt.DisruptionMode != nil
}
func priorityClassNameInUse(pgt *scheduling.PodGroupTemplate) bool {
return pgt != nil && pgt.PriorityClassName != ""
}
func priorityInUse(pgt *scheduling.PodGroupTemplate) bool {
return pgt != nil && pgt.Priority != nil
}

View file

@ -87,7 +87,6 @@ func TestStrategyCreate(t *testing.T) {
obj *scheduling.Workload
expectObj *scheduling.Workload
enableTopologyAwareScheduling bool
enableWorkloadAwarePreemption bool
expectValidationError string
}{
"simple": {
@ -156,41 +155,31 @@ func TestStrategyCreate(t *testing.T) {
enableTopologyAwareScheduling: true,
expectValidationError: requiredError,
},
"workload aware preemption disabled - drop disruption mode": {
"disruption mode single": {
obj: func() *scheduling.Workload {
w := workload.DeepCopy()
w.Spec.PodGroupTemplates[0].DisruptionMode = &scheduling.DisruptionMode{Single: &scheduling.SingleDisruptionMode{}}
return w
}(),
expectObj: workload,
},
"workload aware preemption enabled - preserve disruption mode (pod)": {
obj: func() *scheduling.Workload {
w := workload.DeepCopy()
w.Spec.PodGroupTemplates[0].DisruptionMode = &scheduling.DisruptionMode{Single: &scheduling.SingleDisruptionMode{}}
return w
}(),
enableWorkloadAwarePreemption: true,
expectObj: func() *scheduling.Workload {
w := workload.DeepCopy()
w.Spec.PodGroupTemplates[0].DisruptionMode = &scheduling.DisruptionMode{Single: &scheduling.SingleDisruptionMode{}}
return w
}(),
},
"workload aware preemption enabled - preserve disruption mode (pod group)": {
"disruption mode all": {
obj: func() *scheduling.Workload {
w := workload.DeepCopy()
w.Spec.PodGroupTemplates[0].DisruptionMode = &scheduling.DisruptionMode{All: &scheduling.AllDisruptionMode{}}
return w
}(),
enableWorkloadAwarePreemption: true,
expectObj: func() *scheduling.Workload {
w := workload.DeepCopy()
w.Spec.PodGroupTemplates[0].DisruptionMode = &scheduling.DisruptionMode{All: &scheduling.AllDisruptionMode{}}
return w
}(),
},
"workload aware preemption enabled - both disruption modes set": {
"both disruption modes set": {
obj: func() *scheduling.Workload {
w := workload.DeepCopy()
w.Spec.PodGroupTemplates[0].DisruptionMode = &scheduling.DisruptionMode{
@ -199,38 +188,27 @@ func TestStrategyCreate(t *testing.T) {
}
return w
}(),
enableWorkloadAwarePreemption: true,
expectValidationError: "must specify exactly one of",
expectValidationError: "must specify exactly one of",
},
"workload aware preemption enabled - preserve priorityClassName": {
"priorityClassName set": {
obj: func() *scheduling.Workload {
w := workload.DeepCopy()
w.Spec.PodGroupTemplates[0].PriorityClassName = "high-priority"
return w
}(),
enableWorkloadAwarePreemption: true,
expectObj: func() *scheduling.Workload {
w := workload.DeepCopy()
w.Spec.PodGroupTemplates[0].PriorityClassName = "high-priority"
return w
}(),
},
"workload aware preemption disabled - drop priorityClassName": {
obj: func() *scheduling.Workload {
w := workload.DeepCopy()
w.Spec.PodGroupTemplates[0].PriorityClassName = "high-priority"
return w
}(),
expectObj: workload,
},
"workload aware preemption enabled - invalid priorityClassName": {
"invalid priorityClassName": {
obj: func() *scheduling.Workload {
w := workload.DeepCopy()
w.Spec.PodGroupTemplates[0].PriorityClassName = "invalid/priority/class/name"
return w
}(),
enableWorkloadAwarePreemption: true,
expectValidationError: subdomainNameError,
expectValidationError: subdomainNameError,
},
}
@ -241,8 +219,6 @@ func TestStrategyCreate(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.TopologyAwareWorkloadScheduling: tc.enableTopologyAwareScheduling,
features.GangScheduling: tc.enableWorkloadAwarePreemption,
features.WorkloadAwarePreemption: tc.enableWorkloadAwarePreemption,
})
Strategy.PrepareForCreate(ctx, workload)
@ -275,7 +251,6 @@ func TestStrategyUpdate(t *testing.T) {
oldObj *scheduling.Workload
newObj *scheduling.Workload
enableTopologyAwareScheduling bool
enableWorkloadAwarePreemption bool
expectValidationError string
expectWorkload *scheduling.Workload
}{
@ -479,30 +454,16 @@ func TestStrategyUpdate(t *testing.T) {
enableTopologyAwareScheduling: true,
expectValidationError: fieldImmutableError,
},
"disruption mode update, workload aware preemption disabled": {
oldObj: func() *scheduling.Workload {
w := workload.DeepCopy()
w.Spec.PodGroupTemplates[0].DisruptionMode = &scheduling.DisruptionMode{All: &scheduling.AllDisruptionMode{}}
return w
}(),
newObj: func() *scheduling.Workload {
w := workload.DeepCopy()
w.Spec.PodGroupTemplates[0].DisruptionMode = &scheduling.DisruptionMode{Single: &scheduling.SingleDisruptionMode{}}
return w
}(),
expectValidationError: fieldImmutableError,
},
"disruption mode update, workload aware preemption enabled": {
"changing disruption mode": {
oldObj: workload,
newObj: func() *scheduling.Workload {
w := workload.DeepCopy()
w.Spec.PodGroupTemplates[0].DisruptionMode = &scheduling.DisruptionMode{Single: &scheduling.SingleDisruptionMode{}}
return w
}(),
enableWorkloadAwarePreemption: true,
expectValidationError: fieldImmutableError,
expectValidationError: fieldImmutableError,
},
"priorityClassName update, workload aware preemption disabled": {
"changing priorityClassName": {
oldObj: func() *scheduling.Workload {
w := workload.DeepCopy()
w.Spec.PodGroupTemplates[0].PriorityClassName = "high-priority"
@ -515,20 +476,6 @@ func TestStrategyUpdate(t *testing.T) {
}(),
expectValidationError: fieldImmutableError,
},
"priorityClassName update, workload aware preemption enabled": {
oldObj: func() *scheduling.Workload {
w := workload.DeepCopy()
w.Spec.PodGroupTemplates[0].PriorityClassName = "high-priority"
return w
}(),
newObj: func() *scheduling.Workload {
w := workload.DeepCopy()
w.Spec.PodGroupTemplates[0].PriorityClassName = "low-priority"
return w
}(),
enableWorkloadAwarePreemption: true,
expectValidationError: fieldImmutableError,
},
}
for name, tc := range testCases {
@ -536,8 +483,6 @@ func TestStrategyUpdate(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.TopologyAwareWorkloadScheduling: tc.enableTopologyAwareScheduling,
features.GangScheduling: tc.enableWorkloadAwarePreemption,
features.WorkloadAwarePreemption: tc.enableWorkloadAwarePreemption,
})
oldWorkload := tc.oldObj.DeepCopy()
newWorkload := tc.newObj.DeepCopy()

View file

@ -64,7 +64,7 @@ func applyFeatureGates(config *v1.Plugins) {
if utilfeature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation) {
applyDynamicResources(config)
}
if utilfeature.DefaultFeatureGate.Enabled(features.GangScheduling) {
if utilfeature.DefaultFeatureGate.Enabled(features.GenericWorkload) {
applyGangScheduling(config)
}
if utilfeature.DefaultFeatureGate.Enabled(features.TopologyAwareWorkloadScheduling) {

View file

@ -164,9 +164,8 @@ func TestApplyFeatureGates(t *testing.T) {
},
},
{
name: "Feature gate GangScheduling enabled",
name: "Feature gate GenericWorkload enabled",
features: map[featuregate.Feature]bool{
features.GangScheduling: true,
features.GenericWorkload: true,
},
wantConfig: &v1.Plugins{
@ -226,6 +225,7 @@ func TestApplyFeatureGates(t *testing.T) {
{Name: names.ImageLocality, Weight: ptr.To[int32](1)},
{Name: names.DefaultBinder},
{Name: names.NodeDeclaredFeatures},
{Name: names.GangScheduling},
{Name: names.TopologyPlacementGenerator},
{Name: names.PodGroupPodsCount, Weight: ptr.To[int32](1)},
},

View file

@ -1021,7 +1021,6 @@ func Test_InFlightPods(t *testing.T) {
t.Run(fmt.Sprintf("%s (genericWorkloadEnabled: %v)", test.name, genericWorkloadEnabled), func(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: genericWorkloadEnabled,
features.GangScheduling: true,
})
logger, ctx := ktesting.NewTestContext(t)
ctx, cancel := context.WithCancel(ctx)
@ -1392,7 +1391,6 @@ func TestPriorityQueue_Pop(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: tt.genericWorkloadEnabled,
features.GangScheduling: tt.genericWorkloadEnabled,
features.SchedulerPopFromBackoffQ: tt.popFromBackoffQEnabled,
})
@ -6132,7 +6130,6 @@ func TestAddPodGroupMember(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
})
_, ctx := ktesting.NewTestContext(t)
@ -6333,7 +6330,6 @@ func TestDeletePodGroupMember(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
})
logger, ctx := ktesting.NewTestContext(t)
@ -6517,7 +6513,6 @@ func TestUpdatePodGroupMember(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
})
_, ctx := ktesting.NewTestContext(t)
@ -6682,7 +6677,6 @@ func TestActivatePodGroupMember(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
})
logger, ctx := ktesting.NewTestContext(t)
@ -6845,7 +6839,6 @@ func TestMoveAllToActiveOrBackoffQueuePodGroupMember(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
})
logger, ctx := ktesting.NewTestContext(t)
@ -6989,7 +6982,6 @@ func TestFlushBackoffQCompletedPodGroupMember(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
})
logger, ctx := ktesting.NewTestContext(t)
@ -7092,7 +7084,6 @@ func TestFlushUnschedulableEntitiesLeftoverPodGroupMember(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
})
logger, ctx := ktesting.NewTestContext(t)
@ -7266,7 +7257,6 @@ func TestAddUnschedulablePodIfNotPresentPodGroupMember(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
})
logger, ctx := ktesting.NewTestContext(t)

View file

@ -212,7 +212,7 @@ func (sched *Scheduler) addPodToSchedulingQueue(pod *v1.Pod) {
logger.V(3).Info("Add event for unscheduled pod", "pod", klog.KObj(pod))
sched.Cache.AddPodGroupMember(pod)
sched.SchedulingQueue.Add(klog.NewContext(context.Background(), logger), pod)
if utilfeature.DefaultFeatureGate.Enabled(features.GangScheduling) {
if utilfeature.DefaultFeatureGate.Enabled(features.GenericWorkload) {
sched.SchedulingQueue.MoveAllToActiveOrBackoffQueue(logger, framework.EventUnscheduledPodAdd, nil, pod, nil)
}
}

View file

@ -113,10 +113,8 @@ func New(_ context.Context, dpArgs runtime.Object, fh fwk.Handle, fts feature.Fe
pl.Executor = preemption.NewExecutor(fh, fts)
pl.Evaluator = preemption.NewEvaluator(Name, fh, &pl, pl.Executor)
if pl.fts.EnableWorkloadAwarePreemption || pl.fts.EnableTopologyAwareWorkloadScheduling {
if pl.fts.EnableGenericWorkload {
pl.pgLister = fh.SharedInformerFactory().Scheduling().V1alpha3().PodGroups().Lister()
}
if pl.fts.EnableWorkloadAwarePreemption {
pl.podGroupEvaluator = preemption.NewPodGroupEvaluator(fh, pl.Executor)
}
@ -138,19 +136,8 @@ func (pl *DefaultPreemption) PostFilter(ctx context.Context, state fwk.CycleStat
metrics.PreemptionAttempts.Inc()
}()
if pod.Spec.SchedulingGroup != nil && pl.fts.EnableTopologyAwareWorkloadScheduling {
pg, err := pl.pgLister.PodGroups(pod.Namespace).Get(*pod.Spec.SchedulingGroup.PodGroupName)
if err != nil {
return nil, fwk.NewStatus(fwk.Unschedulable, "preemption: pod group for pod not found")
}
if pg.Spec.SchedulingConstraints != nil {
// When TAS is enabled, the default preemption logic needs to be disabled to avoid performing preemption multiple times for each topology option.
// The TAS-compatible preemption logic will be implemented in Delayed Preemption KEP 4671 or Workload-aware preemption KEP 5710 features.
return nil, fwk.NewStatus(fwk.Unschedulable, "preemption: not eligible due to placement-based pod group scheduling limitation")
}
}
if pod.Spec.SchedulingGroup != nil && pl.fts.EnableWorkloadAwarePreemption {
// When WAP is enabled, the default preemption logic needs to be disabled for pod group scheduling to avoid performing preemption in pod by pod cycle
if pod.Spec.SchedulingGroup != nil && pl.fts.EnableGenericWorkload {
// When GenericWorkload is enabled, the default preemption logic needs to be disabled for pod group scheduling to avoid performing preemption in pod by pod cycle
// of pod group scheduling. Instead the WAP will be called to perform preemption for the entire pod group.
return nil, fwk.NewStatus(fwk.Unschedulable, "preemption: not eligible due to workload aware preemption enabled")
}
@ -167,7 +154,7 @@ func (pl *DefaultPreemption) PreEnqueue(ctx context.Context, p *v1.Pod) *fwk.Sta
if !pl.fts.EnableAsyncPreemption {
return nil
}
if p.Spec.SchedulingGroup != nil && pl.fts.EnableWorkloadAwarePreemption {
if p.Spec.SchedulingGroup != nil && pl.fts.EnableGenericWorkload {
pg, err := pl.pgLister.PodGroups(p.Namespace).Get(*p.Spec.SchedulingGroup.PodGroupName)
// If the pg is not found do not block the pod. It's not a default preemption responsibility
// to block pods from pod group without pg from entering the queue.

View file

@ -409,31 +409,12 @@ func TestPostFilter(t *testing.T) {
filteredNodesStatuses: framework.NewNodeToStatus(map[string]*fwk.Status{
"node1": fwk.NewStatus(fwk.Unschedulable),
}, fwk.NewStatus(fwk.UnschedulableAndUnresolvable)),
features: feature.Features{EnableTopologyAwareWorkloadScheduling: true},
features: feature.Features{EnableGenericWorkload: true, EnableTopologyAwareWorkloadScheduling: true},
wantResult: nil,
wantStatus: fwk.NewStatus(fwk.Unschedulable, "preemption: not eligible due to placement-based pod group scheduling limitation"),
wantStatus: fwk.NewStatus(fwk.Unschedulable, "preemption: not eligible due to workload aware preemption enabled"),
},
{
name: "pod with SchedulingGroup with TAS with scheduling constraint enabled should not preempt even when WAP is enabled",
pod: st.MakePod().Name("p-with-podgroup").Namespace(v1.NamespaceDefault).PodGroupName("foo").Priority(highPriority).Obj(),
pods: []*v1.Pod{
st.MakePod().Name("p1").UID("p1").Namespace(v1.NamespaceDefault).Node("node1").Obj(),
},
nodes: []*v1.Node{
st.MakeNode().Name("node1").Capacity(onePodRes).Obj(),
},
podGroups: []*v1alpha3.PodGroup{
st.MakePodGroup().Name("foo").Namespace(v1.NamespaceDefault).TopologyKey("rack").Obj(),
},
filteredNodesStatuses: framework.NewNodeToStatus(map[string]*fwk.Status{
"node1": fwk.NewStatus(fwk.Unschedulable),
}, fwk.NewStatus(fwk.UnschedulableAndUnresolvable)),
features: feature.Features{EnableTopologyAwareWorkloadScheduling: true, EnableWorkloadAwarePreemption: true},
wantResult: nil,
wantStatus: fwk.NewStatus(fwk.Unschedulable, "preemption: not eligible due to placement-based pod group scheduling limitation"),
},
{
name: "pod with SchedulingGroup with TAS without scheduling constraint enabled should preempt",
name: "pod with SchedulingGroup with TAS without scheduling constraint enabled should not preempt",
pod: st.MakePod().Name("p-with-podgroup").Namespace(v1.NamespaceDefault).PodGroupName("foo").Priority(highPriority).Obj(),
pods: []*v1.Pod{
st.MakePod().Name("p1").UID("p1").Namespace(v1.NamespaceDefault).Node("node1").Obj(),
@ -447,31 +428,12 @@ func TestPostFilter(t *testing.T) {
filteredNodesStatuses: framework.NewNodeToStatus(map[string]*fwk.Status{
"node1": fwk.NewStatus(fwk.Unschedulable),
}, fwk.NewStatus(fwk.UnschedulableAndUnresolvable)),
features: feature.Features{EnableTopologyAwareWorkloadScheduling: true},
wantResult: framework.NewPostFilterResultWithNominatedNode("node1"),
wantStatus: fwk.NewStatus(fwk.Success),
},
{
name: "pod with SchedulingGroup with TAS with WAP enabled should not preempt",
pod: st.MakePod().Name("p-with-podgroup").Namespace(v1.NamespaceDefault).PodGroupName("foo").Priority(highPriority).Obj(),
pods: []*v1.Pod{
st.MakePod().Name("p1").UID("p1").Namespace(v1.NamespaceDefault).Node("node1").Obj(),
},
nodes: []*v1.Node{
st.MakeNode().Name("node1").Capacity(onePodRes).Obj(),
},
podGroups: []*v1alpha3.PodGroup{
st.MakePodGroup().Name("foo").Namespace(v1.NamespaceDefault).Obj(),
},
filteredNodesStatuses: framework.NewNodeToStatus(map[string]*fwk.Status{
"node1": fwk.NewStatus(fwk.Unschedulable),
}, fwk.NewStatus(fwk.UnschedulableAndUnresolvable)),
features: feature.Features{EnableTopologyAwareWorkloadScheduling: true, EnableWorkloadAwarePreemption: true},
features: feature.Features{EnableGenericWorkload: true, EnableTopologyAwareWorkloadScheduling: true},
wantResult: nil,
wantStatus: fwk.NewStatus(fwk.Unschedulable, "preemption: not eligible due to workload aware preemption enabled"),
},
{
name: "pod with SchedulingGroup with WAP enabled should not preempt",
name: "pod with SchedulingGroup should not preempt",
pod: st.MakePod().Name("p-with-podgroup").PodGroupName("foo").Priority(highPriority).Obj(),
pods: []*v1.Pod{
st.MakePod().Name("p1").UID("p1").Namespace(v1.NamespaceDefault).Node("node1").Obj(),
@ -482,12 +444,12 @@ func TestPostFilter(t *testing.T) {
filteredNodesStatuses: framework.NewNodeToStatus(map[string]*fwk.Status{
"node1": fwk.NewStatus(fwk.Unschedulable),
}, fwk.NewStatus(fwk.UnschedulableAndUnresolvable)),
features: feature.Features{EnableWorkloadAwarePreemption: true},
features: feature.Features{EnableGenericWorkload: true},
wantResult: nil,
wantStatus: fwk.NewStatus(fwk.Unschedulable, "preemption: not eligible due to workload aware preemption enabled"),
},
{
name: "pod with SchedulingGroup with TAS and WAP disabled should preempt",
name: "pod with SchedulingGroup with GenericWorkload and TAS disabled should preempt",
pod: st.MakePod().Name("p-with-podgroup").PodGroupName("foo").Priority(highPriority).Obj(),
pods: []*v1.Pod{
st.MakePod().Name("p1").UID("p1").Namespace(v1.NamespaceDefault).Node("node1").Obj(),
@ -498,7 +460,7 @@ func TestPostFilter(t *testing.T) {
filteredNodesStatuses: framework.NewNodeToStatus(map[string]*fwk.Status{
"node1": fwk.NewStatus(fwk.Unschedulable),
}, fwk.NewStatus(fwk.UnschedulableAndUnresolvable)),
features: feature.Features{EnableTopologyAwareWorkloadScheduling: false, EnableWorkloadAwarePreemption: false},
features: feature.Features{EnableGenericWorkload: false, EnableTopologyAwareWorkloadScheduling: false},
wantResult: framework.NewPostFilterResultWithNominatedNode("node1"),
wantStatus: fwk.NewStatus(fwk.Success),
},
@ -2508,47 +2470,47 @@ func TestPreEnqueue(t *testing.T) {
wantStatus: nil,
},
{
name: "WAP enabled, pod in same PodGroup, returns UnschedulableAndUnresolvable",
name: "GenericWorkload enabled, pod in same PodGroup, returns UnschedulableAndUnresolvable",
podToTriggerPreemption: st.MakePod().Name("p").UID("p").Namespace(v1.NamespaceDefault).PodGroupName("pg1").Priority(highPriority).Obj(),
podToCheck: st.MakePod().Name("p_other").UID("p_other").Namespace(v1.NamespaceDefault).PodGroupName("pg1").Priority(highPriority).Obj(),
pgs: []*v1alpha3.PodGroup{
st.MakePodGroup().Name("pg1").UID("pg1").Namespace(v1.NamespaceDefault).Priority(highPriority).Obj(),
},
features: feature.Features{EnableAsyncPreemption: true, EnableWorkloadAwarePreemption: true},
features: feature.Features{EnableAsyncPreemption: true, EnableGenericWorkload: true},
expectPreemption: true,
wantStatus: fwk.NewStatus(fwk.UnschedulableAndUnresolvable, "waiting for the preemption for this pod group to be finished"),
},
{
name: "WAP disabled, pod in same PodGroup, returns nil",
name: "GenericWorkload disabled, pod in same PodGroup, returns nil",
podToTriggerPreemption: st.MakePod().Name("p").UID("p").Namespace(v1.NamespaceDefault).PodGroupName("pg1").Priority(highPriority).Obj(),
podToCheck: st.MakePod().Name("p_other").UID("p_other").Namespace(v1.NamespaceDefault).PodGroupName("pg1").Priority(highPriority).Obj(),
pgs: []*v1alpha3.PodGroup{
st.MakePodGroup().Name("pg1").UID("pg1").Namespace(v1.NamespaceDefault).Obj(),
},
features: feature.Features{EnableAsyncPreemption: true, EnableWorkloadAwarePreemption: false},
features: feature.Features{EnableAsyncPreemption: true, EnableGenericWorkload: false},
expectPreemption: true,
wantStatus: nil,
},
{
name: "WAP enabled, pod in different PodGroup, returns nil",
name: "GenericWorkload enabled, pod in different PodGroup, returns nil",
podToTriggerPreemption: st.MakePod().Name("p").UID("p").Namespace(v1.NamespaceDefault).PodGroupName("pg1").Priority(highPriority).Obj(),
podToCheck: st.MakePod().Name("p_other").UID("p_other").Namespace(v1.NamespaceDefault).PodGroupName("pg2").Priority(highPriority).Obj(),
pgs: []*v1alpha3.PodGroup{
st.MakePodGroup().Name("pg1").UID("pg1").Namespace(v1.NamespaceDefault).Priority(highPriority).Obj(),
st.MakePodGroup().Name("pg2").UID("pg2").Namespace(v1.NamespaceDefault).Priority(highPriority).Obj(),
},
features: feature.Features{EnableAsyncPreemption: true, EnableWorkloadAwarePreemption: true},
features: feature.Features{EnableAsyncPreemption: true, EnableGenericWorkload: true},
expectPreemption: true,
wantStatus: nil,
},
{
name: "WAP enabled, pod group not found, returns nil",
name: "GenericWorkload enabled, pod group not found, returns nil",
podToTriggerPreemption: st.MakePod().Name("p").UID("p").Namespace(v1.NamespaceDefault).PodGroupName("pg1").Priority(highPriority).Obj(),
podToCheck: st.MakePod().Name("p_other").UID("p_other").Namespace(v1.NamespaceDefault).PodGroupName("pg_missing").Priority(highPriority).Obj(),
pgs: []*v1alpha3.PodGroup{
st.MakePodGroup().Name("pg1").UID("pg1").Namespace(v1.NamespaceDefault).Priority(highPriority).Obj(),
},
features: feature.Features{EnableAsyncPreemption: true, EnableWorkloadAwarePreemption: true},
features: feature.Features{EnableAsyncPreemption: true, EnableGenericWorkload: true},
expectPreemption: false,
wantStatus: nil,
},
@ -2631,7 +2593,7 @@ func TestPreEnqueue(t *testing.T) {
// Trigger preemption. Given custom PreemptPod implementation, the async preemption will not finish until
// finishPreemption is closed.
if tt.features.EnableWorkloadAwarePreemption && tt.podToTriggerPreemption.Spec.SchedulingGroup != nil {
if tt.features.EnableGenericWorkload && tt.podToTriggerPreemption.Spec.SchedulingGroup != nil {
pg, err := informerFactory.Scheduling().V1alpha3().PodGroups().Lister().PodGroups(tt.podToTriggerPreemption.Namespace).Get(*tt.podToTriggerPreemption.Spec.SchedulingGroup.PodGroupName)
if err != nil {
t.Fatalf("could not find pg: %v", err)
@ -2699,7 +2661,7 @@ func TestDefaultPreemption_PodGroupPostFilter_ErrorWrapping(t *testing.T) {
}
features := feature.Features{
EnableWorkloadAwarePreemption: true,
EnableGenericWorkload: true,
}
pl, err := New(ctx, getDefaultDefaultPreemptionArgs(), f, features)
if err != nil {

View file

@ -47,12 +47,10 @@ type Features struct {
EnablePodLevelResources bool
EnableStorageCapacityScoring bool
EnableNodeDeclaredFeatures bool
EnableGangScheduling bool
EnableGenericWorkload bool
EnableTaintTolerationComparisonOperators bool
EnableInPlacePodLevelResourcesVerticalScaling bool
EnableTopologyAwareWorkloadScheduling bool
EnableWorkloadAwarePreemption bool
}
// NewSchedulerFeaturesFromGates copies the current state of the feature gates into the struct.
@ -79,12 +77,10 @@ func NewSchedulerFeaturesFromGates(featureGate featuregate.FeatureGate) Features
EnableDRAPartitionableDevices: featureGate.Enabled(features.DRAPartitionableDevices),
EnableStorageCapacityScoring: featureGate.Enabled(features.StorageCapacityScoring),
EnableNodeDeclaredFeatures: featureGate.Enabled(features.NodeDeclaredFeatures),
EnableGangScheduling: featureGate.Enabled(features.GangScheduling),
EnableGenericWorkload: featureGate.Enabled(features.GenericWorkload),
EnableTaintTolerationComparisonOperators: featureGate.Enabled(features.TaintTolerationComparisonOperators),
EnableInPlacePodLevelResourcesVerticalScaling: featureGate.Enabled(features.InPlacePodLevelResourcesVerticalScaling),
EnableTopologyAwareWorkloadScheduling: featureGate.Enabled(features.TopologyAwareWorkloadScheduling),
EnableDRANodeAllocatableResources: featureGate.Enabled(features.DRANodeAllocatableResources),
EnableWorkloadAwarePreemption: featureGate.Enabled(features.WorkloadAwarePreemption),
}
}

View file

@ -305,7 +305,7 @@ func TestGangSchedulingFlow(t *testing.T) {
}
cache.AddPodGroupMember(tt.pod)
p, err := New(ctx, nil, fh, feature.Features{EnableGangScheduling: true})
p, err := New(ctx, nil, fh, feature.Features{EnableGenericWorkload: true})
if err != nil {
t.Fatalf("Failed to create plugin: %v", err)
}
@ -612,7 +612,7 @@ func TestPlacementFeasible(t *testing.T) {
t.Fatalf("Failed to create framework: %v", err)
}
p, err := New(ctx, nil, fh, feature.Features{EnableGangScheduling: true})
p, err := New(ctx, nil, fh, feature.Features{EnableGenericWorkload: true})
if err != nil {
t.Fatalf("Failed to create plugin: %v", err)
}

View file

@ -320,7 +320,7 @@ func (ev *PodGroupEvaluator) getPodPriority(p *v1.Pod) int32 {
//
// 1. Priority: Higher priority units are always more important.
//
// 2. Workload Type (if WorkloadAwarePreemption is enabled):
// 2. Workload Type:
// Atomic workloads (PodGroups) are considered more important than individual Pods
// of the same priority.
//

View file

@ -476,7 +476,7 @@ func NewFramework(ctx context.Context, r Registry, profile *config.KubeScheduler
}
// Put default preemption as the only PodGroupPostFilterPlugin
if utilfeature.DefaultFeatureGate.Enabled(features.WorkloadAwarePreemption) {
if utilfeature.DefaultFeatureGate.Enabled(features.GenericWorkload) {
if dp, ok := f.pluginsMap[names.DefaultPreemption]; ok {
if _, ok := dp.(framework.PodGroupPostFilterPlugin); ok {
f.podGroupPostFilterPlugins = append(f.podGroupPostFilterPlugins, dp.(framework.PodGroupPostFilterPlugin))

View file

@ -865,9 +865,7 @@ func TestPodGroupPostFilterPlugins(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
if tc.featureGate {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
features.WorkloadAwarePreemption: true,
features.GenericWorkload: true,
})
}

View file

@ -193,7 +193,7 @@ func (sched *Scheduler) podGroupCycle(ctx context.Context, schedFwk framework.Fr
// Run workload aware preemption if required. If the preemption is successful,
// we need to put the pods from pod group back into the scheduling queue.
if sched.workloadAwarePreemptionEnabled && result.status.Code() == fwk.Unschedulable {
if result.status.Code() == fwk.Unschedulable {
pgPostFilterResult, status := sched.runWorkloadAwarePreemption(ctx, schedFwk, podGroupCycleState, podGroupInfo)
if status.IsSuccess() {
result.waitingOnPreemption = true

View file

@ -466,13 +466,12 @@ func TestPodGroupCycle_FillsPodResultsOnFewerResults(t *testing.T) {
var lock sync.Mutex
sched := &Scheduler{
Profiles: profile.Map{"test-scheduler": schedFwk},
SchedulingQueue: internalqueue.NewTestQueue(ctx, nil),
Cache: cache,
client: client,
podGroupLister: podGroupLister,
nodeInfoSnapshot: internalcache.NewEmptySnapshot(),
workloadAwarePreemptionEnabled: false,
Profiles: profile.Map{"test-scheduler": schedFwk},
SchedulingQueue: internalqueue.NewTestQueue(ctx, nil),
Cache: cache,
client: client,
podGroupLister: podGroupLister,
nodeInfoSnapshot: internalcache.NewEmptySnapshot(),
FailureHandler: func(ctx context.Context, fwk framework.Framework, p *framework.QueuedPodInfo, status *fwk.Status, ni *fwk.NominatingInfo, start time.Time) {
lock.Lock()
defer lock.Unlock()
@ -525,25 +524,25 @@ func TestPodGroupCycle_FillsPodResultsOnFewerResults(t *testing.T) {
func TestPodGroupCycle_PodGroupPostFilter(t *testing.T) {
tests := []struct {
name string
wapFeatureGateEnabled bool
genericWorkloadEnabled bool
postFilterPlugin string
expectedPodGroupPostFilterCalled bool
}{
{
name: "runs pod group post filter when WAP is enabled and DefaultPreemption is registered",
wapFeatureGateEnabled: true,
name: "runs pod group post filter when GenericWorkload is enabled and DefaultPreemption is registered",
genericWorkloadEnabled: true,
postFilterPlugin: "DefaultPreemption",
expectedPodGroupPostFilterCalled: true,
},
{
name: "disables pod group post filter when WAP feature gate is disabled",
wapFeatureGateEnabled: false,
name: "disables pod group post filter when GenericWorkload feature gate is disabled",
genericWorkloadEnabled: false,
postFilterPlugin: "DefaultPreemption",
expectedPodGroupPostFilterCalled: false,
},
{
name: "disables pod group post filter when DefaultPreemption is not registered",
wapFeatureGateEnabled: true,
genericWorkloadEnabled: true,
postFilterPlugin: "FakePodGroupPlugin",
expectedPodGroupPostFilterCalled: false,
},
@ -551,11 +550,8 @@ func TestPodGroupCycle_PodGroupPostFilter(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Enable feature gates
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.WorkloadAwarePreemption: tt.wapFeatureGateEnabled,
features.GangScheduling: true,
features.GenericWorkload: tt.genericWorkloadEnabled,
})
testPodGroup := st.MakePodGroup().Name("pg").Namespace("default").Obj()
@ -645,13 +641,13 @@ func TestPodGroupCycle_PodGroupPostFilter(t *testing.T) {
cache.AddNode(logger, testNode)
sched := &Scheduler{
Profiles: profile.Map{"test-scheduler": schedFwk},
SchedulingQueue: internalqueue.NewTestQueue(ctx, nil),
Cache: cache,
client: client,
podGroupLister: podGroupLister,
nodeInfoSnapshot: internalcache.NewEmptySnapshot(),
workloadAwarePreemptionEnabled: tt.wapFeatureGateEnabled,
Profiles: profile.Map{"test-scheduler": schedFwk},
SchedulingQueue: internalqueue.NewTestQueue(ctx, nil),
Cache: cache,
client: client,
podGroupLister: podGroupLister,
nodeInfoSnapshot: internalcache.NewEmptySnapshot(),
genericWorkloadEnabled: tt.genericWorkloadEnabled,
FailureHandler: func(ctx context.Context, fwk framework.Framework, p *framework.QueuedPodInfo, status *fwk.Status, ni *fwk.NominatingInfo, start time.Time) {
},
}
@ -2674,7 +2670,6 @@ func TestPlacementCycleStateLifecycle(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.TopologyAwareWorkloadScheduling: true,
features.GenericWorkload: true,
features.GangScheduling: true,
})
// A single scenario exercises both isolation and continuity:
@ -2884,11 +2879,8 @@ func TestRunWorkloadAwarePreemption(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Enable feature gate before framework initialization
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.WorkloadAwarePreemption: tt.pluginsRegistered,
features.GangScheduling: true,
features.GenericWorkload: true,
})
logger, ctx := ktesting.NewTestContext(t)
@ -2980,11 +2972,7 @@ func TestRunWorkloadAwarePreemption(t *testing.T) {
}
func TestPodGroupCycle_NominatedNodes(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.WorkloadAwarePreemption: true,
features.GangScheduling: true,
})
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.GenericWorkload, true)
testPodGroup := st.MakePodGroup().Name("pg").Namespace("default").Obj()
p1 := st.MakePod().Name("p1").UID("p1").PodGroupName("pg").SchedulerName("test-scheduler").Obj()
@ -3056,13 +3044,12 @@ func TestPodGroupCycle_NominatedNodes(t *testing.T) {
cache := internalcache.New(ctx, nil, true)
sched := &Scheduler{
Profiles: profile.Map{"test-scheduler": schedFwk},
Cache: cache,
nodeInfoSnapshot: internalcache.NewEmptySnapshot(),
podGroupLister: podGroupLister,
workloadAwarePreemptionEnabled: true,
client: client,
SchedulingQueue: internalqueue.NewTestQueue(ctx, nil),
Profiles: profile.Map{"test-scheduler": schedFwk},
Cache: cache,
nodeInfoSnapshot: internalcache.NewEmptySnapshot(),
podGroupLister: podGroupLister,
client: client,
SchedulingQueue: internalqueue.NewTestQueue(ctx, nil),
}
// Mock SchedulePod to return Unschedulable initially, and success on subsequent calls

View file

@ -121,7 +121,6 @@ type Scheduler struct {
nominatedNodeNameForExpectationEnabled bool
genericWorkloadEnabled bool
workloadAwarePreemptionEnabled bool
}
func (sched *Scheduler) applyDefaultHandlers() {
@ -455,7 +454,6 @@ func New(ctx context.Context,
nominatedNodeNameForExpectationEnabled: feature.DefaultFeatureGate.Enabled(features.NominatedNodeNameForExpectation),
podGroupLister: podGroupLister,
genericWorkloadEnabled: feature.DefaultFeatureGate.Enabled(features.GenericWorkload),
workloadAwarePreemptionEnabled: feature.DefaultFeatureGate.Enabled(features.WorkloadAwarePreemption),
}
sched.NextEntity = podQueue.Pop
sched.applyDefaultHandlers()

View file

@ -844,7 +844,7 @@ func Test_UnionedGVKs(t *testing.T) {
enableInPlacePodVerticalScaling bool
enableDynamicResourceAllocation bool
enableNodeDeclaredFeatures bool
enableGangScheduling bool
enableGenericWorkload bool
}{
{
name: "filter without EnqueueExtensions plugin",
@ -896,7 +896,7 @@ func Test_UnionedGVKs(t *testing.T) {
fwk.DeviceClass: fwk.All,
fwk.PodGroup: fwk.All,
},
enableGangScheduling: true,
enableGenericWorkload: true,
enableInPlacePodVerticalScaling: true,
enableDynamicResourceAllocation: true,
},
@ -1055,7 +1055,7 @@ func Test_UnionedGVKs(t *testing.T) {
fwk.ResourceSlice: fwk.All - fwk.Delete,
fwk.PodGroup: fwk.Add,
},
enableGangScheduling: true,
enableGenericWorkload: true,
enableInPlacePodVerticalScaling: true,
enableDynamicResourceAllocation: true,
},
@ -1080,11 +1080,9 @@ func Test_UnionedGVKs(t *testing.T) {
}
}
} else {
featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.NodeDeclaredFeatures, tt.enableNodeDeclaredFeatures)
featuregatetesting.SetFeatureGatesDuringTest(t, feature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.NodeDeclaredFeatures: tt.enableNodeDeclaredFeatures,
features.GenericWorkload: tt.enableGangScheduling,
features.GangScheduling: tt.enableGangScheduling,
features.GenericWorkload: tt.enableGenericWorkload,
})
}
featuregatetesting.SetFeatureGatesDuringTest(t, feature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{

View file

@ -279,7 +279,6 @@ func PodGroupPriority(pg *schedulingv1alpha3.PodGroup) int32 {
}
// When priority of a pod group is nil, it means it was created at a time
// that there was no global default priority class and the priority class
// name of the pod group was empty (or when the WorkloadAwarePreemption
// feature gate was disabled). So, we resolve to the static default priority.
// name of the pod group was empty. So, we resolve to the static default priority.
return 0
}

View file

@ -194,7 +194,7 @@ func (p *Plugin) admitPod(a admission.Attributes) error {
// admitPodGroup makes sure a new pod group does not set spec.Priority field. It also makes sure that
// the PriorityClassName exists if it is provided and resolves the pod group priority from the PriorityClassName.
func (p *Plugin) admitPodGroup(attributes admission.Attributes) error {
if !utilfeature.DefaultFeatureGate.Enabled(features.WorkloadAwarePreemption) {
if !utilfeature.DefaultFeatureGate.Enabled(features.GenericWorkload) {
return nil
}

View file

@ -812,40 +812,40 @@ func TestAdmitPodGroup(t *testing.T) {
}
testCases := []struct {
name string
priorityClasses []*scheduling.PriorityClass
preparePodGroup *scheduling.PodGroup
operation admission.Operation
expectedPriorityClass string
expectedPriority int32
enableWorkloadAwarePreemption bool
expectError bool
name string
priorityClasses []*scheduling.PriorityClass
preparePodGroup *scheduling.PodGroup
operation admission.Operation
expectedPriorityClass string
expectedPriority int32
enableGenericWorkload bool
expectError bool
}{
{
name: "pod group with empty priorityClassName, accepted and set to global default",
priorityClasses: []*scheduling.PriorityClass{defaultClass1, nondefaultClass1},
preparePodGroup: podGroup("" /* empty priorityClassName */),
operation: admission.Create,
expectedPriorityClass: "default1",
expectedPriority: defaultClass1.Value,
enableWorkloadAwarePreemption: true,
name: "pod group with empty priorityClassName, accepted and set to global default",
priorityClasses: []*scheduling.PriorityClass{defaultClass1, nondefaultClass1},
preparePodGroup: podGroup("" /* empty priorityClassName */),
operation: admission.Create,
expectedPriorityClass: "default1",
expectedPriority: defaultClass1.Value,
enableGenericWorkload: true,
},
{
name: "pod group with explicit priorityClassName, accepted",
priorityClasses: []*scheduling.PriorityClass{defaultClass1, nondefaultClass1},
preparePodGroup: podGroup("nondefault1"),
operation: admission.Create,
expectedPriorityClass: "nondefault1",
expectedPriority: nondefaultClass1.Value,
enableWorkloadAwarePreemption: true,
name: "pod group with explicit priorityClassName, accepted",
priorityClasses: []*scheduling.PriorityClass{defaultClass1, nondefaultClass1},
preparePodGroup: podGroup("nondefault1"),
operation: admission.Create,
expectedPriorityClass: "nondefault1",
expectedPriority: nondefaultClass1.Value,
enableGenericWorkload: true,
},
{
name: "pod group with non-existent priorityClassName, rejected",
priorityClasses: []*scheduling.PriorityClass{defaultClass1, nondefaultClass1},
preparePodGroup: podGroup("non-existent"),
operation: admission.Create,
enableWorkloadAwarePreemption: true,
expectError: true,
name: "pod group with non-existent priorityClassName, rejected",
priorityClasses: []*scheduling.PriorityClass{defaultClass1, nondefaultClass1},
preparePodGroup: podGroup("non-existent"),
operation: admission.Create,
enableGenericWorkload: true,
expectError: true,
},
{
name: "pod group with any priorityClassName but feature gate disabled, skips validation",
@ -854,46 +854,44 @@ func TestAdmitPodGroup(t *testing.T) {
operation: admission.Create,
},
{
name: "pod group with no priorityClassName and no global default, accepted and priority should be zero",
priorityClasses: []*scheduling.PriorityClass{nondefaultClass1},
preparePodGroup: podGroup("" /* empty priorityClassName */),
operation: admission.Create,
expectedPriorityClass: "",
expectedPriority: 0,
enableWorkloadAwarePreemption: true,
name: "pod group with no priorityClassName and no global default, accepted and priority should be zero",
priorityClasses: []*scheduling.PriorityClass{nondefaultClass1},
preparePodGroup: podGroup("" /* empty priorityClassName */),
operation: admission.Create,
expectedPriorityClass: "",
expectedPriority: 0,
enableGenericWorkload: true,
},
{
name: "pod group create with pre-set Priority matching computed value, accepted",
priorityClasses: []*scheduling.PriorityClass{defaultClass1, nondefaultClass1},
preparePodGroup: podGroupWithPriority("nondefault1", nondefaultClass1.Value),
operation: admission.Create,
expectedPriorityClass: "nondefault1",
expectedPriority: nondefaultClass1.Value,
enableWorkloadAwarePreemption: true,
name: "pod group create with pre-set Priority matching computed value, accepted",
priorityClasses: []*scheduling.PriorityClass{defaultClass1, nondefaultClass1},
preparePodGroup: podGroupWithPriority("nondefault1", nondefaultClass1.Value),
operation: admission.Create,
expectedPriorityClass: "nondefault1",
expectedPriority: nondefaultClass1.Value,
enableGenericWorkload: true,
},
{
name: "pod group create with pre-set Priority not matching computed value, rejected",
priorityClasses: []*scheduling.PriorityClass{defaultClass1, nondefaultClass1},
preparePodGroup: podGroupWithPriority("nondefault1", int32(9999)),
operation: admission.Create,
enableWorkloadAwarePreemption: true,
expectError: true,
name: "pod group create with pre-set Priority not matching computed value, rejected",
priorityClasses: []*scheduling.PriorityClass{defaultClass1, nondefaultClass1},
preparePodGroup: podGroupWithPriority("nondefault1", int32(9999)),
operation: admission.Create,
enableGenericWorkload: true,
expectError: true,
},
{
name: "update operation is a no-op, admission does not mutate pod group on update",
priorityClasses: []*scheduling.PriorityClass{defaultClass1, nondefaultClass1},
preparePodGroup: podGroup("non-existent"),
operation: admission.Update,
enableWorkloadAwarePreemption: true,
name: "update operation is a no-op, admission does not mutate pod group on update",
priorityClasses: []*scheduling.PriorityClass{defaultClass1, nondefaultClass1},
preparePodGroup: podGroup("non-existent"),
operation: admission.Update,
enableGenericWorkload: true,
},
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, feature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
features.WorkloadAwarePreemption: tt.enableWorkloadAwarePreemption,
features.GenericWorkload: tt.enableGenericWorkload,
})
admissionPlugin := NewPlugin()
@ -907,7 +905,7 @@ func TestAdmitPodGroup(t *testing.T) {
if (err != nil) != tt.expectError {
t.Errorf("PodGroup Admit(), error = %v, want = %v", err, tt.expectError)
}
if !tt.expectError && tt.operation == admission.Create && tt.enableWorkloadAwarePreemption && tt.preparePodGroup.Spec.PodGroupTemplateRef == nil {
if !tt.expectError && tt.operation == admission.Create && tt.enableGenericWorkload && tt.preparePodGroup.Spec.PodGroupTemplateRef == nil {
if tt.preparePodGroup.Spec.PriorityClassName != tt.expectedPriorityClass {
t.Errorf("PodGroup Admit(), priorityClassName = %v, want = %v", tt.preparePodGroup.Spec.PriorityClassName, tt.expectedPriorityClass)
}

View file

@ -269,15 +269,11 @@ message PodGroupSpec {
// Controllers are expected to fill this field by copying it from a PodGroupTemplate.
// One of Single, All. Defaults to Single if unset.
// This field is immutable.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +default={"single": {}}
// +optional
// +k8s:ifDisabled("WorkloadAwarePreemption")=+k8s:forbidden
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:optional
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:immutable
// +k8s:optional
// +k8s:immutable
optional DisruptionMode disruptionMode = 5;
// PriorityClassName defines the priority that should be considered when scheduling this pod group.
@ -286,15 +282,11 @@ message PodGroupSpec {
// (i.e. if no priority class is specified, admission control can set this to the global default
// priority class if it exists. Otherwise, the pod group's priority will be zero).
// This field is immutable.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +optional
// +k8s:ifDisabled("WorkloadAwarePreemption")=+k8s:forbidden
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:optional
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:format=k8s-long-name
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:immutable
// +k8s:optional
// +k8s:immutable
// +k8s:format=k8s-long-name
optional string priorityClassName = 6;
// Priority is the value of priority of this pod group. Various system components
@ -303,15 +295,11 @@ message PodGroupSpec {
// controller populates this field from PriorityClassName.
// The higher the value, the higher the priority.
// This field is immutable.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +optional
// +k8s:ifDisabled("WorkloadAwarePreemption")=+k8s:forbidden
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:optional
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:immutable
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:maximum=1000000000 # HighestUserDefinablePriority
// +k8s:optional
// +k8s:immutable
// +k8s:maximum=1000000000 # HighestUserDefinablePriority
optional int32 priority = 7;
}
@ -407,27 +395,19 @@ message PodGroupTemplate {
// DisruptionMode defines the mode in which a given PodGroup can be disrupted.
// One of Single, All.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +optional
// +k8s:ifDisabled("WorkloadAwarePreemption")=+k8s:forbidden
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:optional
// +k8s:optional
optional DisruptionMode disruptionMode = 5;
// PriorityClassName indicates the priority that should be considered when scheduling
// a pod group created from this template. If no priority class is specified, admission
// control can set this to the global default priority class if it exists. Otherwise,
// pod groups created from this template will have the priority set to zero.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +optional
// +k8s:ifDisabled("WorkloadAwarePreemption")=+k8s:forbidden
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:optional
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:format=k8s-long-name
// +k8s:optional
// +k8s:format=k8s-long-name
optional string priorityClassName = 6;
// Priority is the value of priority of pod groups created from this template. Various
@ -435,14 +415,10 @@ message PodGroupTemplate {
// Priority Admission Controller is enabled, it prevents users from setting this field.
// The admission controller populates this field from PriorityClassName.
// The higher the value, the higher the priority.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +optional
// +k8s:ifDisabled("WorkloadAwarePreemption")=+k8s:forbidden
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:optional
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:maximum=1000000000 # HighestUserDefinablePriority
// +k8s:optional
// +k8s:maximum=1000000000 # HighestUserDefinablePriority
optional int32 priority = 7;
}

View file

@ -164,27 +164,19 @@ type PodGroupTemplate struct {
// DisruptionMode defines the mode in which a given PodGroup can be disrupted.
// One of Single, All.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +optional
// +k8s:ifDisabled("WorkloadAwarePreemption")=+k8s:forbidden
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:optional
// +k8s:optional
DisruptionMode *DisruptionMode `json:"disruptionMode,omitempty" protobuf:"bytes,5,opt,name=disruptionMode"`
// PriorityClassName indicates the priority that should be considered when scheduling
// a pod group created from this template. If no priority class is specified, admission
// control can set this to the global default priority class if it exists. Otherwise,
// pod groups created from this template will have the priority set to zero.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +optional
// +k8s:ifDisabled("WorkloadAwarePreemption")=+k8s:forbidden
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:optional
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:format=k8s-long-name
// +k8s:optional
// +k8s:format=k8s-long-name
PriorityClassName string `json:"priorityClassName,omitempty" protobuf:"bytes,6,opt,name=priorityClassName"`
// Priority is the value of priority of pod groups created from this template. Various
@ -192,14 +184,10 @@ type PodGroupTemplate struct {
// Priority Admission Controller is enabled, it prevents users from setting this field.
// The admission controller populates this field from PriorityClassName.
// The higher the value, the higher the priority.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +optional
// +k8s:ifDisabled("WorkloadAwarePreemption")=+k8s:forbidden
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:optional
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:maximum=1000000000 # HighestUserDefinablePriority
// +k8s:optional
// +k8s:maximum=1000000000 # HighestUserDefinablePriority
Priority *int32 `json:"priority,omitempty" protobuf:"varint,7,opt,name=priority"`
}
@ -427,15 +415,11 @@ type PodGroupSpec struct {
// Controllers are expected to fill this field by copying it from a PodGroupTemplate.
// One of Single, All. Defaults to Single if unset.
// This field is immutable.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +default={"single": {}}
// +optional
// +k8s:ifDisabled("WorkloadAwarePreemption")=+k8s:forbidden
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:optional
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:immutable
// +k8s:optional
// +k8s:immutable
DisruptionMode *DisruptionMode `json:"disruptionMode,omitempty" protobuf:"bytes,5,opt,name=disruptionMode"`
// PriorityClassName defines the priority that should be considered when scheduling this pod group.
@ -444,15 +428,11 @@ type PodGroupSpec struct {
// (i.e. if no priority class is specified, admission control can set this to the global default
// priority class if it exists. Otherwise, the pod group's priority will be zero).
// This field is immutable.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +optional
// +k8s:ifDisabled("WorkloadAwarePreemption")=+k8s:forbidden
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:optional
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:format=k8s-long-name
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:immutable
// +k8s:optional
// +k8s:immutable
// +k8s:format=k8s-long-name
PriorityClassName string `json:"priorityClassName,omitempty" protobuf:"bytes,6,opt,name=priorityClassName"`
// Priority is the value of priority of this pod group. Various system components
@ -461,15 +441,11 @@ type PodGroupSpec struct {
// controller populates this field from PriorityClassName.
// The higher the value, the higher the priority.
// This field is immutable.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
//
// +featureGate=WorkloadAwarePreemption
// +optional
// +k8s:ifDisabled("WorkloadAwarePreemption")=+k8s:forbidden
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:optional
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:immutable
// +k8s:ifEnabled("WorkloadAwarePreemption")=+k8s:maximum=1000000000 # HighestUserDefinablePriority
// +k8s:optional
// +k8s:immutable
// +k8s:maximum=1000000000 # HighestUserDefinablePriority
Priority *int32 `json:"priority,omitempty" protobuf:"varint,7,opt,name=priority"`
}

View file

@ -129,9 +129,9 @@ var map_PodGroupSpec = map[string]string{
"schedulingPolicy": "SchedulingPolicy defines the scheduling policy for this instance of the PodGroup. Controllers are expected to fill this field by copying it from a PodGroupTemplate. This field is immutable.",
"schedulingConstraints": "SchedulingConstraints defines optional scheduling constraints (e.g. topology) for this PodGroup. Controllers are expected to fill this field by copying it from a PodGroupTemplate. This field is immutable. This field is only available when the TopologyAwareWorkloadScheduling feature gate is enabled.",
"resourceClaims": "ResourceClaims defines which ResourceClaims may be shared among Pods in the group. Pods consume the devices allocated to a PodGroup's claim by defining a claim in its own Spec.ResourceClaims that matches the PodGroup's claim exactly. The claim must have the same name and refer to the same ResourceClaim or ResourceClaimTemplate.\n\nThis is an alpha-level field and requires that the DRAWorkloadResourceClaims feature gate is enabled.\n\nThis field is immutable.",
"disruptionMode": "DisruptionMode defines the mode in which a given PodGroup can be disrupted. Controllers are expected to fill this field by copying it from a PodGroupTemplate. One of Single, All. Defaults to Single if unset. This field is immutable. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
"priorityClassName": "PriorityClassName defines the priority that should be considered when scheduling this pod group. Controllers are expected to fill this field by copying it from a PodGroupTemplate. Otherwise, it is validated and resolved similarly to the PriorityClassName on PodGroupTemplate (i.e. if no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, the pod group's priority will be zero). This field is immutable. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
"priority": "Priority is the value of priority of this pod group. Various system components use this field to find the priority of the pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
"disruptionMode": "DisruptionMode defines the mode in which a given PodGroup can be disrupted. Controllers are expected to fill this field by copying it from a PodGroupTemplate. One of Single, All. Defaults to Single if unset. This field is immutable.",
"priorityClassName": "PriorityClassName defines the priority that should be considered when scheduling this pod group. Controllers are expected to fill this field by copying it from a PodGroupTemplate. Otherwise, it is validated and resolved similarly to the PriorityClassName on PodGroupTemplate (i.e. if no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, the pod group's priority will be zero). This field is immutable.",
"priority": "Priority is the value of priority of this pod group. Various system components use this field to find the priority of the pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable.",
}
func (PodGroupSpec) SwaggerDoc() map[string]string {
@ -154,9 +154,9 @@ var map_PodGroupTemplate = map[string]string{
"schedulingPolicy": "SchedulingPolicy defines the scheduling policy for this PodGroupTemplate.",
"schedulingConstraints": "SchedulingConstraints defines optional scheduling constraints (e.g. topology) for this PodGroupTemplate. This field is only available when the TopologyAwareWorkloadScheduling feature gate is enabled.",
"resourceClaims": "ResourceClaims defines which ResourceClaims may be shared among Pods in the group. Pods consume the devices allocated to a PodGroup's claim by defining a claim in its own Spec.ResourceClaims that matches the PodGroup's claim exactly. The claim must have the same name and refer to the same ResourceClaim or ResourceClaimTemplate.\n\nThis is an alpha-level field and requires that the DRAWorkloadResourceClaims feature gate is enabled.\n\nThis field is immutable.",
"disruptionMode": "DisruptionMode defines the mode in which a given PodGroup can be disrupted. One of Single, All. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
"priorityClassName": "PriorityClassName indicates the priority that should be considered when scheduling a pod group created from this template. If no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, pod groups created from this template will have the priority set to zero. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
"priority": "Priority is the value of priority of pod groups created from this template. Various system components use this field to find the priority of the pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is available only when the WorkloadAwarePreemption feature gate is enabled.",
"disruptionMode": "DisruptionMode defines the mode in which a given PodGroup can be disrupted. One of Single, All.",
"priorityClassName": "PriorityClassName indicates the priority that should be considered when scheduling a pod group created from this template. If no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, pod groups created from this template will have the priority set to zero.",
"priority": "Priority is the value of priority of pod groups created from this template. Various system components use this field to find the priority of the pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority.",
}
func (PodGroupTemplate) SwaggerDoc() map[string]string {

View file

@ -50,8 +50,6 @@ type PodGroupSpecApplyConfiguration struct {
// Controllers are expected to fill this field by copying it from a PodGroupTemplate.
// One of Single, All. Defaults to Single if unset.
// This field is immutable.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
DisruptionMode *DisruptionModeApplyConfiguration `json:"disruptionMode,omitempty"`
// PriorityClassName defines the priority that should be considered when scheduling this pod group.
// Controllers are expected to fill this field by copying it from a PodGroupTemplate.
@ -59,8 +57,6 @@ type PodGroupSpecApplyConfiguration struct {
// (i.e. if no priority class is specified, admission control can set this to the global default
// priority class if it exists. Otherwise, the pod group's priority will be zero).
// This field is immutable.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
PriorityClassName *string `json:"priorityClassName,omitempty"`
// Priority is the value of priority of this pod group. Various system components
// use this field to find the priority of the pod group. When Priority Admission
@ -68,8 +64,6 @@ type PodGroupSpecApplyConfiguration struct {
// controller populates this field from PriorityClassName.
// The higher the value, the higher the priority.
// This field is immutable.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
Priority *int32 `json:"priority,omitempty"`
}

View file

@ -44,23 +44,17 @@ type PodGroupTemplateApplyConfiguration struct {
ResourceClaims []PodGroupResourceClaimApplyConfiguration `json:"resourceClaims,omitempty"`
// DisruptionMode defines the mode in which a given PodGroup can be disrupted.
// One of Single, All.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
DisruptionMode *DisruptionModeApplyConfiguration `json:"disruptionMode,omitempty"`
// PriorityClassName indicates the priority that should be considered when scheduling
// a pod group created from this template. If no priority class is specified, admission
// control can set this to the global default priority class if it exists. Otherwise,
// pod groups created from this template will have the priority set to zero.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
PriorityClassName *string `json:"priorityClassName,omitempty"`
// Priority is the value of priority of pod groups created from this template. Various
// system components use this field to find the priority of the pod group. When
// Priority Admission Controller is enabled, it prevents users from setting this field.
// The admission controller populates this field from PriorityClassName.
// The higher the value, the higher the priority.
// This field is available only when the WorkloadAwarePreemption feature gate
// is enabled.
Priority *int32 `json:"priority,omitempty"`
}

View file

@ -79,7 +79,6 @@
| ExecProbeTimeout | :ballot_box_with_check: 1.20+ | :closed_lock_with_key: 1.35+ | | | 1.20 | | | [code](https://cs.k8s.io/?q=%5CbExecProbeTimeout%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbExecProbeTimeout%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| ExtendWebSocketsToKubelet | :ballot_box_with_check: 1.36+ | | | 1.36 | | | NodeDeclaredFeatures | [code](https://cs.k8s.io/?q=%5CbExtendWebSocketsToKubelet%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbExtendWebSocketsToKubelet%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| ExternalServiceAccountTokenSigner | :ballot_box_with_check: 1.34+ | :closed_lock_with_key: 1.36+ | 1.321.33 | 1.341.35 | 1.36 | | | [code](https://cs.k8s.io/?q=%5CbExternalServiceAccountTokenSigner%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbExternalServiceAccountTokenSigner%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| GangScheduling | | | 1.35 | | | | GenericWorkload | [code](https://cs.k8s.io/?q=%5CbGangScheduling%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbGangScheduling%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| GenericWorkload | | | 1.35 | | | | | [code](https://cs.k8s.io/?q=%5CbGenericWorkload%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbGenericWorkload%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| GitRepoVolumeDriver | :ballot_box_with_check: 1.0+ | :closed_lock_with_key: 1.36+ | | | 1.01.32 | 1.33 | | [code](https://cs.k8s.io/?q=%5CbGitRepoVolumeDriver%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbGitRepoVolumeDriver%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| GracefulNodeShutdown | :ballot_box_with_check: 1.21+ | | 1.20 | 1.21 | | | | [code](https://cs.k8s.io/?q=%5CbGracefulNodeShutdown%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbGracefulNodeShutdown%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
@ -226,7 +225,6 @@
| WindowsCPUAndMemoryAffinity | | | 1.32 | | | | | [code](https://cs.k8s.io/?q=%5CbWindowsCPUAndMemoryAffinity%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbWindowsCPUAndMemoryAffinity%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| WindowsGracefulNodeShutdown | :ballot_box_with_check: 1.34+ | | 1.321.33 | 1.34 | | | GracefulNodeShutdown | [code](https://cs.k8s.io/?q=%5CbWindowsGracefulNodeShutdown%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbWindowsGracefulNodeShutdown%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| WindowsHostNetwork | | | 1.261.32 | | | 1.33 | | [code](https://cs.k8s.io/?q=%5CbWindowsHostNetwork%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbWindowsHostNetwork%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| WorkloadAwarePreemption | | | 1.36 | | | | GangScheduling | [code](https://cs.k8s.io/?q=%5CbWorkloadAwarePreemption%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbWorkloadAwarePreemption%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| WorkloadWithJob | | | 1.36 | | | | GenericWorkload | [code](https://cs.k8s.io/?q=%5CbWorkloadWithJob%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbWorkloadWithJob%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
## Legend

View file

@ -663,12 +663,6 @@
lockToDefault: true
preRelease: GA
version: "1.36"
- name: GangScheduling
versionedSpecs:
- default: false
lockToDefault: false
preRelease: Alpha
version: "1.35"
- name: GenericWorkload
versionedSpecs:
- default: false
@ -2121,12 +2115,6 @@
lockToDefault: true
preRelease: GA
version: "1.34"
- name: WorkloadAwarePreemption
versionedSpecs:
- default: false
lockToDefault: false
preRelease: Alpha
version: "1.36"
- name: WorkloadWithJob
versionedSpecs:
- default: false

View file

@ -59,7 +59,6 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) {
input scheduling.PodGroup
enableTopologyAwareScheduling bool
enableDRAWorkloadResourceClaims bool
enableWorkloadAwarePreemption bool
expectedErrs field.ErrorList
}{
"valid": {
@ -167,91 +166,42 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) {
enableTopologyAwareScheduling: true,
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "schedulingConstraints", "topology").Index(0).Child("key"), nil, "").WithOrigin("format=k8s-label-key")},
},
"pod disruption mode, workload aware preemption enabled": {
input: mkValidPodGroup(setDisruptionModeSingle()),
enableWorkloadAwarePreemption: true,
"pod group disruption mode": {
input: mkValidPodGroup(setDisruptionModeAll()),
},
"pod disruption mode, workload aware preemption disabled": {
input: mkValidPodGroup(setDisruptionModeSingle()),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "disruptionMode"), "")},
},
"pod group disruption mode, workload aware preemption enabled": {
input: mkValidPodGroup(setDisruptionModeAll()),
enableWorkloadAwarePreemption: true,
},
"pod group disruption mode, workload aware preemption disabled": {
input: mkValidPodGroup(setDisruptionModeAll()),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "disruptionMode"), "")},
},
"disruption mode with neither single nor all, workload aware preemption enabled": {
input: mkValidPodGroup(setDisruptionModeNeither()),
enableWorkloadAwarePreemption: true,
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "disruptionMode"), nil, "").WithOrigin("union")},
},
"disruption mode with neither single nor all, workload aware preemption disabled": {
"disruption mode with neither single nor all": {
input: mkValidPodGroup(setDisruptionModeNeither()),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "disruptionMode"), "")},
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "disruptionMode"), nil, "").WithOrigin("union")},
},
"disruption mode with both single and all, workload aware preemption enabled": {
input: mkValidPodGroup(setDisruptionModeBoth()),
enableWorkloadAwarePreemption: true,
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "disruptionMode"), nil, "").WithOrigin("union")},
},
"disruption mode with both single and all, workload aware preemption disabled": {
"disruption mode with both single and all": {
input: mkValidPodGroup(setDisruptionModeBoth()),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "disruptionMode"), "")},
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "disruptionMode"), nil, "").WithOrigin("union")},
},
"valid pod group without disruption mode, workload aware preemption enabled": {
input: mkValidPodGroup(),
enableWorkloadAwarePreemption: true,
expectedErrs: field.ErrorList{field.Required(field.NewPath("spec", "disruptionMode"), "")},
"pod group without disruption mode": {
input: mkValidPodGroup(clearDisruptionMode()),
expectedErrs: field.ErrorList{field.Required(field.NewPath("spec", "disruptionMode"), "")},
},
"valid priority class name, workload aware preemption enabled": {
input: mkValidPodGroup(setDisruptionModeSingle(), setPriorityClassName("high-priority")),
enableWorkloadAwarePreemption: true,
"valid priority class name": {
input: mkValidPodGroup(setPriorityClassName("high-priority")),
},
"valid priority class name, workload aware preemption disabled": {
input: mkValidPodGroup(setPriorityClassName("high-priority")),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "priorityClassName"), "")},
},
"invalid priority class name, workload aware preemption enabled": {
input: mkValidPodGroup(setDisruptionModeSingle(), setPriorityClassName("high/priority")),
enableWorkloadAwarePreemption: true,
"invalid priority class name": {
input: mkValidPodGroup(setPriorityClassName("high/priority")),
expectedErrs: field.ErrorList{
field.Invalid(field.NewPath("spec", "priorityClassName"), nil, "").WithOrigin("format=k8s-long-name"),
},
},
"invalid priority class name, workload aware preemption disabled": {
input: mkValidPodGroup(setPriorityClassName("high/priority")),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "priorityClassName"), "")},
"valid priority": {
input: mkValidPodGroup(setPriority(1000)),
},
"valid priority, workload aware preemption enabled": {
input: mkValidPodGroup(setDisruptionModeSingle(), setPriority(1000)),
enableWorkloadAwarePreemption: true,
"valid negative priority": {
input: mkValidPodGroup(setPriority(-2147483648)),
},
"valid priority, workload aware preemption disabled": {
input: mkValidPodGroup(setPriority(1000)),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "priority"), "")},
},
"valid negative priority, workload aware preemption enabled": {
input: mkValidPodGroup(setDisruptionModeSingle(), setPriority(-2147483648)),
enableWorkloadAwarePreemption: true,
},
"valid negative priority, workload aware preemption disabled": {
input: mkValidPodGroup(setPriority(-2147483648)),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "priority"), "")},
},
"too high priority, workload aware preemption enabled": {
input: mkValidPodGroup(setDisruptionModeSingle(), setPriority(scheduling.HighestUserDefinablePriority+1)),
enableWorkloadAwarePreemption: true,
"too high priority": {
input: mkValidPodGroup(setPriority(scheduling.HighestUserDefinablePriority + 1)),
expectedErrs: field.ErrorList{
field.Invalid(field.NewPath("spec", "priority"), nil, "").WithOrigin("maximum"),
},
},
"too high priority, workload aware preemption disabled": {
input: mkValidPodGroup(setPriority(scheduling.HighestUserDefinablePriority + 1)),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "priority"), "")},
},
"ok resourceClaimName reference": {
input: mkValidPodGroup(addResourceClaims(scheduling.PodGroupResourceClaim{Name: "claim", ResourceClaimName: new("resource-claim")})),
},
@ -348,8 +298,6 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) {
features.GenericWorkload: true,
features.TopologyAwareWorkloadScheduling: tc.enableTopologyAwareScheduling,
features.DRAWorkloadResourceClaims: tc.enableDRAWorkloadResourceClaims,
features.GangScheduling: tc.enableWorkloadAwarePreemption,
features.WorkloadAwarePreemption: tc.enableWorkloadAwarePreemption,
})
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, strategy, tc.expectedErrs)
})
@ -380,7 +328,6 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) {
updateObj scheduling.PodGroup
enableTopologyAwareScheduling bool
enableDRAWorkloadResourceClaims bool
enableWorkloadAwarePreemption bool
expectedErrs field.ErrorList
}{
"valid update": {
@ -532,38 +479,20 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) {
enableDRAWorkloadResourceClaims: true,
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "resourceClaims"), nil, "").WithOrigin("immutable")},
},
"invalid update of disruption mode, workload aware preemption enabled": {
oldObj: mkValidPodGroup(setResourceVersion("1"), setDisruptionModeSingle()),
updateObj: mkValidPodGroup(setResourceVersion("1"), setDisruptionModeAll()),
enableWorkloadAwarePreemption: true,
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "disruptionMode"), &scheduling.DisruptionMode{All: &scheduling.AllDisruptionMode{}}, "field is immutable").WithOrigin("immutable")},
},
"invalid update of disruption mode, workload aware preemption disabled": {
oldObj: mkValidPodGroup(setResourceVersion("1"), setDisruptionModeSingle()),
"invalid update of disruption mode": {
oldObj: mkValidPodGroup(setResourceVersion("1")),
updateObj: mkValidPodGroup(setResourceVersion("1"), setDisruptionModeAll()),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "disruptionMode"), "")},
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "disruptionMode"), &scheduling.DisruptionMode{All: &scheduling.AllDisruptionMode{}}, "field is immutable").WithOrigin("immutable")},
},
"invalid update of priority class name, workload aware preemption enabled": {
oldObj: mkValidPodGroup(setResourceVersion("1"), setPriorityClassName("low-priority")),
updateObj: mkValidPodGroup(setResourceVersion("1"), setPriorityClassName("high-priority")),
enableWorkloadAwarePreemption: true,
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "priorityClassName"), nil, "").WithOrigin("immutable")},
},
"invalid update of priority class name, workload aware preemption disabled": {
"invalid update of priority class name": {
oldObj: mkValidPodGroup(setResourceVersion("1"), setPriorityClassName("low-priority")),
updateObj: mkValidPodGroup(setResourceVersion("1"), setPriorityClassName("high-priority")),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "priorityClassName"), "")},
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "priorityClassName"), nil, "").WithOrigin("immutable")},
},
"invalid update of priority, workload aware preemption enabled": {
oldObj: mkValidPodGroup(setResourceVersion("1"), setPriority(1000)),
updateObj: mkValidPodGroup(setResourceVersion("1"), setPriority(2000)),
enableWorkloadAwarePreemption: true,
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "priority"), nil, "").WithOrigin("immutable")},
},
"invalid update of priority, workload aware preemption disabled": {
"invalid update of priority": {
oldObj: mkValidPodGroup(setResourceVersion("1"), setPriority(1000)),
updateObj: mkValidPodGroup(setResourceVersion("1"), setPriority(2000)),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "priority"), "")},
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "priority"), nil, "").WithOrigin("immutable")},
},
}
for k, tc := range testCases {
@ -572,8 +501,6 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) {
features.GenericWorkload: true,
features.TopologyAwareWorkloadScheduling: tc.enableTopologyAwareScheduling,
features.DRAWorkloadResourceClaims: tc.enableDRAWorkloadResourceClaims,
features.GangScheduling: tc.enableWorkloadAwarePreemption,
features.WorkloadAwarePreemption: tc.enableWorkloadAwarePreemption,
})
strategy := registry.NewStrategy()
apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, strategy, tc.expectedErrs)
@ -729,6 +656,9 @@ func mkValidPodGroup(tweaks ...func(pg *scheduling.PodGroup)) scheduling.PodGrou
MinCount: 5,
},
},
DisruptionMode: &scheduling.DisruptionMode{
Single: &scheduling.SingleDisruptionMode{},
},
},
}
for _, tweak := range tweaks {
@ -856,14 +786,6 @@ func addTopologyConstraint(value string) func(obj *scheduling.PodGroup) {
}
}
func setDisruptionModeSingle() func(obj *scheduling.PodGroup) {
return func(obj *scheduling.PodGroup) {
obj.Spec.DisruptionMode = &scheduling.DisruptionMode{
Single: &scheduling.SingleDisruptionMode{},
}
}
}
func setDisruptionModeAll() func(obj *scheduling.PodGroup) {
return func(obj *scheduling.PodGroup) {
obj.Spec.DisruptionMode = &scheduling.DisruptionMode{
@ -898,3 +820,9 @@ func setPriority(priority int32) func(obj *scheduling.PodGroup) {
obj.Spec.Priority = new(priority)
}
}
func clearDisruptionMode() func(obj *scheduling.PodGroup) {
return func(obj *scheduling.PodGroup) {
obj.Spec.DisruptionMode = nil
}
}

View file

@ -31,7 +31,6 @@ func init() {
schema.GroupVersionKind{Group: "scheduling.k8s.io", Version: "v1alpha3", Kind: "PodGroup"},
coverage.FieldRules{
"spec.disruptionMode": {
{ErrorType: "FieldValueForbidden"},
{ErrorType: "FieldValueInvalid", Origin: "immutable"},
{ErrorType: "FieldValueInvalid", Origin: "union"},
{ErrorType: "FieldValueRequired"},
@ -49,12 +48,10 @@ func init() {
{ErrorType: "FieldValueRequired"},
},
"spec.priority": {
{ErrorType: "FieldValueForbidden"},
{ErrorType: "FieldValueInvalid", Origin: "immutable"},
{ErrorType: "FieldValueInvalid", Origin: "maximum"},
},
"spec.priorityClassName": {
{ErrorType: "FieldValueForbidden"},
{ErrorType: "FieldValueInvalid", Origin: "format=k8s-long-name"},
{ErrorType: "FieldValueInvalid", Origin: "immutable"},
},

View file

@ -58,7 +58,6 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) {
input scheduling.Workload
enableTopologyAwareScheduling bool
enableDRAWorkloadResourceClaims bool
enableWorkloadAwarePreemption bool
expectedErrs field.ErrorList
}{
"valid": {
@ -189,87 +188,41 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) {
enableTopologyAwareScheduling: true,
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "podGroupTemplates").Index(0).Child("schedulingConstraints", "topology").Index(0).Child("key"), nil, "").WithOrigin("format=k8s-label-key")},
},
"pod disruption mode, workload aware preemption enabled": {
input: mkValidWorkload(setDisruptionModeSingle(0)),
enableWorkloadAwarePreemption: true,
"disruption mode single": {
input: mkValidWorkload(setDisruptionModeSingle(0)),
},
"pod disruption mode, workload aware preemption disabled": {
input: mkValidWorkload(setDisruptionModeSingle(0)),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "podGroupTemplates").Index(0).Child("disruptionMode"), "")},
"disruption mode all": {
input: mkValidWorkload(setDisruptionModeAll(0)),
},
"pod group disruption mode, workload aware preemption enabled": {
input: mkValidWorkload(setDisruptionModeAll(0)),
enableWorkloadAwarePreemption: true,
},
"pod group disruption mode, workload aware preemption disabled": {
input: mkValidWorkload(setDisruptionModeAll(0)),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "podGroupTemplates").Index(0).Child("disruptionMode"), "")},
},
"disruption mode with neither single nor all, workload aware preemption enabled": {
input: mkValidWorkload(setDisruptionModeNeither(0)),
enableWorkloadAwarePreemption: true,
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "podGroupTemplates").Index(0).Child("disruptionMode"), nil, "").WithOrigin("union")},
},
"disruption mode with neither single nor all, workload aware preemption disabled": {
"disruption mode with neither single nor all": {
input: mkValidWorkload(setDisruptionModeNeither(0)),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "podGroupTemplates").Index(0).Child("disruptionMode"), "")},
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "podGroupTemplates").Index(0).Child("disruptionMode"), nil, "").WithOrigin("union")},
},
"disruption mode with both single and all, workload aware preemption enabled": {
input: mkValidWorkload(setDisruptionModeBoth(0)),
enableWorkloadAwarePreemption: true,
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "podGroupTemplates").Index(0).Child("disruptionMode"), nil, "").WithOrigin("union")},
},
"disruption mode with both single and all, workload aware preemption disabled": {
"disruption mode with both single and all": {
input: mkValidWorkload(setDisruptionModeBoth(0)),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "podGroupTemplates").Index(0).Child("disruptionMode"), "")},
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "podGroupTemplates").Index(0).Child("disruptionMode"), nil, "").WithOrigin("union")},
},
"valid priorityClassName, workload aware preemption enabled": {
input: mkValidWorkload(setPriorityClassName(0, "high-priority")),
enableWorkloadAwarePreemption: true,
"valid priorityClassName": {
input: mkValidWorkload(setPriorityClassName(0, "high-priority")),
},
"valid priorityClassName, workload aware preemption disabled": {
input: mkValidWorkload(setPriorityClassName(0, "high-priority")),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "podGroupTemplates").Index(0).Child("priorityClassName"), "")},
},
"invalid priorityClassName, workload aware preemption enabled": {
input: mkValidWorkload(setPriorityClassName(0, "high/priority")),
enableWorkloadAwarePreemption: true,
"invalid priorityClassName": {
input: mkValidWorkload(setPriorityClassName(0, "high/priority")),
expectedErrs: field.ErrorList{
field.Invalid(field.NewPath("spec", "podGroupTemplates").Index(0).Child("priorityClassName"), nil, "").WithOrigin("format=k8s-long-name"),
},
},
"invalid priorityClassName, workload aware preemption disabled": {
input: mkValidWorkload(setPriorityClassName(0, "high/priority")),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "podGroupTemplates").Index(0).Child("priorityClassName"), "")},
"valid priority": {
input: mkValidWorkload(setPriority(0, 1000)),
},
"valid priority, workload aware preemption enabled": {
input: mkValidWorkload(setPriority(0, 1000)),
enableWorkloadAwarePreemption: true,
"valid negative priority": {
input: mkValidWorkload(setPriority(0, -2147483648)),
},
"valid priority, workload aware preemption disabled": {
input: mkValidWorkload(setPriority(0, 1000)),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "podGroupTemplates").Index(0).Child("priority"), "")},
},
"valid negative priority, workload aware preemption enabled": {
input: mkValidWorkload(setPriority(0, -2147483648)),
enableWorkloadAwarePreemption: true,
},
"valid negative priority, workload aware preemption disabled": {
input: mkValidWorkload(setPriority(0, -2147483648)),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "podGroupTemplates").Index(0).Child("priority"), "")},
},
"too high priority, workload aware preemption enabled": {
input: mkValidWorkload(setPriority(0, scheduling.HighestUserDefinablePriority+1)),
enableWorkloadAwarePreemption: true,
"too high priority": {
input: mkValidWorkload(setPriority(0, scheduling.HighestUserDefinablePriority+1)),
expectedErrs: field.ErrorList{
field.Invalid(field.NewPath("spec", "podGroupTemplates").Index(0).Child("priority"), nil, "").WithOrigin("maximum"),
},
},
"too high priority, workload aware preemption disabled": {
input: mkValidWorkload(setPriority(0, scheduling.HighestUserDefinablePriority+1)),
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "podGroupTemplates").Index(0).Child("priority"), "")},
},
"ok resourceClaimName reference": {
input: mkValidWorkload(addResourceClaims(scheduling.PodGroupResourceClaim{Name: "claim", ResourceClaimName: new("resource-claim")})),
},
@ -369,8 +322,6 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) {
features.GenericWorkload: true,
features.TopologyAwareWorkloadScheduling: tc.enableTopologyAwareScheduling,
features.DRAWorkloadResourceClaims: tc.enableDRAWorkloadResourceClaims,
features.GangScheduling: tc.enableWorkloadAwarePreemption,
features.WorkloadAwarePreemption: tc.enableWorkloadAwarePreemption,
})
apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, registry.Strategy, tc.expectedErrs)
})
@ -392,7 +343,6 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) {
updateObj scheduling.Workload
enableTopologyAwareScheduling bool
enableDRAWorkloadResourceClaims bool
enableWorkloadAwarePreemption bool
expectedErrs field.ErrorList
}{
"valid update": {
@ -566,35 +516,17 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) {
enableDRAWorkloadResourceClaims: true,
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "podGroupTemplates"), nil, "").WithOrigin("immutable")},
},
"invalid update of disruption mode, workload aware preemption enabled": {
oldObj: mkValidWorkload(setResourceVersion("1"), setDisruptionModeSingle(0)),
updateObj: mkValidWorkload(setResourceVersion("1"), setDisruptionModeAll(0)),
enableWorkloadAwarePreemption: true,
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "podGroupTemplates"), nil, "").WithOrigin("immutable")},
},
"invalid update of disruption mode, workload aware preemption disabled": {
"invalid update of disruption mode": {
oldObj: mkValidWorkload(setResourceVersion("1"), setDisruptionModeSingle(0)),
updateObj: mkValidWorkload(setResourceVersion("1"), setDisruptionModeAll(0)),
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "podGroupTemplates"), nil, "").WithOrigin("immutable")},
},
"invalid update of priority class name, workload aware preemption enabled": {
oldObj: mkValidWorkload(setResourceVersion("1"), setPriorityClassName(0, "low-priority")),
updateObj: mkValidWorkload(setResourceVersion("1"), setPriorityClassName(0, "high-priority")),
enableWorkloadAwarePreemption: true,
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "podGroupTemplates"), nil, "").WithOrigin("immutable")},
},
"invalid update of priority class name, workload aware preemption disabled": {
"invalid update of priority class name": {
oldObj: mkValidWorkload(setResourceVersion("1"), setPriorityClassName(0, "low-priority")),
updateObj: mkValidWorkload(setResourceVersion("1"), setPriorityClassName(0, "high-priority")),
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "podGroupTemplates"), nil, "").WithOrigin("immutable")},
},
"invalid update of priority, workload aware preemption enabled": {
oldObj: mkValidWorkload(setResourceVersion("1"), setPriority(0, 1000)),
updateObj: mkValidWorkload(setResourceVersion("1"), setPriority(0, 2000)),
enableWorkloadAwarePreemption: true,
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "podGroupTemplates"), nil, "").WithOrigin("immutable")},
},
"invalid update of priority, workload aware preemption disabled": {
"invalid update of priority": {
oldObj: mkValidWorkload(setResourceVersion("1"), setPriority(0, 1000)),
updateObj: mkValidWorkload(setResourceVersion("1"), setPriority(0, 2000)),
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "podGroupTemplates"), nil, "").WithOrigin("immutable")},
@ -606,8 +538,6 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) {
features.GenericWorkload: true,
features.TopologyAwareWorkloadScheduling: tc.enableTopologyAwareScheduling,
features.DRAWorkloadResourceClaims: tc.enableDRAWorkloadResourceClaims,
features.GangScheduling: tc.enableWorkloadAwarePreemption,
features.WorkloadAwarePreemption: tc.enableWorkloadAwarePreemption,
})
ctx := genericapirequest.WithRequestInfo(genericapirequest.NewDefaultContext(), &genericapirequest.RequestInfo{
APIPrefix: "apis",

View file

@ -53,7 +53,6 @@ func init() {
{ErrorType: "FieldValueDuplicate"},
},
"spec.podGroupTemplates[*].disruptionMode": {
{ErrorType: "FieldValueForbidden"},
{ErrorType: "FieldValueInvalid", Origin: "union"},
},
"spec.podGroupTemplates[*].name": {
@ -61,11 +60,9 @@ func init() {
{ErrorType: "FieldValueRequired"},
},
"spec.podGroupTemplates[*].priority": {
{ErrorType: "FieldValueForbidden"},
{ErrorType: "FieldValueInvalid", Origin: "maximum"},
},
"spec.podGroupTemplates[*].priorityClassName": {
{ErrorType: "FieldValueForbidden"},
{ErrorType: "FieldValueInvalid", Origin: "format=k8s-long-name"},
},
"spec.podGroupTemplates[*].resourceClaims": {

View file

@ -32,7 +32,7 @@ import (
admissionapi "k8s.io/pod-security-admission/api"
)
var _ = SIGDescribe("GangScheduling", framework.WithFeatureGate(features.GangScheduling), func() {
var _ = SIGDescribe("GangScheduling", framework.WithFeatureGate(features.GenericWorkload), func() {
f := framework.NewDefaultFramework("gang-scheduling")
f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged

View file

@ -229,8 +229,7 @@ func run(tCtx ktesting.TContext, whatRE string) {
features.DRAExtendedResource: true,
features.DRANodeAllocatableResources: true,
features.DRAWorkloadResourceClaims: true,
features.GangScheduling: true,
features.GenericWorkload: true, // dependency of DRAWorkloadResourceClaims, GangScheduling
features.GenericWorkload: true, // dependency of DRAWorkloadResourceClaims
},
f: func(tCtx ktesting.TContext) {
// These tests must run in parallel as much as possible to keep overall runtime low!

View file

@ -110,7 +110,6 @@ func TestPodGroupScheduling(t *testing.T) {
tests := []struct {
name string
enableWorkloadAwarePreemption bool
enableTopologyAwareWorkloadScheduling []bool
steps []stepsframework.Step
}{
@ -304,43 +303,6 @@ func TestPodGroupScheduling(t *testing.T) {
},
},
},
{
name: "gang schedules with preemption",
steps: []stepsframework.Step{
{
Name: "Create a low priority pod taking all resources",
CreatePods: []*v1.Pod{lowPriorityBlockerPod},
},
{
Name: "Schedule the low priority resource-blocking pod",
WaitForPodsScheduled: []string{"low-priority-blocker"},
},
{
Name: "Create the PodGroup object",
CreatePodGroup: gangPodGroup,
},
{
Name: "Create high priority gang pods",
CreatePods: []*v1.Pod{p1, p2, p3, p4},
},
{
Name: "Verify all gang pods are scheduled successfully (after preemption)",
WaitForPodsScheduled: []string{"p1", "p2", "p3", "p4"},
},
{
Name: "Verify PodGroup condition is set to Scheduled after preemption completes",
WaitForPodGroupCondition: &stepsframework.PodGroupConditionCheck{
PodGroupName: "pg1",
ConditionStatus: metav1.ConditionTrue,
Reason: "Scheduled",
},
},
{
Name: "Verify preemption victims were removed",
WaitForPodsRemoved: []string{"low-priority-blocker"},
},
},
},
{
name: "basic group schedules when pod group and resources are available, without gang enforcement",
steps: []stepsframework.Step{
@ -407,39 +369,9 @@ func TestPodGroupScheduling(t *testing.T) {
},
},
},
{
name: "basic group schedules with preemption",
steps: []stepsframework.Step{
{
Name: "Create a low priority pod taking all resources",
CreatePods: []*v1.Pod{lowPriorityBlockerPod},
},
{
Name: "Schedule the low priority resource-blocking pod",
WaitForPodsScheduled: []string{"low-priority-blocker"},
},
{
Name: "Create the PodGroup object",
CreatePodGroup: basicPodGroup,
},
{
Name: "Create high priority group's pods",
CreatePods: []*v1.Pod{p1, p2, p3, p4},
},
{
Name: "Verify all group's pods are scheduled successfully (after preemption)",
WaitForPodsScheduled: []string{"p1", "p2", "p3", "p4"},
},
{
Name: "Verify preemption victims were removed",
WaitForPodsRemoved: []string{"low-priority-blocker"},
},
},
},
{
name: "basic group schedules with workload-aware preemption",
enableTopologyAwareWorkloadScheduling: []bool{false},
enableWorkloadAwarePreemption: true,
steps: []stepsframework.Step{
{
Name: "Create a low priority pod taking all resources",
@ -468,8 +400,7 @@ func TestPodGroupScheduling(t *testing.T) {
},
},
{
name: "gang schedules with workload-aware preemption",
enableWorkloadAwarePreemption: true,
name: "gang schedules with workload-aware preemption",
steps: []stepsframework.Step{
{
Name: "Create low priority pods that take up all node resources",
@ -480,7 +411,7 @@ func TestPodGroupScheduling(t *testing.T) {
WaitForPodsScheduled: []string{"low-p1", "low-p2", "low-p3", "low-p4"},
},
{
Name: "Create the Workload object",
Name: "Create the PodGroup object",
CreatePodGroup: gangPodGroup,
},
{
@ -491,6 +422,14 @@ func TestPodGroupScheduling(t *testing.T) {
Name: "Verify all gang pods are scheduled successfully (after workload-aware preemption)",
WaitForPodsScheduled: []string{"p1", "p2", "p3", "p4"},
},
{
Name: "Verify PodGroup condition is set to Scheduled after preemption completes",
WaitForPodGroupCondition: &stepsframework.PodGroupConditionCheck{
PodGroupName: "pg1",
ConditionStatus: metav1.ConditionTrue,
Reason: "Scheduled",
},
},
{
Name: "Verify preemption victims were removed",
WaitForPodsRemoved: []string{"low-p1", "low-p2", "low-p3", "low-p4"},
@ -498,8 +437,7 @@ func TestPodGroupScheduling(t *testing.T) {
},
},
{
name: "gang schedules with partial workload-aware preemption",
enableWorkloadAwarePreemption: true,
name: "gang schedules with partial workload-aware preemption",
steps: []stepsframework.Step{
{
Name: "Create very low and low priority pods that take up all node resources",
@ -555,7 +493,6 @@ func TestPodGroupScheduling(t *testing.T) {
},
{
name: "tas gang with constraint does not use workload preemption",
enableWorkloadAwarePreemption: true,
enableTopologyAwareWorkloadScheduling: []bool{true},
steps: []stepsframework.Step{
{
@ -591,9 +528,7 @@ func TestPodGroupScheduling(t *testing.T) {
t.Run(fmt.Sprintf("%s (TopologyAwareWorkloadScheduling enabled: %v)", tt.name, tasEnabled), func(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
features.TopologyAwareWorkloadScheduling: tasEnabled,
features.WorkloadAwarePreemption: tt.enableWorkloadAwarePreemption,
})
testCtx := testutils.InitTestSchedulerWithNS(t, "podgroup-scheduling",
@ -624,9 +559,7 @@ func TestPodGroupScheduling(t *testing.T) {
func TestWorkloadAwarePreemptionInvocation(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
features.WorkloadAwarePreemption: true,
features.GenericWorkload: true,
})
node := st.MakeNode().Name("node").Capacity(map[v1.ResourceName]string{v1.ResourceCPU: "4"}).Obj()
@ -735,9 +668,7 @@ func (m *mockPostFilterPlugin) PostFilter(ctx context.Context, state framework.C
func TestPostFilterInvocationCount(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
features.WorkloadAwarePreemption: true,
features.GenericWorkload: true,
})
node := st.MakeNode().Name("node").Capacity(map[v1.ResourceName]string{v1.ResourceCPU: "4"}).Obj()

View file

@ -691,7 +691,6 @@ func TestPodGroupQueueing(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
})
var testCtx *testutils.TestContext
@ -835,7 +834,6 @@ func TestPodGroupSequentialQueueing(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
})
testCtx := testutils.InitTestSchedulerWithOptions(

View file

@ -17,7 +17,6 @@ limitations under the License.
package topologyawarescheduling
import (
"fmt"
"testing"
v1 "k8s.io/api/core/v1"
@ -658,7 +657,7 @@ func TestTopologyAwareSchedulingWithGangPolicy(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
runTestScenario(t, tt, true /* gangSchedulingEnabled */)
runTestScenario(t, tt)
})
}
}
@ -1318,19 +1317,16 @@ func TestTopologyAwareSchedulingWithBasicPolicy(t *testing.T) {
},
}
for _, gangSchedulingEnabled := range []bool{true, false} {
for _, tt := range tests {
t.Run(fmt.Sprintf("%s (GangScheduling enabled: %v)", tt.name, gangSchedulingEnabled), func(t *testing.T) {
runTestScenario(t, tt, gangSchedulingEnabled)
})
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
runTestScenario(t, tt)
})
}
}
func runTestScenario(t *testing.T, tt scenario, gangSchedulingEnabled bool) {
func runTestScenario(t *testing.T, tt scenario) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: gangSchedulingEnabled,
features.TopologyAwareWorkloadScheduling: true,
})

View file

@ -50,9 +50,7 @@ import (
// TestPodGroupPreemption tests preemption scenarios involving pod groups.
func TestPodGroupPreemption(t *testing.T) {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
features.WorkloadAwarePreemption: true,
features.GenericWorkload: true,
})
tests := []struct {
name string

View file

@ -111,9 +111,9 @@ type CoreResourceEnqueueTestCase struct {
EnableDRAExtendedResource bool
// EnableNodeDeclaredFeatures indicates if the test case runs with the NodeDeclaredFeatures feature gate enabled.
EnableNodeDeclaredFeatures bool
// EnableGangScheduling indicates wether the test case should run with feature gates
// GenericWorkload and GangScheduling enabled or not.
EnableGangScheduling bool
// EnableGenericWorkload indicates wether the test case should run with feature gate
// GenericWorkload enabled or not.
EnableGenericWorkload bool
}
// We define all the test cases here in the one place,
@ -2543,7 +2543,7 @@ var CoreResourceEnqueueTestCases = []*CoreResourceEnqueueTestCase{
},
ExpectedInitialRejectingPhase: rejectingPhasePreEnqueue,
WantRequeuedPods: sets.New("pod1", "pod3"),
EnableGangScheduling: true,
EnableGenericWorkload: true,
},
{
Name: "Pod rejected by the GangScheduling plugin is requeued when a matching pod group is created",
@ -2564,7 +2564,7 @@ var CoreResourceEnqueueTestCases = []*CoreResourceEnqueueTestCase{
},
ExpectedInitialRejectingPhase: rejectingPhasePreEnqueue,
WantRequeuedPods: sets.New("pod1"),
EnableGangScheduling: true,
EnableGenericWorkload: true,
},
}
@ -2590,10 +2590,9 @@ func RunTestCoreResourceEnqueue(t *testing.T, tt *CoreResourceEnqueueTestCase) {
ndfFramework := ndf.New([]ndf.Feature{mockFeature})
ndftesting.SetFrameworkDuringTest(t, *ndfFramework)
}
if tt.EnableGangScheduling {
if tt.EnableGenericWorkload {
featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{
features.GenericWorkload: true,
features.GangScheduling: true,
})
}
logger, _ := ktesting.NewTestContext(t)

View file

@ -7,7 +7,6 @@
- name: GangScheduling
featureGates:
GenericWorkload: true
GangScheduling: true
workloadTemplate:
- opcode: createNodes
countParam: $initNodes

View file

@ -7,7 +7,6 @@
- name: TopologyAwareScheduling
featureGates:
GenericWorkload: true
GangScheduling: true
TopologyAwareWorkloadScheduling: true
workloadTemplate:
- opcode: createNodes