Skip to content

Commit

Permalink
koord-scheduler: support node cpu amplification
Browse files Browse the repository at this point in the history
Signed-off-by: Zach Zhu <[email protected]>
  • Loading branch information
zqzten committed Sep 11, 2023
1 parent a21d99f commit facedf7
Show file tree
Hide file tree
Showing 18 changed files with 1,904 additions and 7 deletions.
2 changes: 2 additions & 0 deletions .licenseignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ pkg/descheduler/controllers/migration/controllerfinder
pkg/scheduler/plugins/coscheduling
pkg/scheduler/plugins/nodenumaresource/least_allocated.go
pkg/scheduler/plugins/nodenumaresource/most_allocated.go
pkg/scheduler/plugins/nodecpuamplification/least_allocated.go
pkg/scheduler/plugins/nodecpuamplification/most_allocated.go
pkg/scheduler/frameworkext/topologymanager/policy.go
pkg/scheduler/frameworkext/topologymanager/policy_test.go
pkg/scheduler/frameworkext/topologymanager/policy_best_effort.go
Expand Down
16 changes: 9 additions & 7 deletions cmd/koord-scheduler/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/koordinator-sh/koordinator/pkg/scheduler/plugins/deviceshare"
"github.com/koordinator-sh/koordinator/pkg/scheduler/plugins/elasticquota"
"github.com/koordinator-sh/koordinator/pkg/scheduler/plugins/loadaware"
"github.com/koordinator-sh/koordinator/pkg/scheduler/plugins/nodecpuamplification"
"github.com/koordinator-sh/koordinator/pkg/scheduler/plugins/nodenumaresource"
"github.com/koordinator-sh/koordinator/pkg/scheduler/plugins/reservation"

Expand All @@ -40,13 +41,14 @@ import (
)

var koordinatorPlugins = map[string]frameworkruntime.PluginFactory{
loadaware.Name: loadaware.New,
nodenumaresource.Name: nodenumaresource.New,
reservation.Name: reservation.New,
coscheduling.Name: coscheduling.New,
deviceshare.Name: deviceshare.New,
elasticquota.Name: elasticquota.New,
defaultprebind.Name: defaultprebind.New,
loadaware.Name: loadaware.New,
nodenumaresource.Name: nodenumaresource.New,
reservation.Name: reservation.New,
coscheduling.Name: coscheduling.New,
deviceshare.Name: deviceshare.New,
elasticquota.Name: elasticquota.New,
defaultprebind.Name: defaultprebind.New,
nodecpuamplification.Name: nodecpuamplification.New,
}

func flatten(plugins map[string]frameworkruntime.PluginFactory) []app.Option {
Expand Down
10 changes: 10 additions & 0 deletions pkg/scheduler/apis/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,13 @@ type DeviceShareArgs struct {
// ScoringStrategy selects the device resource scoring strategy.
ScoringStrategy *ScoringStrategy
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// NodeCPUAmplificationArgs defines the parameters for NodeCPUAmplification plugin.
type NodeCPUAmplificationArgs struct {
metav1.TypeMeta

// ScoringStrategy selects the normalized node resource scoring strategy.
ScoringStrategy *ScoringStrategy
}
24 changes: 24 additions & 0 deletions pkg/scheduler/apis/config/v1beta2/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ var (
corev1.ResourceMemory: 1,
}

defaultResourceSpec = []schedconfigv1beta2.ResourceSpec{
{Name: string(corev1.ResourceCPU), Weight: 1},
{Name: string(corev1.ResourceMemory), Weight: 1},
}

defaultUsageThresholds = map[corev1.ResourceName]int64{
corev1.ResourceCPU: 65, // 65%
corev1.ResourceMemory: 95, // 95%
Expand Down Expand Up @@ -187,3 +192,22 @@ func SetDefaults_DeviceShareArgs(obj *DeviceShareArgs) {
}
}
}

func SetDefaults_NodeCPUAmplificationArgs(obj *NodeCPUAmplificationArgs) {
if obj.ScoringStrategy == nil {
obj.ScoringStrategy = &ScoringStrategy{
// By default, LeastAllocate is used to ensure high availability of applications
Type: LeastAllocated,
Resources: defaultResourceSpec,
}
}
if len(obj.ScoringStrategy.Resources) == 0 {
// If no resources specified, use the default set.
obj.ScoringStrategy.Resources = append(obj.ScoringStrategy.Resources, defaultResourceSpec...)
}
for i := range obj.ScoringStrategy.Resources {
if obj.ScoringStrategy.Resources[i].Weight == 0 {
obj.ScoringStrategy.Resources[i].Weight = 1
}
}
}
10 changes: 10 additions & 0 deletions pkg/scheduler/apis/config/v1beta2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,13 @@ type DeviceShareArgs struct {
// ScoringStrategy selects the device resource scoring strategy.
ScoringStrategy *ScoringStrategy `json:"scoringStrategy,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// NodeCPUAmplificationArgs defines the parameters for NodeCPUAmplification plugin.
type NodeCPUAmplificationArgs struct {
metav1.TypeMeta

// ScoringStrategy selects the normalized node resource scoring strategy.
ScoringStrategy *ScoringStrategy `json:"scoringStrategy,omitempty"`
}
30 changes: 30 additions & 0 deletions pkg/scheduler/apis/config/v1beta2/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions pkg/scheduler/apis/config/v1beta2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions pkg/scheduler/apis/config/v1beta2/zz_generated.defaults.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions pkg/scheduler/apis/config/validation/validation_pluginargs.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,15 @@ func ValidateNodeNUMAResourceArgs(path *field.Path, args *config.NodeNUMAResourc
}
return allErrs.ToAggregate()
}

func ValidateNodeCPUAmplificationArgs(path *field.Path, args *config.NodeCPUAmplificationArgs) error {
var allErrs field.ErrorList
if args.ScoringStrategy != nil {
allErrs = append(allErrs, validateResources(args.ScoringStrategy.Resources, path.Child("resources"))...)
}

if len(allErrs) == 0 {
return nil
}
return allErrs.ToAggregate()
}
30 changes: 30 additions & 0 deletions pkg/scheduler/apis/config/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 57 additions & 0 deletions pkg/scheduler/plugins/nodecpuamplification/least_allocated.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
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 nodecpuamplification

import (
"k8s.io/kubernetes/pkg/scheduler/framework"
)

// leastResourceScorer favors nodes with fewer requested resources.
// It calculates the percentage of memory, CPU and other resources requested by pods scheduled on the node, and
// prioritizes based on the minimum of the average of the fraction of requested to capacity.
//
// Details:
// (cpu((capacity-requested)*MaxNodeScore*cpuWeight/capacity) + memory((capacity-requested)*MaxNodeScore*memoryWeight/capacity) + ...)/weightSum
func leastResourceScorer(resToWeightMap resourceToWeightMap) func(requested, allocatable resourceToValueMap) int64 {
return func(requested, allocatable resourceToValueMap) int64 {
var nodeScore, weightSum int64
for resource := range requested {
weight := resToWeightMap[resource]
resourceScore := leastRequestedScore(requested[resource], allocatable[resource])
nodeScore += resourceScore * weight
weightSum += weight
}
if weightSum == 0 {
return 0
}
return nodeScore / weightSum
}
}

// The unused capacity is calculated on a scale of 0-MaxNodeScore
// 0 being the lowest priority and `MaxNodeScore` being the highest.
// The more unused resources the higher the score is.
func leastRequestedScore(requested, capacity int64) int64 {
if capacity == 0 {
return 0
}
if requested > capacity {
return 0
}

return ((capacity - requested) * framework.MaxNodeScore) / capacity
}
Loading

0 comments on commit facedf7

Please sign in to comment.