diff --git a/artifacts/deploy/policy.karmada.io_clusterpropagationpolicies.yaml b/artifacts/deploy/policy.karmada.io_clusterpropagationpolicies.yaml index ba0a343f2..022b083d8 100644 --- a/artifacts/deploy/policy.karmada.io_clusterpropagationpolicies.yaml +++ b/artifacts/deploy/policy.karmada.io_clusterpropagationpolicies.yaml @@ -208,6 +208,268 @@ spec: type: string type: object type: array + replicaScheduling: + description: ReplicaScheduling represents the scheduling policy + on dealing with the number of replicas when propagating resources + that have replicas in spec (e.g. deployments, statefulsets) + to member clusters. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this + representation of an object. Servers should convert recognized + schemas to the latest internal value, and may reject unrecognized + values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST + resource this object represents. Servers may infer this + from the endpoint the client submits requests to. Cannot + be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec represents the desired behavior of ReplicaSchedulingPolicy. + properties: + preferences: + description: Preferences describes weight for each cluster + or for each group of cluster. + properties: + staticWeightList: + description: StaticWeightList defines the static cluster + weight. + items: + description: StaticClusterWeight defines the static + cluster weight. + properties: + targetCluster: + description: TargetCluster describes the filter + to select clusters. + properties: + clusterNames: + description: ClusterNames is the list of + clusters to be selected. + items: + type: string + type: array + exclude: + description: ExcludedClusters is the list + of clusters to be ignored. + items: + type: string + type: array + fieldSelector: + description: FieldSelector is a filter to + select member clusters by fields. If non-nil + and non-empty, only the clusters match + this filter will be selected. + properties: + matchExpressions: + description: A list of field selector + requirements. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: Represents a key's + relationship to a set of values. + Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string + values. If the operator is In + or NotIn, the values array must + be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + If the operator is Gt or Lt, + the values array must have a + single element, which will be + interpreted as an integer. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + labelSelector: + description: LabelSelector is a filter to + select member clusters by labels. If non-nil + and non-empty, only the clusters match + this filter will be selected. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + type: object + weight: + description: Weight expressing the preference + to the cluster(s) specified by 'TargetCluster'. + format: int64 + type: integer + required: + - targetCluster + - weight + type: object + type: array + required: + - staticWeightList + type: object + resourceSelectors: + description: ResourceSelectors used to select resources. + items: + description: ResourceSelector the resources will be + selected. + properties: + apiVersion: + description: APIVersion represents the API version + of the target resources. + type: string + kind: + description: Kind represents the Kind of the target + resources. + type: string + labelSelector: + description: A label query over a set of resources. + If name is not empty, labelSelector will be ignored. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + name: + description: Name of the target resource. Default + is empty, which means selecting all resources. + type: string + namespace: + description: Namespace of the target resource. Default + is empty, which means inherit from the parent + object scope. + type: string + required: + - apiVersion + - kind + type: object + type: array + totalReplicas: + description: TotalReplicas represents the total number + of replicas across member clusters. The replicas(spec.replicas) + specified for deployment template will be discarded. + format: int32 + type: integer + required: + - preferences + - resourceSelectors + - totalReplicas + type: object + required: + - spec + type: object spreadConstraints: description: SpreadConstraints represents a list of the scheduling constraints. diff --git a/artifacts/deploy/policy.karmada.io_propagationpolicies.yaml b/artifacts/deploy/policy.karmada.io_propagationpolicies.yaml index 76567d320..ac08cf9e3 100644 --- a/artifacts/deploy/policy.karmada.io_propagationpolicies.yaml +++ b/artifacts/deploy/policy.karmada.io_propagationpolicies.yaml @@ -204,6 +204,268 @@ spec: type: string type: object type: array + replicaScheduling: + description: ReplicaScheduling represents the scheduling policy + on dealing with the number of replicas when propagating resources + that have replicas in spec (e.g. deployments, statefulsets) + to member clusters. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this + representation of an object. Servers should convert recognized + schemas to the latest internal value, and may reject unrecognized + values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST + resource this object represents. Servers may infer this + from the endpoint the client submits requests to. Cannot + be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec represents the desired behavior of ReplicaSchedulingPolicy. + properties: + preferences: + description: Preferences describes weight for each cluster + or for each group of cluster. + properties: + staticWeightList: + description: StaticWeightList defines the static cluster + weight. + items: + description: StaticClusterWeight defines the static + cluster weight. + properties: + targetCluster: + description: TargetCluster describes the filter + to select clusters. + properties: + clusterNames: + description: ClusterNames is the list of + clusters to be selected. + items: + type: string + type: array + exclude: + description: ExcludedClusters is the list + of clusters to be ignored. + items: + type: string + type: array + fieldSelector: + description: FieldSelector is a filter to + select member clusters by fields. If non-nil + and non-empty, only the clusters match + this filter will be selected. + properties: + matchExpressions: + description: A list of field selector + requirements. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: Represents a key's + relationship to a set of values. + Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string + values. If the operator is In + or NotIn, the values array must + be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + If the operator is Gt or Lt, + the values array must have a + single element, which will be + interpreted as an integer. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + labelSelector: + description: LabelSelector is a filter to + select member clusters by labels. If non-nil + and non-empty, only the clusters match + this filter will be selected. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + type: object + weight: + description: Weight expressing the preference + to the cluster(s) specified by 'TargetCluster'. + format: int64 + type: integer + required: + - targetCluster + - weight + type: object + type: array + required: + - staticWeightList + type: object + resourceSelectors: + description: ResourceSelectors used to select resources. + items: + description: ResourceSelector the resources will be + selected. + properties: + apiVersion: + description: APIVersion represents the API version + of the target resources. + type: string + kind: + description: Kind represents the Kind of the target + resources. + type: string + labelSelector: + description: A label query over a set of resources. + If name is not empty, labelSelector will be ignored. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + name: + description: Name of the target resource. Default + is empty, which means selecting all resources. + type: string + namespace: + description: Namespace of the target resource. Default + is empty, which means inherit from the parent + object scope. + type: string + required: + - apiVersion + - kind + type: object + type: array + totalReplicas: + description: TotalReplicas represents the total number + of replicas across member clusters. The replicas(spec.replicas) + specified for deployment template will be discarded. + format: int32 + type: integer + required: + - preferences + - resourceSelectors + - totalReplicas + type: object + required: + - spec + type: object spreadConstraints: description: SpreadConstraints represents a list of the scheduling constraints. diff --git a/artifacts/deploy/work.karmada.io_clusterresourcebindings.yaml b/artifacts/deploy/work.karmada.io_clusterresourcebindings.yaml index 10027320d..7187cc589 100644 --- a/artifacts/deploy/work.karmada.io_clusterresourcebindings.yaml +++ b/artifacts/deploy/work.karmada.io_clusterresourcebindings.yaml @@ -49,6 +49,10 @@ spec: name: description: Name of target cluster. type: string + replicas: + description: Replicas in target cluster + format: int32 + type: integer required: - name type: object @@ -72,6 +76,21 @@ spec: Namespace is required. If Namespace is not specified, means the resource is non-namespace scoped. type: string + replicas: + description: Replicas represents the replica number of the referencing + resource. + format: int32 + type: integer + resourcePerReplicas: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: ReplicaResourceRequirements represents the resources + required by each replica. + type: object resourceVersion: description: ResourceVersion represents the internal version of the referenced object, that can be used by clients to determine diff --git a/artifacts/deploy/work.karmada.io_resourcebindings.yaml b/artifacts/deploy/work.karmada.io_resourcebindings.yaml index 9b53d2658..8ef9f64e6 100644 --- a/artifacts/deploy/work.karmada.io_resourcebindings.yaml +++ b/artifacts/deploy/work.karmada.io_resourcebindings.yaml @@ -49,6 +49,10 @@ spec: name: description: Name of target cluster. type: string + replicas: + description: Replicas in target cluster + format: int32 + type: integer required: - name type: object @@ -72,6 +76,21 @@ spec: Namespace is required. If Namespace is not specified, means the resource is non-namespace scoped. type: string + replicas: + description: Replicas represents the replica number of the referencing + resource. + format: int32 + type: integer + resourcePerReplicas: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: ReplicaResourceRequirements represents the resources + required by each replica. + type: object resourceVersion: description: ResourceVersion represents the internal version of the referenced object, that can be used by clients to determine diff --git a/pkg/apis/policy/v1alpha1/propagation_types.go b/pkg/apis/policy/v1alpha1/propagation_types.go index bd85dd986..d7db95d43 100644 --- a/pkg/apis/policy/v1alpha1/propagation_types.go +++ b/pkg/apis/policy/v1alpha1/propagation_types.go @@ -100,6 +100,11 @@ type Placement struct { // SpreadConstraints represents a list of the scheduling constraints. // +optional SpreadConstraints []SpreadConstraint `json:"spreadConstraints,omitempty"` + + // ReplicaScheduling represents the scheduling policy on dealing with the number of replicas + // when propagating resources that have replicas in spec (e.g. deployments, statefulsets) to member clusters. + // +optional + ReplicaScheduling *ReplicaSchedulingPolicy `json:"replicaScheduling,omitempty"` } // SpreadFieldValue is the type to define valid values for SpreadConstraint.SpreadByField @@ -163,6 +168,53 @@ type ClusterAffinity struct { ExcludeClusters []string `json:"exclude,omitempty"` } +// ReplicaSchedulingType describes scheduling methods for the "replicas" in a resouce. +type ReplicaSchedulingType string + +const ( + // ReplicaSchedulingTypeDuplicated means when propagating a resource, + // each candidate member cluster will directly apply the original replicas. + ReplicaSchedulingTypeDuplicated ReplicaSchedulingType = "Duplicated" + // ReplicaSchedulingTypeDivided means when propagating a resource, + // each candidate member cluster will get only a part of original replicas. + ReplicaSchedulingTypeDivided ReplicaSchedulingType = "Divided" +) + +// ReplicaDivisionPreference describes options of how replicas can be scheduled. +type ReplicaDivisionPreference string + +const ( + // ReplicaDivisionPreferenceAggregated divides replicas into clusters as few as possible, + // while respecting clusters' resource availabilities during the division. + ReplicaDivisionPreferenceAggregated ReplicaDivisionPreference = "Aggregated" + // ReplicaDivisionPreferenceWeighted divides replicas by weight according to WeightPreference. + ReplicaDivisionPreferenceWeighted ReplicaDivisionPreference = "Weighted" +) + +// ReplicaSchedulingStrategy represents the assignment strategy of replicas. +type ReplicaSchedulingStrategy struct { + // ReplicaSchedulingType determines how the replicas is scheduled when karmada propagating + // a resource. Valid options are Duplicated and Divided. + // "Duplicated" duplicates the same replicas to each candidate member cluster from resource. + // "Divided" divides replicas into parts according to number of valid candidate member + // clusters, and exact replicas for each cluster are determined by ReplicaDivisionPreference. + // +optional + ReplicaSchedulingType ReplicaSchedulingType `json:"replicaSchedulingType,omitempty"` + + // ReplicaDivisionPreference determines how the replicas is divided + // when ReplicaSchedulingType is "Divided". Valid options are Aggregated and Weighted. + // "Aggregated" divides replicas into clusters as few as possible, + // while respecting clusters' resource availabilities during the division. + // "Weighted" divides replicas by weight according to WeightPreference. + // +optional + ReplicaDivisionPreference ReplicaDivisionPreference `json:"replicaDivisionPreference,omitempty"` + + // WeightPreference describes weight for each cluster or for each group of cluster + // If ReplicaDivisionPreference is set to "Weighted", and WeightPreference is not set, scheduler will weight all clusters the same. + // +optional + WeightPreference *ClusterPreferences `json:"weightPreference,omitempty"` +} + // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // PropagationPolicyList contains a list of PropagationPolicy. diff --git a/pkg/apis/policy/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/policy/v1alpha1/zz_generated.deepcopy.go index 0a0bd8d7b..01fdb5d1a 100644 --- a/pkg/apis/policy/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/policy/v1alpha1/zz_generated.deepcopy.go @@ -388,6 +388,11 @@ func (in *Placement) DeepCopyInto(out *Placement) { *out = make([]SpreadConstraint, len(*in)) copy(*out, *in) } + if in.ReplicaScheduling != nil { + in, out := &in.ReplicaScheduling, &out.ReplicaScheduling + *out = new(ReplicaSchedulingPolicy) + (*in).DeepCopyInto(*out) + } return } @@ -591,6 +596,27 @@ func (in *ReplicaSchedulingSpec) DeepCopy() *ReplicaSchedulingSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReplicaSchedulingStrategy) DeepCopyInto(out *ReplicaSchedulingStrategy) { + *out = *in + if in.WeightPreference != nil { + in, out := &in.WeightPreference, &out.WeightPreference + *out = new(ClusterPreferences) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicaSchedulingStrategy. +func (in *ReplicaSchedulingStrategy) DeepCopy() *ReplicaSchedulingStrategy { + if in == nil { + return nil + } + out := new(ReplicaSchedulingStrategy) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResourceSelector) DeepCopyInto(out *ResourceSelector) { *out = *in diff --git a/pkg/apis/work/v1alpha1/binding_types.go b/pkg/apis/work/v1alpha1/binding_types.go index 222527ad8..f0f4718c0 100644 --- a/pkg/apis/work/v1alpha1/binding_types.go +++ b/pkg/apis/work/v1alpha1/binding_types.go @@ -1,6 +1,7 @@ package v1alpha1 import ( + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -54,12 +55,23 @@ type ObjectReference struct { // determine when object has changed. // +optional ResourceVersion string `json:"resourceVersion,omitempty"` + + // ReplicaResourceRequirements represents the resources required by each replica. + // +optional + ReplicaResourceRequirements corev1.ResourceList `json:"resourcePerReplicas,omitempty"` + + // Replicas represents the replica number of the referencing resource. + // +optional + Replicas int32 `json:"replicas,omitempty"` } // TargetCluster represents the identifier of a member cluster. type TargetCluster struct { // Name of target cluster. Name string `json:"name"` + // Replicas in target cluster + // +optional + Replicas int32 `json:"replicas,omitempty"` } // ResourceBindingStatus represents the overall status of the strategy as well as the referenced resources. diff --git a/pkg/apis/work/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/work/v1alpha1/zz_generated.deepcopy.go index 697c507fe..aba953d3c 100644 --- a/pkg/apis/work/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/work/v1alpha1/zz_generated.deepcopy.go @@ -5,7 +5,8 @@ package v1alpha1 import ( - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -125,6 +126,13 @@ func (in *ManifestStatus) DeepCopy() *ManifestStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ObjectReference) DeepCopyInto(out *ObjectReference) { *out = *in + if in.ReplicaResourceRequirements != nil { + in, out := &in.ReplicaResourceRequirements, &out.ReplicaResourceRequirements + *out = make(v1.ResourceList, len(*in)) + for key, val := range *in { + (*out)[key] = val.DeepCopy() + } + } return } @@ -202,7 +210,7 @@ func (in *ResourceBindingList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResourceBindingSpec) DeepCopyInto(out *ResourceBindingSpec) { *out = *in - out.Resource = in.Resource + in.Resource.DeepCopyInto(&out.Resource) if in.Clusters != nil { in, out := &in.Clusters, &out.Clusters *out = make([]TargetCluster, len(*in)) @@ -226,7 +234,7 @@ func (in *ResourceBindingStatus) DeepCopyInto(out *ResourceBindingStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions - *out = make([]v1.Condition, len(*in)) + *out = make([]metav1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -366,7 +374,7 @@ func (in *WorkStatus) DeepCopyInto(out *WorkStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions - *out = make([]v1.Condition, len(*in)) + *out = make([]metav1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) }