diff --git a/api/api-rules/violation_exceptions.list b/api/api-rules/violation_exceptions.list index ebb0bd6f40f..8aa34f61471 100644 --- a/api/api-rules/violation_exceptions.list +++ b/api/api-rules/violation_exceptions.list @@ -377,7 +377,6 @@ API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,Policy,Pre API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,Policy,Priorities API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,RequestedToCapacityRatioArguments,Resources API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,RequestedToCapacityRatioArguments,Shape -API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,ServiceAffinity,Labels API rule violation: list_type_missing,k8s.io/kubelet/config/v1alpha1,CredentialProvider,Args API rule violation: list_type_missing,k8s.io/kubelet/config/v1alpha1,CredentialProvider,Env API rule violation: list_type_missing,k8s.io/kubelet/config/v1alpha1,CredentialProvider,MatchImages diff --git a/pkg/scheduler/apis/config/legacy_types.go b/pkg/scheduler/apis/config/legacy_types.go index 576379c1e7f..48e169820b5 100644 --- a/pkg/scheduler/apis/config/legacy_types.go +++ b/pkg/scheduler/apis/config/legacy_types.go @@ -74,9 +74,6 @@ type PriorityPolicy struct { // PredicateArgument represents the arguments to configure predicate functions in scheduler policy configuration. // Only one of its members may be specified type PredicateArgument struct { - // The predicate that provides affinity for pods belonging to a service - // It uses a label to identify nodes that belong to the same "group" - ServiceAffinity *ServiceAffinity // The predicate that checks whether a particular node has a certain label // defined or not, regardless of value LabelsPresence *LabelsPresence @@ -85,9 +82,6 @@ type PredicateArgument struct { // PriorityArgument represents the arguments to configure priority functions in scheduler policy configuration. // Only one of its members may be specified type PriorityArgument struct { - // The priority function that ensures a good spread (anti-affinity) for pods belonging to a service - // It uses a label to identify nodes that belong to the same "group" - ServiceAntiAffinity *ServiceAntiAffinity // The priority function that checks whether a particular node has a certain label // defined or not, regardless of value LabelPreference *LabelPreference @@ -95,13 +89,6 @@ type PriorityArgument struct { RequestedToCapacityRatioArguments *RequestedToCapacityRatioArguments } -// ServiceAffinity holds the parameters that are used to configure the corresponding predicate in scheduler policy configuration. -type ServiceAffinity struct { - // The list of labels that identify node "groups" - // All of the labels should match for the node to be considered a fit for hosting the pod - Labels []string -} - // LabelsPresence holds the parameters that are used to configure the corresponding predicate in scheduler policy configuration. type LabelsPresence struct { // The list of labels that identify node "groups" @@ -111,12 +98,6 @@ type LabelsPresence struct { Presence bool } -// ServiceAntiAffinity holds the parameters that are used to configure the corresponding priority function -type ServiceAntiAffinity struct { - // Used to identify node "groups" - Label string -} - // LabelPreference holds the parameters that are used to configure the corresponding priority function type LabelPreference struct { // Used to identify node "groups" diff --git a/pkg/scheduler/apis/config/register.go b/pkg/scheduler/apis/config/register.go index 14052808df6..d6b6cf0f37a 100644 --- a/pkg/scheduler/apis/config/register.go +++ b/pkg/scheduler/apis/config/register.go @@ -45,7 +45,6 @@ func addKnownTypes(scheme *runtime.Scheme) error { &NodeResourcesFitArgs{}, &PodTopologySpreadArgs{}, &RequestedToCapacityRatioArgs{}, - &ServiceAffinityArgs{}, &VolumeBindingArgs{}, &NodeResourcesLeastAllocatedArgs{}, &NodeResourcesMostAllocatedArgs{}, diff --git a/pkg/scheduler/apis/config/types_pluginargs.go b/pkg/scheduler/apis/config/types_pluginargs.go index 2f237a28fa3..644fe9ba51b 100644 --- a/pkg/scheduler/apis/config/types_pluginargs.go +++ b/pkg/scheduler/apis/config/types_pluginargs.go @@ -198,25 +198,6 @@ type ResourceSpec struct { // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// ServiceAffinityArgs holds arguments used to configure the ServiceAffinity -// plugin. -// -// This plugin has been deprecated and is only configurable through the -// scheduler policy API and the v1beta1 component config API. It is recommended -// to use the InterPodAffinity plugin instead. -type ServiceAffinityArgs struct { - metav1.TypeMeta - - // AffinityLabels are homogeneous for pods that are scheduled to a node. - // (i.e. it returns true IFF this pod can be added to this node such that all other pods in - // the same service are running on nodes with the exact same values for Labels). - AffinityLabels []string - // AntiAffinityLabelsPreference are the labels to consider for service anti affinity scoring. - AntiAffinityLabelsPreference []string -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - // VolumeBindingArgs holds arguments used to configure the VolumeBinding plugin. type VolumeBindingArgs struct { metav1.TypeMeta diff --git a/pkg/scheduler/apis/config/v1/zz_generated.conversion.go b/pkg/scheduler/apis/config/v1/zz_generated.conversion.go index 677a54672e7..3fd1867300f 100644 --- a/pkg/scheduler/apis/config/v1/zz_generated.conversion.go +++ b/pkg/scheduler/apis/config/v1/zz_generated.conversion.go @@ -147,26 +147,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1.ServiceAffinity)(nil), (*config.ServiceAffinity)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1_ServiceAffinity_To_config_ServiceAffinity(a.(*v1.ServiceAffinity), b.(*config.ServiceAffinity), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*config.ServiceAffinity)(nil), (*v1.ServiceAffinity)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_config_ServiceAffinity_To_v1_ServiceAffinity(a.(*config.ServiceAffinity), b.(*v1.ServiceAffinity), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*v1.ServiceAntiAffinity)(nil), (*config.ServiceAntiAffinity)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1_ServiceAntiAffinity_To_config_ServiceAntiAffinity(a.(*v1.ServiceAntiAffinity), b.(*config.ServiceAntiAffinity), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*config.ServiceAntiAffinity)(nil), (*v1.ServiceAntiAffinity)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_config_ServiceAntiAffinity_To_v1_ServiceAntiAffinity(a.(*config.ServiceAntiAffinity), b.(*v1.ServiceAntiAffinity), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*v1.UtilizationShapePoint)(nil), (*config.UtilizationShapePoint)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1_UtilizationShapePoint_To_config_UtilizationShapePoint(a.(*v1.UtilizationShapePoint), b.(*config.UtilizationShapePoint), scope) }); err != nil { @@ -339,7 +319,6 @@ func Convert_config_Policy_To_v1_Policy(in *config.Policy, out *v1.Policy, s con } func autoConvert_v1_PredicateArgument_To_config_PredicateArgument(in *v1.PredicateArgument, out *config.PredicateArgument, s conversion.Scope) error { - out.ServiceAffinity = (*config.ServiceAffinity)(unsafe.Pointer(in.ServiceAffinity)) out.LabelsPresence = (*config.LabelsPresence)(unsafe.Pointer(in.LabelsPresence)) return nil } @@ -350,7 +329,6 @@ func Convert_v1_PredicateArgument_To_config_PredicateArgument(in *v1.PredicateAr } func autoConvert_config_PredicateArgument_To_v1_PredicateArgument(in *config.PredicateArgument, out *v1.PredicateArgument, s conversion.Scope) error { - out.ServiceAffinity = (*v1.ServiceAffinity)(unsafe.Pointer(in.ServiceAffinity)) out.LabelsPresence = (*v1.LabelsPresence)(unsafe.Pointer(in.LabelsPresence)) return nil } @@ -383,7 +361,6 @@ func Convert_config_PredicatePolicy_To_v1_PredicatePolicy(in *config.PredicatePo } func autoConvert_v1_PriorityArgument_To_config_PriorityArgument(in *v1.PriorityArgument, out *config.PriorityArgument, s conversion.Scope) error { - out.ServiceAntiAffinity = (*config.ServiceAntiAffinity)(unsafe.Pointer(in.ServiceAntiAffinity)) out.LabelPreference = (*config.LabelPreference)(unsafe.Pointer(in.LabelPreference)) out.RequestedToCapacityRatioArguments = (*config.RequestedToCapacityRatioArguments)(unsafe.Pointer(in.RequestedToCapacityRatioArguments)) return nil @@ -395,7 +372,6 @@ func Convert_v1_PriorityArgument_To_config_PriorityArgument(in *v1.PriorityArgum } func autoConvert_config_PriorityArgument_To_v1_PriorityArgument(in *config.PriorityArgument, out *v1.PriorityArgument, s conversion.Scope) error { - out.ServiceAntiAffinity = (*v1.ServiceAntiAffinity)(unsafe.Pointer(in.ServiceAntiAffinity)) out.LabelPreference = (*v1.LabelPreference)(unsafe.Pointer(in.LabelPreference)) out.RequestedToCapacityRatioArguments = (*v1.RequestedToCapacityRatioArguments)(unsafe.Pointer(in.RequestedToCapacityRatioArguments)) return nil @@ -474,46 +450,6 @@ func Convert_config_ResourceSpec_To_v1_ResourceSpec(in *config.ResourceSpec, out return autoConvert_config_ResourceSpec_To_v1_ResourceSpec(in, out, s) } -func autoConvert_v1_ServiceAffinity_To_config_ServiceAffinity(in *v1.ServiceAffinity, out *config.ServiceAffinity, s conversion.Scope) error { - out.Labels = *(*[]string)(unsafe.Pointer(&in.Labels)) - return nil -} - -// Convert_v1_ServiceAffinity_To_config_ServiceAffinity is an autogenerated conversion function. -func Convert_v1_ServiceAffinity_To_config_ServiceAffinity(in *v1.ServiceAffinity, out *config.ServiceAffinity, s conversion.Scope) error { - return autoConvert_v1_ServiceAffinity_To_config_ServiceAffinity(in, out, s) -} - -func autoConvert_config_ServiceAffinity_To_v1_ServiceAffinity(in *config.ServiceAffinity, out *v1.ServiceAffinity, s conversion.Scope) error { - out.Labels = *(*[]string)(unsafe.Pointer(&in.Labels)) - return nil -} - -// Convert_config_ServiceAffinity_To_v1_ServiceAffinity is an autogenerated conversion function. -func Convert_config_ServiceAffinity_To_v1_ServiceAffinity(in *config.ServiceAffinity, out *v1.ServiceAffinity, s conversion.Scope) error { - return autoConvert_config_ServiceAffinity_To_v1_ServiceAffinity(in, out, s) -} - -func autoConvert_v1_ServiceAntiAffinity_To_config_ServiceAntiAffinity(in *v1.ServiceAntiAffinity, out *config.ServiceAntiAffinity, s conversion.Scope) error { - out.Label = in.Label - return nil -} - -// Convert_v1_ServiceAntiAffinity_To_config_ServiceAntiAffinity is an autogenerated conversion function. -func Convert_v1_ServiceAntiAffinity_To_config_ServiceAntiAffinity(in *v1.ServiceAntiAffinity, out *config.ServiceAntiAffinity, s conversion.Scope) error { - return autoConvert_v1_ServiceAntiAffinity_To_config_ServiceAntiAffinity(in, out, s) -} - -func autoConvert_config_ServiceAntiAffinity_To_v1_ServiceAntiAffinity(in *config.ServiceAntiAffinity, out *v1.ServiceAntiAffinity, s conversion.Scope) error { - out.Label = in.Label - return nil -} - -// Convert_config_ServiceAntiAffinity_To_v1_ServiceAntiAffinity is an autogenerated conversion function. -func Convert_config_ServiceAntiAffinity_To_v1_ServiceAntiAffinity(in *config.ServiceAntiAffinity, out *v1.ServiceAntiAffinity, s conversion.Scope) error { - return autoConvert_config_ServiceAntiAffinity_To_v1_ServiceAntiAffinity(in, out, s) -} - func autoConvert_v1_UtilizationShapePoint_To_config_UtilizationShapePoint(in *v1.UtilizationShapePoint, out *config.UtilizationShapePoint, s conversion.Scope) error { out.Utilization = in.Utilization out.Score = in.Score diff --git a/pkg/scheduler/apis/config/validation/validation.go b/pkg/scheduler/apis/config/validation/validation.go index 060d82a457d..c785ad3917e 100644 --- a/pkg/scheduler/apis/config/validation/validation.go +++ b/pkg/scheduler/apis/config/validation/validation.go @@ -363,10 +363,6 @@ func validateCustomPriorities(priorities map[string]config.PriorityPolicy, prior if err := verifyDifferentWeights("LabelPreference"); err != nil { return err } - } else if priority.Argument.ServiceAntiAffinity != nil { - if err := verifyDifferentWeights("ServiceAntiAffinity"); err != nil { - return err - } } else if priority.Argument.RequestedToCapacityRatioArguments != nil { if err := verifyRedeclaration("RequestedToCapacityRatio"); err != nil { return err diff --git a/pkg/scheduler/apis/config/validation/validation_test.go b/pkg/scheduler/apis/config/validation/validation_test.go index 9a6967a53e1..c9da674c71a 100644 --- a/pkg/scheduler/apis/config/validation/validation_test.go +++ b/pkg/scheduler/apis/config/validation/validation_test.go @@ -502,7 +502,7 @@ func TestValidateKubeSchedulerConfigurationV1beta3(t *testing.T) { badRemovedPlugins1.Profiles[0].Plugins.Score.Enabled = append(badRemovedPlugins1.Profiles[0].Plugins.Score.Enabled, config.Plugin{Name: "ServiceAffinity", Weight: 2}) badRemovedPlugins2 := validConfig.DeepCopy() - badRemovedPlugins2.Profiles[0].Plugins.Score.Enabled = append(badRemovedPlugins2.Profiles[0].Plugins.Score.Enabled, config.Plugin{Name: "ServiceAffinity", Weight: 2}) + badRemovedPlugins2.Profiles[0].Plugins.Score.Enabled = append(badRemovedPlugins2.Profiles[0].Plugins.Score.Enabled, config.Plugin{Name: "RequestedToCapacityRatio", Weight: 2}) badRemovedPlugins3 := validConfig.DeepCopy() badRemovedPlugins3.Profiles[0].Plugins.Score.Enabled = append(badRemovedPlugins3.Profiles[0].Plugins.Score.Enabled, config.Plugin{Name: "NodeResourcesMostAllocated", Weight: 2}) @@ -731,16 +731,6 @@ func TestValidatePolicy(t *testing.T) { }, expected: errors.New("LabelPreference priority \"customPriority2\" has a different weight with \"customPriority1\""), }, - { - name: "different weights for ServiceAntiAffinity custom priority", - policy: config.Policy{ - Priorities: []config.PriorityPolicy{ - {Name: "customPriority1", Weight: 1, Argument: &config.PriorityArgument{ServiceAntiAffinity: &config.ServiceAntiAffinity{}}}, - {Name: "customPriority2", Weight: 2, Argument: &config.PriorityArgument{ServiceAntiAffinity: &config.ServiceAntiAffinity{}}}, - }, - }, - expected: errors.New("ServiceAntiAffinity priority \"customPriority2\" has a different weight with \"customPriority1\""), - }, { name: "invalid hardPodAffinitySymmetricWeight, above the range", policy: config.Policy{ diff --git a/pkg/scheduler/apis/config/zz_generated.deepcopy.go b/pkg/scheduler/apis/config/zz_generated.deepcopy.go index 4fcfe314c76..d6e52d0c610 100644 --- a/pkg/scheduler/apis/config/zz_generated.deepcopy.go +++ b/pkg/scheduler/apis/config/zz_generated.deepcopy.go @@ -631,11 +631,6 @@ func (in *Policy) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PredicateArgument) DeepCopyInto(out *PredicateArgument) { *out = *in - if in.ServiceAffinity != nil { - in, out := &in.ServiceAffinity, &out.ServiceAffinity - *out = new(ServiceAffinity) - (*in).DeepCopyInto(*out) - } if in.LabelsPresence != nil { in, out := &in.LabelsPresence, &out.LabelsPresence *out = new(LabelsPresence) @@ -678,11 +673,6 @@ func (in *PredicatePolicy) DeepCopy() *PredicatePolicy { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PriorityArgument) DeepCopyInto(out *PriorityArgument) { *out = *in - if in.ServiceAntiAffinity != nil { - in, out := &in.ServiceAntiAffinity, &out.ServiceAntiAffinity - *out = new(ServiceAntiAffinity) - **out = **in - } if in.LabelPreference != nil { in, out := &in.LabelPreference, &out.LabelPreference *out = new(LabelPreference) @@ -851,78 +841,6 @@ func (in *ScoringStrategy) DeepCopy() *ScoringStrategy { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceAffinity) DeepCopyInto(out *ServiceAffinity) { - *out = *in - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAffinity. -func (in *ServiceAffinity) DeepCopy() *ServiceAffinity { - if in == nil { - return nil - } - out := new(ServiceAffinity) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceAffinityArgs) DeepCopyInto(out *ServiceAffinityArgs) { - *out = *in - out.TypeMeta = in.TypeMeta - if in.AffinityLabels != nil { - in, out := &in.AffinityLabels, &out.AffinityLabels - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.AntiAffinityLabelsPreference != nil { - in, out := &in.AntiAffinityLabelsPreference, &out.AntiAffinityLabelsPreference - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAffinityArgs. -func (in *ServiceAffinityArgs) DeepCopy() *ServiceAffinityArgs { - if in == nil { - return nil - } - out := new(ServiceAffinityArgs) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ServiceAffinityArgs) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceAntiAffinity) DeepCopyInto(out *ServiceAntiAffinity) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAntiAffinity. -func (in *ServiceAntiAffinity) DeepCopy() *ServiceAntiAffinity { - if in == nil { - return nil - } - out := new(ServiceAntiAffinity) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *UtilizationShapePoint) DeepCopyInto(out *UtilizationShapePoint) { *out = *in diff --git a/pkg/scheduler/eventhandlers.go b/pkg/scheduler/eventhandlers.go index 2a7032eee71..db691d5829c 100644 --- a/pkg/scheduler/eventhandlers.go +++ b/pkg/scheduler/eventhandlers.go @@ -399,11 +399,6 @@ func addAllEventHandlers( }, ) } - case framework.Service: - // ServiceAffinity: affected by the selector of the service is updated. - informerFactory.Core().V1().Services().Informer().AddEventHandler( - buildEvtResHandler(at, framework.Service, "Service"), - ) default: // Tests may not instantiate dynInformerFactory. if dynInformerFactory == nil { diff --git a/pkg/scheduler/framework/plugins/legacy_registry.go b/pkg/scheduler/framework/plugins/legacy_registry.go index ceb9eac93be..d2d60871c51 100644 --- a/pkg/scheduler/framework/plugins/legacy_registry.go +++ b/pkg/scheduler/framework/plugins/legacy_registry.go @@ -20,7 +20,7 @@ import ( "fmt" "sort" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apiserver/pkg/util/feature" "k8s.io/klog/v2" @@ -38,7 +38,6 @@ import ( "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodevolumelimits" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/podtopologyspread" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/selectorspread" - "k8s.io/kubernetes/pkg/scheduler/framework/plugins/serviceaffinity" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/tainttoleration" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumebinding" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumerestrictions" @@ -106,8 +105,6 @@ const ( CheckNodeUnschedulablePred = "CheckNodeUnschedulable" // CheckNodeLabelPresencePred defines the name of predicate CheckNodeLabelPresence. CheckNodeLabelPresencePred = "CheckNodeLabelPresence" - // CheckServiceAffinityPred defines the name of predicate checkServiceAffinity. - CheckServiceAffinityPred = "CheckServiceAffinity" // MaxEBSVolumeCountPred defines the name of predicate MaxEBSVolumeCount. // DEPRECATED // All cloudprovider specific predicates are deprecated in favour of MaxCSIVolumeCountPred. @@ -138,7 +135,7 @@ var predicateOrdering = []string{ GeneralPred, HostNamePred, PodFitsHostPortsPred, MatchNodeSelectorPred, PodFitsResourcesPred, NoDiskConflictPred, PodToleratesNodeTaintsPred, CheckNodeLabelPresencePred, - CheckServiceAffinityPred, MaxEBSVolumeCountPred, MaxGCEPDVolumeCountPred, MaxCSIVolumeCountPred, + MaxEBSVolumeCountPred, MaxGCEPDVolumeCountPred, MaxCSIVolumeCountPred, MaxAzureDiskVolumeCountPred, MaxCinderVolumeCountPred, CheckVolumeBindingPred, NoVolumeZoneConflictPred, EvenPodsSpreadPred, MatchInterPodAffinityPred, } @@ -166,8 +163,6 @@ type ConfigProducerArgs struct { NodeLabelArgs *config.NodeLabelArgs // RequestedToCapacityRatioArgs is the args for the RequestedToCapacityRatio plugin. RequestedToCapacityRatioArgs *config.RequestedToCapacityRatioArgs - // ServiceAffinityArgs is the args for the ServiceAffinity plugin. - ServiceAffinityArgs *config.ServiceAffinityArgs // NodeResourcesFitArgs is the args for the NodeResources fit filter. NodeResourcesFitArgs *config.NodeResourcesFitArgs // InterPodAffinityArgs is the args for InterPodAffinity plugin @@ -315,15 +310,6 @@ func NewLegacyRegistry() *LegacyRegistry { config.PluginConfig{Name: nodelabel.Name, Args: args.NodeLabelArgs}) } }) - registry.registerPredicateConfigProducer(CheckServiceAffinityPred, - func(args ConfigProducerArgs, plugins *config.Plugins, pluginConfig *[]config.PluginConfig) { - plugins.Filter = appendToPluginSet(plugins.Filter, serviceaffinity.Name, nil) - if args.ServiceAffinityArgs != nil { - *pluginConfig = append(*pluginConfig, - config.PluginConfig{Name: serviceaffinity.Name, Args: args.ServiceAffinityArgs}) - } - plugins.PreFilter = appendToPluginSet(plugins.PreFilter, serviceaffinity.Name, nil) - }) registry.registerPredicateConfigProducer(EvenPodsSpreadPred, func(_ ConfigProducerArgs, plugins *config.Plugins, _ *[]config.PluginConfig) { plugins.PreFilter = appendToPluginSet(plugins.PreFilter, podtopologyspread.Name, nil) @@ -430,18 +416,6 @@ func NewLegacyRegistry() *LegacyRegistry { config.PluginConfig{Name: nodelabel.Name, Args: args.NodeLabelArgs}) } }) - registry.registerPriorityConfigProducer(serviceaffinity.Name, - func(args ConfigProducerArgs, plugins *config.Plugins, pluginConfig *[]config.PluginConfig) { - // If there are n ServiceAffinity priorities in the policy, the weight for the corresponding - // score plugin is n*weight (note that the validation logic verifies that all ServiceAffinity - // priorities specified in Policy have the same weight). - weight := args.Weight * int32(len(args.ServiceAffinityArgs.AntiAffinityLabelsPreference)) - plugins.Score = appendToPluginSet(plugins.Score, serviceaffinity.Name, &weight) - if args.ServiceAffinityArgs != nil { - *pluginConfig = append(*pluginConfig, - config.PluginConfig{Name: serviceaffinity.Name, Args: args.ServiceAffinityArgs}) - } - }) registry.registerPriorityConfigProducer(EvenPodsSpreadPriority, func(args ConfigProducerArgs, plugins *config.Plugins, pluginConfig *[]config.PluginConfig) { plugins.PreScore = appendToPluginSet(plugins.PreScore, podtopologyspread.Name, nil) @@ -579,25 +553,10 @@ func (lr *LegacyRegistry) ProcessPredicatePolicy(policy config.PredicatePolicy, return predicateName, nil } - if policy.Argument == nil || (policy.Argument.ServiceAffinity == nil && - policy.Argument.LabelsPresence == nil) { + if policy.Argument == nil || policy.Argument.LabelsPresence == nil { return "", fmt.Errorf("predicate type not found for %q", predicateName) } - // generate the predicate function, if a custom type is requested - if policy.Argument.ServiceAffinity != nil { - // map LabelsPresence policy to ConfigProducerArgs that's used to configure the ServiceAffinity plugin. - if pluginArgs.ServiceAffinityArgs == nil { - pluginArgs.ServiceAffinityArgs = &config.ServiceAffinityArgs{} - } - pluginArgs.ServiceAffinityArgs.AffinityLabels = append(pluginArgs.ServiceAffinityArgs.AffinityLabels, policy.Argument.ServiceAffinity.Labels...) - - // We use the ServiceAffinity predicate name for all ServiceAffinity custom predicates. - // It may get called multiple times but we essentially only register one instance of ServiceAffinity predicate. - // This name is then used to find the registered plugin and run the plugin instead of the predicate. - predicateName = CheckServiceAffinityPred - } - if policy.Argument.LabelsPresence != nil { // Map LabelPresence policy to ConfigProducerArgs that's used to configure the NodeLabel plugin. if pluginArgs.NodeLabelArgs == nil { @@ -638,27 +597,11 @@ func (lr *LegacyRegistry) ProcessPriorityPolicy(policy config.PriorityPolicy, co // generate the priority function, if a custom priority is requested if policy.Argument == nil || - (policy.Argument.ServiceAntiAffinity == nil && - policy.Argument.RequestedToCapacityRatioArguments == nil && + (policy.Argument.RequestedToCapacityRatioArguments == nil && policy.Argument.LabelPreference == nil) { return "", fmt.Errorf("priority type not found for %q", priorityName) } - if policy.Argument.ServiceAntiAffinity != nil { - // We use the ServiceAffinity plugin name for all ServiceAffinity custom priorities. - // It may get called multiple times but we essentially only register one instance of - // ServiceAffinity priority. - // This name is then used to find the registered plugin and run the plugin instead of the priority. - priorityName = serviceaffinity.Name - if configProducerArgs.ServiceAffinityArgs == nil { - configProducerArgs.ServiceAffinityArgs = &config.ServiceAffinityArgs{} - } - configProducerArgs.ServiceAffinityArgs.AntiAffinityLabelsPreference = append( - configProducerArgs.ServiceAffinityArgs.AntiAffinityLabelsPreference, - policy.Argument.ServiceAntiAffinity.Label, - ) - } - if policy.Argument.LabelPreference != nil { // We use the NodeLabel plugin name for all NodeLabel custom priorities. // It may get called multiple times but we essentially only register one instance of NodeLabel priority. @@ -712,9 +655,6 @@ func (lr *LegacyRegistry) ProcessPriorityPolicy(policy config.PriorityPolicy, co func validatePredicate(predicate config.PredicatePolicy) error { if predicate.Argument != nil { numArgs := 0 - if predicate.Argument.ServiceAffinity != nil { - numArgs++ - } if predicate.Argument.LabelsPresence != nil { numArgs++ } @@ -728,9 +668,6 @@ func validatePredicate(predicate config.PredicatePolicy) error { func validatePriority(priority config.PriorityPolicy) error { if priority.Argument != nil { numArgs := 0 - if priority.Argument.ServiceAntiAffinity != nil { - numArgs++ - } if priority.Argument.LabelPreference != nil { numArgs++ } diff --git a/pkg/scheduler/framework/plugins/registry.go b/pkg/scheduler/framework/plugins/registry.go index fc33eedde43..8f6e12f6015 100644 --- a/pkg/scheduler/framework/plugins/registry.go +++ b/pkg/scheduler/framework/plugins/registry.go @@ -35,7 +35,6 @@ import ( "k8s.io/kubernetes/pkg/scheduler/framework/plugins/podtopologyspread" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/queuesort" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/selectorspread" - "k8s.io/kubernetes/pkg/scheduler/framework/plugins/serviceaffinity" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/tainttoleration" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumebinding" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumerestrictions" @@ -82,7 +81,6 @@ func NewInTreeRegistry() runtime.Registry { nodevolumelimits.CinderName: runtime.FactoryAdapter(fts, nodevolumelimits.NewCinder), interpodaffinity.Name: runtime.FactoryAdapter(fts, interpodaffinity.New), nodelabel.Name: nodelabel.New, - serviceaffinity.Name: serviceaffinity.New, queuesort.Name: queuesort.New, defaultbinder.Name: defaultbinder.New, defaultpreemption.Name: runtime.FactoryAdapter(fts, defaultpreemption.New), diff --git a/pkg/scheduler/framework/plugins/serviceaffinity/service_affinity.go b/pkg/scheduler/framework/plugins/serviceaffinity/service_affinity.go deleted file mode 100644 index eb92cef8c9c..00000000000 --- a/pkg/scheduler/framework/plugins/serviceaffinity/service_affinity.go +++ /dev/null @@ -1,463 +0,0 @@ -/* -Copyright 2019 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// This plugin has been deprecated and is only configurable through the -// scheduler policy API and the v1beta1 component config API. It is recommended -// to use the InterPodAffinity plugin instead. -package serviceaffinity - -import ( - "context" - "fmt" - - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" - corelisters "k8s.io/client-go/listers/core/v1" - "k8s.io/klog/v2" - "k8s.io/kubernetes/pkg/scheduler/apis/config" - "k8s.io/kubernetes/pkg/scheduler/framework" - "k8s.io/kubernetes/pkg/scheduler/framework/plugins/helper" - "k8s.io/kubernetes/pkg/scheduler/framework/plugins/names" -) - -const ( - // Name is the name of the plugin used in the plugin registry and configurations. - Name = names.ServiceAffinity - - // preFilterStateKey is the key in CycleState to ServiceAffinity pre-computed data. - // Using the name of the plugin will likely help us avoid collisions with other plugins. - preFilterStateKey = "PreFilter" + Name - - // ErrReason is used for CheckServiceAffinity predicate error. - ErrReason = "node(s) didn't match service affinity" -) - -// preFilterState computed at PreFilter and used at Filter. -type preFilterState struct { - matchingPodList []*v1.Pod - matchingPodServices []*v1.Service -} - -// Clone the prefilter state. -func (s *preFilterState) Clone() framework.StateData { - if s == nil { - return nil - } - - copy := preFilterState{} - copy.matchingPodServices = append([]*v1.Service(nil), - s.matchingPodServices...) - copy.matchingPodList = append([]*v1.Pod(nil), - s.matchingPodList...) - - return © -} - -// New initializes a new plugin and returns it. -func New(plArgs runtime.Object, handle framework.Handle) (framework.Plugin, error) { - args, err := getArgs(plArgs) - if err != nil { - return nil, err - } - serviceLister := handle.SharedInformerFactory().Core().V1().Services().Lister() - - klog.Warning("ServiceAffinity plugin is deprecated and will be removed in a future version; use InterPodAffinity instead") - return &ServiceAffinity{ - sharedLister: handle.SnapshotSharedLister(), - serviceLister: serviceLister, - args: args, - }, nil -} - -func getArgs(obj runtime.Object) (config.ServiceAffinityArgs, error) { - ptr, ok := obj.(*config.ServiceAffinityArgs) - if !ok { - return config.ServiceAffinityArgs{}, fmt.Errorf("want args to be of type ServiceAffinityArgs, got %T", obj) - } - return *ptr, nil -} - -// ServiceAffinity is a plugin that checks service affinity. -type ServiceAffinity struct { - args config.ServiceAffinityArgs - sharedLister framework.SharedLister - serviceLister corelisters.ServiceLister -} - -var _ framework.PreFilterPlugin = &ServiceAffinity{} -var _ framework.FilterPlugin = &ServiceAffinity{} -var _ framework.ScorePlugin = &ServiceAffinity{} -var _ framework.EnqueueExtensions = &ServiceAffinity{} - -// Name returns name of the plugin. It is used in logs, etc. -func (pl *ServiceAffinity) Name() string { - return Name -} - -func (pl *ServiceAffinity) createPreFilterState(pod *v1.Pod) (*preFilterState, error) { - if pod == nil { - return nil, fmt.Errorf("a pod is required to calculate service affinity preFilterState") - } - // Store services which match the pod. - matchingPodServices, err := helper.GetPodServices(pl.serviceLister, pod) - if err != nil { - return nil, fmt.Errorf("listing pod services: %w", err) - } - selector := createSelectorFromLabels(pod.Labels) - - // consider only the pods that belong to the same namespace - nodeInfos, err := pl.sharedLister.NodeInfos().List() - if err != nil { - return nil, fmt.Errorf("listing nodeInfos: %w", err) - } - matchingPodList := filterPods(nodeInfos, selector, pod.Namespace) - - return &preFilterState{ - matchingPodList: matchingPodList, - matchingPodServices: matchingPodServices, - }, nil -} - -// PreFilter invoked at the prefilter extension point. -func (pl *ServiceAffinity) PreFilter(ctx context.Context, cycleState *framework.CycleState, pod *v1.Pod) *framework.Status { - if len(pl.args.AffinityLabels) == 0 { - return nil - } - - s, err := pl.createPreFilterState(pod) - if err != nil { - return framework.AsStatus(fmt.Errorf("could not create preFilterState: %w", err)) - } - cycleState.Write(preFilterStateKey, s) - return nil -} - -// PreFilterExtensions returns prefilter extensions, pod add and remove. -func (pl *ServiceAffinity) PreFilterExtensions() framework.PreFilterExtensions { - if len(pl.args.AffinityLabels) == 0 { - return nil - } - return pl -} - -// AddPod from pre-computed data in cycleState. -func (pl *ServiceAffinity) AddPod(ctx context.Context, cycleState *framework.CycleState, podToSchedule *v1.Pod, podInfoToAdd *framework.PodInfo, nodeInfo *framework.NodeInfo) *framework.Status { - s, err := getPreFilterState(cycleState) - if err != nil { - return framework.AsStatus(err) - } - - // If addedPod is in the same namespace as the pod, update the list - // of matching pods if applicable. - if podInfoToAdd.Pod.Namespace != podToSchedule.Namespace { - return nil - } - - selector := createSelectorFromLabels(podToSchedule.Labels) - if selector.Matches(labels.Set(podInfoToAdd.Pod.Labels)) { - s.matchingPodList = append(s.matchingPodList, podInfoToAdd.Pod) - } - - return nil -} - -// RemovePod from pre-computed data in cycleState. -func (pl *ServiceAffinity) RemovePod(ctx context.Context, cycleState *framework.CycleState, podToSchedule *v1.Pod, podInfoToRemove *framework.PodInfo, nodeInfo *framework.NodeInfo) *framework.Status { - s, err := getPreFilterState(cycleState) - if err != nil { - return framework.AsStatus(err) - } - - if len(s.matchingPodList) == 0 || - podInfoToRemove.Pod.Namespace != s.matchingPodList[0].Namespace { - return nil - } - - for i, pod := range s.matchingPodList { - if pod.Name == podInfoToRemove.Pod.Name && pod.Namespace == podInfoToRemove.Pod.Namespace { - s.matchingPodList = append(s.matchingPodList[:i], s.matchingPodList[i+1:]...) - break - } - } - - return nil -} - -func getPreFilterState(cycleState *framework.CycleState) (*preFilterState, error) { - c, err := cycleState.Read(preFilterStateKey) - if err != nil { - // preFilterState doesn't exist, likely PreFilter wasn't invoked. - return nil, fmt.Errorf("error reading %q from cycleState: %w", preFilterStateKey, err) - } - - if c == nil { - return nil, nil - } - - s, ok := c.(*preFilterState) - if !ok { - return nil, fmt.Errorf("%+v convert to interpodaffinity.state error", c) - } - return s, nil -} - -// EventsToRegister returns the possible events that may make a Pod -// failed by this plugin schedulable. -func (pl *ServiceAffinity) EventsToRegister() []framework.ClusterEvent { - if len(pl.args.AffinityLabels) == 0 { - return nil - } - - return []framework.ClusterEvent{ - // Suppose there is a running Pod backs a Service, and the unschedulable Pod subjects - // to the same Service, but failed because of mis-matched affinity labels. - // - if the running Pod's labels get updated, it may not back the Service anymore, and - // hence make the unschedulable Pod schedulable. - // - if the running Pod gets deleted, the unschedulable Pod may also become schedulable. - {Resource: framework.Pod, ActionType: framework.Update | framework.Delete}, - // A new Node or updating a Node's labels may make a Pod schedulable. - {Resource: framework.Node, ActionType: framework.Add | framework.UpdateNodeLabel}, - // Update or delete of a Service may break the correlation of the Pods that previously - // backed it, and hence make a Pod schedulable. - {Resource: framework.Service, ActionType: framework.Update | framework.Delete}, - } -} - -// Filter matches nodes in such a way to force that -// ServiceAffinity.labels are homogeneous for pods that are scheduled to a node. -// (i.e. it returns true IFF this pod can be added to this node such that all other pods in -// the same service are running on nodes with the exact same ServiceAffinity.label values). -// -// For example: -// If the first pod of a service was scheduled to a node with label "region=foo", -// all the other subsequent pods belong to the same service will be schedule on -// nodes with the same "region=foo" label. -// -// Details: -// -// If (the svc affinity labels are not a subset of pod's label selectors ) -// The pod has all information necessary to check affinity, the pod's label selector is sufficient to calculate -// the match. -// Otherwise: -// Create an "implicit selector" which guarantees pods will land on nodes with similar values -// for the affinity labels. -// -// To do this, we "reverse engineer" a selector by introspecting existing pods running under the same service+namespace. -// These backfilled labels in the selector "L" are defined like so: -// - L is a label that the ServiceAffinity object needs as a matching constraint. -// - L is not defined in the pod itself already. -// - and SOME pod, from a service, in the same namespace, ALREADY scheduled onto a node, has a matching value. -func (pl *ServiceAffinity) Filter(ctx context.Context, cycleState *framework.CycleState, pod *v1.Pod, nodeInfo *framework.NodeInfo) *framework.Status { - if len(pl.args.AffinityLabels) == 0 { - return nil - } - - node := nodeInfo.Node() - if node == nil { - return framework.AsStatus(fmt.Errorf("node not found")) - } - - s, err := getPreFilterState(cycleState) - if err != nil { - return framework.AsStatus(err) - } - - pods, services := s.matchingPodList, s.matchingPodServices - filteredPods := nodeInfo.FilterOutPods(pods) - // check if the pod being scheduled has the affinity labels specified in its NodeSelector - affinityLabels := findLabelsInSet(pl.args.AffinityLabels, labels.Set(pod.Spec.NodeSelector)) - // Step 1: If we don't have all constraints, introspect nodes to find the missing constraints. - if len(pl.args.AffinityLabels) > len(affinityLabels) { - if len(services) > 0 { - if len(filteredPods) > 0 { - nodeWithAffinityLabels, err := pl.sharedLister.NodeInfos().Get(filteredPods[0].Spec.NodeName) - if err != nil { - return framework.AsStatus(fmt.Errorf("node not found")) - } - addUnsetLabelsToMap(affinityLabels, pl.args.AffinityLabels, labels.Set(nodeWithAffinityLabels.Node().Labels)) - } - } - } - // Step 2: Finally complete the affinity predicate based on whatever set of predicates we were able to find. - if createSelectorFromLabels(affinityLabels).Matches(labels.Set(node.Labels)) { - return nil - } - - return framework.NewStatus(framework.Unschedulable, ErrReason) -} - -// Score invoked at the Score extension point. -func (pl *ServiceAffinity) Score(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) (int64, *framework.Status) { - nodeInfo, err := pl.sharedLister.NodeInfos().Get(nodeName) - if err != nil { - return 0, framework.AsStatus(fmt.Errorf("getting node %q from Snapshot: %w", nodeName, err)) - } - - node := nodeInfo.Node() - if node == nil { - return 0, framework.AsStatus(fmt.Errorf("node not found")) - } - - // Pods matched namespace,selector on current node. - var selector labels.Selector - if services, err := helper.GetPodServices(pl.serviceLister, pod); err == nil && len(services) > 0 { - selector = labels.SelectorFromSet(services[0].Spec.Selector) - } else { - selector = labels.NewSelector() - } - - if len(nodeInfo.Pods) == 0 || selector.Empty() { - return 0, nil - } - var score int64 - for _, existingPod := range nodeInfo.Pods { - // Ignore pods being deleted for spreading purposes - // Similar to how it is done for SelectorSpreadPriority - if pod.Namespace == existingPod.Pod.Namespace && existingPod.Pod.DeletionTimestamp == nil { - if selector.Matches(labels.Set(existingPod.Pod.Labels)) { - score++ - } - } - } - - return score, nil -} - -// NormalizeScore invoked after scoring all nodes. -func (pl *ServiceAffinity) NormalizeScore(ctx context.Context, _ *framework.CycleState, pod *v1.Pod, scores framework.NodeScoreList) *framework.Status { - reduceResult := make([]float64, len(scores)) - for _, label := range pl.args.AntiAffinityLabelsPreference { - if err := pl.updateNodeScoresForLabel(pl.sharedLister, scores, reduceResult, label); err != nil { - return framework.AsStatus(err) - } - } - - // Update the result after all labels have been evaluated. - for i, nodeScore := range reduceResult { - scores[i].Score = int64(nodeScore) - } - return nil -} - -// updateNodeScoresForLabel updates the node scores for a single label. Note it does not update the -// original result from the map phase directly, but instead updates the reduceResult, which is used -// to update the original result finally. This makes sure that each call to updateNodeScoresForLabel -// receives the same mapResult to work with. -// Why are doing this? This is a workaround for the migration from priorities to score plugins. -// Historically the priority is designed to handle only one label, and multiple priorities are configured -// to work with multiple labels. Using multiple plugins is not allowed in the new framework. Therefore -// we need to modify the old priority to be able to handle multiple labels so that it can be mapped -// to a single plugin. -// TODO: This will be deprecated soon. -func (pl *ServiceAffinity) updateNodeScoresForLabel(sharedLister framework.SharedLister, mapResult framework.NodeScoreList, reduceResult []float64, label string) error { - var numServicePods int64 - var labelValue string - podCounts := map[string]int64{} - labelNodesStatus := map[string]string{} - maxPriorityFloat64 := float64(framework.MaxNodeScore) - - for _, nodePriority := range mapResult { - numServicePods += nodePriority.Score - nodeInfo, err := sharedLister.NodeInfos().Get(nodePriority.Name) - if err != nil { - return err - } - if !labels.Set(nodeInfo.Node().Labels).Has(label) { - continue - } - - labelValue = labels.Set(nodeInfo.Node().Labels).Get(label) - labelNodesStatus[nodePriority.Name] = labelValue - podCounts[labelValue] += nodePriority.Score - } - - //score int - scale of 0-maxPriority - // 0 being the lowest priority and maxPriority being the highest - for i, nodePriority := range mapResult { - labelValue, ok := labelNodesStatus[nodePriority.Name] - if !ok { - continue - } - // initializing to the default/max node score of maxPriority - fScore := maxPriorityFloat64 - if numServicePods > 0 { - fScore = maxPriorityFloat64 * (float64(numServicePods-podCounts[labelValue]) / float64(numServicePods)) - } - // The score of current label only accounts for 1/len(s.labels) of the total score. - // The policy API definition only allows a single label to be configured, associated with a weight. - // This is compensated by the fact that the total weight is the sum of all weights configured - // in each policy config. - reduceResult[i] += fScore / float64(len(pl.args.AntiAffinityLabelsPreference)) - } - - return nil -} - -// ScoreExtensions of the Score plugin. -func (pl *ServiceAffinity) ScoreExtensions() framework.ScoreExtensions { - return pl -} - -// addUnsetLabelsToMap backfills missing values with values we find in a map. -func addUnsetLabelsToMap(aL map[string]string, labelsToAdd []string, labelSet labels.Set) { - for _, l := range labelsToAdd { - // if the label is already there, don't overwrite it. - if _, exists := aL[l]; exists { - continue - } - // otherwise, backfill this label. - if labelSet.Has(l) { - aL[l] = labelSet.Get(l) - } - } -} - -// createSelectorFromLabels is used to define a selector that corresponds to the keys in a map. -func createSelectorFromLabels(aL map[string]string) labels.Selector { - if len(aL) == 0 { - return labels.Everything() - } - return labels.Set(aL).AsSelector() -} - -// filterPods filters pods outside a namespace from the given list. -func filterPods(nodeInfos []*framework.NodeInfo, selector labels.Selector, ns string) []*v1.Pod { - maxSize := 0 - for _, n := range nodeInfos { - maxSize += len(n.Pods) - } - pods := make([]*v1.Pod, 0, maxSize) - for _, n := range nodeInfos { - for _, p := range n.Pods { - if p.Pod.Namespace == ns && selector.Matches(labels.Set(p.Pod.Labels)) { - pods = append(pods, p.Pod) - } - } - } - return pods -} - -// findLabelsInSet gets as many key/value pairs as possible out of a label set. -func findLabelsInSet(labelsToKeep []string, selector labels.Set) map[string]string { - aL := make(map[string]string) - for _, l := range labelsToKeep { - if selector.Has(l) { - aL[l] = selector.Get(l) - } - } - return aL -} diff --git a/pkg/scheduler/framework/plugins/serviceaffinity/service_affinity_test.go b/pkg/scheduler/framework/plugins/serviceaffinity/service_affinity_test.go deleted file mode 100644 index b2e6da83218..00000000000 --- a/pkg/scheduler/framework/plugins/serviceaffinity/service_affinity_test.go +++ /dev/null @@ -1,625 +0,0 @@ -/* -Copyright 2019 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package serviceaffinity - -import ( - "context" - "fmt" - "reflect" - "sort" - "testing" - - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/kubernetes/pkg/scheduler/apis/config" - "k8s.io/kubernetes/pkg/scheduler/framework" - fakeframework "k8s.io/kubernetes/pkg/scheduler/framework/fake" - "k8s.io/kubernetes/pkg/scheduler/internal/cache" -) - -func TestServiceAffinity(t *testing.T) { - selector := map[string]string{"foo": "bar"} - labels1 := map[string]string{ - "region": "r1", - "zone": "z11", - } - labels2 := map[string]string{ - "region": "r1", - "zone": "z12", - } - labels3 := map[string]string{ - "region": "r2", - "zone": "z21", - } - labels4 := map[string]string{ - "region": "r2", - "zone": "z22", - } - node1 := v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labels1}} - node2 := v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labels2}} - node3 := v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labels3}} - node4 := v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "machine4", Labels: labels4}} - node5 := v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "machine5", Labels: labels4}} - tests := []struct { - name string - pod *v1.Pod - pods []*v1.Pod - services []*v1.Service - node *v1.Node - labels []string - res framework.Code - }{ - { - name: "nothing scheduled", - pod: new(v1.Pod), - node: &node1, - labels: []string{"region"}, - res: framework.Success, - }, - { - name: "pod with region label match", - pod: &v1.Pod{Spec: v1.PodSpec{NodeSelector: map[string]string{"region": "r1"}}}, - node: &node1, - labels: []string{"region"}, - res: framework.Success, - }, - { - name: "pod with region label mismatch", - pod: &v1.Pod{Spec: v1.PodSpec{NodeSelector: map[string]string{"region": "r2"}}}, - node: &node1, - labels: []string{"region"}, - res: framework.Unschedulable, - }, - { - name: "service pod on same node", - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod1", Labels: selector, UID: types.UID("pod1")}}, - pods: []*v1.Pod{{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Name: "pod2", Labels: selector, UID: types.UID("pod2")}}}, - node: &node1, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: selector}}}, - labels: []string{"region"}, - res: framework.Success, - }, - { - name: "service pod on different node, region match", - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod1", Labels: selector, UID: types.UID("pod1")}}, - pods: []*v1.Pod{{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: metav1.ObjectMeta{Name: "pod2", Labels: selector, UID: types.UID("pod2")}}}, - node: &node1, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: selector}}}, - labels: []string{"region"}, - res: framework.Success, - }, - { - name: "service pod on different node, region mismatch", - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod1", Labels: selector, UID: types.UID("pod1")}}, - pods: []*v1.Pod{{Spec: v1.PodSpec{NodeName: "machine3"}, ObjectMeta: metav1.ObjectMeta{Name: "pod2", Labels: selector, UID: types.UID("pod2")}}}, - node: &node1, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: selector}}}, - labels: []string{"region"}, - res: framework.Unschedulable, - }, - { - name: "service in different namespace, region mismatch", - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod1", Labels: selector, Namespace: "ns1", UID: types.UID("pod1")}}, - pods: []*v1.Pod{{Spec: v1.PodSpec{NodeName: "machine3"}, ObjectMeta: metav1.ObjectMeta{Name: "pod2", Labels: selector, Namespace: "ns1", UID: types.UID("pod2")}}}, - node: &node1, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: selector}, ObjectMeta: metav1.ObjectMeta{Namespace: "ns2"}}}, - labels: []string{"region"}, - res: framework.Success, - }, - { - name: "pod in different namespace, region mismatch", - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod1", Labels: selector, Namespace: "ns1", UID: types.UID("pod1")}}, - pods: []*v1.Pod{{Spec: v1.PodSpec{NodeName: "machine3"}, ObjectMeta: metav1.ObjectMeta{Name: "pod2", Labels: selector, Namespace: "ns2", UID: types.UID("pod2")}}}, - node: &node1, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: selector}, ObjectMeta: metav1.ObjectMeta{Namespace: "ns1"}}}, - labels: []string{"region"}, - res: framework.Success, - }, - { - name: "service and pod in same namespace, region mismatch", - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod1", Labels: selector, Namespace: "ns1", UID: types.UID("pod1")}}, - pods: []*v1.Pod{{Spec: v1.PodSpec{NodeName: "machine3"}, ObjectMeta: metav1.ObjectMeta{Name: "pod2", Labels: selector, Namespace: "ns1", UID: types.UID("pod2")}}}, - node: &node1, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: selector}, ObjectMeta: metav1.ObjectMeta{Namespace: "ns1"}}}, - labels: []string{"region"}, - res: framework.Unschedulable, - }, - { - name: "service pod on different node, multiple labels, not all match", - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod1", Labels: selector, UID: types.UID("pod1")}}, - pods: []*v1.Pod{{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: metav1.ObjectMeta{Name: "pod2", Labels: selector, UID: types.UID("pod2")}}}, - node: &node1, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: selector}}}, - labels: []string{"region", "zone"}, - res: framework.Unschedulable, - }, - { - name: "service pod on different node, multiple labels, all match", - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod1", Labels: selector, UID: types.UID("pod1")}}, - pods: []*v1.Pod{{Spec: v1.PodSpec{NodeName: "machine5"}, ObjectMeta: metav1.ObjectMeta{Name: "pod2", Labels: selector, UID: types.UID("pod2")}}}, - node: &node4, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: selector}}}, - labels: []string{"region", "zone"}, - res: framework.Success, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - nodes := []*v1.Node{&node1, &node2, &node3, &node4, &node5} - snapshot := cache.NewSnapshot(test.pods, nodes) - - p := &ServiceAffinity{ - sharedLister: snapshot, - serviceLister: fakeframework.ServiceLister(test.services), - args: config.ServiceAffinityArgs{ - AffinityLabels: test.labels, - }, - } - - state := framework.NewCycleState() - if s := p.PreFilter(context.Background(), state, test.pod); !s.IsSuccess() { - t.Errorf("PreFilter failed: %v", s.Message()) - } - nodeInfo := mustGetNodeInfo(t, snapshot, test.node.Name) - status := p.Filter(context.Background(), state, test.pod, nodeInfo) - if status.Code() != test.res { - t.Errorf("Status mismatch. got: %v, want: %v", status.Code(), test.res) - } - }) - } -} -func TestServiceAffinityScore(t *testing.T) { - labels1 := map[string]string{ - "foo": "bar", - "baz": "blah", - } - labels2 := map[string]string{ - "bar": "foo", - "baz": "blah", - } - zone1 := map[string]string{ - "zone": "zone1", - } - zone1Rack1 := map[string]string{ - "zone": "zone1", - "rack": "rack1", - } - zone1Rack2 := map[string]string{ - "zone": "zone1", - "rack": "rack2", - } - zone2 := map[string]string{ - "zone": "zone2", - } - zone2Rack1 := map[string]string{ - "zone": "zone2", - "rack": "rack1", - } - nozone := map[string]string{ - "name": "value", - } - zone0Spec := v1.PodSpec{ - NodeName: "machine01", - } - zone1Spec := v1.PodSpec{ - NodeName: "machine11", - } - zone2Spec := v1.PodSpec{ - NodeName: "machine21", - } - labeledNodes := map[string]map[string]string{ - "machine01": nozone, "machine02": nozone, - "machine11": zone1, "machine12": zone1, - "machine21": zone2, "machine22": zone2, - } - nodesWithZoneAndRackLabels := map[string]map[string]string{ - "machine01": nozone, "machine02": nozone, - "machine11": zone1Rack1, "machine12": zone1Rack2, - "machine21": zone2Rack1, "machine22": zone2Rack1, - } - tests := []struct { - pod *v1.Pod - pods []*v1.Pod - nodes map[string]map[string]string - services []*v1.Service - labels []string - expectedList framework.NodeScoreList - name string - }{ - { - pod: new(v1.Pod), - nodes: labeledNodes, - labels: []string{"zone"}, - expectedList: []framework.NodeScore{{Name: "machine11", Score: framework.MaxNodeScore}, {Name: "machine12", Score: framework.MaxNodeScore}, - {Name: "machine21", Score: framework.MaxNodeScore}, {Name: "machine22", Score: framework.MaxNodeScore}, - {Name: "machine01", Score: 0}, {Name: "machine02", Score: 0}}, - name: "nothing scheduled", - }, - { - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - pods: []*v1.Pod{{Spec: zone1Spec}}, - nodes: labeledNodes, - labels: []string{"zone"}, - expectedList: []framework.NodeScore{{Name: "machine11", Score: framework.MaxNodeScore}, {Name: "machine12", Score: framework.MaxNodeScore}, - {Name: "machine21", Score: framework.MaxNodeScore}, {Name: "machine22", Score: framework.MaxNodeScore}, - {Name: "machine01", Score: 0}, {Name: "machine02", Score: 0}}, - name: "no services", - }, - { - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - pods: []*v1.Pod{{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}}, - nodes: labeledNodes, - labels: []string{"zone"}, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: map[string]string{"key": "value"}}}}, - expectedList: []framework.NodeScore{{Name: "machine11", Score: framework.MaxNodeScore}, {Name: "machine12", Score: framework.MaxNodeScore}, - {Name: "machine21", Score: framework.MaxNodeScore}, {Name: "machine22", Score: framework.MaxNodeScore}, - {Name: "machine01", Score: 0}, {Name: "machine02", Score: 0}}, - name: "different services", - }, - { - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - pods: []*v1.Pod{ - {Spec: zone0Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, - {Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, - {Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - }, - nodes: labeledNodes, - labels: []string{"zone"}, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: labels1}}}, - expectedList: []framework.NodeScore{{Name: "machine11", Score: framework.MaxNodeScore}, {Name: "machine12", Score: framework.MaxNodeScore}, - {Name: "machine21", Score: 0}, {Name: "machine22", Score: 0}, - {Name: "machine01", Score: 0}, {Name: "machine02", Score: 0}}, - name: "three pods, one service pod", - }, - { - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - pods: []*v1.Pod{ - {Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, - {Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - {Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - }, - nodes: labeledNodes, - labels: []string{"zone"}, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: labels1}}}, - expectedList: []framework.NodeScore{{Name: "machine11", Score: 50}, {Name: "machine12", Score: 50}, - {Name: "machine21", Score: 50}, {Name: "machine22", Score: 50}, - {Name: "machine01", Score: 0}, {Name: "machine02", Score: 0}}, - name: "three pods, two service pods on different machines", - }, - { - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: metav1.NamespaceDefault}}, - pods: []*v1.Pod{ - {Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - {Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: metav1.NamespaceDefault}}, - {Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - {Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: "ns1"}}, - }, - nodes: labeledNodes, - labels: []string{"zone"}, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: labels1}, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault}}}, - expectedList: []framework.NodeScore{{Name: "machine11", Score: 0}, {Name: "machine12", Score: 0}, - {Name: "machine21", Score: framework.MaxNodeScore}, {Name: "machine22", Score: framework.MaxNodeScore}, - {Name: "machine01", Score: 0}, {Name: "machine02", Score: 0}}, - name: "three service label match pods in different namespaces", - }, - { - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - pods: []*v1.Pod{ - {Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, - {Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - {Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - {Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - }, - nodes: labeledNodes, - labels: []string{"zone"}, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: labels1}}}, - expectedList: []framework.NodeScore{{Name: "machine11", Score: 66}, {Name: "machine12", Score: 66}, - {Name: "machine21", Score: 33}, {Name: "machine22", Score: 33}, - {Name: "machine01", Score: 0}, {Name: "machine02", Score: 0}}, - name: "four pods, three service pods", - }, - { - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - pods: []*v1.Pod{ - {Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, - {Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - {Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - }, - nodes: labeledNodes, - labels: []string{"zone"}, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: map[string]string{"baz": "blah"}}}}, - expectedList: []framework.NodeScore{{Name: "machine11", Score: 33}, {Name: "machine12", Score: 33}, - {Name: "machine21", Score: 66}, {Name: "machine22", Score: 66}, - {Name: "machine01", Score: 0}, {Name: "machine02", Score: 0}}, - name: "service with partial pod label matches", - }, - { - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - pods: []*v1.Pod{ - {Spec: zone0Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - {Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - {Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - {Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - }, - nodes: labeledNodes, - labels: []string{"zone"}, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: labels1}}}, - expectedList: []framework.NodeScore{{Name: "machine11", Score: 75}, {Name: "machine12", Score: 75}, - {Name: "machine21", Score: 50}, {Name: "machine22", Score: 50}, - {Name: "machine01", Score: 0}, {Name: "machine02", Score: 0}}, - name: "service pod on non-zoned node", - }, - { - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - pods: []*v1.Pod{ - {Spec: zone0Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, - {Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - {Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, - }, - nodes: nodesWithZoneAndRackLabels, - labels: []string{"zone", "rack"}, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: labels1}}}, - expectedList: []framework.NodeScore{{Name: "machine11", Score: 25}, {Name: "machine12", Score: 75}, - {Name: "machine21", Score: 25}, {Name: "machine22", Score: 25}, - {Name: "machine01", Score: 0}, {Name: "machine02", Score: 0}}, - name: "three pods, two service pods, with rack label", - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - nodes := makeLabeledNodeList(test.nodes) - snapshot := cache.NewSnapshot(test.pods, nodes) - serviceLister := fakeframework.ServiceLister(test.services) - - p := &ServiceAffinity{ - sharedLister: snapshot, - serviceLister: serviceLister, - args: config.ServiceAffinityArgs{ - AntiAffinityLabelsPreference: test.labels, - }, - } - state := framework.NewCycleState() - - var gotList framework.NodeScoreList - for _, n := range makeLabeledNodeList(test.nodes) { - score, status := p.Score(context.Background(), state, test.pod, n.Name) - if !status.IsSuccess() { - t.Errorf("unexpected error: %v", status) - } - gotList = append(gotList, framework.NodeScore{Name: n.Name, Score: score}) - } - - status := p.ScoreExtensions().NormalizeScore(context.Background(), state, test.pod, gotList) - if !status.IsSuccess() { - t.Errorf("unexpected error: %v", status) - } - - // sort the two lists to avoid failures on account of different ordering - sortNodeScoreList(test.expectedList) - sortNodeScoreList(gotList) - if !reflect.DeepEqual(test.expectedList, gotList) { - t.Errorf("expected %#v, got %#v", test.expectedList, gotList) - } - }) - } -} - -func TestPreFilterStateAddRemovePod(t *testing.T) { - var label1 = map[string]string{ - "region": "r1", - "zone": "z11", - } - var label2 = map[string]string{ - "region": "r1", - "zone": "z12", - } - var label3 = map[string]string{ - "region": "r2", - "zone": "z21", - } - selector1 := map[string]string{"foo": "bar"} - - tests := []struct { - name string - pendingPod *v1.Pod - addedPod *v1.Pod - existingPods []*v1.Pod - nodes []*v1.Node - services []*v1.Service - }{ - { - name: "no anti-affinity or service affinity exist", - pendingPod: &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: "pending", Labels: selector1}, - }, - existingPods: []*v1.Pod{ - {ObjectMeta: metav1.ObjectMeta{Name: "p1", Labels: selector1}, - Spec: v1.PodSpec{NodeName: "nodeA"}, - }, - {ObjectMeta: metav1.ObjectMeta{Name: "p2"}, - Spec: v1.PodSpec{NodeName: "nodeC"}, - }, - }, - addedPod: &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: "addedPod", Labels: selector1}, - Spec: v1.PodSpec{NodeName: "nodeB"}, - }, - nodes: []*v1.Node{ - {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: label1}}, - {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: label2}}, - {ObjectMeta: metav1.ObjectMeta{Name: "nodeC", Labels: label3}}, - }, - }, - { - name: "metadata service-affinity data are updated correctly after adding and removing a pod", - pendingPod: &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: "pending", Labels: selector1}, - }, - existingPods: []*v1.Pod{ - {ObjectMeta: metav1.ObjectMeta{Name: "p1", Labels: selector1}, - Spec: v1.PodSpec{NodeName: "nodeA"}, - }, - {ObjectMeta: metav1.ObjectMeta{Name: "p2"}, - Spec: v1.PodSpec{NodeName: "nodeC"}, - }, - }, - addedPod: &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: "addedPod", Labels: selector1}, - Spec: v1.PodSpec{NodeName: "nodeB"}, - }, - services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: selector1}}}, - nodes: []*v1.Node{ - {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: label1}}, - {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: label2}}, - {ObjectMeta: metav1.ObjectMeta{Name: "nodeC", Labels: label3}}, - }, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - // getMeta creates predicate meta data given the list of pods. - getState := func(pods []*v1.Pod) (*ServiceAffinity, *framework.CycleState, *preFilterState, *cache.Snapshot) { - snapshot := cache.NewSnapshot(pods, test.nodes) - - p := &ServiceAffinity{ - sharedLister: snapshot, - serviceLister: fakeframework.ServiceLister(test.services), - args: config.ServiceAffinityArgs{ - AffinityLabels: []string{"region", "zone"}, - }, - } - cycleState := framework.NewCycleState() - preFilterStatus := p.PreFilter(context.Background(), cycleState, test.pendingPod) - if !preFilterStatus.IsSuccess() { - t.Errorf("prefilter failed with status: %v", preFilterStatus) - } - - plState, err := getPreFilterState(cycleState) - if err != nil { - t.Errorf("failed to get metadata from cycleState: %v", err) - } - - return p, cycleState, plState, snapshot - } - - sortState := func(plState *preFilterState) *preFilterState { - sort.SliceStable(plState.matchingPodList, func(i, j int) bool { - return plState.matchingPodList[i].Name < plState.matchingPodList[j].Name - }) - sort.SliceStable(plState.matchingPodServices, func(i, j int) bool { - return plState.matchingPodServices[i].Name < plState.matchingPodServices[j].Name - }) - return plState - } - - // allPodsState is the state produced when all pods, including test.addedPod are given to prefilter. - _, _, plStateAllPods, _ := getState(append(test.existingPods, test.addedPod)) - - // state is produced for test.existingPods (without test.addedPod). - ipa, state, plState, snapshot := getState(test.existingPods) - // clone the state so that we can compare it later when performing Remove. - plStateOriginal, _ := plState.Clone().(*preFilterState) - - // Add test.addedPod to state1 and verify it is equal to allPodsState. - nodeInfo := mustGetNodeInfo(t, snapshot, test.addedPod.Spec.NodeName) - addedPodInfo := framework.NewPodInfo(test.addedPod) - if err := ipa.AddPod(context.Background(), state, test.pendingPod, addedPodInfo, nodeInfo); err != nil { - t.Errorf("error adding pod to preFilterState: %v", err) - } - - if !reflect.DeepEqual(sortState(plStateAllPods), sortState(plState)) { - t.Errorf("State is not equal, got: %v, want: %v", plState, plStateAllPods) - } - - // Remove the added pod and make sure it is equal to the original state. - if err := ipa.RemovePod(context.Background(), state, test.pendingPod, addedPodInfo, nodeInfo); err != nil { - t.Errorf("error removing pod from preFilterState: %v", err) - } - if !reflect.DeepEqual(sortState(plStateOriginal), sortState(plState)) { - t.Errorf("State is not equal, got: %v, want: %v", plState, plStateOriginal) - } - }) - } -} - -func TestPreFilterStateClone(t *testing.T) { - source := &preFilterState{ - matchingPodList: []*v1.Pod{ - {ObjectMeta: metav1.ObjectMeta{Name: "pod1"}}, - {ObjectMeta: metav1.ObjectMeta{Name: "pod2"}}, - }, - matchingPodServices: []*v1.Service{ - {ObjectMeta: metav1.ObjectMeta{Name: "service1"}}, - }, - } - - clone := source.Clone() - if clone == source { - t.Errorf("Clone returned the exact same object!") - } - if !reflect.DeepEqual(clone, source) { - t.Errorf("Copy is not equal to source!") - } -} - -func makeLabeledNodeList(nodeMap map[string]map[string]string) []*v1.Node { - nodes := make([]*v1.Node, 0, len(nodeMap)) - for nodeName, labels := range nodeMap { - nodes = append(nodes, &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: nodeName, Labels: labels}}) - } - return nodes -} - -func sortNodeScoreList(out framework.NodeScoreList) { - sort.Slice(out, func(i, j int) bool { - if out[i].Score == out[j].Score { - return out[i].Name < out[j].Name - } - return out[i].Score < out[j].Score - }) -} - -func mustGetNodeInfo(t *testing.T, snapshot *cache.Snapshot, name string) *framework.NodeInfo { - t.Helper() - nodeInfo, err := snapshot.NodeInfos().Get(name) - if err != nil { - t.Fatal(err) - } - return nodeInfo -} - -func TestPreFilterDisabled(t *testing.T) { - pod := &v1.Pod{} - nodeInfo := framework.NewNodeInfo() - node := v1.Node{} - nodeInfo.SetNode(&node) - p := &ServiceAffinity{ - args: config.ServiceAffinityArgs{ - AffinityLabels: []string{"region"}, - }, - } - cycleState := framework.NewCycleState() - gotStatus := p.Filter(context.Background(), cycleState, pod, nodeInfo) - wantStatus := framework.AsStatus(fmt.Errorf(`error reading "PreFilterServiceAffinity" from cycleState: %w`, framework.ErrNotFound)) - if !reflect.DeepEqual(gotStatus, wantStatus) { - t.Errorf("status does not match: %v, want: %v", gotStatus, wantStatus) - } -} diff --git a/staging/src/k8s.io/kube-scheduler/config/v1/types.go b/staging/src/k8s.io/kube-scheduler/config/v1/types.go index 353bab4a384..86ea52cec1c 100644 --- a/staging/src/k8s.io/kube-scheduler/config/v1/types.go +++ b/staging/src/k8s.io/kube-scheduler/config/v1/types.go @@ -72,9 +72,6 @@ type PriorityPolicy struct { // PredicateArgument represents the arguments to configure predicate functions in scheduler policy configuration. // Only one of its members may be specified type PredicateArgument struct { - // The predicate that provides affinity for pods belonging to a service - // It uses a label to identify nodes that belong to the same "group" - ServiceAffinity *ServiceAffinity `json:"serviceAffinity"` // The predicate that checks whether a particular node has a certain label // defined or not, regardless of value LabelsPresence *LabelsPresence `json:"labelsPresence"` @@ -83,9 +80,6 @@ type PredicateArgument struct { // PriorityArgument represents the arguments to configure priority functions in scheduler policy configuration. // Only one of its members may be specified type PriorityArgument struct { - // The priority function that ensures a good spread (anti-affinity) for pods belonging to a service - // It uses a label to identify nodes that belong to the same "group" - ServiceAntiAffinity *ServiceAntiAffinity `json:"serviceAntiAffinity"` // The priority function that checks whether a particular node has a certain label // defined or not, regardless of value LabelPreference *LabelPreference `json:"labelPreference"` @@ -93,13 +87,6 @@ type PriorityArgument struct { RequestedToCapacityRatioArguments *RequestedToCapacityRatioArguments `json:"requestedToCapacityRatioArguments"` } -// ServiceAffinity holds the parameters that are used to configure the corresponding predicate in scheduler policy configuration. -type ServiceAffinity struct { - // The list of labels that identify node "groups" - // All of the labels should match for the node to be considered a fit for hosting the pod - Labels []string `json:"labels"` -} - // LabelsPresence holds the parameters that are used to configure the corresponding predicate in scheduler policy configuration. type LabelsPresence struct { // The list of labels that identify node "groups" @@ -109,12 +96,6 @@ type LabelsPresence struct { Presence bool `json:"presence"` } -// ServiceAntiAffinity holds the parameters that are used to configure the corresponding priority function -type ServiceAntiAffinity struct { - // Used to identify node "groups" - Label string `json:"label"` -} - // LabelPreference holds the parameters that are used to configure the corresponding priority function type LabelPreference struct { // Used to identify node "groups" diff --git a/staging/src/k8s.io/kube-scheduler/config/v1/zz_generated.deepcopy.go b/staging/src/k8s.io/kube-scheduler/config/v1/zz_generated.deepcopy.go index 6c1816653f7..f65cae100f5 100644 --- a/staging/src/k8s.io/kube-scheduler/config/v1/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/kube-scheduler/config/v1/zz_generated.deepcopy.go @@ -184,11 +184,6 @@ func (in *Policy) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PredicateArgument) DeepCopyInto(out *PredicateArgument) { *out = *in - if in.ServiceAffinity != nil { - in, out := &in.ServiceAffinity, &out.ServiceAffinity - *out = new(ServiceAffinity) - (*in).DeepCopyInto(*out) - } if in.LabelsPresence != nil { in, out := &in.LabelsPresence, &out.LabelsPresence *out = new(LabelsPresence) @@ -231,11 +226,6 @@ func (in *PredicatePolicy) DeepCopy() *PredicatePolicy { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PriorityArgument) DeepCopyInto(out *PriorityArgument) { *out = *in - if in.ServiceAntiAffinity != nil { - in, out := &in.ServiceAntiAffinity, &out.ServiceAntiAffinity - *out = new(ServiceAntiAffinity) - **out = **in - } if in.LabelPreference != nil { in, out := &in.LabelPreference, &out.LabelPreference *out = new(LabelPreference) @@ -322,43 +312,6 @@ func (in *ResourceSpec) DeepCopy() *ResourceSpec { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceAffinity) DeepCopyInto(out *ServiceAffinity) { - *out = *in - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAffinity. -func (in *ServiceAffinity) DeepCopy() *ServiceAffinity { - if in == nil { - return nil - } - out := new(ServiceAffinity) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceAntiAffinity) DeepCopyInto(out *ServiceAntiAffinity) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAntiAffinity. -func (in *ServiceAntiAffinity) DeepCopy() *ServiceAntiAffinity { - if in == nil { - return nil - } - out := new(ServiceAntiAffinity) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *UtilizationShapePoint) DeepCopyInto(out *UtilizationShapePoint) { *out = *in