From 081c4664d302286e90019762966b3289c2f28e69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20K=C5=82obuszewski?= Date: Thu, 24 Jun 2021 16:49:14 +0200 Subject: [PATCH] Add a flag to control DaemonSet eviction on non-empty nodes --- cluster-autoscaler/config/autoscaling_options.go | 2 ++ cluster-autoscaler/core/scale_down.go | 9 +++++++++ cluster-autoscaler/main.go | 2 ++ 3 files changed, 13 insertions(+) diff --git a/cluster-autoscaler/config/autoscaling_options.go b/cluster-autoscaler/config/autoscaling_options.go index 0071bfada451..4dcd95245f59 100644 --- a/cluster-autoscaler/config/autoscaling_options.go +++ b/cluster-autoscaler/config/autoscaling_options.go @@ -161,6 +161,8 @@ type AutoscalingOptions struct { CordonNodeBeforeTerminate bool // DaemonSetEvictionForEmptyNodes is whether CA will gracefully terminate DaemonSet pods from empty nodes. DaemonSetEvictionForEmptyNodes bool + // DaemonSetEvictionForOccupiedNodes is whether CA will gracefully terminate DaemonSet pods from non-empty nodes. + DaemonSetEvictionForOccupiedNodes bool // User agent to use for HTTP calls. UserAgent string } diff --git a/cluster-autoscaler/core/scale_down.go b/cluster-autoscaler/core/scale_down.go index ea543f0a833b..2f804a7d6c83 100644 --- a/cluster-autoscaler/core/scale_down.go +++ b/cluster-autoscaler/core/scale_down.go @@ -1226,6 +1226,8 @@ func (sd *ScaleDown) deleteNode(node *apiv1.Node, pods []*apiv1.Pod, daemonSetPo sd.context.Recorder.Eventf(node, apiv1.EventTypeNormal, "ScaleDown", "marked the node as toBeDeleted/unschedulable") + daemonSetPods = podsToEvict(daemonSetPods, sd.context.DaemonSetEvictionForOccupiedNodes) + // attempt drain evictionResults, err := drainNode(node, pods, daemonSetPods, sd.context.ClientSet, sd.context.Recorder, sd.context.MaxGracefulTerminationSec, MaxPodEvictionTime, EvictionRetryTime, PodEvictionHeadroom) if err != nil { @@ -1247,6 +1249,13 @@ func (sd *ScaleDown) deleteNode(node *apiv1.Node, pods []*apiv1.Pod, daemonSetPo return status.NodeDeleteResult{ResultType: status.NodeDeleteOk} } +func podsToEvict(pods []*apiv1.Pod, shouldEvict bool) []*apiv1.Pod { + if shouldEvict { + return pods + } + return []*apiv1.Pod{} +} + func evictPod(podToEvict *apiv1.Pod, isDaemonSetPod bool, client kube_client.Interface, recorder kube_record.EventRecorder, maxGracefulTerminationSec int, retryUntil time.Time, waitBetweenRetries time.Duration) status.PodEvictionResult { recorder.Eventf(podToEvict, apiv1.EventTypeNormal, "ScaleDown", "deleting pod for node scale down") diff --git a/cluster-autoscaler/main.go b/cluster-autoscaler/main.go index c7c18d22b12b..37459a175bf1 100644 --- a/cluster-autoscaler/main.go +++ b/cluster-autoscaler/main.go @@ -178,6 +178,7 @@ var ( clusterAPICloudConfigAuthoritative = flag.Bool("clusterapi-cloud-config-authoritative", false, "Treat the cloud-config flag authoritatively (do not fallback to using kubeconfig flag). ClusterAPI only") cordonNodeBeforeTerminate = flag.Bool("cordon-node-before-terminating", false, "Should CA cordon nodes before terminating during downscale process") daemonSetEvictionForEmptyNodes = flag.Bool("daemonset-eviction-for-empty-nodes", false, "DaemonSet pods will be gracefully terminated from empty nodes") + daemonSetEvictionForOccupiedNodes = flag.Bool("daemonset-eviction-for-occupied-nodes", true, "DaemonSet pods will be gracefully terminated from non-empty nodes") userAgent = flag.String("user-agent", "cluster-autoscaler", "User agent used for HTTP calls.") ) @@ -254,6 +255,7 @@ func createAutoscalingOptions() config.AutoscalingOptions { ClusterAPICloudConfigAuthoritative: *clusterAPICloudConfigAuthoritative, CordonNodeBeforeTerminate: *cordonNodeBeforeTerminate, DaemonSetEvictionForEmptyNodes: *daemonSetEvictionForEmptyNodes, + DaemonSetEvictionForOccupiedNodes: *daemonSetEvictionForOccupiedNodes, UserAgent: *userAgent, } }