1
0
mirror of https://github.com/kubernetes-sigs/descheduler.git synced 2026-01-26 05:14:13 +01:00

Merge pull request #364 from lixiang233/ft_allow_custom_priority_threshold

Allow custom priority threshold
This commit is contained in:
Kubernetes Prow Robot
2020-08-12 07:35:45 -07:00
committed by GitHub
20 changed files with 420 additions and 57 deletions

View File

@@ -52,8 +52,8 @@ type Namespaces struct {
}
// Besides Namespaces only one of its members may be specified
// TODO(jchaloup): move Namespaces to individual strategies once the policy
// version is bumped to v1alpha2
// TODO(jchaloup): move Namespaces ThresholdPriority and ThresholdPriorityClassName to individual strategies
// once the policy version is bumped to v1alpha2
type StrategyParameters struct {
NodeResourceUtilizationThresholds *NodeResourceUtilizationThresholds
NodeAffinityType []string
@@ -61,6 +61,8 @@ type StrategyParameters struct {
MaxPodLifeTimeSeconds *uint
RemoveDuplicates *RemoveDuplicates
Namespaces Namespaces
ThresholdPriority *int32
ThresholdPriorityClassName string
}
type Percentage float64

View File

@@ -51,7 +51,7 @@ type Namespaces struct {
Exclude []string `json:"exclude"`
}
// Besides Namespaces only one of its members may be specified
// Besides Namespaces ThresholdPriority and ThresholdPriorityClassName only one of its members may be specified
type StrategyParameters struct {
NodeResourceUtilizationThresholds *NodeResourceUtilizationThresholds `json:"nodeResourceUtilizationThresholds,omitempty"`
NodeAffinityType []string `json:"nodeAffinityType,omitempty"`
@@ -59,6 +59,8 @@ type StrategyParameters struct {
MaxPodLifeTimeSeconds *uint `json:"maxPodLifeTimeSeconds,omitempty"`
RemoveDuplicates *RemoveDuplicates `json:"removeDuplicates,omitempty"`
Namespaces Namespaces `json:"namespaces"`
ThresholdPriority *int32 `json:"thresholdPriority"`
ThresholdPriorityClassName string `json:"thresholdPriorityClassName"`
}
type Percentage float64

View File

@@ -249,6 +249,8 @@ func autoConvert_v1alpha1_StrategyParameters_To_api_StrategyParameters(in *Strat
if err := Convert_v1alpha1_Namespaces_To_api_Namespaces(&in.Namespaces, &out.Namespaces, s); err != nil {
return err
}
out.ThresholdPriority = (*int32)(unsafe.Pointer(in.ThresholdPriority))
out.ThresholdPriorityClassName = in.ThresholdPriorityClassName
return nil
}
@@ -266,6 +268,8 @@ func autoConvert_api_StrategyParameters_To_v1alpha1_StrategyParameters(in *api.S
if err := Convert_api_Namespaces_To_v1alpha1_Namespaces(&in.Namespaces, &out.Namespaces, s); err != nil {
return err
}
out.ThresholdPriority = (*int32)(unsafe.Pointer(in.ThresholdPriority))
out.ThresholdPriorityClassName = in.ThresholdPriorityClassName
return nil
}

View File

@@ -243,6 +243,11 @@ func (in *StrategyParameters) DeepCopyInto(out *StrategyParameters) {
(*in).DeepCopyInto(*out)
}
in.Namespaces.DeepCopyInto(&out.Namespaces)
if in.ThresholdPriority != nil {
in, out := &in.ThresholdPriority, &out.ThresholdPriority
*out = new(int32)
**out = **in
}
return
}

View File

@@ -243,6 +243,11 @@ func (in *StrategyParameters) DeepCopyInto(out *StrategyParameters) {
(*in).DeepCopyInto(*out)
}
in.Namespaces.DeepCopyInto(&out.Namespaces)
if in.ThresholdPriority != nil {
in, out := &in.ThresholdPriority, &out.ThresholdPriority
*out = new(int32)
**out = **in
}
return
}

View File

@@ -78,12 +78,16 @@ func NewPodEvictor(
}
// IsEvictable checks if a pod is evictable or not.
func (pe *PodEvictor) IsEvictable(pod *v1.Pod) bool {
func (pe *PodEvictor) IsEvictable(pod *v1.Pod, thresholdPriority int32) bool {
checkErrs := []error{}
if IsCriticalPod(pod) {
checkErrs = append(checkErrs, fmt.Errorf("pod is critical"))
}
if !IsPodEvictableBasedOnPriority(pod, thresholdPriority) {
checkErrs = append(checkErrs, fmt.Errorf("pod is not evictable due to its priority"))
}
ownerRefList := podutil.OwnerRef(pod)
if IsDaemonsetPod(ownerRefList) {
checkErrs = append(checkErrs, fmt.Errorf("pod is a DaemonSet pod"))
@@ -216,3 +220,8 @@ func IsPodWithLocalStorage(pod *v1.Pod) bool {
return false
}
// IsPodEvictableBasedOnPriority checks if the given pod is evictable based on priority resolved from pod Spec.
func IsPodEvictableBasedOnPriority(pod *v1.Pod, priority int32) bool {
return pod.Spec.Priority == nil || (*pod.Spec.Priority < priority && *pod.Spec.Priority < utils.SystemCriticalPriority)
}

View File

@@ -71,10 +71,13 @@ func TestEvictPod(t *testing.T) {
func TestIsEvictable(t *testing.T) {
n1 := test.BuildTestNode("node1", 1000, 2000, 13, nil)
lowPriority := int32(800)
highPriority := int32(900)
type testCase struct {
pod *v1.Pod
runBefore func(*v1.Pod)
evictLocalStoragePods bool
priorityThreshold *int32
result bool
}
@@ -179,6 +182,7 @@ func TestIsEvictable(t *testing.T) {
}, {
pod: test.BuildTestPod("p10", 400, 0, n1.Name, nil),
runBefore: func(pod *v1.Pod) {
pod.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
pod.Annotations = test.GetMirrorPodAnnotation()
},
evictLocalStoragePods: false,
@@ -186,6 +190,7 @@ func TestIsEvictable(t *testing.T) {
}, {
pod: test.BuildTestPod("p11", 400, 0, n1.Name, nil),
runBefore: func(pod *v1.Pod) {
pod.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
pod.Annotations = test.GetMirrorPodAnnotation()
pod.Annotations["descheduler.alpha.kubernetes.io/evict"] = "true"
},
@@ -194,6 +199,7 @@ func TestIsEvictable(t *testing.T) {
}, {
pod: test.BuildTestPod("p12", 400, 0, n1.Name, nil),
runBefore: func(pod *v1.Pod) {
pod.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
priority := utils.SystemCriticalPriority
pod.Spec.Priority = &priority
},
@@ -202,6 +208,7 @@ func TestIsEvictable(t *testing.T) {
}, {
pod: test.BuildTestPod("p13", 400, 0, n1.Name, nil),
runBefore: func(pod *v1.Pod) {
pod.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
priority := utils.SystemCriticalPriority
pod.Spec.Priority = &priority
pod.Annotations = map[string]string{
@@ -210,6 +217,25 @@ func TestIsEvictable(t *testing.T) {
},
evictLocalStoragePods: false,
result: true,
}, {
pod: test.BuildTestPod("p14", 400, 0, n1.Name, nil),
runBefore: func(pod *v1.Pod) {
pod.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
pod.Spec.Priority = &highPriority
},
evictLocalStoragePods: false,
priorityThreshold: &lowPriority,
result: false,
}, {
pod: test.BuildTestPod("p15", 400, 0, n1.Name, nil),
runBefore: func(pod *v1.Pod) {
pod.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
pod.Annotations = map[string]string{"descheduler.alpha.kubernetes.io/evict": "true"}
pod.Spec.Priority = &highPriority
},
evictLocalStoragePods: false,
priorityThreshold: &lowPriority,
result: true,
},
}
@@ -218,7 +244,11 @@ func TestIsEvictable(t *testing.T) {
podEvictor := &PodEvictor{
evictLocalStoragePods: test.evictLocalStoragePods,
}
result := podEvictor.IsEvictable(test.pod)
testPriorityThreshold := utils.SystemCriticalPriority
if test.priorityThreshold != nil {
testPriorityThreshold = *test.priorityThreshold
}
result := podEvictor.IsEvictable(test.pod, testPriorityThreshold)
if result != test.result {
t.Errorf("IsEvictable should return for pod %s %t, but it returns %t", test.pod.Name, test.result, result)
}
@@ -233,10 +263,6 @@ func TestPodTypes(t *testing.T) {
p2 := test.BuildTestPod("p2", 400, 0, n1.Name, nil)
p3 := test.BuildTestPod("p3", 400, 0, n1.Name, nil)
p4 := test.BuildTestPod("p4", 400, 0, n1.Name, nil)
p5 := test.BuildTestPod("p5", 400, 0, n1.Name, nil)
p6 := test.BuildTestPod("p6", 400, 0, n1.Name, nil)
p6.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
p1.ObjectMeta.OwnerReferences = test.GetReplicaSetOwnerRefList()
// The following 4 pods won't get evicted.
@@ -257,18 +283,9 @@ func TestPodTypes(t *testing.T) {
}
// A Mirror Pod.
p4.Annotations = test.GetMirrorPodAnnotation()
// A Critical Pod.
p5.Namespace = "kube-system"
priority := utils.SystemCriticalPriority
p5.Spec.Priority = &priority
systemCriticalPriority := utils.SystemCriticalPriority
p5.Spec.Priority = &systemCriticalPriority
if !IsMirrorPod(p4) {
t.Errorf("Expected p4 to be a mirror pod.")
}
if !IsCriticalPod(p5) {
t.Errorf("Expected p5 to be a critical pod.")
}
if !IsPodWithLocalStorage(p3) {
t.Errorf("Expected p3 to be a pod with local storage.")
}

View File

@@ -18,6 +18,7 @@ package strategies
import (
"context"
"fmt"
"reflect"
"sort"
"strings"
@@ -31,8 +32,20 @@ import (
"sigs.k8s.io/descheduler/pkg/api"
"sigs.k8s.io/descheduler/pkg/descheduler/evictions"
podutil "sigs.k8s.io/descheduler/pkg/descheduler/pod"
"sigs.k8s.io/descheduler/pkg/utils"
)
func validateRemoveDuplicatePodsParams(params *api.StrategyParameters) error {
if params == nil {
return nil
}
if params.ThresholdPriority != nil && params.ThresholdPriorityClassName != "" {
return fmt.Errorf("only one of thresholdPriority and thresholdPriorityClassName can be set")
}
return nil
}
// RemoveDuplicatePods removes the duplicate pods on node. This strategy evicts all duplicate pods on node.
// A pod is said to be a duplicate of other if both of them are from same creator, kind and are within the same
// namespace, and have at least one container with the same image.
@@ -44,9 +57,21 @@ func RemoveDuplicatePods(
nodes []*v1.Node,
podEvictor *evictions.PodEvictor,
) {
if err := validateRemoveDuplicatePodsParams(strategy.Params); err != nil {
klog.V(1).Info(err)
return
}
thresholdPriority, err := utils.GetPriorityFromStrategyParams(ctx, client, strategy.Params)
if err != nil {
klog.V(1).Infof("failed to get threshold priority from strategy's params: %#v", err)
return
}
for _, node := range nodes {
klog.V(1).Infof("Processing node: %#v", node.Name)
pods, err := podutil.ListPodsOnANode(ctx, client, node, podutil.WithFilter(podEvictor.IsEvictable))
pods, err := podutil.ListPodsOnANode(ctx, client, node, podutil.WithFilter(func(pod *v1.Pod) bool {
return podEvictor.IsEvictable(pod, thresholdPriority)
}))
if err != nil {
klog.Errorf("error listing evictable pods on node %s: %+v", node.Name, err)
continue

View File

@@ -50,13 +50,28 @@ const (
MaxResourcePercentage = 100
)
func validateLowNodeUtilizationParams(params *api.StrategyParameters) error {
if params == nil || params.NodeResourceUtilizationThresholds == nil {
return fmt.Errorf("NodeResourceUtilizationThresholds not set")
}
if params.ThresholdPriority != nil && params.ThresholdPriorityClassName != "" {
return fmt.Errorf("only one of thresholdPriority and thresholdPriorityClassName can be set")
}
return nil
}
// LowNodeUtilization evicts pods from overutilized nodes to underutilized nodes. Note that CPU/Memory requests are used
// to calculate nodes' utilization and not the actual resource usage.
func LowNodeUtilization(ctx context.Context, client clientset.Interface, strategy api.DeschedulerStrategy, nodes []*v1.Node, podEvictor *evictions.PodEvictor) {
// todo: move to config validation?
// TODO: May be create a struct for the strategy as well, so that we don't have to pass along the all the params?
if strategy.Params == nil || strategy.Params.NodeResourceUtilizationThresholds == nil {
klog.V(1).Infof("NodeResourceUtilizationThresholds not set")
if err := validateLowNodeUtilizationParams(strategy.Params); err != nil {
klog.V(1).Info(err)
return
}
thresholdPriority, err := utils.GetPriorityFromStrategyParams(ctx, client, strategy.Params)
if err != nil {
klog.V(1).Infof("failed to get threshold priority from strategy's params: %#v", err)
return
}
@@ -116,7 +131,8 @@ func LowNodeUtilization(ctx context.Context, client clientset.Interface, strateg
targetNodes,
lowNodes,
targetThresholds,
podEvictor)
podEvictor,
thresholdPriority)
klog.V(1).Infof("Total number of pods evicted: %v", podEvictor.TotalEvicted())
}
@@ -196,6 +212,7 @@ func evictPodsFromTargetNodes(
targetNodes, lowNodes []NodeUsageMap,
targetThresholds api.ResourceThresholds,
podEvictor *evictions.PodEvictor,
thresholdPriority int32,
) {
sortNodesByUsage(targetNodes)
@@ -232,7 +249,7 @@ func evictPodsFromTargetNodes(
}
klog.V(3).Infof("evicting pods from node %#v with usage: %#v", node.node.Name, node.usage)
nonRemovablePods, removablePods := classifyPods(node.allPods, podEvictor)
nonRemovablePods, removablePods := classifyPods(node.allPods, podEvictor, thresholdPriority)
klog.V(2).Infof("allPods:%v, nonRemovablePods:%v, removablePods:%v", len(node.allPods), len(nonRemovablePods), len(removablePods))
if len(removablePods) == 0 {
@@ -393,11 +410,11 @@ func nodeUtilization(node *v1.Node, pods []*v1.Pod) api.ResourceThresholds {
}
}
func classifyPods(pods []*v1.Pod, evictor *evictions.PodEvictor) ([]*v1.Pod, []*v1.Pod) {
func classifyPods(pods []*v1.Pod, evictor *evictions.PodEvictor, thresholdPriority int32) ([]*v1.Pod, []*v1.Pod) {
var nonRemovablePods, removablePods []*v1.Pod
for _, pod := range pods {
if !evictor.IsEvictable(pod) {
if !evictor.IsEvictable(pod, thresholdPriority) {
nonRemovablePods = append(nonRemovablePods, pod)
} else {
removablePods = append(removablePods, pod)

View File

@@ -28,6 +28,7 @@ import (
"sigs.k8s.io/descheduler/pkg/descheduler/evictions"
nodeutil "sigs.k8s.io/descheduler/pkg/descheduler/node"
podutil "sigs.k8s.io/descheduler/pkg/descheduler/pod"
"sigs.k8s.io/descheduler/pkg/utils"
)
func validatePodsViolatingNodeAffinityParams(params *api.StrategyParameters) error {
@@ -38,6 +39,9 @@ func validatePodsViolatingNodeAffinityParams(params *api.StrategyParameters) err
if len(params.Namespaces.Include) > 0 && len(params.Namespaces.Exclude) > 0 {
return fmt.Errorf("only one of Include/Exclude namespaces can be set")
}
if params.ThresholdPriority != nil && params.ThresholdPriorityClassName != "" {
return fmt.Errorf("only one of thresholdPriority and thresholdPriorityClassName can be set")
}
return nil
}
@@ -48,6 +52,12 @@ func RemovePodsViolatingNodeAffinity(ctx context.Context, client clientset.Inter
klog.V(1).Info(err)
return
}
thresholdPriority, err := utils.GetPriorityFromStrategyParams(ctx, client, strategy.Params)
if err != nil {
klog.V(1).Infof("failed to get threshold priority from strategy's params: %#v", err)
return
}
for _, nodeAffinity := range strategy.Params.NodeAffinityType {
klog.V(2).Infof("Executing for nodeAffinityType: %v", nodeAffinity)
@@ -61,7 +71,7 @@ func RemovePodsViolatingNodeAffinity(ctx context.Context, client clientset.Inter
client,
node,
podutil.WithFilter(func(pod *v1.Pod) bool {
return podEvictor.IsEvictable(pod) &&
return podEvictor.IsEvictable(pod, thresholdPriority) &&
!nodeutil.PodFitsCurrentNode(pod, node) &&
nodeutil.PodFitsAnyNode(pod, nodes)
}),

View File

@@ -39,6 +39,9 @@ func validateRemovePodsViolatingNodeTaintsParams(params *api.StrategyParameters)
if len(params.Namespaces.Include) > 0 && len(params.Namespaces.Exclude) > 0 {
return fmt.Errorf("only one of Include/Exclude namespaces can be set")
}
if params.ThresholdPriority != nil && params.ThresholdPriorityClassName != "" {
return fmt.Errorf("only one of thresholdPriority and thresholdPriorityClassName can be set")
}
return nil
}
@@ -53,6 +56,11 @@ func RemovePodsViolatingNodeTaints(ctx context.Context, client clientset.Interfa
if strategy.Params != nil {
namespaces = strategy.Params.Namespaces
}
thresholdPriority, err := utils.GetPriorityFromStrategyParams(ctx, client, strategy.Params)
if err != nil {
klog.V(1).Infof("failed to get threshold priority from strategy's params: %#v", err)
return
}
for _, node := range nodes {
klog.V(1).Infof("Processing node: %#v\n", node.Name)
@@ -60,7 +68,9 @@ func RemovePodsViolatingNodeTaints(ctx context.Context, client clientset.Interfa
ctx,
client,
node,
podutil.WithFilter(podEvictor.IsEvictable),
podutil.WithFilter(func(pod *v1.Pod) bool {
return podEvictor.IsEvictable(pod, thresholdPriority)
}),
podutil.WithNamespaces(namespaces.Include),
podutil.WithoutNamespaces(namespaces.Exclude),
)

View File

@@ -40,6 +40,9 @@ func validateRemovePodsViolatingInterPodAntiAffinityParams(params *api.StrategyP
if len(params.Namespaces.Include) > 0 && len(params.Namespaces.Exclude) > 0 {
return fmt.Errorf("only one of Include/Exclude namespaces can be set")
}
if params.ThresholdPriority != nil && params.ThresholdPriorityClassName != "" {
return fmt.Errorf("only one of thresholdPriority and thresholdPriorityClassName can be set")
}
return nil
}
@@ -54,6 +57,11 @@ func RemovePodsViolatingInterPodAntiAffinity(ctx context.Context, client clients
if strategy.Params != nil {
namespaces = strategy.Params.Namespaces
}
thresholdPriority, err := utils.GetPriorityFromStrategyParams(ctx, client, strategy.Params)
if err != nil {
klog.V(1).Infof("failed to get threshold priority from strategy's params: %#v", err)
return
}
for _, node := range nodes {
klog.V(1).Infof("Processing node: %#v\n", node.Name)
@@ -61,7 +69,9 @@ func RemovePodsViolatingInterPodAntiAffinity(ctx context.Context, client clients
ctx,
client,
node,
podutil.WithFilter(podEvictor.IsEvictable),
podutil.WithFilter(func(pod *v1.Pod) bool {
return podEvictor.IsEvictable(pod, thresholdPriority)
}),
podutil.WithNamespaces(namespaces.Include),
podutil.WithoutNamespaces(namespaces.Exclude),
)

View File

@@ -28,6 +28,7 @@ import (
"sigs.k8s.io/descheduler/pkg/api"
"sigs.k8s.io/descheduler/pkg/descheduler/evictions"
podutil "sigs.k8s.io/descheduler/pkg/descheduler/pod"
"sigs.k8s.io/descheduler/pkg/utils"
)
func validatePodLifeTimeParams(params *api.StrategyParameters) error {
@@ -39,6 +40,9 @@ func validatePodLifeTimeParams(params *api.StrategyParameters) error {
if len(params.Namespaces.Include) > 0 && len(params.Namespaces.Exclude) > 0 {
return fmt.Errorf("only one of Include/Exclude namespaces can be set")
}
if params.ThresholdPriority != nil && params.ThresholdPriorityClassName != "" {
return fmt.Errorf("only one of thresholdPriority and thresholdPriorityClassName can be set")
}
return nil
}
@@ -49,11 +53,16 @@ func PodLifeTime(ctx context.Context, client clientset.Interface, strategy api.D
klog.V(1).Info(err)
return
}
thresholdPriority, err := utils.GetPriorityFromStrategyParams(ctx, client, strategy.Params)
if err != nil {
klog.V(1).Infof("failed to get threshold priority from strategy's params: %#v", err)
return
}
for _, node := range nodes {
klog.V(1).Infof("Processing node: %#v", node.Name)
pods := listOldPodsOnNode(ctx, client, node, strategy.Params, podEvictor)
pods := listOldPodsOnNode(ctx, client, node, strategy.Params, podEvictor, thresholdPriority)
for _, pod := range pods {
success, err := podEvictor.EvictPod(ctx, pod, node, "PodLifeTime")
if success {
@@ -69,12 +78,14 @@ func PodLifeTime(ctx context.Context, client clientset.Interface, strategy api.D
}
}
func listOldPodsOnNode(ctx context.Context, client clientset.Interface, node *v1.Node, params *api.StrategyParameters, evictor *evictions.PodEvictor) []*v1.Pod {
func listOldPodsOnNode(ctx context.Context, client clientset.Interface, node *v1.Node, params *api.StrategyParameters, podEvictor *evictions.PodEvictor, thresholdPriority int32) []*v1.Pod {
pods, err := podutil.ListPodsOnANode(
ctx,
client,
node,
podutil.WithFilter(evictor.IsEvictable),
podutil.WithFilter(func(pod *v1.Pod) bool {
return podEvictor.IsEvictable(pod, thresholdPriority)
}),
podutil.WithNamespaces(params.Namespaces.Include),
podutil.WithoutNamespaces(params.Namespaces.Exclude),
)

View File

@@ -27,6 +27,7 @@ import (
"sigs.k8s.io/descheduler/pkg/api"
"sigs.k8s.io/descheduler/pkg/descheduler/evictions"
podutil "sigs.k8s.io/descheduler/pkg/descheduler/pod"
"sigs.k8s.io/descheduler/pkg/utils"
)
func validateRemovePodsHavingTooManyRestartsParams(params *api.StrategyParameters) error {
@@ -38,6 +39,9 @@ func validateRemovePodsHavingTooManyRestartsParams(params *api.StrategyParameter
if len(params.Namespaces.Include) > 0 && len(params.Namespaces.Exclude) > 0 {
return fmt.Errorf("only one of Include/Exclude namespaces can be set")
}
if params.ThresholdPriority != nil && params.ThresholdPriorityClassName != "" {
return fmt.Errorf("only one of thresholdPriority and thresholdPriorityClassName can be set")
}
return nil
}
@@ -50,13 +54,21 @@ func RemovePodsHavingTooManyRestarts(ctx context.Context, client clientset.Inter
klog.V(1).Info(err)
return
}
thresholdPriority, err := utils.GetPriorityFromStrategyParams(ctx, client, strategy.Params)
if err != nil {
klog.V(1).Infof("failed to get threshold priority from strategy's params: %#v", err)
return
}
for _, node := range nodes {
klog.V(1).Infof("Processing node: %s", node.Name)
pods, err := podutil.ListPodsOnANode(
ctx,
client,
node,
podutil.WithFilter(podEvictor.IsEvictable),
podutil.WithFilter(func(pod *v1.Pod) bool {
return podEvictor.IsEvictable(pod, thresholdPriority)
}),
podutil.WithNamespaces(strategy.Params.Namespaces.Include),
podutil.WithoutNamespaces(strategy.Params.Namespaces.Exclude),
)

View File

@@ -104,7 +104,7 @@ func GetPodSource(pod *v1.Pod) (string, error) {
return "", fmt.Errorf("cannot get source of pod %q", pod.UID)
}
// IsCriticalPod returns true if pod's priority is greater than or equal to SystemCriticalPriority.
// IsCriticalPod returns true if the pod is a static or mirror pod.
func IsCriticalPod(pod *v1.Pod) bool {
if IsStaticPod(pod) {
return true
@@ -112,17 +112,9 @@ func IsCriticalPod(pod *v1.Pod) bool {
if IsMirrorPod(pod) {
return true
}
if pod.Spec.Priority != nil && IsCriticalPodBasedOnPriority(*pod.Spec.Priority) {
return true
}
return false
}
// IsCriticalPodBasedOnPriority checks if the given pod is a critical pod based on priority resolved from pod Spec.
func IsCriticalPodBasedOnPriority(priority int32) bool {
return priority >= SystemCriticalPriority
}
// PodRequestsAndLimits returns a dictionary of all defined resources summed up for all
// containers of the pod. If PodOverhead feature is enabled, pod overhead is added to the
// total container resource requests and to the total container limits which have a

View File

@@ -1,9 +1,15 @@
package utils
import (
"context"
"fmt"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/sets"
clientset "k8s.io/client-go/kubernetes"
"sigs.k8s.io/descheduler/pkg/api"
)
const SystemCriticalPriority = 2 * int32(1000000000)
@@ -33,3 +39,36 @@ func PodMatchesTermsNamespaceAndSelector(pod *v1.Pod, namespaces sets.String, se
}
return true
}
// GetPriorityFromPriorityClass gets priority from the given priority class.
// If no priority class is provided, it will return SystemCriticalPriority by default.
func GetPriorityFromPriorityClass(ctx context.Context, client clientset.Interface, name string) (int32, error) {
if name != "" {
priorityClass, err := client.SchedulingV1().PriorityClasses().Get(ctx, name, metav1.GetOptions{})
if err != nil {
return 0, err
}
return priorityClass.Value, nil
}
return SystemCriticalPriority, nil
}
// GetPriorityFromStrategyParams gets priority from the given StrategyParameters.
// It will return SystemCriticalPriority by default.
func GetPriorityFromStrategyParams(ctx context.Context, client clientset.Interface, params *api.StrategyParameters) (priority int32, err error) {
if params == nil {
return SystemCriticalPriority, nil
}
if params.ThresholdPriority != nil {
priority = *params.ThresholdPriority
} else {
priority, err = GetPriorityFromPriorityClass(ctx, client, params.ThresholdPriorityClassName)
if err != nil {
return
}
}
if priority > SystemCriticalPriority {
return 0, fmt.Errorf("Priority threshold can't be greater than %d", SystemCriticalPriority)
}
return
}