mirror of
https://github.com/kubernetes-sigs/descheduler.git
synced 2026-01-26 05:14:13 +01:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f38146bbf | ||
|
|
1473e1d024 | ||
|
|
7b4b9d9e7e | ||
|
|
7d079813e5 | ||
|
|
e02857e00a | ||
|
|
acfd4f8680 | ||
|
|
c29c9db41e | ||
|
|
5d3f987dde | ||
|
|
97732cf62d | ||
|
|
4afc4dfb16 | ||
|
|
023ccd99f5 |
11
Makefile
11
Makefile
@@ -15,15 +15,22 @@
|
|||||||
.PHONY: test
|
.PHONY: test
|
||||||
|
|
||||||
# VERSION is currently based on the last commit
|
# VERSION is currently based on the last commit
|
||||||
VERSION:=$(shell git rev-parse --short HEAD)
|
VERSION=`git describe --tags`
|
||||||
|
COMMIT=`git rev-parse HEAD`
|
||||||
|
BUILD=`date +%FT%T%z`
|
||||||
|
LDFLAG_LOCATION=github.com/kubernetes-incubator/descheduler/cmd/descheduler/app
|
||||||
|
|
||||||
|
LDFLAGS=-ldflags "-X ${LDFLAG_LOCATION}.version=${VERSION} -X ${LDFLAG_LOCATION}.buildDate=${BUILD} -X ${LDFLAG_LOCATION}.gitCommit=${COMMIT}"
|
||||||
|
|
||||||
|
|
||||||
# IMAGE is the image name of descheduler
|
# IMAGE is the image name of descheduler
|
||||||
|
# Should this be changed?
|
||||||
IMAGE:=descheduler:$(VERSION)
|
IMAGE:=descheduler:$(VERSION)
|
||||||
|
|
||||||
all: build
|
all: build
|
||||||
|
|
||||||
build:
|
build:
|
||||||
go build -o _output/bin/descheduler github.com/kubernetes-incubator/descheduler/cmd/descheduler
|
go build ${LDFLAGS} -o _output/bin/descheduler github.com/kubernetes-incubator/descheduler/cmd/descheduler
|
||||||
|
|
||||||
image: build
|
image: build
|
||||||
docker build -t $(IMAGE) .
|
docker build -t $(IMAGE) .
|
||||||
|
|||||||
@@ -53,4 +53,6 @@ func (rs *DeschedulerServer) AddFlags(fs *pflag.FlagSet) {
|
|||||||
fs.StringVar(&rs.KubeconfigFile, "kubeconfig-file", rs.KubeconfigFile, "File with kube configuration.")
|
fs.StringVar(&rs.KubeconfigFile, "kubeconfig-file", rs.KubeconfigFile, "File with kube configuration.")
|
||||||
fs.StringVar(&rs.PolicyConfigFile, "policy-config-file", rs.PolicyConfigFile, "File with descheduler policy configuration.")
|
fs.StringVar(&rs.PolicyConfigFile, "policy-config-file", rs.PolicyConfigFile, "File with descheduler policy configuration.")
|
||||||
fs.BoolVar(&rs.DryRun, "dry-run", rs.DryRun, "execute descheduler in dry run mode.")
|
fs.BoolVar(&rs.DryRun, "dry-run", rs.DryRun, "execute descheduler in dry run mode.")
|
||||||
|
// node-selector query causes descheduler to run only on nodes that matches the node labels in the query
|
||||||
|
fs.StringVar(&rs.NodeSelector, "node-selector", rs.NodeSelector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
||||||
"github.com/kubernetes-incubator/descheduler/pkg/descheduler"
|
"github.com/kubernetes-incubator/descheduler/pkg/descheduler"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
aflag "k8s.io/apiserver/pkg/util/flag"
|
aflag "k8s.io/apiserver/pkg/util/flag"
|
||||||
@@ -43,7 +43,7 @@ func NewDeschedulerCommand(out io.Writer) *cobra.Command {
|
|||||||
defer logs.FlushLogs()
|
defer logs.FlushLogs()
|
||||||
err := Run(s)
|
err := Run(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
glog.Errorf("%v", err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
86
cmd/descheduler/app/version.go
Normal file
86
cmd/descheduler/app/version.go
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 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 app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// gitCommit is a constant representing the source version that
|
||||||
|
// generated this build. It should be set during build via -ldflags.
|
||||||
|
gitCommit string
|
||||||
|
// version is a constant representing the version tag that
|
||||||
|
// generated this build. It should be set during build via -ldflags.
|
||||||
|
version string
|
||||||
|
// buildDate in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||||
|
//It should be set during build via -ldflags.
|
||||||
|
buildDate string
|
||||||
|
)
|
||||||
|
|
||||||
|
// Info holds the information related to descheduler app version.
|
||||||
|
type Info struct {
|
||||||
|
Major string `json:"major"`
|
||||||
|
Minor string `json:"minor"`
|
||||||
|
GitCommit string `json:"gitCommit"`
|
||||||
|
GitVersion string `json:"gitVersion"`
|
||||||
|
BuildDate string `json:"buildDate"`
|
||||||
|
GoVersion string `json:"goVersion"`
|
||||||
|
Compiler string `json:"compiler"`
|
||||||
|
Platform string `json:"platform"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the overall codebase version. It's for detecting
|
||||||
|
// what code a binary was built from.
|
||||||
|
func Get() Info {
|
||||||
|
majorVersion, minorVersion := splitVersion(version)
|
||||||
|
return Info{
|
||||||
|
Major: majorVersion,
|
||||||
|
Minor: minorVersion,
|
||||||
|
GitCommit: gitCommit,
|
||||||
|
GitVersion: version,
|
||||||
|
BuildDate: buildDate,
|
||||||
|
GoVersion: runtime.Version(),
|
||||||
|
Compiler: runtime.Compiler,
|
||||||
|
Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVersionCommand() *cobra.Command {
|
||||||
|
var versionCmd = &cobra.Command{
|
||||||
|
Use: "version",
|
||||||
|
Short: "Version of descheduler",
|
||||||
|
Long: `Prints the version of descheduler.`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Printf("Descheduler version %+v\n", Get())
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return versionCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// splitVersion splits the git version to generate major and minor versions needed.
|
||||||
|
func splitVersion(version string) (string, string) {
|
||||||
|
if version == "" {
|
||||||
|
return "", ""
|
||||||
|
}
|
||||||
|
// A sample version would be of form v0.1.0-7-ge884046, so split at first '.' and
|
||||||
|
// then return 0 and 1+(+ appended to follow semver convention) for major and minor versions.
|
||||||
|
return strings.Trim(strings.Split(version, ".")[0], "v"), strings.Split(version, ".")[1] + "+"
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
out := os.Stdout
|
out := os.Stdout
|
||||||
cmd := app.NewDeschedulerCommand(out)
|
cmd := app.NewDeschedulerCommand(out)
|
||||||
|
cmd.AddCommand(app.NewVersionCommand())
|
||||||
if err := cmd.Execute(); err != nil {
|
if err := cmd.Execute(); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ kind: "DeschedulerPolicy"
|
|||||||
strategies:
|
strategies:
|
||||||
"RemoveDuplicates":
|
"RemoveDuplicates":
|
||||||
enabled: true
|
enabled: true
|
||||||
|
"RemovePodsViolatingInterPodAntiAffinity":
|
||||||
|
enabled: true
|
||||||
"LowNodeUtilization":
|
"LowNodeUtilization":
|
||||||
enabled: true
|
enabled: true
|
||||||
params:
|
params:
|
||||||
|
|||||||
@@ -81,16 +81,16 @@ func (x *DeschedulerConfiguration) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||||||
} else {
|
} else {
|
||||||
yysep2 := !z.EncBinary()
|
yysep2 := !z.EncBinary()
|
||||||
yy2arr2 := z.EncBasicHandle().StructToArray
|
yy2arr2 := z.EncBasicHandle().StructToArray
|
||||||
var yyq2 [6]bool
|
var yyq2 [7]bool
|
||||||
_, _, _ = yysep2, yyq2, yy2arr2
|
_, _, _ = yysep2, yyq2, yy2arr2
|
||||||
const yyr2 bool = false
|
const yyr2 bool = false
|
||||||
yyq2[0] = x.Kind != ""
|
yyq2[0] = x.Kind != ""
|
||||||
yyq2[1] = x.APIVersion != ""
|
yyq2[1] = x.APIVersion != ""
|
||||||
var yynn2 int
|
var yynn2 int
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
r.EncodeArrayStart(6)
|
r.EncodeArrayStart(7)
|
||||||
} else {
|
} else {
|
||||||
yynn2 = 4
|
yynn2 = 5
|
||||||
for _, b := range yyq2 {
|
for _, b := range yyq2 {
|
||||||
if b {
|
if b {
|
||||||
yynn2++
|
yynn2++
|
||||||
@@ -227,6 +227,25 @@ func (x *DeschedulerConfiguration) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||||||
r.EncodeBool(bool(x.DryRun))
|
r.EncodeBool(bool(x.DryRun))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if yyr2 || yy2arr2 {
|
||||||
|
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
||||||
|
yym22 := z.EncBinary()
|
||||||
|
_ = yym22
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
r.EncodeString(codecSelferC_UTF81234, string(x.NodeSelector))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
||||||
|
r.EncodeString(codecSelferC_UTF81234, string("NodeSelector"))
|
||||||
|
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
||||||
|
yym23 := z.EncBinary()
|
||||||
|
_ = yym23
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
r.EncodeString(codecSelferC_UTF81234, string(x.NodeSelector))
|
||||||
|
}
|
||||||
|
}
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
|
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
} else {
|
} else {
|
||||||
@@ -361,6 +380,18 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromMap(l int, d *codec1978.De
|
|||||||
*((*bool)(yyv14)) = r.DecodeBool()
|
*((*bool)(yyv14)) = r.DecodeBool()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "NodeSelector":
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.NodeSelector = ""
|
||||||
|
} else {
|
||||||
|
yyv16 := &x.NodeSelector
|
||||||
|
yym17 := z.DecBinary()
|
||||||
|
_ = yym17
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*string)(yyv16)) = r.DecodeString()
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
z.DecStructFieldNotFound(-1, yys3)
|
z.DecStructFieldNotFound(-1, yys3)
|
||||||
} // end switch yys3
|
} // end switch yys3
|
||||||
@@ -372,16 +403,16 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.
|
|||||||
var h codecSelfer1234
|
var h codecSelfer1234
|
||||||
z, r := codec1978.GenHelperDecoder(d)
|
z, r := codec1978.GenHelperDecoder(d)
|
||||||
_, _, _ = h, z, r
|
_, _, _ = h, z, r
|
||||||
var yyj16 int
|
var yyj18 int
|
||||||
var yyb16 bool
|
var yyb18 bool
|
||||||
var yyhl16 bool = l >= 0
|
var yyhl18 bool = l >= 0
|
||||||
yyj16++
|
yyj18++
|
||||||
if yyhl16 {
|
if yyhl18 {
|
||||||
yyb16 = yyj16 > l
|
yyb18 = yyj18 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb18 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb18 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -389,29 +420,7 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.
|
|||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
x.Kind = ""
|
x.Kind = ""
|
||||||
} else {
|
} else {
|
||||||
yyv17 := &x.Kind
|
yyv19 := &x.Kind
|
||||||
yym18 := z.DecBinary()
|
|
||||||
_ = yym18
|
|
||||||
if false {
|
|
||||||
} else {
|
|
||||||
*((*string)(yyv17)) = r.DecodeString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
yyj16++
|
|
||||||
if yyhl16 {
|
|
||||||
yyb16 = yyj16 > l
|
|
||||||
} else {
|
|
||||||
yyb16 = r.CheckBreak()
|
|
||||||
}
|
|
||||||
if yyb16 {
|
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
|
||||||
if r.TryDecodeAsNil() {
|
|
||||||
x.APIVersion = ""
|
|
||||||
} else {
|
|
||||||
yyv19 := &x.APIVersion
|
|
||||||
yym20 := z.DecBinary()
|
yym20 := z.DecBinary()
|
||||||
_ = yym20
|
_ = yym20
|
||||||
if false {
|
if false {
|
||||||
@@ -419,13 +428,35 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.
|
|||||||
*((*string)(yyv19)) = r.DecodeString()
|
*((*string)(yyv19)) = r.DecodeString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yyj16++
|
yyj18++
|
||||||
if yyhl16 {
|
if yyhl18 {
|
||||||
yyb16 = yyj16 > l
|
yyb18 = yyj18 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb18 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb18 {
|
||||||
|
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.APIVersion = ""
|
||||||
|
} else {
|
||||||
|
yyv21 := &x.APIVersion
|
||||||
|
yym22 := z.DecBinary()
|
||||||
|
_ = yym22
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*string)(yyv21)) = r.DecodeString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yyj18++
|
||||||
|
if yyhl18 {
|
||||||
|
yyb18 = yyj18 > l
|
||||||
|
} else {
|
||||||
|
yyb18 = r.CheckBreak()
|
||||||
|
}
|
||||||
|
if yyb18 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -433,22 +464,22 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.
|
|||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
x.DeschedulingInterval = 0
|
x.DeschedulingInterval = 0
|
||||||
} else {
|
} else {
|
||||||
yyv21 := &x.DeschedulingInterval
|
yyv23 := &x.DeschedulingInterval
|
||||||
yym22 := z.DecBinary()
|
yym24 := z.DecBinary()
|
||||||
_ = yym22
|
_ = yym24
|
||||||
if false {
|
if false {
|
||||||
} else if z.HasExtensions() && z.DecExt(yyv21) {
|
} else if z.HasExtensions() && z.DecExt(yyv23) {
|
||||||
} else {
|
} else {
|
||||||
*((*int64)(yyv21)) = int64(r.DecodeInt(64))
|
*((*int64)(yyv23)) = int64(r.DecodeInt(64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yyj16++
|
yyj18++
|
||||||
if yyhl16 {
|
if yyhl18 {
|
||||||
yyb16 = yyj16 > l
|
yyb18 = yyj18 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb18 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb18 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -456,29 +487,7 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.
|
|||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
x.KubeconfigFile = ""
|
x.KubeconfigFile = ""
|
||||||
} else {
|
} else {
|
||||||
yyv23 := &x.KubeconfigFile
|
yyv25 := &x.KubeconfigFile
|
||||||
yym24 := z.DecBinary()
|
|
||||||
_ = yym24
|
|
||||||
if false {
|
|
||||||
} else {
|
|
||||||
*((*string)(yyv23)) = r.DecodeString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
yyj16++
|
|
||||||
if yyhl16 {
|
|
||||||
yyb16 = yyj16 > l
|
|
||||||
} else {
|
|
||||||
yyb16 = r.CheckBreak()
|
|
||||||
}
|
|
||||||
if yyb16 {
|
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
|
||||||
if r.TryDecodeAsNil() {
|
|
||||||
x.PolicyConfigFile = ""
|
|
||||||
} else {
|
|
||||||
yyv25 := &x.PolicyConfigFile
|
|
||||||
yym26 := z.DecBinary()
|
yym26 := z.DecBinary()
|
||||||
_ = yym26
|
_ = yym26
|
||||||
if false {
|
if false {
|
||||||
@@ -486,13 +495,35 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.
|
|||||||
*((*string)(yyv25)) = r.DecodeString()
|
*((*string)(yyv25)) = r.DecodeString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yyj16++
|
yyj18++
|
||||||
if yyhl16 {
|
if yyhl18 {
|
||||||
yyb16 = yyj16 > l
|
yyb18 = yyj18 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb18 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb18 {
|
||||||
|
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.PolicyConfigFile = ""
|
||||||
|
} else {
|
||||||
|
yyv27 := &x.PolicyConfigFile
|
||||||
|
yym28 := z.DecBinary()
|
||||||
|
_ = yym28
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*string)(yyv27)) = r.DecodeString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yyj18++
|
||||||
|
if yyhl18 {
|
||||||
|
yyb18 = yyj18 > l
|
||||||
|
} else {
|
||||||
|
yyb18 = r.CheckBreak()
|
||||||
|
}
|
||||||
|
if yyb18 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -500,26 +531,48 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.
|
|||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
x.DryRun = false
|
x.DryRun = false
|
||||||
} else {
|
} else {
|
||||||
yyv27 := &x.DryRun
|
yyv29 := &x.DryRun
|
||||||
yym28 := z.DecBinary()
|
yym30 := z.DecBinary()
|
||||||
_ = yym28
|
_ = yym30
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
*((*bool)(yyv27)) = r.DecodeBool()
|
*((*bool)(yyv29)) = r.DecodeBool()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yyj18++
|
||||||
|
if yyhl18 {
|
||||||
|
yyb18 = yyj18 > l
|
||||||
|
} else {
|
||||||
|
yyb18 = r.CheckBreak()
|
||||||
|
}
|
||||||
|
if yyb18 {
|
||||||
|
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.NodeSelector = ""
|
||||||
|
} else {
|
||||||
|
yyv31 := &x.NodeSelector
|
||||||
|
yym32 := z.DecBinary()
|
||||||
|
_ = yym32
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*string)(yyv31)) = r.DecodeString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
yyj16++
|
yyj18++
|
||||||
if yyhl16 {
|
if yyhl18 {
|
||||||
yyb16 = yyj16 > l
|
yyb18 = yyj18 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb18 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb18 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||||
z.DecStructFieldNotFound(yyj16-1, "")
|
z.DecStructFieldNotFound(yyj18-1, "")
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,4 +37,7 @@ type DeschedulerConfiguration struct {
|
|||||||
|
|
||||||
// Dry run
|
// Dry run
|
||||||
DryRun bool
|
DryRun bool
|
||||||
|
|
||||||
|
// Node selectors
|
||||||
|
NodeSelector string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ func (x *DeschedulerConfiguration) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||||||
} else {
|
} else {
|
||||||
yysep2 := !z.EncBinary()
|
yysep2 := !z.EncBinary()
|
||||||
yy2arr2 := z.EncBasicHandle().StructToArray
|
yy2arr2 := z.EncBasicHandle().StructToArray
|
||||||
var yyq2 [6]bool
|
var yyq2 [7]bool
|
||||||
_, _, _ = yysep2, yyq2, yy2arr2
|
_, _, _ = yysep2, yyq2, yy2arr2
|
||||||
const yyr2 bool = false
|
const yyr2 bool = false
|
||||||
yyq2[0] = x.Kind != ""
|
yyq2[0] = x.Kind != ""
|
||||||
@@ -89,9 +89,10 @@ func (x *DeschedulerConfiguration) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||||||
yyq2[2] = x.DeschedulingInterval != 0
|
yyq2[2] = x.DeschedulingInterval != 0
|
||||||
yyq2[4] = x.PolicyConfigFile != ""
|
yyq2[4] = x.PolicyConfigFile != ""
|
||||||
yyq2[5] = x.DryRun != false
|
yyq2[5] = x.DryRun != false
|
||||||
|
yyq2[6] = x.NodeSelector != ""
|
||||||
var yynn2 int
|
var yynn2 int
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
r.EncodeArrayStart(6)
|
r.EncodeArrayStart(7)
|
||||||
} else {
|
} else {
|
||||||
yynn2 = 1
|
yynn2 = 1
|
||||||
for _, b := range yyq2 {
|
for _, b := range yyq2 {
|
||||||
@@ -248,6 +249,31 @@ func (x *DeschedulerConfiguration) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if yyr2 || yy2arr2 {
|
||||||
|
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
||||||
|
if yyq2[6] {
|
||||||
|
yym22 := z.EncBinary()
|
||||||
|
_ = yym22
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
r.EncodeString(codecSelferC_UTF81234, string(x.NodeSelector))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r.EncodeString(codecSelferC_UTF81234, "")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if yyq2[6] {
|
||||||
|
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
||||||
|
r.EncodeString(codecSelferC_UTF81234, string("nodeSelector"))
|
||||||
|
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
||||||
|
yym23 := z.EncBinary()
|
||||||
|
_ = yym23
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
r.EncodeString(codecSelferC_UTF81234, string(x.NodeSelector))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if yyr2 || yy2arr2 {
|
if yyr2 || yy2arr2 {
|
||||||
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
|
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
} else {
|
} else {
|
||||||
@@ -382,6 +408,18 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromMap(l int, d *codec1978.De
|
|||||||
*((*bool)(yyv14)) = r.DecodeBool()
|
*((*bool)(yyv14)) = r.DecodeBool()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "nodeSelector":
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.NodeSelector = ""
|
||||||
|
} else {
|
||||||
|
yyv16 := &x.NodeSelector
|
||||||
|
yym17 := z.DecBinary()
|
||||||
|
_ = yym17
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*string)(yyv16)) = r.DecodeString()
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
z.DecStructFieldNotFound(-1, yys3)
|
z.DecStructFieldNotFound(-1, yys3)
|
||||||
} // end switch yys3
|
} // end switch yys3
|
||||||
@@ -393,16 +431,16 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.
|
|||||||
var h codecSelfer1234
|
var h codecSelfer1234
|
||||||
z, r := codec1978.GenHelperDecoder(d)
|
z, r := codec1978.GenHelperDecoder(d)
|
||||||
_, _, _ = h, z, r
|
_, _, _ = h, z, r
|
||||||
var yyj16 int
|
var yyj18 int
|
||||||
var yyb16 bool
|
var yyb18 bool
|
||||||
var yyhl16 bool = l >= 0
|
var yyhl18 bool = l >= 0
|
||||||
yyj16++
|
yyj18++
|
||||||
if yyhl16 {
|
if yyhl18 {
|
||||||
yyb16 = yyj16 > l
|
yyb18 = yyj18 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb18 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb18 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -410,29 +448,7 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.
|
|||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
x.Kind = ""
|
x.Kind = ""
|
||||||
} else {
|
} else {
|
||||||
yyv17 := &x.Kind
|
yyv19 := &x.Kind
|
||||||
yym18 := z.DecBinary()
|
|
||||||
_ = yym18
|
|
||||||
if false {
|
|
||||||
} else {
|
|
||||||
*((*string)(yyv17)) = r.DecodeString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
yyj16++
|
|
||||||
if yyhl16 {
|
|
||||||
yyb16 = yyj16 > l
|
|
||||||
} else {
|
|
||||||
yyb16 = r.CheckBreak()
|
|
||||||
}
|
|
||||||
if yyb16 {
|
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
|
||||||
if r.TryDecodeAsNil() {
|
|
||||||
x.APIVersion = ""
|
|
||||||
} else {
|
|
||||||
yyv19 := &x.APIVersion
|
|
||||||
yym20 := z.DecBinary()
|
yym20 := z.DecBinary()
|
||||||
_ = yym20
|
_ = yym20
|
||||||
if false {
|
if false {
|
||||||
@@ -440,13 +456,35 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.
|
|||||||
*((*string)(yyv19)) = r.DecodeString()
|
*((*string)(yyv19)) = r.DecodeString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yyj16++
|
yyj18++
|
||||||
if yyhl16 {
|
if yyhl18 {
|
||||||
yyb16 = yyj16 > l
|
yyb18 = yyj18 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb18 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb18 {
|
||||||
|
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.APIVersion = ""
|
||||||
|
} else {
|
||||||
|
yyv21 := &x.APIVersion
|
||||||
|
yym22 := z.DecBinary()
|
||||||
|
_ = yym22
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*string)(yyv21)) = r.DecodeString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yyj18++
|
||||||
|
if yyhl18 {
|
||||||
|
yyb18 = yyj18 > l
|
||||||
|
} else {
|
||||||
|
yyb18 = r.CheckBreak()
|
||||||
|
}
|
||||||
|
if yyb18 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -454,22 +492,22 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.
|
|||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
x.DeschedulingInterval = 0
|
x.DeschedulingInterval = 0
|
||||||
} else {
|
} else {
|
||||||
yyv21 := &x.DeschedulingInterval
|
yyv23 := &x.DeschedulingInterval
|
||||||
yym22 := z.DecBinary()
|
yym24 := z.DecBinary()
|
||||||
_ = yym22
|
_ = yym24
|
||||||
if false {
|
if false {
|
||||||
} else if z.HasExtensions() && z.DecExt(yyv21) {
|
} else if z.HasExtensions() && z.DecExt(yyv23) {
|
||||||
} else {
|
} else {
|
||||||
*((*int64)(yyv21)) = int64(r.DecodeInt(64))
|
*((*int64)(yyv23)) = int64(r.DecodeInt(64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yyj16++
|
yyj18++
|
||||||
if yyhl16 {
|
if yyhl18 {
|
||||||
yyb16 = yyj16 > l
|
yyb18 = yyj18 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb18 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb18 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -477,29 +515,7 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.
|
|||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
x.KubeconfigFile = ""
|
x.KubeconfigFile = ""
|
||||||
} else {
|
} else {
|
||||||
yyv23 := &x.KubeconfigFile
|
yyv25 := &x.KubeconfigFile
|
||||||
yym24 := z.DecBinary()
|
|
||||||
_ = yym24
|
|
||||||
if false {
|
|
||||||
} else {
|
|
||||||
*((*string)(yyv23)) = r.DecodeString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
yyj16++
|
|
||||||
if yyhl16 {
|
|
||||||
yyb16 = yyj16 > l
|
|
||||||
} else {
|
|
||||||
yyb16 = r.CheckBreak()
|
|
||||||
}
|
|
||||||
if yyb16 {
|
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
|
||||||
if r.TryDecodeAsNil() {
|
|
||||||
x.PolicyConfigFile = ""
|
|
||||||
} else {
|
|
||||||
yyv25 := &x.PolicyConfigFile
|
|
||||||
yym26 := z.DecBinary()
|
yym26 := z.DecBinary()
|
||||||
_ = yym26
|
_ = yym26
|
||||||
if false {
|
if false {
|
||||||
@@ -507,13 +523,35 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.
|
|||||||
*((*string)(yyv25)) = r.DecodeString()
|
*((*string)(yyv25)) = r.DecodeString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yyj16++
|
yyj18++
|
||||||
if yyhl16 {
|
if yyhl18 {
|
||||||
yyb16 = yyj16 > l
|
yyb18 = yyj18 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb18 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb18 {
|
||||||
|
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.PolicyConfigFile = ""
|
||||||
|
} else {
|
||||||
|
yyv27 := &x.PolicyConfigFile
|
||||||
|
yym28 := z.DecBinary()
|
||||||
|
_ = yym28
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*string)(yyv27)) = r.DecodeString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yyj18++
|
||||||
|
if yyhl18 {
|
||||||
|
yyb18 = yyj18 > l
|
||||||
|
} else {
|
||||||
|
yyb18 = r.CheckBreak()
|
||||||
|
}
|
||||||
|
if yyb18 {
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -521,26 +559,48 @@ func (x *DeschedulerConfiguration) codecDecodeSelfFromArray(l int, d *codec1978.
|
|||||||
if r.TryDecodeAsNil() {
|
if r.TryDecodeAsNil() {
|
||||||
x.DryRun = false
|
x.DryRun = false
|
||||||
} else {
|
} else {
|
||||||
yyv27 := &x.DryRun
|
yyv29 := &x.DryRun
|
||||||
yym28 := z.DecBinary()
|
yym30 := z.DecBinary()
|
||||||
_ = yym28
|
_ = yym30
|
||||||
if false {
|
if false {
|
||||||
} else {
|
} else {
|
||||||
*((*bool)(yyv27)) = r.DecodeBool()
|
*((*bool)(yyv29)) = r.DecodeBool()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yyj18++
|
||||||
|
if yyhl18 {
|
||||||
|
yyb18 = yyj18 > l
|
||||||
|
} else {
|
||||||
|
yyb18 = r.CheckBreak()
|
||||||
|
}
|
||||||
|
if yyb18 {
|
||||||
|
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||||
|
if r.TryDecodeAsNil() {
|
||||||
|
x.NodeSelector = ""
|
||||||
|
} else {
|
||||||
|
yyv31 := &x.NodeSelector
|
||||||
|
yym32 := z.DecBinary()
|
||||||
|
_ = yym32
|
||||||
|
if false {
|
||||||
|
} else {
|
||||||
|
*((*string)(yyv31)) = r.DecodeString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
yyj16++
|
yyj18++
|
||||||
if yyhl16 {
|
if yyhl18 {
|
||||||
yyb16 = yyj16 > l
|
yyb18 = yyj18 > l
|
||||||
} else {
|
} else {
|
||||||
yyb16 = r.CheckBreak()
|
yyb18 = r.CheckBreak()
|
||||||
}
|
}
|
||||||
if yyb16 {
|
if yyb18 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||||
z.DecStructFieldNotFound(yyj16-1, "")
|
z.DecStructFieldNotFound(yyj18-1, "")
|
||||||
}
|
}
|
||||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,4 +37,7 @@ type DeschedulerConfiguration struct {
|
|||||||
|
|
||||||
// Dry run
|
// Dry run
|
||||||
DryRun bool `json:"dryRun,omitempty"`
|
DryRun bool `json:"dryRun,omitempty"`
|
||||||
|
|
||||||
|
// Node selectors
|
||||||
|
NodeSelector string `json:"nodeSelector,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ func autoConvert_v1alpha1_DeschedulerConfiguration_To_componentconfig_Deschedule
|
|||||||
out.KubeconfigFile = in.KubeconfigFile
|
out.KubeconfigFile = in.KubeconfigFile
|
||||||
out.PolicyConfigFile = in.PolicyConfigFile
|
out.PolicyConfigFile = in.PolicyConfigFile
|
||||||
out.DryRun = in.DryRun
|
out.DryRun = in.DryRun
|
||||||
|
out.NodeSelector = in.NodeSelector
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +59,7 @@ func autoConvert_componentconfig_DeschedulerConfiguration_To_v1alpha1_Deschedule
|
|||||||
out.KubeconfigFile = in.KubeconfigFile
|
out.KubeconfigFile = in.KubeconfigFile
|
||||||
out.PolicyConfigFile = in.PolicyConfigFile
|
out.PolicyConfigFile = in.PolicyConfigFile
|
||||||
out.DryRun = in.DryRun
|
out.DryRun = in.DryRun
|
||||||
|
out.NodeSelector = in.NodeSelector
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ package descheduler
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
|
||||||
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
||||||
"github.com/kubernetes-incubator/descheduler/pkg/descheduler/client"
|
"github.com/kubernetes-incubator/descheduler/pkg/descheduler/client"
|
||||||
eutils "github.com/kubernetes-incubator/descheduler/pkg/descheduler/evictions/utils"
|
eutils "github.com/kubernetes-incubator/descheduler/pkg/descheduler/evictions/utils"
|
||||||
@@ -39,22 +41,28 @@ func Run(rs *options.DeschedulerServer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if deschedulerPolicy == nil {
|
if deschedulerPolicy == nil {
|
||||||
return fmt.Errorf("\ndeschedulerPolicy is nil\n")
|
return fmt.Errorf("deschedulerPolicy is nil")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
evictionPolicyGroupVersion, err := eutils.SupportEviction(rs.Client)
|
evictionPolicyGroupVersion, err := eutils.SupportEviction(rs.Client)
|
||||||
if err != nil || len(evictionPolicyGroupVersion) == 0 {
|
if err != nil || len(evictionPolicyGroupVersion) == 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
stopChannel := make(chan struct{})
|
stopChannel := make(chan struct{})
|
||||||
nodes, err := nodeutil.ReadyNodes(rs.Client, stopChannel)
|
nodes, err := nodeutil.ReadyNodes(rs.Client, rs.NodeSelector, stopChannel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(nodes) == 0 {
|
||||||
|
glog.V(1).Infof("node list is empty")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
strategies.RemoveDuplicatePods(rs, deschedulerPolicy.Strategies["RemoveDuplicates"], evictionPolicyGroupVersion, nodes)
|
strategies.RemoveDuplicatePods(rs, deschedulerPolicy.Strategies["RemoveDuplicates"], evictionPolicyGroupVersion, nodes)
|
||||||
strategies.LowNodeUtilization(rs, deschedulerPolicy.Strategies["LowNodeUtilization"], evictionPolicyGroupVersion, nodes)
|
strategies.LowNodeUtilization(rs, deschedulerPolicy.Strategies["LowNodeUtilization"], evictionPolicyGroupVersion, nodes)
|
||||||
|
strategies.RemovePodsViolatingInterPodAntiAffinity(rs, deschedulerPolicy.Strategies["RemovePodsViolatingInterPodAntiAffinity"], evictionPolicyGroupVersion, nodes)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,20 +31,33 @@ import (
|
|||||||
|
|
||||||
// ReadyNodes returns ready nodes irrespective of whether they are
|
// ReadyNodes returns ready nodes irrespective of whether they are
|
||||||
// schedulable or not.
|
// schedulable or not.
|
||||||
func ReadyNodes(client clientset.Interface, stopChannel <-chan struct{}) ([]*v1.Node, error) {
|
func ReadyNodes(client clientset.Interface, nodeSelector string, stopChannel <-chan struct{}) ([]*v1.Node, error) {
|
||||||
nl := GetNodeLister(client, stopChannel)
|
ns, err := labels.Parse(nodeSelector)
|
||||||
nodes, err := nl.List(labels.Everything())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []*v1.Node{}, err
|
return []*v1.Node{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var nodes []*v1.Node
|
||||||
|
nl := GetNodeLister(client, stopChannel)
|
||||||
|
if nl != nil {
|
||||||
|
// err is defined above
|
||||||
|
if nodes, err = nl.List(ns); err != nil {
|
||||||
|
return []*v1.Node{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(nodes) == 0 {
|
if len(nodes) == 0 {
|
||||||
var err error
|
glog.V(2).Infof("node lister returned empty list, now fetch directly")
|
||||||
nItems, err := client.Core().Nodes().List(metav1.ListOptions{})
|
|
||||||
|
nItems, err := client.Core().Nodes().List(metav1.ListOptions{LabelSelector: nodeSelector})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []*v1.Node{}, err
|
return []*v1.Node{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if nItems == nil || len(nItems.Items) == 0 {
|
||||||
|
return []*v1.Node{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
for i := range nItems.Items {
|
for i := range nItems.Items {
|
||||||
node := nItems.Items[i]
|
node := nItems.Items[i]
|
||||||
nodes = append(nodes, &node)
|
nodes = append(nodes, &node)
|
||||||
@@ -61,6 +74,9 @@ func ReadyNodes(client clientset.Interface, stopChannel <-chan struct{}) ([]*v1.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetNodeLister(client clientset.Interface, stopChannel <-chan struct{}) corelisters.NodeLister {
|
func GetNodeLister(client clientset.Interface, stopChannel <-chan struct{}) corelisters.NodeLister {
|
||||||
|
if stopChannel == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
listWatcher := cache.NewListWatchFromClient(client.Core().RESTClient(), "nodes", v1.NamespaceAll, fields.Everything())
|
listWatcher := cache.NewListWatchFromClient(client.Core().RESTClient(), "nodes", v1.NamespaceAll, fields.Everything())
|
||||||
store := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
|
store := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
|
||||||
nodeLister := corelisters.NewNodeLister(store)
|
nodeLister := corelisters.NewNodeLister(store)
|
||||||
|
|||||||
@@ -17,18 +17,14 @@ limitations under the License.
|
|||||||
package node
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/kubernetes-incubator/descheduler/test"
|
"github.com/kubernetes-incubator/descheduler/test"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
core "k8s.io/client-go/testing"
|
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset/fake"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset/fake"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReadyNodes(t *testing.T) {
|
func TestReadyNodes(t *testing.T) {
|
||||||
fakeClient := &fake.Clientset{}
|
|
||||||
node1 := test.BuildTestNode("node1", 1000, 2000, 9)
|
node1 := test.BuildTestNode("node1", 1000, 2000, 9)
|
||||||
node1.Status.Conditions = []v1.NodeCondition{{Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue}}
|
node1.Status.Conditions = []v1.NodeCondition{{Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue}}
|
||||||
node2 := test.BuildTestNode("node2", 1000, 2000, 9)
|
node2 := test.BuildTestNode("node2", 1000, 2000, 9)
|
||||||
@@ -41,25 +37,6 @@ func TestReadyNodes(t *testing.T) {
|
|||||||
node6 := test.BuildTestNode("node6", 1000, 2000, 9)
|
node6 := test.BuildTestNode("node6", 1000, 2000, 9)
|
||||||
node6.Status.Conditions = []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionFalse}}
|
node6.Status.Conditions = []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionFalse}}
|
||||||
|
|
||||||
fakeClient.Fake.AddReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) {
|
|
||||||
getAction := action.(core.GetAction)
|
|
||||||
switch getAction.GetName() {
|
|
||||||
case node1.Name:
|
|
||||||
return true, node1, nil
|
|
||||||
case node2.Name:
|
|
||||||
return true, node2, nil
|
|
||||||
case node3.Name:
|
|
||||||
return true, node3, nil
|
|
||||||
case node4.Name:
|
|
||||||
return true, node4, nil
|
|
||||||
case node5.Name:
|
|
||||||
return true, node5, nil
|
|
||||||
case node6.Name:
|
|
||||||
return true, node6, nil
|
|
||||||
}
|
|
||||||
return true, nil, fmt.Errorf("Wrong node: %v", getAction.GetName())
|
|
||||||
})
|
|
||||||
|
|
||||||
if !IsReady(node1) {
|
if !IsReady(node1) {
|
||||||
t.Errorf("Expected %v to be ready", node1.Name)
|
t.Errorf("Expected %v to be ready", node1.Name)
|
||||||
}
|
}
|
||||||
@@ -80,3 +57,18 @@ func TestReadyNodes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReadyNodesWithNodeSelector(t *testing.T) {
|
||||||
|
node1 := test.BuildTestNode("node1", 1000, 2000, 9)
|
||||||
|
node1.Labels = map[string]string{"type": "compute"}
|
||||||
|
node2 := test.BuildTestNode("node2", 1000, 2000, 9)
|
||||||
|
node2.Labels = map[string]string{"type": "infra"}
|
||||||
|
|
||||||
|
fakeClient := fake.NewSimpleClientset(node1, node2)
|
||||||
|
nodeSelector := "type=compute"
|
||||||
|
nodes, _ := ReadyNodes(fakeClient, nodeSelector, nil)
|
||||||
|
|
||||||
|
if nodes[0].Name != "node1" {
|
||||||
|
t.Errorf("Expected node1, got %s", nodes[0].Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
102
pkg/descheduler/strategies/pod_antiaffinity.go
Normal file
102
pkg/descheduler/strategies/pod_antiaffinity.go
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 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 strategies
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kubernetes-incubator/descheduler/cmd/descheduler/app/options"
|
||||||
|
"github.com/kubernetes-incubator/descheduler/pkg/api"
|
||||||
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"github.com/kubernetes-incubator/descheduler/pkg/descheduler/evictions"
|
||||||
|
podutil "github.com/kubernetes-incubator/descheduler/pkg/descheduler/pod"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
//TODO: Change to client-go instead of generated clientset.
|
||||||
|
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||||
|
priorityutil "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/priorities/util"
|
||||||
|
"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RemovePodsViolatingInterPodAntiAffinity with elimination strategy
|
||||||
|
func RemovePodsViolatingInterPodAntiAffinity(ds *options.DeschedulerServer, strategy api.DeschedulerStrategy, policyGroupVersion string, nodes []*v1.Node) {
|
||||||
|
if !strategy.Enabled {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
removePodsWithAffinityRules(ds.Client, policyGroupVersion, nodes, ds.DryRun)
|
||||||
|
}
|
||||||
|
|
||||||
|
// removePodsWithAffinityRules evicts pods on the node which are having a pod affinity rules.
|
||||||
|
func removePodsWithAffinityRules(client clientset.Interface, policyGroupVersion string, nodes []*v1.Node, dryRun bool) int {
|
||||||
|
podsEvicted := 0
|
||||||
|
for _, node := range nodes {
|
||||||
|
glog.V(1).Infof("Processing node: %#v\n", node.Name)
|
||||||
|
pods, err := podutil.ListPodsOnANode(client, node)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
totalPods := len(pods)
|
||||||
|
for i := 0; i < totalPods; i++ {
|
||||||
|
if checkPodsWithAntiAffinityExist(pods[i], pods) {
|
||||||
|
success, err := evictions.EvictPod(client, pods[i], policyGroupVersion, dryRun)
|
||||||
|
if !success {
|
||||||
|
glog.Infof("Error when evicting pod: %#v (%#v)\n", pods[i].Name, err)
|
||||||
|
} else {
|
||||||
|
podsEvicted++
|
||||||
|
glog.V(1).Infof("Evicted pod: %#v (%#v)\n because of existing anti-affinity", pods[i].Name, err)
|
||||||
|
// Since the current pod is evicted all other pods which have anti-affinity with this
|
||||||
|
// pod need not be evicted.
|
||||||
|
// Update pods.
|
||||||
|
pods = append(pods[:i], pods[i+1:]...)
|
||||||
|
i--
|
||||||
|
totalPods--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return podsEvicted
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkPodsWithAntiAffinityExist checks if there are other pods on the node that the current pod cannot tolerate.
|
||||||
|
func checkPodsWithAntiAffinityExist(pod *v1.Pod, pods []*v1.Pod) bool {
|
||||||
|
affinity := schedulercache.ReconcileAffinity(pod)
|
||||||
|
if affinity != nil && affinity.PodAntiAffinity != nil {
|
||||||
|
for _, term := range getPodAntiAffinityTerms(affinity.PodAntiAffinity) {
|
||||||
|
namespaces := priorityutil.GetNamespacesFromPodAffinityTerm(pod, &term)
|
||||||
|
selector, err := metav1.LabelSelectorAsSelector(term.LabelSelector)
|
||||||
|
if err != nil {
|
||||||
|
glog.Infof("%v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, existingPod := range pods {
|
||||||
|
if existingPod.Name != pod.Name && priorityutil.PodMatchesTermsNamespaceAndSelector(existingPod, namespaces, selector) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// getPodAntiAffinityTerms gets the antiaffinity terms for the given pod.
|
||||||
|
func getPodAntiAffinityTerms(podAntiAffinity *v1.PodAntiAffinity) (terms []v1.PodAffinityTerm) {
|
||||||
|
if podAntiAffinity != nil {
|
||||||
|
if len(podAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution) != 0 {
|
||||||
|
terms = podAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return terms
|
||||||
|
}
|
||||||
86
pkg/descheduler/strategies/pod_antiaffinity_test.go
Normal file
86
pkg/descheduler/strategies/pod_antiaffinity_test.go
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 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 strategies
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"fmt"
|
||||||
|
"github.com/kubernetes-incubator/descheduler/test"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
core "k8s.io/client-go/testing"
|
||||||
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
|
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset/fake"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPodAntiAffinity(t *testing.T) {
|
||||||
|
node := test.BuildTestNode("n1", 2000, 3000, 10)
|
||||||
|
p1 := test.BuildTestPod("p1", 100, 0, node.Name)
|
||||||
|
p2 := test.BuildTestPod("p2", 100, 0, node.Name)
|
||||||
|
p3 := test.BuildTestPod("p3", 100, 0, node.Name)
|
||||||
|
p3.Labels = map[string]string{"foo": "bar"}
|
||||||
|
p1.Spec.Affinity = &v1.Affinity{
|
||||||
|
PodAntiAffinity: &v1.PodAntiAffinity{
|
||||||
|
RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
|
||||||
|
{
|
||||||
|
LabelSelector: &metav1.LabelSelector{
|
||||||
|
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: "foo",
|
||||||
|
Operator: metav1.LabelSelectorOpIn,
|
||||||
|
Values: []string{"bar"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TopologyKey: "region",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
p3.Spec.Affinity = &v1.Affinity{
|
||||||
|
PodAntiAffinity: &v1.PodAntiAffinity{
|
||||||
|
RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
|
||||||
|
{
|
||||||
|
LabelSelector: &metav1.LabelSelector{
|
||||||
|
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: "foo",
|
||||||
|
Operator: metav1.LabelSelectorOpIn,
|
||||||
|
Values: []string{"bar"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TopologyKey: "region",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
fakeClient := &fake.Clientset{}
|
||||||
|
fakeClient.Fake.AddReactor("list", "pods", func(action core.Action) (bool, runtime.Object, error) {
|
||||||
|
return true, &v1.PodList{Items: []v1.Pod{*p1, *p2, *p3}}, nil
|
||||||
|
})
|
||||||
|
fakeClient.Fake.AddReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) {
|
||||||
|
return true, node, nil
|
||||||
|
})
|
||||||
|
expectedEvictedPodCount := 1
|
||||||
|
podsEvicted := removePodsWithAffinityRules(fakeClient, "v1", []*v1.Node{node}, false)
|
||||||
|
if podsEvicted != expectedEvictedPodCount {
|
||||||
|
fmt.Println(podsEvicted)
|
||||||
|
t.Errorf("Unexpected no of pods evicted")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user