Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply taints using taint block in aws_eks_node_group resource #78

Closed
Show file tree
Hide file tree
Changes from all 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
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ Available targets:
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13.3 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.43 |
| <a name="requirement_local"></a> [local](#requirement\_local) | >= 1.3 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 2.0 |
| <a name="requirement_template"></a> [template](#requirement\_template) | >= 2.0 |
Expand All @@ -218,7 +218,7 @@ Available targets:

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.0 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.43 |
| <a name="provider_random"></a> [random](#provider\_random) | >= 2.0 |

## Modules
Expand Down Expand Up @@ -284,7 +284,7 @@ Available targets:
| <a name="input_instance_types"></a> [instance\_types](#input\_instance\_types) | Instance types to use for this node group (up to 20). Defaults to ["t3.medium"].<br>Ignored when `launch_template_id` is supplied. | `list(string)` | <pre>[<br> "t3.medium"<br>]</pre> | no |
| <a name="input_kubelet_additional_options"></a> [kubelet\_additional\_options](#input\_kubelet\_additional\_options) | Additional flags to pass to kubelet.<br>DO NOT include `--node-labels` or `--node-taints`,<br>use `kubernetes_labels` and `kubernetes_taints` to specify those." | `string` | `""` | no |
| <a name="input_kubernetes_labels"></a> [kubernetes\_labels](#input\_kubernetes\_labels) | Key-value mapping of Kubernetes labels. Only labels that are applied with the EKS API are managed by this argument.<br>Other Kubernetes labels applied to the EKS Node Group will not be managed. | `map(string)` | `{}` | no |
| <a name="input_kubernetes_taints"></a> [kubernetes\_taints](#input\_kubernetes\_taints) | Key-value mapping of Kubernetes taints. | `map(string)` | `{}` | no |
| <a name="input_kubernetes_taints"></a> [kubernetes\_taints](#input\_kubernetes\_taints) | Key-value mapping of Kubernetes taints in the form of `<key>=<value>:<effect>`. | `map(string)` | `{}` | no |
| <a name="input_kubernetes_version"></a> [kubernetes\_version](#input\_kubernetes\_version) | Kubernetes version. Defaults to EKS Cluster Kubernetes version. Terraform will only perform drift detection if a configuration value is provided | `string` | `null` | no |
| <a name="input_label_key_case"></a> [label\_key\_case](#input\_label\_key\_case) | The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`.<br>Possible values: `lower`, `title`, `upper`.<br>Default value: `title`. | `string` | `null` | no |
| <a name="input_label_order"></a> [label\_order](#input\_label\_order) | The naming order of the id output and Name tag.<br>Defaults to ["namespace", "environment", "stage", "name", "attributes"].<br>You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no |
Expand Down Expand Up @@ -313,7 +313,7 @@ Available targets:
| <a name="input_subnet_ids"></a> [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs to launch resources in | `list(string)` | n/a | yes |
| <a name="input_tags"></a> [tags](#input\_tags) | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no |
| <a name="input_update_timeout"></a> [update\_timeout](#input\_update\_timeout) | If provided, it will increase or decrease the timeout for updating the node group https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group#timeouts"<br> It would be necessary on node groups with a lot of nodes. Because the changing this node groups would take a lot of time | `string` | `"60m"` | no |
| <a name="input_userdata_override_base64"></a> [userdata\_override\_base64](#input\_userdata\_override\_base64) | Many features of this module rely on the `bootstrap.sh` provided with Amazon Linux, and this module<br>may generate "user data" that expects to find that script. If you want to use an AMI that is not<br>compatible with the Amazon Linux `bootstrap.sh` initialization, then use `userdata_override_base64` to provide<br>your own (Base64 encoded) user data. Use "" to prevent any user data from being set.<br><br>Setting `userdata_override_base64` disables `kubernetes_taints`, `kubelet_additional_options`,<br>`before_cluster_joining_userdata`, `after_cluster_joining_userdata`, and `bootstrap_additional_options`. | `string` | `null` | no |
| <a name="input_userdata_override_base64"></a> [userdata\_override\_base64](#input\_userdata\_override\_base64) | Many features of this module rely on the `bootstrap.sh` provided with Amazon Linux, and this module<br>may generate "user data" that expects to find that script. If you want to use an AMI that is not<br>compatible with the Amazon Linux `bootstrap.sh` initialization, then use `userdata_override_base64` to provide<br>your own (Base64 encoded) user data. Use "" to prevent any user data from being set.<br><br>Setting `userdata_override_base64` disables `kubelet_additional_options`,<br>`before_cluster_joining_userdata`, `after_cluster_joining_userdata`, and `bootstrap_additional_options`. | `string` | `null` | no |
| <a name="input_worker_role_autoscale_iam_enabled"></a> [worker\_role\_autoscale\_iam\_enabled](#input\_worker\_role\_autoscale\_iam\_enabled) | If true, the worker IAM role will be authorized to perform autoscaling operations. Not recommended.<br>Use [EKS IAM role for cluster autoscaler service account](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) instead. | `bool` | `false` | no |
| <a name="input_worker_role_cni_iam_enabled"></a> [worker\_role\_cni\_iam\_enabled](#input\_worker\_role\_cni\_iam\_enabled) | If true, the worker IAM role will be authorized to perform CNI operations. Defaults to true for ease of use.<br>Recommended to use [EKS IAM role for aws-node service account](https://docs.aws.amazon.com/eks/latest/userguide/cni-iam-role.html) instead. | `bool` | `true` | no |

Expand Down
8 changes: 4 additions & 4 deletions docs/terraform.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13.3 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.43 |
| <a name="requirement_local"></a> [local](#requirement\_local) | >= 1.3 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 2.0 |
| <a name="requirement_template"></a> [template](#requirement\_template) | >= 2.0 |
Expand All @@ -13,7 +13,7 @@

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.0 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.43 |
| <a name="provider_random"></a> [random](#provider\_random) | >= 2.0 |

## Modules
Expand Down Expand Up @@ -79,7 +79,7 @@
| <a name="input_instance_types"></a> [instance\_types](#input\_instance\_types) | Instance types to use for this node group (up to 20). Defaults to ["t3.medium"].<br>Ignored when `launch_template_id` is supplied. | `list(string)` | <pre>[<br> "t3.medium"<br>]</pre> | no |
| <a name="input_kubelet_additional_options"></a> [kubelet\_additional\_options](#input\_kubelet\_additional\_options) | Additional flags to pass to kubelet.<br>DO NOT include `--node-labels` or `--node-taints`,<br>use `kubernetes_labels` and `kubernetes_taints` to specify those." | `string` | `""` | no |
| <a name="input_kubernetes_labels"></a> [kubernetes\_labels](#input\_kubernetes\_labels) | Key-value mapping of Kubernetes labels. Only labels that are applied with the EKS API are managed by this argument.<br>Other Kubernetes labels applied to the EKS Node Group will not be managed. | `map(string)` | `{}` | no |
| <a name="input_kubernetes_taints"></a> [kubernetes\_taints](#input\_kubernetes\_taints) | Key-value mapping of Kubernetes taints. | `map(string)` | `{}` | no |
| <a name="input_kubernetes_taints"></a> [kubernetes\_taints](#input\_kubernetes\_taints) | Key-value mapping of Kubernetes taints in the form of `<key>=<value>:<effect>`. | `map(string)` | `{}` | no |
| <a name="input_kubernetes_version"></a> [kubernetes\_version](#input\_kubernetes\_version) | Kubernetes version. Defaults to EKS Cluster Kubernetes version. Terraform will only perform drift detection if a configuration value is provided | `string` | `null` | no |
| <a name="input_label_key_case"></a> [label\_key\_case](#input\_label\_key\_case) | The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`.<br>Possible values: `lower`, `title`, `upper`.<br>Default value: `title`. | `string` | `null` | no |
| <a name="input_label_order"></a> [label\_order](#input\_label\_order) | The naming order of the id output and Name tag.<br>Defaults to ["namespace", "environment", "stage", "name", "attributes"].<br>You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no |
Expand Down Expand Up @@ -108,7 +108,7 @@
| <a name="input_subnet_ids"></a> [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs to launch resources in | `list(string)` | n/a | yes |
| <a name="input_tags"></a> [tags](#input\_tags) | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no |
| <a name="input_update_timeout"></a> [update\_timeout](#input\_update\_timeout) | If provided, it will increase or decrease the timeout for updating the node group https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group#timeouts"<br> It would be necessary on node groups with a lot of nodes. Because the changing this node groups would take a lot of time | `string` | `"60m"` | no |
| <a name="input_userdata_override_base64"></a> [userdata\_override\_base64](#input\_userdata\_override\_base64) | Many features of this module rely on the `bootstrap.sh` provided with Amazon Linux, and this module<br>may generate "user data" that expects to find that script. If you want to use an AMI that is not<br>compatible with the Amazon Linux `bootstrap.sh` initialization, then use `userdata_override_base64` to provide<br>your own (Base64 encoded) user data. Use "" to prevent any user data from being set.<br><br>Setting `userdata_override_base64` disables `kubernetes_taints`, `kubelet_additional_options`,<br>`before_cluster_joining_userdata`, `after_cluster_joining_userdata`, and `bootstrap_additional_options`. | `string` | `null` | no |
| <a name="input_userdata_override_base64"></a> [userdata\_override\_base64](#input\_userdata\_override\_base64) | Many features of this module rely on the `bootstrap.sh` provided with Amazon Linux, and this module<br>may generate "user data" that expects to find that script. If you want to use an AMI that is not<br>compatible with the Amazon Linux `bootstrap.sh` initialization, then use `userdata_override_base64` to provide<br>your own (Base64 encoded) user data. Use "" to prevent any user data from being set.<br><br>Setting `userdata_override_base64` disables `kubelet_additional_options`,<br>`before_cluster_joining_userdata`, `after_cluster_joining_userdata`, and `bootstrap_additional_options`. | `string` | `null` | no |
| <a name="input_worker_role_autoscale_iam_enabled"></a> [worker\_role\_autoscale\_iam\_enabled](#input\_worker\_role\_autoscale\_iam\_enabled) | If true, the worker IAM role will be authorized to perform autoscaling operations. Not recommended.<br>Use [EKS IAM role for cluster autoscaler service account](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) instead. | `bool` | `false` | no |
| <a name="input_worker_role_cni_iam_enabled"></a> [worker\_role\_cni\_iam\_enabled](#input\_worker\_role\_cni\_iam\_enabled) | If true, the worker IAM role will be authorized to perform CNI operations. Defaults to true for ease of use.<br>Recommended to use [EKS IAM role for aws-node service account](https://docs.aws.amazon.com/eks/latest/userguide/cni-iam-role.html) instead. | `bool` | `true` | no |

Expand Down
5 changes: 5 additions & 0 deletions examples/complete/fixtures.us-east-2.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,8 @@ before_cluster_joining_userdata = <<-EOT
EOT

remote_access_enabled = true

kubernetes_taints = {
"test" = "true:PreferNoSchedule"
"testNoValue" = "PreferNoSchedule"
}
1 change: 1 addition & 0 deletions examples/complete/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ module "eks_node_group" {
max_size = var.max_size
kubernetes_version = var.kubernetes_version
kubernetes_labels = var.kubernetes_labels
kubernetes_taints = var.kubernetes_taints
disk_size = var.disk_size
ec2_ssh_key = module.ssh_key_pair.key_name
remote_access_enabled = var.remote_access_enabled
Expand Down
6 changes: 6 additions & 0 deletions examples/complete/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,9 @@ variable "remote_access_enabled" {
type = bool
description = "Whether to enable remote access to EKS node group, requires `ec2_ssh_key` to be defined."
}

variable "kubernetes_taints" {
type = map(string)
description = "Key-value mapping of Kubernetes taints in the form of `<key>=<value>:<effect>`."
default = {}
}
2 changes: 1 addition & 1 deletion examples/complete/versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.0"
version = ">= 3.43"
}
template = {
source = "hashicorp/template"
Expand Down
29 changes: 29 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,17 @@ locals {
need_remote_access = local.ng_needs_remote_access
ec2_ssh_key = local.remote_access_enabled ? var.ec2_ssh_key : "none"
source_security_group_ids = local.ng_needs_remote_access ? sort(concat(module.security_group.*.id, var.security_groups)) : []

# Configure taints
taints = length(var.kubernetes_taints) > 0 ? { for k, v in var.kubernetes_taints : k => {
value = length(split(":", v)) > 1 ? element(split(":", v), 0) : null
effect = try(element(split(":", v), 1), v)
} } : {}
taint_lookup_map = {
NoSchedule = "NO_SCHEDULE"
NoExecute = "NO_EXECUTE"
PreferNoSchedule = "PREFER_NO_SCHEDULE"
}
}
}

Expand Down Expand Up @@ -186,6 +197,15 @@ resource "aws_eks_node_group" "default" {
}
}

dynamic "taint" {
for_each = local.ng.taints
content {
key = taint.key
value = taint.value.value
effect = local.ng.taint_lookup_map[taint.value.effect]
}
}

# Ensure that IAM Role permissions are created before and deleted after EKS Node Group handling.
# Otherwise, EKS will not be able to properly delete EC2 Instances and Elastic Network Interfaces.
depends_on = [
Expand Down Expand Up @@ -255,6 +275,15 @@ resource "aws_eks_node_group" "cbd" {
}
}

dynamic "taint" {
for_each = local.ng.taints
content {
key = taint.key
value = taint.value.value
effect = local.ng.taint_lookup_map[taint.value.effect]
}
}

# Ensure that IAM Role permissions are created before and deleted after EKS Node Group handling.
# Otherwise, EKS will not be able to properly delete EC2 Instances and Elastic Network Interfaces.
depends_on = [
Expand Down
29 changes: 29 additions & 0 deletions test/src/examples_complete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,33 @@ func TestExamplesComplete(t *testing.T) {
fmt.Println(msg)
assert.Fail(t, msg)
}

// List nodegroups (should only be 1)
// Describe nodegroup returned by list
// For each Taint struct in Taints attribute in Nodegroup struct, create map: Taint.Key => Taint
// Validate each Taint is assigned correctly using Taint.Key against the var.kubernetes_taints map
listNgInput := &eks.ListNodegroupsInput{
ClusterName: aws.String(clusterName),
MaxResults: func(i int64) *int64 { return &i }(1),
}
listNgResult, err := eksSvc.ListNodegroups(listNgInput)
assert.NoError(t, err)

describeNgInput := &eks.DescribeNodegroupInput{
ClusterName: aws.String(clusterName),
NodegroupName: aws.String(*listNgResult.Nodegroups[0]),
}
describeNgResult, err := eksSvc.DescribeNodegroup(describeNgInput)
assert.NoError(t, err)

m := make(map[string]map[string]string)
for _, t := range describeNgResult.Nodegroup.Taints {
m[*t.Key] = map[string]string{
"key": *t.Key,
"value": *t.Value,
"effect": *t.Effect,
}
}
assert.Equal(t, map[string]string{"key":"test","value":"true","effect":"PREFER_NO_SCHEDULE"}, m["test"])
assert.Equal(t, map[string]string{"key":"testNoValue","value":"","effect":"PREFER_NO_SCHEDULE"}, m["testNoValue"])
}
2 changes: 1 addition & 1 deletion test/src/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/cloudposse/terraform-aws-eks-node-group
go 1.13

require (
github.com/aws/aws-sdk-go v1.33.6
github.com/aws/aws-sdk-go v1.38.56
github.com/gruntwork-io/terratest v0.28.8
github.com/stretchr/testify v1.6.1
k8s.io/api v0.18.6
Expand Down
Loading