From 6b4a1295e59f9357eab1359f00ab425758cc6fba Mon Sep 17 00:00:00 2001
From: Marcin Cuber <5611060+marcincuber@users.noreply.github.com>
Date: Sat, 20 May 2023 09:22:54 +0100
Subject: [PATCH] Add support for create-before-destroy plus upgrades (#1)
---
.pre-commit-config.yaml | 6 +-
README.md | 9 +-
.../versions.tf | 10 ++
examples/single-node-group/versions.tf | 10 ++
main.tf | 93 ++++++++++++++++++-
outputs.tf | 6 +-
variables.tf | 12 +++
versions.tf | 2 +-
8 files changed, 136 insertions(+), 12 deletions(-)
create mode 100644 examples/single-node-group-with-launch-template/versions.tf
create mode 100644 examples/single-node-group/versions.tf
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 5ff3c08..d921b00 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.1.0
+ rev: v4.4.0
hooks:
- id: check-added-large-files
args: ['--maxkb=500']
@@ -17,8 +17,8 @@ repos:
- id: detect-aws-credentials
args: ['--allow-missing-credentials']
- id: trailing-whitespace
-- repo: git://github.com/antonbabenko/pre-commit-terraform
- rev: 48bc03ca3f0f2f782d2f430069868019a6892062
+- repo: https://github.com/antonbabenko/pre-commit-terraform
+ rev: v1.79.1
hooks:
- id: terraform_fmt
- id: terraform_docs
diff --git a/README.md b/README.md
index c8fe39e..ec61d8d 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ Terraform module to provision EKS Managed Node Group
```hcl
module "eks-node-group" {
source = "native-cube/eks-node-group/aws"
- version = "~> 1.0.0"
+ version = "~> 1.1.0"
cluster_name = aws_eks_cluster.cluster.id
@@ -61,13 +61,13 @@ module "eks-node-group" {
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= 1.0.0 |
-| [aws](#requirement\_aws) | >= 4.0.0 |
+| [aws](#requirement\_aws) | >= 4.64.0 |
## Providers
| Name | Version |
|------|---------|
-| [aws](#provider\_aws) | >= 4.0.0 |
+| [aws](#provider\_aws) | >= 4.64.0 |
## Modules
@@ -78,6 +78,7 @@ No modules.
| Name | Type |
|------|------|
| [aws_eks_node_group.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource |
+| [aws_eks_node_group.main_create_before_destroy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource |
| [aws_iam_role.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
## Inputs
@@ -88,6 +89,7 @@ No modules.
| [ami\_type](#input\_ami\_type) | Type of Amazon Machine Image (AMI) associated with the EKS Node Group. Valid values: AL2\_x86\_64 \| AL2\_x86\_64\_GPU \| AL2\_ARM\_64 \| CUSTOM \| BOTTLEROCKET\_ARM\_64 \| BOTTLEROCKET\_x86\_64. Terraform will only perform drift detection if a configuration value is provided. | `string` | `null` | no |
| [capacity\_type](#input\_capacity\_type) | Type of capacity associated with the EKS Node Group. Defaults to ON\_DEMAND. Valid values: ON\_DEMAND, SPOT. | `string` | `"ON_DEMAND"` | no |
| [cluster\_name](#input\_cluster\_name) | The name of the EKS cluster. | `string` | n/a | yes |
+| [create\_before\_destroy](#input\_create\_before\_destroy) | Create new node group before destroying an old one. To be used with node\_group\_name\_prefix argument. | `bool` | `false` | no |
| [create\_iam\_role](#input\_create\_iam\_role) | Create IAM role for node group. Set to false if pass `node_role_arn` as an argument | `bool` | `true` | no |
| [desired\_size](#input\_desired\_size) | Desired number of worker nodes. | `number` | n/a | yes |
| [disk\_size](#input\_disk\_size) | Disk size in GiB for worker nodes. Defaults to 20. Terraform will only perform drift detection if a configuration value is provided. | `number` | `null` | no |
@@ -108,6 +110,7 @@ No modules.
| [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs to launch resources in. | `list(string)` | n/a | yes |
| [tags](#input\_tags) | A map of tags (key-value pairs) passed to resources. | `map(string)` | `{}` | no |
| [taints](#input\_taints) | List of objects containing Kubernetes taints which will be applied to the nodes in the node group. Maximum of 50 taints per node group. | `list(object({ key = string, value = any, effect = string }))` | `[]` | no |
+| [timeouts](#input\_timeouts) | Create, update, and delete timeout configurations for the node group | `map(string)` | `{}` | no |
| [update\_config](#input\_update\_config) | Update config configuration block which is a key-value map. Accepted argmuents are `max_unavailable` and `max_unavailable_percentage`. | `map(any)` | `{}` | no |
## Outputs
diff --git a/examples/single-node-group-with-launch-template/versions.tf b/examples/single-node-group-with-launch-template/versions.tf
new file mode 100644
index 0000000..3b23820
--- /dev/null
+++ b/examples/single-node-group-with-launch-template/versions.tf
@@ -0,0 +1,10 @@
+terraform {
+ required_version = ">= 1.0"
+
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 4.64.0"
+ }
+ }
+}
diff --git a/examples/single-node-group/versions.tf b/examples/single-node-group/versions.tf
new file mode 100644
index 0000000..3b23820
--- /dev/null
+++ b/examples/single-node-group/versions.tf
@@ -0,0 +1,10 @@
+terraform {
+ required_version = ">= 1.0"
+
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 4.64.0"
+ }
+ }
+}
diff --git a/main.tf b/main.tf
index 18b2965..bd09c52 100644
--- a/main.tf
+++ b/main.tf
@@ -1,9 +1,11 @@
resource "aws_eks_node_group" "main" {
+ count = var.create_before_destroy ? 0 : 1
+
cluster_name = var.cluster_name
node_group_name_prefix = var.node_group_name_prefix
node_group_name = var.node_group_name
- node_role_arn = var.node_role_arn == null ? join("", aws_iam_role.main.*.arn) : var.node_role_arn
+ node_role_arn = var.node_role_arn == null ? aws_iam_role.main[0].arn : var.node_role_arn
subnet_ids = var.subnet_ids
@@ -61,7 +63,94 @@ resource "aws_eks_node_group" "main" {
}
}
+ timeouts {
+ create = lookup(var.timeouts, "create", null)
+ update = lookup(var.timeouts, "update", null)
+ delete = lookup(var.timeouts, "delete", null)
+ }
+
+ lifecycle {
+ ignore_changes = [
+ scaling_config[0].desired_size
+ ]
+ }
+}
+
+resource "aws_eks_node_group" "main_create_before_destroy" {
+ count = var.create_before_destroy ? 1 : 0
+
+ cluster_name = var.cluster_name
+
+ node_group_name_prefix = var.node_group_name_prefix
+ node_group_name = var.node_group_name
+ node_role_arn = var.node_role_arn == null ? aws_iam_role.main[0].arn : var.node_role_arn
+
+ subnet_ids = var.subnet_ids
+
+ ami_type = var.ami_type
+ disk_size = var.disk_size
+ instance_types = var.instance_types
+ capacity_type = var.capacity_type
+
+ labels = var.labels
+
+ release_version = var.ami_release_version
+ version = var.kubernetes_version
+
+ force_update_version = var.force_update_version
+
+ tags = var.tags
+
+ scaling_config {
+ desired_size = var.desired_size
+ max_size = var.max_size
+ min_size = var.min_size
+ }
+
+ dynamic "taint" {
+ for_each = var.taints
+ content {
+ key = lookup(taint.value, "key")
+ value = lookup(taint.value, "value")
+ effect = lookup(taint.value, "effect")
+ }
+ }
+
+ dynamic "remote_access" {
+ for_each = var.ec2_ssh_key != null || var.source_security_group_ids != null ? ["true"] : []
+ content {
+ ec2_ssh_key = var.ec2_ssh_key
+ source_security_group_ids = var.source_security_group_ids
+ }
+ }
+
+ dynamic "update_config" {
+ for_each = length(var.update_config) == 0 ? [] : [var.update_config]
+ content {
+ max_unavailable = lookup(update_config.value, "max_unavailable", null)
+ max_unavailable_percentage = lookup(update_config.value, "max_unavailable_percentage", null)
+ }
+ }
+
+ dynamic "launch_template" {
+ for_each = length(var.launch_template) == 0 ? [] : [var.launch_template]
+ content {
+ id = lookup(launch_template.value, "id", null)
+ name = lookup(launch_template.value, "name", null)
+ version = lookup(launch_template.value, "version")
+ }
+ }
+
+ timeouts {
+ create = lookup(var.timeouts, "create", null)
+ update = lookup(var.timeouts, "update", null)
+ delete = lookup(var.timeouts, "delete", null)
+ }
+
lifecycle {
- ignore_changes = [scaling_config.0.desired_size]
+ create_before_destroy = true
+ ignore_changes = [
+ scaling_config[0].desired_size
+ ]
}
}
diff --git a/outputs.tf b/outputs.tf
index 0a28922..005b373 100644
--- a/outputs.tf
+++ b/outputs.tf
@@ -1,14 +1,14 @@
output "iam_role_arn" {
description = "IAM role ARN used by node group."
- value = join("", aws_iam_role.main.*.arn)
+ value = try(aws_iam_role.main[0].arn, null)
}
output "iam_role_id" {
description = "IAM role ID used by node group."
- value = join("", aws_iam_role.main.*.id)
+ value = try(aws_iam_role.main[0].id, null)
}
output "node_group" {
description = "Outputs from EKS node group. See `aws_eks_node_group` Terraform documentation for values"
- value = aws_eks_node_group.main
+ value = var.create_before_destroy ? try(aws_eks_node_group.main_create_before_destroy[0], null) : try(aws_eks_node_group.main[0], null)
}
diff --git a/variables.tf b/variables.tf
index afca795..9937c6c 100644
--- a/variables.tf
+++ b/variables.tf
@@ -142,3 +142,15 @@ variable "taints" {
description = "List of objects containing Kubernetes taints which will be applied to the nodes in the node group. Maximum of 50 taints per node group."
default = []
}
+
+variable "create_before_destroy" {
+ type = bool
+ description = "Create new node group before destroying an old one. To be used with node_group_name_prefix argument."
+ default = false
+}
+
+variable "timeouts" {
+ description = "Create, update, and delete timeout configurations for the node group"
+ type = map(string)
+ default = {}
+}
diff --git a/versions.tf b/versions.tf
index 97f0cf5..c7d3f4c 100644
--- a/versions.tf
+++ b/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 4.0.0"
+ version = ">= 4.64.0"
}
}
}