Skip to content

Commit 78ffbd5

Browse files
authored
Merge pull request #6597 from LivingCcj/feature/optimize_karmada_scheduler
Improve the performance of karmada-scheduler
2 parents 7148248 + 2841f04 commit 78ffbd5

15 files changed

+307
-305
lines changed

pkg/scheduler/core/assignment.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ import (
2121

2222
"k8s.io/apimachinery/pkg/util/sets"
2323

24-
clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
2524
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
2625
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
26+
"github.com/karmada-io/karmada/pkg/scheduler/core/spreadconstraint"
2727
"github.com/karmada-io/karmada/pkg/util"
2828
"github.com/karmada-io/karmada/pkg/util/helper"
2929
)
@@ -67,7 +67,7 @@ const (
6767

6868
// assignState is a wrapper of the input for assigning function.
6969
type assignState struct {
70-
candidates []*clusterv1alpha1.Cluster
70+
candidates []spreadconstraint.ClusterDetailInfo
7171
strategy *policyv1alpha1.ReplicaSchedulingStrategy
7272
spec *workv1alpha2.ResourceBindingSpec
7373

@@ -86,7 +86,7 @@ type assignState struct {
8686
targetReplicas int32
8787
}
8888

89-
func newAssignState(candidates []*clusterv1alpha1.Cluster, spec *workv1alpha2.ResourceBindingSpec,
89+
func newAssignState(candidates []spreadconstraint.ClusterDetailInfo, spec *workv1alpha2.ResourceBindingSpec,
9090
status *workv1alpha2.ResourceBindingStatus) *assignState {
9191
var strategyType string
9292

pkg/scheduler/core/assignment_test.go

Lines changed: 145 additions & 153 deletions
Large diffs are not rendered by default.

pkg/scheduler/core/common.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"fmt"
2121
"time"
2222

23-
clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
2423
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
2524
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
2625
"github.com/karmada-io/karmada/pkg/scheduler/core/spreadconstraint"
@@ -30,7 +29,7 @@ import (
3029

3130
// SelectClusters selects clusters based on the placement and resource binding spec.
3231
func SelectClusters(clustersScore framework.ClusterScoreList,
33-
placement *policyv1alpha1.Placement, spec *workv1alpha2.ResourceBindingSpec) ([]*clusterv1alpha1.Cluster, error) {
32+
placement *policyv1alpha1.Placement, spec *workv1alpha2.ResourceBindingSpec) ([]spreadconstraint.ClusterDetailInfo, error) {
3433
startTime := time.Now()
3534
defer metrics.ScheduleStep(metrics.ScheduleStepSelect, startTime)
3635

@@ -40,7 +39,7 @@ func SelectClusters(clustersScore framework.ClusterScoreList,
4039

4140
// AssignReplicas assigns replicas to clusters based on the placement and resource binding spec.
4241
func AssignReplicas(
43-
clusters []*clusterv1alpha1.Cluster,
42+
clusters []spreadconstraint.ClusterDetailInfo,
4443
spec *workv1alpha2.ResourceBindingSpec,
4544
status *workv1alpha2.ResourceBindingStatus,
4645
) ([]workv1alpha2.TargetCluster, error) {
@@ -69,7 +68,7 @@ func AssignReplicas(
6968
// If not workload, assign all clusters without considering replicas.
7069
targetClusters := make([]workv1alpha2.TargetCluster, len(clusters))
7170
for i, cluster := range clusters {
72-
targetClusters[i] = workv1alpha2.TargetCluster{Name: cluster.Name}
71+
targetClusters[i] = workv1alpha2.TargetCluster{Name: cluster.Cluster.Name}
7372
}
7473
return targetClusters, nil
7574
}

pkg/scheduler/core/common_test.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ import (
2525
clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
2626
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
2727
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
28+
"github.com/karmada-io/karmada/pkg/scheduler/core/spreadconstraint"
2829
"github.com/karmada-io/karmada/pkg/scheduler/framework"
30+
"github.com/karmada-io/karmada/test/helper"
2931
)
3032

3133
func TestSelectClusters(t *testing.T) {
@@ -112,7 +114,7 @@ func TestSelectClusters(t *testing.T) {
112114

113115
actualNames := make([]string, len(result))
114116
for i, cluster := range result {
115-
actualNames[i] = cluster.Name
117+
actualNames[i] = cluster.Cluster.Name
116118
}
117119

118120
assert.ElementsMatch(t, expectedNames, actualNames)
@@ -124,7 +126,7 @@ func TestSelectClusters(t *testing.T) {
124126
func TestAssignReplicas(t *testing.T) {
125127
tests := []struct {
126128
name string
127-
clusters []*clusterv1alpha1.Cluster
129+
clusters []spreadconstraint.ClusterDetailInfo
128130
spec *workv1alpha2.ResourceBindingSpec
129131
status *workv1alpha2.ResourceBindingStatus
130132
expectedResult []workv1alpha2.TargetCluster
@@ -133,8 +135,8 @@ func TestAssignReplicas(t *testing.T) {
133135
}{
134136
{
135137
name: "Assign replicas to single cluster",
136-
clusters: []*clusterv1alpha1.Cluster{
137-
{ObjectMeta: metav1.ObjectMeta{Name: "cluster1"}},
138+
clusters: []spreadconstraint.ClusterDetailInfo{
139+
{Name: ClusterMember1, Cluster: helper.NewCluster(ClusterMember1)},
138140
},
139141
spec: &workv1alpha2.ResourceBindingSpec{
140142
Replicas: 3,
@@ -146,12 +148,12 @@ func TestAssignReplicas(t *testing.T) {
146148
},
147149
},
148150
status: &workv1alpha2.ResourceBindingStatus{},
149-
expectedResult: []workv1alpha2.TargetCluster{{Name: "cluster1", Replicas: 3}},
151+
expectedResult: []workv1alpha2.TargetCluster{{Name: ClusterMember1, Replicas: 3}},
150152
expectedError: false,
151153
},
152154
{
153155
name: "No clusters available",
154-
clusters: []*clusterv1alpha1.Cluster{},
156+
clusters: []spreadconstraint.ClusterDetailInfo{},
155157
spec: &workv1alpha2.ResourceBindingSpec{Replicas: 1},
156158
status: &workv1alpha2.ResourceBindingStatus{},
157159
expectedResult: nil,
@@ -160,21 +162,21 @@ func TestAssignReplicas(t *testing.T) {
160162
},
161163
{
162164
name: "Non-workload scenario (zero replicas)",
163-
clusters: []*clusterv1alpha1.Cluster{
164-
{ObjectMeta: metav1.ObjectMeta{Name: "cluster1"}},
165-
{ObjectMeta: metav1.ObjectMeta{Name: "cluster2"}},
165+
clusters: []spreadconstraint.ClusterDetailInfo{
166+
{Name: ClusterMember1, Cluster: helper.NewCluster(ClusterMember1)},
167+
{Name: ClusterMember2, Cluster: helper.NewCluster(ClusterMember2)},
166168
},
167169
spec: &workv1alpha2.ResourceBindingSpec{
168170
Replicas: 0,
169171
},
170172
status: &workv1alpha2.ResourceBindingStatus{},
171-
expectedResult: []workv1alpha2.TargetCluster{{Name: "cluster1"}, {Name: "cluster2"}},
173+
expectedResult: []workv1alpha2.TargetCluster{{Name: ClusterMember1}, {Name: ClusterMember2}},
172174
expectedError: false,
173175
},
174176
{
175177
name: "Unsupported replica scheduling strategy",
176-
clusters: []*clusterv1alpha1.Cluster{
177-
{Spec: clusterv1alpha1.ClusterSpec{ID: "cluster1"}},
178+
clusters: []spreadconstraint.ClusterDetailInfo{
179+
{Name: ClusterMember1, Cluster: helper.NewCluster(ClusterMember1)},
178180
},
179181
spec: &workv1alpha2.ResourceBindingSpec{
180182
Replicas: 3,

pkg/scheduler/core/division_algorithm.go

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ import (
2020
"fmt"
2121
"sort"
2222

23-
clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
2423
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
2524
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
25+
"github.com/karmada-io/karmada/pkg/scheduler/core/spreadconstraint"
2626
"github.com/karmada-io/karmada/pkg/scheduler/framework"
2727
"github.com/karmada-io/karmada/pkg/util"
2828
"github.com/karmada-io/karmada/pkg/util/helper"
@@ -35,14 +35,14 @@ func (a TargetClustersList) Len() int { return len(a) }
3535
func (a TargetClustersList) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
3636
func (a TargetClustersList) Less(i, j int) bool { return a[i].Replicas > a[j].Replicas }
3737

38-
func getStaticWeightInfoList(clusters []*clusterv1alpha1.Cluster, weightList []policyv1alpha1.StaticClusterWeight,
38+
func getStaticWeightInfoList(clusters []spreadconstraint.ClusterDetailInfo, weightList []policyv1alpha1.StaticClusterWeight,
3939
lastTargetClusters []workv1alpha2.TargetCluster) helper.ClusterWeightInfoList {
4040
list := make(helper.ClusterWeightInfoList, 0)
4141
for _, cluster := range clusters {
4242
var weight int64
4343
var lastReplicas int32
4444
for _, staticWeightRule := range weightList {
45-
if util.ClusterMatches(cluster, staticWeightRule.TargetCluster) {
45+
if util.ClusterMatches(cluster.Cluster, staticWeightRule.TargetCluster) {
4646
weight = util.MaxInt64(weight, staticWeightRule.Weight)
4747
}
4848
}
@@ -107,7 +107,7 @@ func dynamicScaleDown(state *assignState) ([]workv1alpha2.TargetCluster, error)
107107
// 3. scheduledClusters and assignedReplicas are not set, which implicates we consider this action as a first schedule.
108108
state.targetReplicas = state.spec.Replicas
109109
state.scheduledClusters = nil
110-
state.buildAvailableClusters(func(_ []*clusterv1alpha1.Cluster, spec *workv1alpha2.ResourceBindingSpec) []workv1alpha2.TargetCluster {
110+
state.buildAvailableClusters(func(_ []spreadconstraint.ClusterDetailInfo, spec *workv1alpha2.ResourceBindingSpec) []workv1alpha2.TargetCluster {
111111
availableClusters := make(TargetClustersList, len(spec.Clusters))
112112
copy(availableClusters, spec.Clusters)
113113
sort.Sort(availableClusters)
@@ -119,8 +119,14 @@ func dynamicScaleDown(state *assignState) ([]workv1alpha2.TargetCluster, error)
119119
func dynamicScaleUp(state *assignState) ([]workv1alpha2.TargetCluster, error) {
120120
// Target is the extra ones.
121121
state.targetReplicas = state.spec.Replicas - state.assignedReplicas
122-
state.buildAvailableClusters(func(clusters []*clusterv1alpha1.Cluster, spec *workv1alpha2.ResourceBindingSpec) []workv1alpha2.TargetCluster {
123-
clusterAvailableReplicas := calAvailableReplicas(clusters, spec)
122+
state.buildAvailableClusters(func(clusters []spreadconstraint.ClusterDetailInfo, _ *workv1alpha2.ResourceBindingSpec) []workv1alpha2.TargetCluster {
123+
clusterAvailableReplicas := make([]workv1alpha2.TargetCluster, len(clusters))
124+
for i, cluster := range clusters {
125+
clusterAvailableReplicas[i] = workv1alpha2.TargetCluster{
126+
Name: cluster.Name,
127+
Replicas: cluster.AllocatableReplicas,
128+
}
129+
}
124130
sort.Sort(TargetClustersList(clusterAvailableReplicas))
125131
return clusterAvailableReplicas
126132
})
@@ -131,8 +137,14 @@ func dynamicScaleUp(state *assignState) ([]workv1alpha2.TargetCluster, error) {
131137
func dynamicFreshScale(state *assignState) ([]workv1alpha2.TargetCluster, error) {
132138
// 1. targetReplicas is set to desired replicas
133139
state.targetReplicas = state.spec.Replicas
134-
state.buildAvailableClusters(func(clusters []*clusterv1alpha1.Cluster, spec *workv1alpha2.ResourceBindingSpec) []workv1alpha2.TargetCluster {
135-
clusterAvailableReplicas := calAvailableReplicas(clusters, spec)
140+
state.buildAvailableClusters(func(clusters []spreadconstraint.ClusterDetailInfo, _ *workv1alpha2.ResourceBindingSpec) []workv1alpha2.TargetCluster {
141+
clusterAvailableReplicas := make([]workv1alpha2.TargetCluster, len(clusters))
142+
for i, cluster := range clusters {
143+
clusterAvailableReplicas[i] = workv1alpha2.TargetCluster{
144+
Name: cluster.Name,
145+
Replicas: cluster.AllocatableReplicas,
146+
}
147+
}
136148
// 2. clusterAvailableReplicas should take into account the replicas already allocated
137149
for _, scheduledCluster := range state.scheduledClusters {
138150
for i, availableCluster := range clusterAvailableReplicas {

pkg/scheduler/core/generic_scheduler.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
2828
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
2929
"github.com/karmada-io/karmada/pkg/scheduler/cache"
30+
"github.com/karmada-io/karmada/pkg/scheduler/core/spreadconstraint"
3031
"github.com/karmada-io/karmada/pkg/scheduler/framework"
3132
"github.com/karmada-io/karmada/pkg/scheduler/framework/runtime"
3233
"github.com/karmada-io/karmada/pkg/scheduler/metrics"
@@ -94,20 +95,20 @@ func (g *genericScheduler) Schedule(
9495
}
9596
klog.V(4).Infof("Feasible clusters scores: %v", clustersScore)
9697

97-
clusters, err := g.selectClusters(clustersScore, spec.Placement, spec)
98+
selectedClusters, err := g.selectClusters(clustersScore, spec.Placement, spec)
9899
if err != nil {
99100
return result, fmt.Errorf("failed to select clusters: %w", err)
100101
}
101-
klog.V(4).Infof("Selected clusters: %v", clusters)
102+
klog.V(4).Infof("Selected clusters: %v", selectedClusters)
102103

103-
clustersWithReplicas, err := g.assignReplicas(clusters, spec, status)
104+
clustersWithReplicas, err := g.assignReplicas(selectedClusters, spec, status)
104105
if err != nil {
105106
return result, fmt.Errorf("failed to assign replicas: %w", err)
106107
}
107108
klog.V(4).Infof("Assigned Replicas: %v", clustersWithReplicas)
108109

109110
if scheduleAlgorithmOption.EnableEmptyWorkloadPropagation {
110-
clustersWithReplicas = attachZeroReplicasCluster(clusters, clustersWithReplicas)
111+
clustersWithReplicas = attachZeroReplicasCluster(selectedClusters, clustersWithReplicas)
111112
}
112113
result.SuggestedClusters = clustersWithReplicas
113114

@@ -182,11 +183,11 @@ func (g *genericScheduler) prioritizeClusters(
182183
}
183184

184185
func (g *genericScheduler) selectClusters(clustersScore framework.ClusterScoreList,
185-
placement *policyv1alpha1.Placement, spec *workv1alpha2.ResourceBindingSpec) ([]*clusterv1alpha1.Cluster, error) {
186+
placement *policyv1alpha1.Placement, spec *workv1alpha2.ResourceBindingSpec) ([]spreadconstraint.ClusterDetailInfo, error) {
186187
return SelectClusters(clustersScore, placement, spec)
187188
}
188189

189-
func (g *genericScheduler) assignReplicas(clusters []*clusterv1alpha1.Cluster, spec *workv1alpha2.ResourceBindingSpec,
190+
func (g *genericScheduler) assignReplicas(clusters []spreadconstraint.ClusterDetailInfo, spec *workv1alpha2.ResourceBindingSpec,
190191
status *workv1alpha2.ResourceBindingStatus) ([]workv1alpha2.TargetCluster, error) {
191192
return AssignReplicas(clusters, spec, status)
192193
}

0 commit comments

Comments
 (0)