Skip to content

Commit

Permalink
Log drainability override
Browse files Browse the repository at this point in the history
  • Loading branch information
artemvmin committed Oct 18, 2023
1 parent 87013c2 commit a0d56b3
Show file tree
Hide file tree
Showing 14 changed files with 85 additions and 5 deletions.
12 changes: 12 additions & 0 deletions cluster-autoscaler/simulator/drain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -790,18 +790,30 @@ func TestGetPodsToMove(t *testing.T) {

type alwaysDrain struct{}

func (a alwaysDrain) Name() string {
return "AlwaysDrain"
}

func (a alwaysDrain) Drainable(*drainability.DrainContext, *apiv1.Pod) drainability.Status {
return drainability.NewDrainableStatus()
}

type neverDrain struct{}

func (n neverDrain) Name() string {
return "NeverDrain"
}

func (n neverDrain) Drainable(*drainability.DrainContext, *apiv1.Pod) drainability.Status {
return drainability.NewBlockedStatus(drain.UnexpectedError, fmt.Errorf("nope"))
}

type cantDecide struct{}

func (c cantDecide) Name() string {
return "CantDecide"
}

func (c cantDecide) Drainable(*drainability.DrainContext, *apiv1.Pod) drainability.Status {
return drainability.NewUndefinedStatus()
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ func New() *Rule {
return &Rule{}
}

// Name returns the name of the rule.
func (r *Rule) Name() string {
return "DaemonSet"
}

// Drainable decides what to do with daemon set pods on node drain.
func (r *Rule) Drainable(drainCtx *drainability.DrainContext, pod *apiv1.Pod) drainability.Status {
if pod_util.IsDaemonSetPod(pod) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ func New() *Rule {
return &Rule{}
}

// Name returns the name of the rule.
func (r *Rule) Name() string {
return "LocalStorage"
}

// Drainable decides what to do with local storage pods on node drain.
func (r *Rule) Drainable(drainCtx *drainability.DrainContext, pod *apiv1.Pod) drainability.Status {
if drain.HasBlockingLocalStorage(pod) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ func New() *Rule {
return &Rule{}
}

// Name returns the name of the rule.
func (r *Rule) Name() string {
return "LongTerminating"
}

// Drainable decides what to do with long terminating pods on node drain.
func (r *Rule) Drainable(drainCtx *drainability.DrainContext, pod *apiv1.Pod) drainability.Status {
if drain.IsPodLongTerminating(pod, drainCtx.Timestamp) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ func New() *Rule {
return &Rule{}
}

// Name returns the name of the rule.
func (r *Rule) Name() string {
return "Mirror"
}

// Drainable decides what to do with mirror pods on node drain.
func (Rule) Drainable(drainCtx *drainability.DrainContext, pod *apiv1.Pod) drainability.Status {
if pod_util.IsMirrorPod(pod) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ func New() *Rule {
return &Rule{}
}

// Name returns the name of the rule.
func (r *Rule) Name() string {
return "NotSafeToEvict"
}

// Drainable decides what to do with not safe to evict pods on node drain.
func (Rule) Drainable(drainCtx *drainability.DrainContext, pod *apiv1.Pod) drainability.Status {
if drain.HasNotSafeToEvictAnnotation(pod) {
Expand Down
5 changes: 5 additions & 0 deletions cluster-autoscaler/simulator/drainability/rules/pdb/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ func New() *Rule {
return &Rule{}
}

// Name returns the name of the rule.
func (r *Rule) Name() string {
return "PDB"
}

// Drainable decides how to handle pods with pdbs on node drain.
func (Rule) Drainable(drainCtx *drainability.DrainContext, pod *apiv1.Pod) drainability.Status {
for _, pdb := range drainCtx.RemainingPdbTracker.MatchingPdbs(pod) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ func New(minReplicaCount int) *Rule {
}
}

// Name returns the name of the rule.
func (r *Rule) Name() string {
return "ReplicaCount"
}

// Drainable decides what to do with replicated pods on node drain.
func (r *Rule) Drainable(drainCtx *drainability.DrainContext, pod *apiv1.Pod) drainability.Status {
if drainCtx.Listers == nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ func New(skipNodesWithCustomControllerPods bool) *Rule {
}
}

// Name returns the name of the rule.
func (r *Rule) Name() string {
return "Replicated"
}

// Drainable decides what to do with replicated pods on node drain.
func (r *Rule) Drainable(drainCtx *drainability.DrainContext, pod *apiv1.Pod) drainability.Status {
controllerRef := drain.ControllerRef(pod)
Expand Down
17 changes: 13 additions & 4 deletions cluster-autoscaler/simulator/drainability/rules/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ import (
"k8s.io/autoscaler/cluster-autoscaler/simulator/drainability/rules/system"
"k8s.io/autoscaler/cluster-autoscaler/simulator/drainability/rules/terminal"
"k8s.io/autoscaler/cluster-autoscaler/simulator/options"
"k8s.io/klog/v2"
)

// Rule determines whether a given pod can be drained or not.
type Rule interface {
// The name of the rule.
Name() string
// Drainable determines whether a given pod is drainable according to
// the specific Rule.
//
Expand Down Expand Up @@ -86,18 +89,19 @@ func (rs Rules) Drainable(drainCtx *drainability.DrainContext, pod *apiv1.Pod) d
drainCtx.RemainingPdbTracker = pdb.NewBasicRemainingPdbTracker()
}

var candidates []drainability.Status
var candidates []overrideCandidate

for _, r := range rs {
status := r.Drainable(drainCtx, pod)
if len(status.Overrides) > 0 {
candidates = append(candidates, status)
candidates = append(candidates, overrideCandidate{r.Name(), status})
continue
}
for _, candidate := range candidates {
for _, override := range candidate.Overrides {
for _, override := range candidate.status.Overrides {
if status.Outcome == override {
return candidate
klog.V(5).Info("Overriding pod %s/%s drainability rule %s with rule %s, outcome %v", pod.GetNamespace(), pod.GetName(), r.Name(), candidate.name, candidate.status.Outcome)
return candidate.status
}
}
}
Expand All @@ -107,3 +111,8 @@ func (rs Rules) Drainable(drainCtx *drainability.DrainContext, pod *apiv1.Pod) d
}
return drainability.NewUndefinedStatus()
}

type overrideCandidate struct {
name string
status drainability.Status
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func TestDrainable(t *testing.T) {
},
} {
t.Run(desc, func(t *testing.T) {
got := tc.rules.Drainable(nil, nil)
got := tc.rules.Drainable(nil, &apiv1.Pod{})
if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("Drainable(): got status diff (-want +got):\n%s", diff)
}
Expand All @@ -123,6 +123,10 @@ type fakeRule struct {
status drainability.Status
}

func (r fakeRule) Name() string {
return "FakeRule"
}

func (r fakeRule) Drainable(*drainability.DrainContext, *apiv1.Pod) drainability.Status {
return r.status
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ func New() *Rule {
return &Rule{}
}

// Name returns the name of the rule.
func (r *Rule) Name() string {
return "SafeToEvict"
}

// Drainable decides what to do with safe to evict pods on node drain.
func (r *Rule) Drainable(drainCtx *drainability.DrainContext, pod *apiv1.Pod) drainability.Status {
if drain.HasSafeToEvictAnnotation(pod) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ func New() *Rule {
return &Rule{}
}

// Name returns the name of the rule.
func (r *Rule) Name() string {
return "System"
}

// Drainable decides what to do with system pods on node drain.
func (r *Rule) Drainable(drainCtx *drainability.DrainContext, pod *apiv1.Pod) drainability.Status {
if pod.Namespace == "kube-system" && len(drainCtx.RemainingPdbTracker.MatchingPdbs(pod)) == 0 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ func New() *Rule {
return &Rule{}
}

// Name returns the name of the rule.
func (r *Rule) Name() string {
return "Terminal"
}

// Drainable decides what to do with terminal pods on node drain.
func (r *Rule) Drainable(drainCtx *drainability.DrainContext, pod *apiv1.Pod) drainability.Status {
if drain.IsPodTerminal(pod) {
Expand Down

0 comments on commit a0d56b3

Please sign in to comment.