Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,20 @@ push-release-images: release-image.amd64 release-image.arm64v8
update-vendor:
hack/update-vendor.sh

.PHONY: build-diskioplugin
build-diskioplugin:
$(COMMONENVVAR) CGO_ENABLED=1 go build -buildmode=plugin -ldflags '-X k8s.io/component-base/version.gitVersion=$(VERSION) -w' -o pkg/diskioaware/sampleplugin/foo/foo.so ./pkg/diskioaware/sampleplugin/foo/foo.go

.PHONY: unit-test
unit-test: install-envtest
unit-test: install-envtest build-diskioplugin
hack/unit-test.sh $(ARGS)

.PHONY: install-envtest
install-envtest:
hack/install-envtest.sh

.PHONY: integration-test
integration-test: install-envtest
integration-test: install-envtest build-diskioplugin
$(INTEGTESTENVVAR) hack/integration-test.sh $(ARGS)

.PHONY: verify
Expand All @@ -139,3 +143,4 @@ verify:
.PHONY: clean
clean:
rm -rf ./bin
rm -f ./pkg/diskioaware/sampleplugin/foo/foo.so
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ The kube-scheduler binary includes the below list of plugins. They can be config

* [Capacity Scheduling](pkg/capacityscheduling/README.md)
* [Coscheduling](pkg/coscheduling/README.md)
* [Disk IO aware Scheduling](pkg/diskioaware/README.md)
* [Node Resources](pkg/noderesources/README.md)
* [Node Resource Topology](pkg/noderesourcetopology/README.md)
* [Preemption Toleration](pkg/preemptiontoleration/README.md)
Expand Down
1 change: 1 addition & 0 deletions apis/config/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&TopologicalSortArgs{},
&NetworkOverheadArgs{},
&SySchedArgs{},
&DiskIOArgs{},
)
return nil
}
Expand Down
10 changes: 10 additions & 0 deletions apis/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,13 @@ type SySchedArgs struct {
// CR name of the default profile for all system calls
DefaultProfileName string
}

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

type DiskIOArgs struct {
metav1.TypeMeta

ScoreStrategy string
DiskIOModelConfig string // the path to the config file for the disk IO models
NSWhiteList []string // the whitelisted pod namespaces
}
21 changes: 21 additions & 0 deletions apis/config/v1/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ var (
DefaultSySchedProfileNamespace = "default"
// DefaultSySchedProfileName is the name of the default syscall profile CR for SySched plugin
DefaultSySchedProfileName = "all-syscalls"

// Defaults for DiskIO aware
// defaultDiskIOScoreStrategy is the default score strategy for disk io aware plugin
defaultDiskIOScoreStrategy string = "LeastAllocated"
// defaultDiskIOModelConfig is the default file path for model plugin configurations
defaultDiskIOModelConfig string = "/etc/kubernetes/disk-config/diskVendors"
)

// SetDefaults_CoschedulingArgs sets the default parameters for Coscheduling plugin.
Expand Down Expand Up @@ -250,3 +256,18 @@ func SetDefaults_SySchedArgs(obj *SySchedArgs) {
obj.DefaultProfileName = &DefaultSySchedProfileName
}
}

// SetDefaults_ResourceIOArgs sets the default parameters for ResourceIO plugin.
func SetDefaults_DiskIOArgs(obj *DiskIOArgs) {
if obj.ScoreStrategy == nil {
obj.ScoreStrategy = &defaultDiskIOScoreStrategy
}

if obj.DiskIOModelConfig == nil {
obj.DiskIOModelConfig = &defaultDiskIOModelConfig
}

if obj.NSWhiteList == nil {
obj.NSWhiteList = []string{}
}
}
1 change: 1 addition & 0 deletions apis/config/v1/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&TopologicalSortArgs{},
&NetworkOverheadArgs{},
&SySchedArgs{},
&DiskIOArgs{},
)
return nil
}
Expand Down
12 changes: 12 additions & 0 deletions apis/config/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,3 +277,15 @@ type SySchedArgs struct {
// CR name of the default profile for all system calls
DefaultProfileName *string `json:"defaultProfileName,omitempty"`
}

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

// DiskIOArgs holds arguments used to configure DiskIO plugin.
type DiskIOArgs struct {
metav1.TypeMeta `json:",inline"`

ScoreStrategy *string `json:"scoreStrategy,omitempty"`
DiskIOModelConfig *string `json:"diskIOModelConfig,omitempty"`
NSWhiteList []string `json:"nsWhiteList,omitempty"`
}
42 changes: 42 additions & 0 deletions apis/config/v1/zz_generated.conversion.go

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

40 changes: 40 additions & 0 deletions apis/config/v1/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 apis/config/v1/zz_generated.defaults.go

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

51 changes: 50 additions & 1 deletion apis/config/validation/validation_pluginargs.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ limitations under the License.
package validation

import (
"os"

apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation/field"

"sigs.k8s.io/scheduler-plugins/apis/config"
)

Expand All @@ -30,6 +32,11 @@ var validScoringStrategy = sets.NewString(
string(config.LeastNUMANodes),
)

var validDiskIOScoreStrategy = sets.NewString(
string(config.MostAllocated),
string(config.LeastAllocated),
)

func ValidateNodeResourceTopologyMatchArgs(path *field.Path, args *config.NodeResourceTopologyMatchArgs) error {
var allErrs field.ErrorList
scoringStrategyTypePath := path.Child("scoringStrategy.type")
Expand All @@ -46,3 +53,45 @@ func validateScoringStrategyType(scoringStrategy config.ScoringStrategyType, pat
}
return nil
}

func ValidateDiskIOArgs(path *field.Path, args *config.DiskIOArgs) error {
var allErrs field.ErrorList
scoreStrategyPath := path.Child("scoreStrategy")
if err := validateDiskIOScoreStrategy(args.ScoreStrategy, scoreStrategyPath); err != nil {
allErrs = append(allErrs, err)
}
nswlPath := path.Child("nsWhiteList")
if err := validateDiskIOWhiteListNamespace(args.NSWhiteList, nswlPath); err != nil {
allErrs = append(allErrs, err)
}
mcPath := path.Child("diskIOModelConfig")
if err := validateDiskIOModelConfig(args.DiskIOModelConfig, mcPath); err != nil {
allErrs = append(allErrs, err)
}

return allErrs.ToAggregate()
}

func validateDiskIOModelConfig(configPath string, path *field.Path) *field.Error {
if _, err := os.Stat(configPath); err != nil {
return field.Invalid(path, configPath, "invalid DiskIOModelConfig")
}
return nil
}

func validateDiskIOScoreStrategy(scoreStrategy string, path *field.Path) *field.Error {
if !validDiskIOScoreStrategy.Has(string(scoreStrategy)) {
return field.Invalid(path, scoreStrategy, "invalid ScoreStrategy")
}
return nil
}

func validateDiskIOWhiteListNamespace(nsWhiteList []string, path *field.Path) *field.Error {
for _, ns := range nsWhiteList {
errs := apimachineryvalidation.ValidateNamespaceName(ns, false)
if len(errs) > 0 {
return field.Invalid(path, ns, "invalid namespace format")
}
}
return nil
}
66 changes: 66 additions & 0 deletions apis/config/validation/validation_plugingargs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package validation

import (
"fmt"
"os"
"strings"
"testing"

Expand Down Expand Up @@ -67,3 +68,68 @@ func TestValidateNodeResourceTopologyMatchArgs(t *testing.T) {
})
}
}

func TestValidateDiskIOArgs(t *testing.T) {
tempFile, err := os.CreateTemp(os.TempDir(), "validateDiskIOArgs")
if err != nil {
t.Fatal("Failed to create temp file", err)
}
defer os.Remove(tempFile.Name())
testCases := []struct {
args *config.DiskIOArgs
expectedErr error
description string
}{
{
description: "correct config",
args: &config.DiskIOArgs{
ScoreStrategy: string(config.LeastAllocated),
NSWhiteList: []string{"ns1", "ns2"},
DiskIOModelConfig: tempFile.Name(),
},
},
{
description: "incorrect config, wrong ScoreStrategy type",
args: &config.DiskIOArgs{
ScoreStrategy: "UnknownStrategy",
NSWhiteList: nil,
},
expectedErr: fmt.Errorf("scoreStrategy: Invalid value"),
},
{
description: "incorrect config, wrong namespace format",
args: &config.DiskIOArgs{
ScoreStrategy: string(config.LeastAllocated),
NSWhiteList: []string{"!!!!"},
},
expectedErr: fmt.Errorf("invalid namespace format"),
},
{
description: "incorrect config, wrong model config path",
args: &config.DiskIOArgs{
ScoreStrategy: string(config.LeastAllocated),
NSWhiteList: []string{"kube-system"},
DiskIOModelConfig: "!@#$$",
},
expectedErr: fmt.Errorf("invalid DiskIOModelConfig"),
},
}

for _, testCase := range testCases {
t.Run(testCase.description, func(t *testing.T) {
err := ValidateDiskIOArgs(nil, testCase.args)
if testCase.expectedErr != nil {
if err == nil {
t.Errorf("expected err to equal %v not nil", testCase.expectedErr)
}

if !strings.Contains(err.Error(), testCase.expectedErr.Error()) {
t.Errorf("expected err to contain %s in error message: %s", testCase.expectedErr.Error(), err.Error())
}
}
if testCase.expectedErr == nil && err != nil {
t.Errorf("unexpected error: %v", err)
}
})
}
}
Loading