Merge pull request #90212 from pancernik/pod-topology-spread-plugin-args

Add PodTopologySpread plugin arg types to kube-scheduler.config.k8s.io
This commit is contained in:
Kubernetes Prow Robot 2020-04-16 13:59:21 -07:00 committed by GitHub
commit d0f99fe39c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 157 additions and 28 deletions

View File

@ -13,6 +13,7 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/scheduler/apis/config",
visibility = ["//visibility:public"],
deps = [
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",

View File

@ -42,6 +42,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&InterPodAffinityArgs{},
&NodeLabelArgs{},
&NodeResourcesFitArgs{},
&PodTopologySpreadArgs{},
&RequestedToCapacityRatioArgs{},
&ServiceAffinityArgs{},
)

View File

@ -17,6 +17,7 @@ limitations under the License.
package config
import (
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -33,7 +34,7 @@ type InterPodAffinityArgs struct {
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// NodeLabelArgs holds arguments that used to configure the NodeLabel plugin.
// NodeLabelArgs holds arguments used to configure the NodeLabel plugin.
type NodeLabelArgs struct {
metav1.TypeMeta
@ -60,6 +61,21 @@ type NodeResourcesFitArgs struct {
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// PodTopologySpreadArgs holds arguments used to configure the PodTopologySpread plugin.
type PodTopologySpreadArgs struct {
metav1.TypeMeta
// DefaultConstraints defines topology spread constraints to be applied to
// pods that don't define any in `pod.spec.topologySpreadConstraints`.
// `topologySpreadConstraint.labelSelectors` must be empty, as they are
// deduced the pods' membership to Services, Replication Controllers, Replica
// Sets or Stateful Sets.
// Empty by default.
DefaultConstraints []v1.TopologySpreadConstraint
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// RequestedToCapacityRatioArgs holds arguments used to configure RequestedToCapacityRatio plugin.
type RequestedToCapacityRatioArgs struct {
metav1.TypeMeta

View File

@ -16,6 +16,7 @@ go_library(
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/scheduler/apis/config:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",

View File

@ -23,6 +23,7 @@ package v1alpha2
import (
unsafe "unsafe"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
@ -129,6 +130,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1alpha2.PodTopologySpreadArgs)(nil), (*config.PodTopologySpreadArgs)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha2_PodTopologySpreadArgs_To_config_PodTopologySpreadArgs(a.(*v1alpha2.PodTopologySpreadArgs), b.(*config.PodTopologySpreadArgs), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*config.PodTopologySpreadArgs)(nil), (*v1alpha2.PodTopologySpreadArgs)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_config_PodTopologySpreadArgs_To_v1alpha2_PodTopologySpreadArgs(a.(*config.PodTopologySpreadArgs), b.(*v1alpha2.PodTopologySpreadArgs), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1alpha2.RequestedToCapacityRatioArgs)(nil), (*config.RequestedToCapacityRatioArgs)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha2_RequestedToCapacityRatioArgs_To_config_RequestedToCapacityRatioArgs(a.(*v1alpha2.RequestedToCapacityRatioArgs), b.(*config.RequestedToCapacityRatioArgs), scope)
}); err != nil {
@ -763,6 +774,26 @@ func Convert_config_Plugins_To_v1alpha2_Plugins(in *config.Plugins, out *v1alpha
return autoConvert_config_Plugins_To_v1alpha2_Plugins(in, out, s)
}
func autoConvert_v1alpha2_PodTopologySpreadArgs_To_config_PodTopologySpreadArgs(in *v1alpha2.PodTopologySpreadArgs, out *config.PodTopologySpreadArgs, s conversion.Scope) error {
out.DefaultConstraints = *(*[]corev1.TopologySpreadConstraint)(unsafe.Pointer(&in.DefaultConstraints))
return nil
}
// Convert_v1alpha2_PodTopologySpreadArgs_To_config_PodTopologySpreadArgs is an autogenerated conversion function.
func Convert_v1alpha2_PodTopologySpreadArgs_To_config_PodTopologySpreadArgs(in *v1alpha2.PodTopologySpreadArgs, out *config.PodTopologySpreadArgs, s conversion.Scope) error {
return autoConvert_v1alpha2_PodTopologySpreadArgs_To_config_PodTopologySpreadArgs(in, out, s)
}
func autoConvert_config_PodTopologySpreadArgs_To_v1alpha2_PodTopologySpreadArgs(in *config.PodTopologySpreadArgs, out *v1alpha2.PodTopologySpreadArgs, s conversion.Scope) error {
out.DefaultConstraints = *(*[]corev1.TopologySpreadConstraint)(unsafe.Pointer(&in.DefaultConstraints))
return nil
}
// Convert_config_PodTopologySpreadArgs_To_v1alpha2_PodTopologySpreadArgs is an autogenerated conversion function.
func Convert_config_PodTopologySpreadArgs_To_v1alpha2_PodTopologySpreadArgs(in *config.PodTopologySpreadArgs, out *v1alpha2.PodTopologySpreadArgs, s conversion.Scope) error {
return autoConvert_config_PodTopologySpreadArgs_To_v1alpha2_PodTopologySpreadArgs(in, out, s)
}
func autoConvert_v1alpha2_RequestedToCapacityRatioArgs_To_config_RequestedToCapacityRatioArgs(in *v1alpha2.RequestedToCapacityRatioArgs, out *config.RequestedToCapacityRatioArgs, s conversion.Scope) error {
out.Shape = *(*[]config.UtilizationShapePoint)(unsafe.Pointer(&in.Shape))
out.Resources = *(*[]config.ResourceSpec)(unsafe.Pointer(&in.Resources))

View File

@ -21,6 +21,7 @@ limitations under the License.
package config
import (
v1 "k8s.io/api/core/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@ -454,6 +455,38 @@ func (in *Plugins) DeepCopy() *Plugins {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PodTopologySpreadArgs) DeepCopyInto(out *PodTopologySpreadArgs) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.DefaultConstraints != nil {
in, out := &in.DefaultConstraints, &out.DefaultConstraints
*out = make([]v1.TopologySpreadConstraint, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodTopologySpreadArgs.
func (in *PodTopologySpreadArgs) DeepCopy() *PodTopologySpreadArgs {
if in == nil {
return nil
}
out := new(PodTopologySpreadArgs)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PodTopologySpreadArgs) 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 *Policy) DeepCopyInto(out *Policy) {
*out = *in

View File

@ -24,6 +24,7 @@ go_library(
"//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/listers/apps/v1:go_default_library",
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
"//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)
@ -49,6 +50,7 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
"//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library",
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
"//vendor/k8s.io/utils/pointer:go_default_library",
],

View File

@ -42,7 +42,7 @@ type topologySpreadConstraint struct {
// .DefaultConstraints and the selectors from the services, replication
// controllers, replica sets and stateful sets that match the pod.
func (pl *PodTopologySpread) defaultConstraints(p *v1.Pod, action v1.UnsatisfiableConstraintAction) ([]topologySpreadConstraint, error) {
constraints, err := filterTopologySpreadConstraints(pl.DefaultConstraints, action)
constraints, err := filterTopologySpreadConstraints(pl.args.DefaultConstraints, action)
if err != nil || len(constraints) == 0 {
return nil, err
}

View File

@ -28,6 +28,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
"k8s.io/kubernetes/pkg/scheduler/internal/parallelize"
@ -517,7 +518,7 @@ func TestPreFilterState(t *testing.T) {
informerFactory := informers.NewSharedInformerFactory(fake.NewSimpleClientset(tt.objs...), 0)
pl := PodTopologySpread{
sharedLister: cache.NewSnapshot(tt.existingPods, tt.nodes),
Args: Args{
args: schedulerv1alpha2.PodTopologySpreadArgs{
DefaultConstraints: tt.defaultConstraints,
},
}

View File

@ -19,7 +19,7 @@ package podtopologyspread
import (
"fmt"
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
metav1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/sets"
@ -27,6 +27,7 @@ import (
"k8s.io/client-go/informers"
appslisters "k8s.io/client-go/listers/apps/v1"
corelisters "k8s.io/client-go/listers/core/v1"
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
)
@ -39,22 +40,9 @@ var (
supportedScheduleActions = sets.NewString(string(v1.DoNotSchedule), string(v1.ScheduleAnyway))
)
// Args holds the arguments to configure the plugin.
type Args struct {
// DefaultConstraints defines topology spread constraints to be applied to
// pods that don't define any in `pod.spec.topologySpreadConstraints`.
// `topologySpreadConstraint.labelSelectors` must be empty, as they are
// deduced the pods' membership to Services, Replication Controllers, Replica
// Sets or Stateful Sets.
// Empty by default.
// +optional
// +listType=atomic
DefaultConstraints []v1.TopologySpreadConstraint `json:"defaultConstraints"`
}
// PodTopologySpread is a plugin that ensures pod's topologySpreadConstraints is satisfied.
type PodTopologySpread struct {
Args
args schedulerv1alpha2.PodTopologySpreadArgs
sharedLister framework.SharedLister
services corelisters.ServiceLister
replicationCtrls corelisters.ReplicationControllerLister
@ -79,7 +67,7 @@ func (pl *PodTopologySpread) Name() string {
// BuildArgs returns the arguments used to build the plugin.
func (pl *PodTopologySpread) BuildArgs() interface{} {
return pl.Args
return pl.args
}
// New initializes a new plugin and returns it.
@ -88,13 +76,13 @@ func New(args runtime.Object, h framework.FrameworkHandle) (framework.Plugin, er
return nil, fmt.Errorf("SnapshotSharedlister is nil")
}
pl := &PodTopologySpread{sharedLister: h.SnapshotSharedLister()}
if err := framework.DecodeInto(args, &pl.Args); err != nil {
if err := framework.DecodeInto(args, &pl.args); err != nil {
return nil, err
}
if err := validateArgs(&pl.Args); err != nil {
if err := validateArgs(&pl.args); err != nil {
return nil, err
}
if len(pl.DefaultConstraints) != 0 {
if len(pl.args.DefaultConstraints) != 0 {
if h.SharedInformerFactory() == nil {
return nil, fmt.Errorf("SharedInformerFactory is nil")
}
@ -113,7 +101,7 @@ func (pl *PodTopologySpread) setListers(factory informers.SharedInformerFactory)
// validateArgs replicates the validation from
// pkg/apis/core/validation.validateTopologySpreadConstraints.
// This has the additional check for .labelSelector to be nil.
func validateArgs(args *Args) error {
func validateArgs(args *schedulerv1alpha2.PodTopologySpreadArgs) error {
var allErrs field.ErrorList
path := field.NewPath("defaultConstraints")
for i, c := range args.DefaultConstraints {

View File

@ -25,6 +25,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
)
@ -34,7 +35,7 @@ func TestNew(t *testing.T) {
name string
args runtime.Unknown
wantErr string
wantArgs Args
wantArgs schedulerv1alpha2.PodTopologySpreadArgs
}{
{name: "empty args"},
{
@ -50,7 +51,7 @@ func TestNew(t *testing.T) {
whenUnsatisfiable: "DoNotSchedule"
`),
},
wantArgs: Args{
wantArgs: schedulerv1alpha2.PodTopologySpreadArgs{
DefaultConstraints: []v1.TopologySpreadConstraint{
{
MaxSkew: 1,

View File

@ -27,6 +27,7 @@ import (
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
"k8s.io/kubernetes/pkg/scheduler/internal/parallelize"
@ -194,7 +195,7 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
informerFactory := informers.NewSharedInformerFactory(fake.NewSimpleClientset(tt.objs...), 0)
pl := PodTopologySpread{
sharedLister: cache.NewSnapshot(nil, tt.nodes),
Args: Args{
args: schedulerv1alpha2.PodTopologySpreadArgs{
DefaultConstraints: tt.defaultConstraints,
},
}
@ -728,7 +729,7 @@ func BenchmarkTestDefaultEvenPodsSpreadPriority(b *testing.B) {
snapshot := cache.NewSnapshot(existingPods, allNodes)
p := &PodTopologySpread{
sharedLister: snapshot,
Args: Args{
args: schedulerv1alpha2.PodTopologySpreadArgs{
DefaultConstraints: []v1.TopologySpreadConstraint{
{MaxSkew: 1, TopologyKey: v1.LabelHostname, WhenUnsatisfiable: v1.ScheduleAnyway},
{MaxSkew: 1, TopologyKey: v1.LabelZoneFailureDomain, WhenUnsatisfiable: v1.ScheduleAnyway},

View File

@ -13,6 +13,7 @@ go_library(
importpath = "k8s.io/kube-scheduler/config/v1alpha2",
visibility = ["//visibility:public"],
deps = [
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",

View File

@ -41,6 +41,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&InterPodAffinityArgs{},
&NodeLabelArgs{},
&NodeResourcesFitArgs{},
&PodTopologySpreadArgs{},
&RequestedToCapacityRatioArgs{},
&ServiceAffinityArgs{},
)

View File

@ -17,6 +17,7 @@ limitations under the License.
package v1alpha2
import (
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -33,7 +34,7 @@ type InterPodAffinityArgs struct {
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// NodeLabelArgs holds arguments that used to configure the NodeLabel plugin.
// NodeLabelArgs holds arguments used to configure the NodeLabel plugin.
type NodeLabelArgs struct {
metav1.TypeMeta `json:",inline"`
@ -65,6 +66,23 @@ type NodeResourcesFitArgs struct {
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// PodTopologySpreadArgs holds arguments used to configure the PodTopologySpread plugin.
type PodTopologySpreadArgs struct {
metav1.TypeMeta `json:",inline"`
// DefaultConstraints defines topology spread constraints to be applied to
// pods that don't define any in `pod.spec.topologySpreadConstraints`.
// `topologySpreadConstraint.labelSelectors` must be empty, as they are
// deduced the pods' membership to Services, Replication Controllers, Replica
// Sets or Stateful Sets.
// Empty by default.
// +optional
// +listType=atomic
DefaultConstraints []v1.TopologySpreadConstraint `json:"defaultConstraints"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// RequestedToCapacityRatioArgs holds arguments used to configure RequestedToCapacityRatio plugin.
type RequestedToCapacityRatioArgs struct {
metav1.TypeMeta `json:",inline"`

View File

@ -21,6 +21,7 @@ limitations under the License.
package v1alpha2
import (
corev1 "k8s.io/api/core/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
v1 "k8s.io/kube-scheduler/config/v1"
)
@ -396,6 +397,38 @@ func (in *Plugins) DeepCopy() *Plugins {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PodTopologySpreadArgs) DeepCopyInto(out *PodTopologySpreadArgs) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.DefaultConstraints != nil {
in, out := &in.DefaultConstraints, &out.DefaultConstraints
*out = make([]corev1.TopologySpreadConstraint, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodTopologySpreadArgs.
func (in *PodTopologySpreadArgs) DeepCopy() *PodTopologySpreadArgs {
if in == nil {
return nil
}
out := new(PodTopologySpreadArgs)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PodTopologySpreadArgs) 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 *RequestedToCapacityRatioArgs) DeepCopyInto(out *RequestedToCapacityRatioArgs) {
*out = *in