pkg/podstate/pod_state.go (62 lines of code) (raw):
/*
Copyright 2020 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 podstate
import (
"context"
"fmt"
"math"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/pkg/scheduler/framework"
)
type PodState struct {
handle framework.Handle
}
var _ = framework.ScorePlugin(&PodState{})
// Name is the name of the plugin used in the Registry and configurations.
const Name = "PodState"
func (ps *PodState) Name() string {
return Name
}
// Score invoked at the score extension point.
func (ps *PodState) Score(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) (int64, *framework.Status) {
nodeInfo, err := ps.handle.SnapshotSharedLister().NodeInfos().Get(nodeName)
if err != nil {
return 0, framework.NewStatus(framework.Error, fmt.Sprintf("getting node %q from Snapshot: %v", nodeName, err))
}
// pe.score favors nodes with terminating pods instead of nominated pods
// It calculates the sum of the node's terminating pods and nominated pods
return ps.score(nodeInfo)
}
// ScoreExtensions of the Score plugin.
func (ps *PodState) ScoreExtensions() framework.ScoreExtensions {
return ps
}
func (ps *PodState) score(nodeInfo *framework.NodeInfo) (int64, *framework.Status) {
var terminatingPodNum, nominatedPodNum int64
// get nominated Pods for node from nominatedPodMap
nominatedPodNum = int64(len(ps.handle.NominatedPodsForNode(nodeInfo.Node().Name)))
for _, p := range nodeInfo.Pods {
// Pod is terminating if DeletionTimestamp has been set
if p.Pod.DeletionTimestamp != nil {
terminatingPodNum++
}
}
return terminatingPodNum - nominatedPodNum, nil
}
func (ps *PodState) NormalizeScore(ctx context.Context, state *framework.CycleState, pod *v1.Pod, scores framework.NodeScoreList) *framework.Status {
// Find highest and lowest scores.
var highest int64 = -math.MaxInt64
var lowest int64 = math.MaxInt64
for _, nodeScore := range scores {
if nodeScore.Score > highest {
highest = nodeScore.Score
}
if nodeScore.Score < lowest {
lowest = nodeScore.Score
}
}
// Transform the highest to the lowest score range to fit the framework's min to max node score range.
oldRange := highest - lowest
newRange := framework.MaxNodeScore - framework.MinNodeScore
for i, nodeScore := range scores {
if oldRange == 0 {
scores[i].Score = framework.MinNodeScore
} else {
scores[i].Score = ((nodeScore.Score - lowest) * newRange / oldRange) + framework.MinNodeScore
}
}
return nil
}
// New initializes a new plugin and returns it.
func New(_ context.Context, _ runtime.Object, h framework.Handle) (framework.Plugin, error) {
return &PodState{handle: h}, nil
}