move Taint and toleration predicate to its Score plugin

This commit is contained in:
SataQiu
2019-12-24 19:22:12 +08:00
parent 39d0710a4b
commit 21c916c3d2
13 changed files with 115 additions and 342 deletions

View File

@@ -241,6 +241,7 @@ func NewDefaultConfigProducerRegistry() *ConfigProducerRegistry {
})
registry.RegisterPriority(priorities.TaintTolerationPriority,
func(args ConfigProducerArgs) (plugins config.Plugins, pluginConfig []config.PluginConfig) {
plugins.PostFilter = appendToPluginSet(plugins.PostFilter, tainttoleration.Name, nil)
plugins.Score = appendToPluginSet(plugins.Score, tainttoleration.Name, &args.Weight)
return
})

View File

@@ -6,6 +6,7 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/scheduler/framework/plugins/tainttoleration",
visibility = ["//visibility:public"],
deps = [
"//pkg/apis/core/v1/helper:go_default_library",
"//pkg/scheduler/algorithm/predicates:go_default_library",
"//pkg/scheduler/algorithm/priorities:go_default_library",
"//pkg/scheduler/framework/plugins/migration:go_default_library",

View File

@@ -22,6 +22,7 @@ import (
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
"k8s.io/kubernetes/pkg/scheduler/algorithm/predicates"
"k8s.io/kubernetes/pkg/scheduler/algorithm/priorities"
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/migration"
@@ -35,10 +36,15 @@ type TaintToleration struct {
}
var _ framework.FilterPlugin = &TaintToleration{}
var _ framework.PostFilterPlugin = &TaintToleration{}
var _ framework.ScorePlugin = &TaintToleration{}
// Name is the name of the plugin used in the plugin registry and configurations.
const Name = "TaintToleration"
const (
// Name is the name of the plugin used in the plugin registry and configurations.
Name = "TaintToleration"
// postFilterStateKey is the key in CycleState to InterPodAffinity pre-computed data for Scoring.
postFilterStateKey = "PostFilter" + Name
)
// Name returns name of the plugin. It is used in logs, etc.
func (pl *TaintToleration) Name() string {
@@ -52,21 +58,91 @@ func (pl *TaintToleration) Filter(ctx context.Context, state *framework.CycleSta
return migration.PredicateResultToFrameworkStatus(reasons, err)
}
// postFilterState computed at PostFilter and used at Score.
type postFilterState struct {
tolerationsPreferNoSchedule []v1.Toleration
}
// Clone implements the mandatory Clone interface. We don't really copy the data since
// there is no need for that.
func (s *postFilterState) Clone() framework.StateData {
return s
}
// getAllTolerationEffectPreferNoSchedule gets the list of all Tolerations with Effect PreferNoSchedule or with no effect.
func getAllTolerationPreferNoSchedule(tolerations []v1.Toleration) (tolerationList []v1.Toleration) {
for _, toleration := range tolerations {
// Empty effect means all effects which includes PreferNoSchedule, so we need to collect it as well.
if len(toleration.Effect) == 0 || toleration.Effect == v1.TaintEffectPreferNoSchedule {
tolerationList = append(tolerationList, toleration)
}
}
return
}
// PostFilter builds and writes cycle state used by Score and NormalizeScore.
func (pl *TaintToleration) PostFilter(ctx context.Context, cycleState *framework.CycleState, pod *v1.Pod, nodes []*v1.Node, _ framework.NodeToStatusMap) *framework.Status {
if len(nodes) == 0 {
return nil
}
tolerationsPreferNoSchedule := getAllTolerationPreferNoSchedule(pod.Spec.Tolerations)
state := &postFilterState{
tolerationsPreferNoSchedule: tolerationsPreferNoSchedule,
}
cycleState.Write(postFilterStateKey, state)
return nil
}
func getPostFilterState(cycleState *framework.CycleState) (*postFilterState, error) {
c, err := cycleState.Read(postFilterStateKey)
if err != nil {
return nil, fmt.Errorf("Error reading %q from cycleState: %v", postFilterStateKey, err)
}
s, ok := c.(*postFilterState)
if !ok {
return nil, fmt.Errorf("%+v convert to tainttoleration.postFilterState error", c)
}
return s, nil
}
// CountIntolerableTaintsPreferNoSchedule gives the count of intolerable taints of a pod with effect PreferNoSchedule
func countIntolerableTaintsPreferNoSchedule(taints []v1.Taint, tolerations []v1.Toleration) (intolerableTaints int) {
for _, taint := range taints {
// check only on taints that have effect PreferNoSchedule
if taint.Effect != v1.TaintEffectPreferNoSchedule {
continue
}
if !v1helper.TolerationsTolerateTaint(tolerations, &taint) {
intolerableTaints++
}
}
return
}
// Score invoked at the Score extension point.
func (pl *TaintToleration) Score(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) (int64, *framework.Status) {
nodeInfo, err := pl.handle.SnapshotSharedLister().NodeInfos().Get(nodeName)
if err != nil {
if err != nil || nodeInfo.Node() == nil {
return 0, framework.NewStatus(framework.Error, fmt.Sprintf("getting node %q from Snapshot: %v", nodeName, err))
}
meta := migration.PriorityMetadata(state)
s, err := priorities.ComputeTaintTolerationPriorityMap(pod, meta, nodeInfo)
return s.Score, migration.ErrorToFrameworkStatus(err)
node := nodeInfo.Node()
s, err := getPostFilterState(state)
if err != nil {
return 0, framework.NewStatus(framework.Error, err.Error())
}
score := int64(countIntolerableTaintsPreferNoSchedule(node.Spec.Taints, s.tolerationsPreferNoSchedule))
return score, nil
}
// NormalizeScore invoked after scoring all nodes.
func (pl *TaintToleration) NormalizeScore(ctx context.Context, _ *framework.CycleState, pod *v1.Pod, scores framework.NodeScoreList) *framework.Status {
// Note that ComputeTaintTolerationPriorityReduce doesn't use priority metadata, hence passing nil here.
err := priorities.ComputeTaintTolerationPriorityReduce(pod, nil, pl.handle.SnapshotSharedLister(), scores)
normalizeFun := priorities.NormalizeReduce(framework.MaxNodeScore, true)
err := normalizeFun(pod, nil, pl.handle.SnapshotSharedLister(), scores)
return migration.ErrorToFrameworkStatus(err)
}

View File

@@ -234,6 +234,10 @@ func TestTaintTolerationScore(t *testing.T) {
fh, _ := framework.NewFramework(nil, nil, nil, framework.WithSnapshotSharedLister(snapshot))
p, _ := New(nil, fh)
status := p.(framework.PostFilterPlugin).PostFilter(context.Background(), state, test.pod, test.nodes, nil)
if !status.IsSuccess() {
t.Errorf("unexpected error: %v", status)
}
var gotList framework.NodeScoreList
for _, n := range test.nodes {
nodeName := n.ObjectMeta.Name
@@ -244,7 +248,7 @@ func TestTaintTolerationScore(t *testing.T) {
gotList = append(gotList, framework.NodeScore{Name: nodeName, Score: score})
}
status := p.(framework.ScorePlugin).ScoreExtensions().NormalizeScore(context.Background(), state, test.pod, gotList)
status = p.(framework.ScorePlugin).ScoreExtensions().NormalizeScore(context.Background(), state, test.pod, gotList)
if !status.IsSuccess() {
t.Errorf("unexpected error: %v", status)
}