Skip to content

Commit

Permalink
Added Propagation of ManagedNodeGroup Tags to their AutoScalingGroups
Browse files Browse the repository at this point in the history
Changes	to ensure that AutoScalingGroups Tags are the same as their
 ManagedNodeGroup.

All tags are copied from the ManagedNodeGroup to the AutoScalingGroup.
If the tags already exists, it is overridden.

This is the default behaviour (as it is for Unmanaged NodeGroup) and
can be disabled using DisableASGTagPropagation boolean in the
configuration.

Issue eksctl-io#1571
  • Loading branch information
SlevinWasAlreadyTaken committed Mar 24, 2022
1 parent 82a94f8 commit 721d02f
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 10 deletions.
14 changes: 11 additions & 3 deletions pkg/apis/eksctl.io/v1alpha5/assets/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,12 @@
"desiredCapacity": {
"type": "integer"
},
"disableASGTagPropagation": {
"type": "boolean",
"description": "disables the tag propagation to ASG.",
"x-intellij-html-description": "disables the tag propagation to ASG.",
"default": false
},
"disableIMDSv1": {
"type": "boolean",
"description": "requires requests to the metadata service to use IMDSv2 tokens",
Expand Down Expand Up @@ -1191,6 +1197,7 @@
"additionalVolumes",
"preBootstrapCommands",
"overrideBootstrapCommand",
"disableASGTagPropagation",
"disableIMDSv1",
"disablePodIMDS",
"placement",
Expand Down Expand Up @@ -1321,8 +1328,9 @@
},
"disableASGTagPropagation": {
"type": "boolean",
"description": "disable the tag propagation in case desired capacity is 0.",
"x-intellij-html-description": "disable the tag propagation in case desired capacity is 0."
"description": "disables the tag propagation to ASG in case desired capacity is 0.",
"x-intellij-html-description": "disables the tag propagation to ASG in case desired capacity is 0.",
"default": false
},
"disableIMDSv1": {
"type": "boolean",
Expand Down Expand Up @@ -1533,6 +1541,7 @@
"additionalVolumes",
"preBootstrapCommands",
"overrideBootstrapCommand",
"disableASGTagPropagation",
"disableIMDSv1",
"disablePodIMDS",
"placement",
Expand All @@ -1550,7 +1559,6 @@
"clusterDNS",
"kubeletExtraConfig",
"containerRuntime",
"disableASGTagPropagation",
"maxInstanceLifetime"
],
"additionalProperties": false,
Expand Down
9 changes: 5 additions & 4 deletions pkg/apis/eksctl.io/v1alpha5/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -992,10 +992,6 @@ type NodeGroup struct {
// +optional
ContainerRuntime *string `json:"containerRuntime,omitempty"`

// DisableASGTagPropagation disable the tag propagation in case desired capacity is 0.
// +optional
DisableASGTagPropagation *bool `json:"disableASGTagPropagation,omitempty"`

// MaxInstanceLifetime defines the maximum amount of time in seconds an instance stays alive.
// +optional
MaxInstanceLifetime *int `json:"maxInstanceLifetime,omitempty"`
Expand Down Expand Up @@ -1359,6 +1355,11 @@ type NodeGroupBase struct {
// +optional
OverrideBootstrapCommand *string `json:"overrideBootstrapCommand,omitempty"`

// DisableASGTagPropagation disables the tag propagation to ASG in case desired capacity is 0.
// Defaults to `false`
// +optional
DisableASGTagPropagation *bool `json:"disableASGTagPropagation,omitempty"`

// DisableIMDSv1 requires requests to the metadata service to use IMDSv2 tokens
// Defaults to `false`
// +optional
Expand Down
10 changes: 9 additions & 1 deletion pkg/cfn/manager/create_tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func (c *StackCollection) NewUnmanagedNodeGroupTask(nodeGroups []*api.NodeGroup,

// NewManagedNodeGroupTask defines tasks required to create managed nodegroups
func (c *StackCollection) NewManagedNodeGroupTask(nodeGroups []*api.ManagedNodeGroup, forceAddCNIPolicy bool, vpcImporter vpc.Importer) *tasks.TaskTree {
taskTree := &tasks.TaskTree{Parallel: true}
taskTree := &tasks.TaskTree{Parallel: false}
for _, ng := range nodeGroups {
taskTree.Append(&managedNodeGroupTask{
stackCollection: c,
Expand All @@ -101,6 +101,14 @@ func (c *StackCollection) NewManagedNodeGroupTask(nodeGroups []*api.ManagedNodeG
vpcImporter: vpcImporter,
info: fmt.Sprintf("create managed nodegroup %q", ng.Name),
})
if ng.DisableASGTagPropagation != nil && *ng.DisableASGTagPropagation {
continue
}
taskTree.Append(&managedNodeGroupTagsToASGPropagationTask{
stackCollection: c,
nodeGroup: ng,
info: fmt.Sprintf("propagate tags to ASG for managed nodegroup %q", ng.Name),
})
}
return taskTree
}
Expand Down
43 changes: 43 additions & 0 deletions pkg/cfn/manager/nodegroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,49 @@ func (c *StackCollection) createManagedNodeGroupTask(errorCh chan error, ng *api
return c.CreateStack(name, stack, ng.Tags, nil, errorCh)
}

func (c *StackCollection) propagateManagedNodeGroupTagsToASGTask(errorCh chan error, ng *api.ManagedNodeGroup) error {
if ng.DisableASGTagPropagation != nil && *ng.DisableASGTagPropagation {
return nil
}

// describe node group to retrieve ASG names
input := &eks.DescribeNodegroupInput{
ClusterName: aws.String(c.spec.Metadata.Name),
NodegroupName: aws.String(ng.Name),
}
res, err := c.eksAPI.DescribeNodegroup(input)
if err != nil {
return errors.Wrapf(err, "couldn't get managed nodegroup details for nodegroup %q", ng.Name)
}

// set the managed nodegroup tags to all the ASGs found
if res.Nodegroup.Resources != nil {
// build the input tags for all ASGs attached to the managed nodegroup
asgTags := []*autoscaling.Tag{}

for _, asg := range res.Nodegroup.Resources.AutoScalingGroups {
for ngTagKey, ngTagValue := range ng.Tags {
asgTag := &autoscaling.Tag{
ResourceId: aws.String(*asg.Name),
ResourceType: aws.String("auto-scaling-group"),
Key: aws.String(ngTagKey),
Value: aws.String(ngTagValue),
PropagateAtLaunch: aws.Bool(false),
}
asgTags = append(asgTags, asgTag)
}
}

input := &autoscaling.CreateOrUpdateTagsInput{Tags: asgTags}
if _, err := c.asgAPI.CreateOrUpdateTags(input); err != nil {
return errors.Wrapf(err, "creating or updating asg tags for managed nodegroup %q", ng.Name)
}
}

go func() { errorCh <- nil }()
return nil
}

// DescribeNodeGroupStacks calls DescribeStacks and filters out nodegroups
func (c *StackCollection) DescribeNodeGroupStacks() ([]*Stack, error) {
stacks, err := c.DescribeStacks()
Expand Down
12 changes: 12 additions & 0 deletions pkg/cfn/manager/tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ func (t *managedNodeGroupTask) Do(errorCh chan error) error {
return t.stackCollection.createManagedNodeGroupTask(errorCh, t.nodeGroup, t.forceAddCNIPolicy, t.vpcImporter)
}

type managedNodeGroupTagsToASGPropagationTask struct {
info string
nodeGroup *api.ManagedNodeGroup
stackCollection *StackCollection
}

func (t *managedNodeGroupTagsToASGPropagationTask) Describe() string { return t.info }

func (t *managedNodeGroupTagsToASGPropagationTask) Do(errorCh chan error) error {
return t.stackCollection.propagateManagedNodeGroupTagsToASGTask(errorCh, t.nodeGroup)
}

type clusterCompatTask struct {
info string
stackCollection *StackCollection
Expand Down
4 changes: 2 additions & 2 deletions userdocs/src/usage/autoscaling.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ nodeGroups:
k8s.io/cluster-autoscaler/node-template/taint/feaster: "true:NoSchedule"
```
For unmanaged noderoups, this is done by `eksctl` automatically if `desiredCapacity` is set to `0`, there is no need to
specify these by hand. This feature is not supported for managed nodegroups. However, if the number of tags added like
For unmanaged and managed nodegroups, this is done by `eksctl` automatically if `desiredCapacity` is set to `0`, there is no need to
However, if the number of tags added like
this exceeds the current ASG tag limit ( 50 at the time of this writing ) or, this feature is not desired, there is a
setting to disable it. Set `disableASGTagPropagation` to `true` like this:

Expand Down

0 comments on commit 721d02f

Please sign in to comment.