karmada/pkg/scheduler/core/assignment.go

79 lines
3.5 KiB
Go

package core
import (
clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
)
var (
assignFuncMap = map[string]func(*assignState) ([]workv1alpha2.TargetCluster, error){
DuplicatedStrategy: assignByDuplicatedStrategy,
AggregatedStrategy: assignByAggregatedStrategy,
StaticWeightStrategy: assignByStaticWeightStrategy,
DynamicWeightStrategy: assignByDynamicWeightStrategy,
}
)
// assignState is a wrapper of the input for assigning function.
type assignState struct {
candidates []*clusterv1alpha1.Cluster
strategy *policyv1alpha1.ReplicaSchedulingStrategy
object *workv1alpha2.ResourceBindingSpec
}
const (
// DuplicatedStrategy indicates each candidate member cluster will directly apply the original replicas.
DuplicatedStrategy = "Duplicated"
// AggregatedStrategy indicates dividing replicas among clusters as few as possible and
// taking clusters' available replicas into consideration as well.
AggregatedStrategy = "Aggregated"
// StaticWeightStrategy indicates dividing replicas by static weight according to WeightPreference.
StaticWeightStrategy = "StaticWeight"
// DynamicWeightStrategy indicates dividing replicas by dynamic weight according to WeightPreference.
DynamicWeightStrategy = "DynamicWeight"
)
// assignByDuplicatedStrategy assigns replicas by DuplicatedStrategy.
func assignByDuplicatedStrategy(state *assignState) ([]workv1alpha2.TargetCluster, error) {
targetClusters := make([]workv1alpha2.TargetCluster, len(state.candidates))
for i, cluster := range state.candidates {
targetClusters[i] = workv1alpha2.TargetCluster{Name: cluster.Name, Replicas: state.object.Replicas}
}
return targetClusters, nil
}
// assignByAggregatedStrategy assigns replicas by AggregatedStrategy.
func assignByAggregatedStrategy(state *assignState) ([]workv1alpha2.TargetCluster, error) {
return divideReplicasByResource(state.candidates, state.object, policyv1alpha1.ReplicaDivisionPreferenceAggregated)
}
/*
* assignByStaticWeightStrategy assigns a total number of replicas to the selected clusters by the weight list.
* For example, we want to assign replicas to two clusters named A and B.
* | Total | Weight(A:B) | Assignment(A:B) |
* | 9 | 1:2 | 3:6 |
* | 9 | 1:3 | 2:7 | Approximate assignment
* Note:
* 1. If any selected cluster which not present on the weight list will be ignored(different with '0' replica).
* 2. In case of not enough replica for specific cluster which will get '0' replica.
*/
func assignByStaticWeightStrategy(state *assignState) ([]workv1alpha2.TargetCluster, error) {
// If ReplicaDivisionPreference is set to "Weighted" and WeightPreference is not set,
// scheduler will weight all clusters averagely.
if state.strategy.WeightPreference == nil {
state.strategy.WeightPreference = getDefaultWeightPreference(state.candidates)
}
weightList := getStaticWeightInfoList(state.candidates, state.strategy.WeightPreference.StaticWeightList)
acc := newDispenser(state.object.Replicas, nil)
acc.takeByWeight(weightList)
return acc.result, nil
}
// assignByDynamicWeightStrategy assigns replicas by assignByDynamicWeightStrategy.
func assignByDynamicWeightStrategy(state *assignState) ([]workv1alpha2.TargetCluster, error) {
return divideReplicasByDynamicWeight(state.candidates, state.strategy.WeightPreference.DynamicWeight, state.object)
}