Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Therefore, this application will not run into any issues if it is restarted, res
| METRICS | Expose metrics in Prometheus format at `:${METRICS_PORT}/metrics` | no | `""` |
| SLOW_MODE | If enabled, every time a node is terminated during an execution, the current execution will stop rather than continuing to the next ASG | no | `false` |
| EAGER_CORDONING | If enabled, all outdated nodes will get cordoned before any rolling update action. The default mode is to cordon a node just before draining it. See [#41](https://github.com/TwiN/aws-eks-asg-rolling-update-handler/issues/41) for possible consequences of enabling this. | no | `false` |
| EXCLUDE_FROM_EXTERNAL_LOAD_BALANCERS | If enabled, node label `node.kubernetes.io/exclude-from-external-load-balancers=true` will be added to nodes before draining. See [#131](https://github.com/TwiN/aws-eks-asg-rolling-update-handler/pull/131) for more information | no | `false` |

**NOTE:** Only one of `CLUSTER_NAME`, `AUTODISCOVERY_TAGS` or `AUTO_SCALING_GROUP_NAMES` must be set.

Expand Down
71 changes: 37 additions & 34 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,48 +12,51 @@ import (
var cfg *config

const (
EnvEnvironment = "ENVIRONMENT"
EnvDebug = "DEBUG"
EnvIgnoreDaemonSets = "IGNORE_DAEMON_SETS"
EnvDeleteLocalData = "DELETE_LOCAL_DATA" // Deprecated: in favor of DeleteEmptyDirData (DELETE_EMPTY_DIR_DATA)
EnvDeleteEmptyDirData = "DELETE_EMPTY_DIR_DATA"
EnvClusterName = "CLUSTER_NAME"
EnvAutodiscoveryTags = "AUTODISCOVERY_TAGS"
EnvAutoScalingGroupNames = "AUTO_SCALING_GROUP_NAMES"
EnvAwsRegion = "AWS_REGION"
EnvExecutionInterval = "EXECUTION_INTERVAL"
EnvExecutionTimeout = "EXECUTION_TIMEOUT"
EnvPodTerminationGracePeriod = "POD_TERMINATION_GRACE_PERIOD"
EnvMetrics = "METRICS"
EnvMetricsPort = "METRICS_PORT"
EnvSlowMode = "SLOW_MODE"
EnvEagerCordoning = "EAGER_CORDONING"
EnvEnvironment = "ENVIRONMENT"
EnvDebug = "DEBUG"
EnvIgnoreDaemonSets = "IGNORE_DAEMON_SETS"
EnvDeleteLocalData = "DELETE_LOCAL_DATA" // Deprecated: in favor of DeleteEmptyDirData (DELETE_EMPTY_DIR_DATA)
EnvDeleteEmptyDirData = "DELETE_EMPTY_DIR_DATA"
EnvClusterName = "CLUSTER_NAME"
EnvAutodiscoveryTags = "AUTODISCOVERY_TAGS"
EnvAutoScalingGroupNames = "AUTO_SCALING_GROUP_NAMES"
EnvAwsRegion = "AWS_REGION"
EnvExecutionInterval = "EXECUTION_INTERVAL"
EnvExecutionTimeout = "EXECUTION_TIMEOUT"
EnvPodTerminationGracePeriod = "POD_TERMINATION_GRACE_PERIOD"
EnvMetrics = "METRICS"
EnvMetricsPort = "METRICS_PORT"
EnvSlowMode = "SLOW_MODE"
EnvEagerCordoning = "EAGER_CORDONING"
EnvExcludeFromExternalLoadBalancers = "EXLUDE_FROM_EXTERNAL_LOAD_BALANCERS"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just noticed you made a typo in the environment variable 😂

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved by 3b8647b

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh damn it :D thanks for fixing this!

)

type config struct {
Environment string // Optional
Debug bool // Defaults to false
AutoScalingGroupNames []string // Required if AutodiscoveryTags not provided
AutodiscoveryTags string // Required if AutoScalingGroupNames not provided
AwsRegion string // Defaults to us-west-2
IgnoreDaemonSets bool // Defaults to true
DeleteEmptyDirData bool // Defaults to true
ExecutionInterval time.Duration // Defaults to 20s
ExecutionTimeout time.Duration // Defaults to 900s
PodTerminationGracePeriod int // Defaults to -1
Metrics bool // Defaults to false
MetricsPort int // Defaults to 8080
SlowMode bool // Defaults to false
EagerCordoning bool // Defaults to false
Environment string // Optional
Debug bool // Defaults to false
AutoScalingGroupNames []string // Required if AutodiscoveryTags not provided
AutodiscoveryTags string // Required if AutoScalingGroupNames not provided
AwsRegion string // Defaults to us-west-2
IgnoreDaemonSets bool // Defaults to true
DeleteEmptyDirData bool // Defaults to true
ExecutionInterval time.Duration // Defaults to 20s
ExecutionTimeout time.Duration // Defaults to 900s
PodTerminationGracePeriod int // Defaults to -1
Metrics bool // Defaults to false
MetricsPort int // Defaults to 8080
SlowMode bool // Defaults to false
EagerCordoning bool // Defaults to false
ExcludeFromExternalLoadBalancers bool // defaults to false
}

// Initialize is used to initialize the application's configuration
func Initialize() error {
cfg = &config{
Environment: strings.ToLower(os.Getenv(EnvEnvironment)),
Debug: strings.ToLower(os.Getenv(EnvDebug)) == "true",
SlowMode: strings.ToLower(os.Getenv(EnvSlowMode)) == "true",
EagerCordoning: strings.ToLower(os.Getenv(EnvEagerCordoning)) == "true",
Environment: strings.ToLower(os.Getenv(EnvEnvironment)),
Debug: strings.ToLower(os.Getenv(EnvDebug)) == "true",
SlowMode: strings.ToLower(os.Getenv(EnvSlowMode)) == "true",
EagerCordoning: strings.ToLower(os.Getenv(EnvEagerCordoning)) == "true",
ExcludeFromExternalLoadBalancers: strings.ToLower(os.Getenv(EnvExcludeFromExternalLoadBalancers)) == "true",
}
if clusterName := os.Getenv(EnvClusterName); len(clusterName) > 0 {
// See "Prerequisites" in https://docs.aws.amazon.com/eks/latest/userguide/autoscaling.html
Expand Down
20 changes: 19 additions & 1 deletion k8s/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"log"

"github.com/aws/aws-sdk-go/service/autoscaling"
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
)

// CheckIfNodeHasEnoughResourcesToTransferAllPodsInNodes calculates the resources available in the target nodes
Expand Down Expand Up @@ -103,3 +103,21 @@ func AnnotateNodeByAutoScalingInstance(client ClientAPI, instance *autoscaling.I
}
return nil
}

// Label Node adds an Label to the Kubernetes node represented by a given AWS instance
func LabelNodeByAutoScalingInstance(client ClientAPI, instance *autoscaling.Instance, key, value string) error {
node, err := client.GetNodeByAutoScalingInstance(instance)
if err != nil {
return err
}
labels := node.GetLabels()
if currentValue := labels[key]; currentValue != value {
labels[key] = value
node.SetLabels(labels)
err = client.UpdateNode(node)
if err != nil {
return err
}
}
return nil
}
4 changes: 4 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ func DoHandleRollingUpgrade(client k8s.ClientAPI, ec2Service ec2iface.EC2API, au
if hasEnoughResources {
log.Printf("[%s][%s] Updated nodes have enough resources available", aws.StringValue(autoScalingGroup.AutoScalingGroupName), aws.StringValue(outdatedInstance.InstanceId))
if minutesSinceDrained == -1 {
if config.Get().ExcludeFromExternalLoadBalancers {
log.Printf("[%s][%s] Label node to exlude from external load balancers", aws.StringValue(autoScalingGroup.AutoScalingGroupName), aws.StringValue(outdatedInstance.InstanceId))
k8s.LabelNodeByAutoScalingInstance(client, outdatedInstance, "node.kubernetes.io/exclude-from-external-load-balancers", "true")
}
log.Printf("[%s][%s] Draining node", aws.StringValue(autoScalingGroup.AutoScalingGroupName), aws.StringValue(outdatedInstance.InstanceId))
err := client.Drain(node.Name, config.Get().IgnoreDaemonSets, config.Get().DeleteEmptyDirData, config.Get().PodTerminationGracePeriod)
if err != nil {
Expand Down