From 73121080c58fd378ec9af835d5b437735a98896d Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Mon, 7 Jul 2025 12:34:36 -0500 Subject: [PATCH 01/25] feat!: Upgrade min AWS provider and Terraform versions to `6.0` and `1.5.7` respectively --- README.md | 6 +++--- examples/eks-auto-mode/README.md | 6 +++--- examples/eks-auto-mode/versions.tf | 4 ++-- examples/eks-hybrid-nodes/README.md | 8 ++++---- examples/eks-hybrid-nodes/versions.tf | 4 ++-- examples/eks-managed-node-group/versions.tf | 4 ++-- examples/karpenter/README.md | 8 ++++---- examples/karpenter/versions.tf | 4 ++-- examples/self-managed-node-group/versions.tf | 4 ++-- modules/_user_data/README.md | 2 +- modules/_user_data/versions.tf | 2 +- modules/aws-auth/README.md | 2 +- modules/aws-auth/versions.tf | 2 +- modules/eks-managed-node-group/README.md | 6 +++--- modules/eks-managed-node-group/versions.tf | 4 ++-- modules/fargate-profile/README.md | 6 +++--- modules/fargate-profile/versions.tf | 4 ++-- modules/hybrid-node-role/README.md | 6 +++--- modules/hybrid-node-role/versions.tf | 4 ++-- modules/karpenter/README.md | 6 +++--- modules/karpenter/versions.tf | 4 ++-- modules/self-managed-node-group/README.md | 6 +++--- modules/self-managed-node-group/versions.tf | 4 ++-- tests/eks-fargate-profile/README.md | 6 +++--- tests/eks-fargate-profile/versions.tf | 4 ++-- tests/eks-hybrid-nodes/README.md | 4 ++-- tests/eks-hybrid-nodes/versions.tf | 4 ++-- tests/eks-managed-node-group/README.md | 6 +++--- tests/eks-managed-node-group/versions.tf | 4 ++-- tests/fast-addons/README.md | 6 +++--- tests/fast-addons/versions.tf | 4 ++-- tests/self-managed-node-group/README.md | 6 +++--- tests/self-managed-node-group/versions.tf | 4 ++-- tests/user-data/README.md | 2 +- tests/user-data/versions.tf | 2 +- versions.tf | 4 ++-- 36 files changed, 81 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index 4767a624e1..b76adf1c3c 100644 --- a/README.md +++ b/README.md @@ -317,8 +317,8 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | -| [aws](#requirement\_aws) | >= 5.95, < 6.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.0 | | [time](#requirement\_time) | >= 0.9 | | [tls](#requirement\_tls) | >= 3.0 | @@ -326,7 +326,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.95, < 6.0.0 | +| [aws](#provider\_aws) | >= 6.0 | | [time](#provider\_time) | >= 0.9 | | [tls](#provider\_tls) | >= 3.0 | diff --git a/examples/eks-auto-mode/README.md b/examples/eks-auto-mode/README.md index 085533d59d..795a041fac 100644 --- a/examples/eks-auto-mode/README.md +++ b/examples/eks-auto-mode/README.md @@ -24,14 +24,14 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | -| [aws](#requirement\_aws) | >= 5.95, < 6.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.95, < 6.0.0 | +| [aws](#provider\_aws) | >= 6.0 | ## Modules diff --git a/examples/eks-auto-mode/versions.tf b/examples/eks-auto-mode/versions.tf index 7884c4e1b2..db13b0a8d2 100644 --- a/examples/eks-auto-mode/versions.tf +++ b/examples/eks-auto-mode/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.95, < 6.0.0" + version = ">= 6.0" } } } diff --git a/examples/eks-hybrid-nodes/README.md b/examples/eks-hybrid-nodes/README.md index ed8825f17b..3bd23f9f17 100644 --- a/examples/eks-hybrid-nodes/README.md +++ b/examples/eks-hybrid-nodes/README.md @@ -25,8 +25,8 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | -| [aws](#requirement\_aws) | >= 5.95, < 6.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.0 | | [helm](#requirement\_helm) | >= 2.7, < 3.0.0 | | [http](#requirement\_http) | >= 3.4 | | [local](#requirement\_local) | >= 2.5 | @@ -36,8 +36,8 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.95, < 6.0.0 | -| [aws.remote](#provider\_aws.remote) | >= 5.95, < 6.0.0 | +| [aws](#provider\_aws) | >= 6.0 | +| [aws.remote](#provider\_aws.remote) | >= 6.0 | | [helm](#provider\_helm) | >= 2.7, < 3.0.0 | | [http](#provider\_http) | >= 3.4 | | [local](#provider\_local) | >= 2.5 | diff --git a/examples/eks-hybrid-nodes/versions.tf b/examples/eks-hybrid-nodes/versions.tf index 391c421395..057254205e 100644 --- a/examples/eks-hybrid-nodes/versions.tf +++ b/examples/eks-hybrid-nodes/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.95, < 6.0.0" + version = ">= 6.0" } helm = { source = "hashicorp/helm" diff --git a/examples/eks-managed-node-group/versions.tf b/examples/eks-managed-node-group/versions.tf index 7884c4e1b2..db13b0a8d2 100644 --- a/examples/eks-managed-node-group/versions.tf +++ b/examples/eks-managed-node-group/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.95, < 6.0.0" + version = ">= 6.0" } } } diff --git a/examples/karpenter/README.md b/examples/karpenter/README.md index 7e10796a2d..24951b07be 100644 --- a/examples/karpenter/README.md +++ b/examples/karpenter/README.md @@ -93,16 +93,16 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | -| [aws](#requirement\_aws) | >= 5.95, < 6.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.0 | | [helm](#requirement\_helm) | >= 2.7, < 3.0.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.95, < 6.0.0 | -| [aws.virginia](#provider\_aws.virginia) | >= 5.95, < 6.0.0 | +| [aws](#provider\_aws) | >= 6.0 | +| [aws.virginia](#provider\_aws.virginia) | >= 6.0 | | [helm](#provider\_helm) | >= 2.7, < 3.0.0 | ## Modules diff --git a/examples/karpenter/versions.tf b/examples/karpenter/versions.tf index f64d6ce245..b1d85d5e91 100644 --- a/examples/karpenter/versions.tf +++ b/examples/karpenter/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.95, < 6.0.0" + version = ">= 6.0" } helm = { source = "hashicorp/helm" diff --git a/examples/self-managed-node-group/versions.tf b/examples/self-managed-node-group/versions.tf index 7884c4e1b2..db13b0a8d2 100644 --- a/examples/self-managed-node-group/versions.tf +++ b/examples/self-managed-node-group/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.95, < 6.0.0" + version = ">= 6.0" } } } diff --git a/modules/_user_data/README.md b/modules/_user_data/README.md index 185335b16a..bfc623cff3 100644 --- a/modules/_user_data/README.md +++ b/modules/_user_data/README.md @@ -9,7 +9,7 @@ See [`tests/user-data/`](https://github.com/terraform-aws-modules/terraform-aws- | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | | [cloudinit](#requirement\_cloudinit) | >= 2.0 | | [null](#requirement\_null) | >= 3.0 | diff --git a/modules/_user_data/versions.tf b/modules/_user_data/versions.tf index 9219addeda..a9802b0dea 100644 --- a/modules/_user_data/versions.tf +++ b/modules/_user_data/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { cloudinit = { diff --git a/modules/aws-auth/README.md b/modules/aws-auth/README.md index d4b97f14ca..dffb4525c8 100644 --- a/modules/aws-auth/README.md +++ b/modules/aws-auth/README.md @@ -44,7 +44,7 @@ module "eks" { | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | | [kubernetes](#requirement\_kubernetes) | >= 2.20 | ## Providers diff --git a/modules/aws-auth/versions.tf b/modules/aws-auth/versions.tf index f330045476..3b2df08b05 100644 --- a/modules/aws-auth/versions.tf +++ b/modules/aws-auth/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { kubernetes = { diff --git a/modules/eks-managed-node-group/README.md b/modules/eks-managed-node-group/README.md index 2eeb0c61c8..a69c6d31fc 100644 --- a/modules/eks-managed-node-group/README.md +++ b/modules/eks-managed-node-group/README.md @@ -63,14 +63,14 @@ module "eks_managed_node_group" { | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | -| [aws](#requirement\_aws) | >= 5.95, < 6.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.95, < 6.0.0 | +| [aws](#provider\_aws) | >= 6.0 | ## Modules diff --git a/modules/eks-managed-node-group/versions.tf b/modules/eks-managed-node-group/versions.tf index 7884c4e1b2..db13b0a8d2 100644 --- a/modules/eks-managed-node-group/versions.tf +++ b/modules/eks-managed-node-group/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.95, < 6.0.0" + version = ">= 6.0" } } } diff --git a/modules/fargate-profile/README.md b/modules/fargate-profile/README.md index 9b4cb99dd3..0d1b40344d 100644 --- a/modules/fargate-profile/README.md +++ b/modules/fargate-profile/README.md @@ -28,14 +28,14 @@ module "fargate_profile" { | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | -| [aws](#requirement\_aws) | >= 5.95, < 6.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.95, < 6.0.0 | +| [aws](#provider\_aws) | >= 6.0 | ## Modules diff --git a/modules/fargate-profile/versions.tf b/modules/fargate-profile/versions.tf index 7884c4e1b2..db13b0a8d2 100644 --- a/modules/fargate-profile/versions.tf +++ b/modules/fargate-profile/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.95, < 6.0.0" + version = ">= 6.0" } } } diff --git a/modules/hybrid-node-role/README.md b/modules/hybrid-node-role/README.md index 3119747f76..6f8ffd1b90 100644 --- a/modules/hybrid-node-role/README.md +++ b/modules/hybrid-node-role/README.md @@ -74,14 +74,14 @@ module "eks_hybrid_node_role" { | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | -| [aws](#requirement\_aws) | >= 5.95, < 6.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.95, < 6.0.0 | +| [aws](#provider\_aws) | >= 6.0 | ## Modules diff --git a/modules/hybrid-node-role/versions.tf b/modules/hybrid-node-role/versions.tf index 7884c4e1b2..db13b0a8d2 100644 --- a/modules/hybrid-node-role/versions.tf +++ b/modules/hybrid-node-role/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.95, < 6.0.0" + version = ">= 6.0" } } } diff --git a/modules/karpenter/README.md b/modules/karpenter/README.md index 43cc3b560b..8ce6f3a100 100644 --- a/modules/karpenter/README.md +++ b/modules/karpenter/README.md @@ -85,14 +85,14 @@ module "karpenter" { | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | -| [aws](#requirement\_aws) | >= 5.95, < 6.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.95, < 6.0.0 | +| [aws](#provider\_aws) | >= 6.0 | ## Modules diff --git a/modules/karpenter/versions.tf b/modules/karpenter/versions.tf index 7884c4e1b2..db13b0a8d2 100644 --- a/modules/karpenter/versions.tf +++ b/modules/karpenter/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.95, < 6.0.0" + version = ">= 6.0" } } } diff --git a/modules/self-managed-node-group/README.md b/modules/self-managed-node-group/README.md index 06747514f2..1dbf618036 100644 --- a/modules/self-managed-node-group/README.md +++ b/modules/self-managed-node-group/README.md @@ -42,14 +42,14 @@ module "self_managed_node_group" { | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | -| [aws](#requirement\_aws) | >= 5.95, < 6.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.95, < 6.0.0 | +| [aws](#provider\_aws) | >= 6.0 | ## Modules diff --git a/modules/self-managed-node-group/versions.tf b/modules/self-managed-node-group/versions.tf index 7884c4e1b2..db13b0a8d2 100644 --- a/modules/self-managed-node-group/versions.tf +++ b/modules/self-managed-node-group/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.95, < 6.0.0" + version = ">= 6.0" } } } diff --git a/tests/eks-fargate-profile/README.md b/tests/eks-fargate-profile/README.md index 419f601de8..397d96228d 100644 --- a/tests/eks-fargate-profile/README.md +++ b/tests/eks-fargate-profile/README.md @@ -17,14 +17,14 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | -| [aws](#requirement\_aws) | >= 5.95, < 6.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.95, < 6.0.0 | +| [aws](#provider\_aws) | >= 6.0 | ## Modules diff --git a/tests/eks-fargate-profile/versions.tf b/tests/eks-fargate-profile/versions.tf index 7884c4e1b2..db13b0a8d2 100644 --- a/tests/eks-fargate-profile/versions.tf +++ b/tests/eks-fargate-profile/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.95, < 6.0.0" + version = ">= 6.0" } } } diff --git a/tests/eks-hybrid-nodes/README.md b/tests/eks-hybrid-nodes/README.md index 67bc82c7a9..efe26912ce 100644 --- a/tests/eks-hybrid-nodes/README.md +++ b/tests/eks-hybrid-nodes/README.md @@ -17,8 +17,8 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | -| [aws](#requirement\_aws) | >= 5.95, < 6.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.0 | | [tls](#requirement\_tls) | >= 4.0 | ## Providers diff --git a/tests/eks-hybrid-nodes/versions.tf b/tests/eks-hybrid-nodes/versions.tf index 20514e1bdd..3c2ec900b1 100644 --- a/tests/eks-hybrid-nodes/versions.tf +++ b/tests/eks-hybrid-nodes/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.95, < 6.0.0" + version = ">= 6.0" } tls = { source = "hashicorp/tls" diff --git a/tests/eks-managed-node-group/README.md b/tests/eks-managed-node-group/README.md index 96a5011da3..9a8cac3a60 100644 --- a/tests/eks-managed-node-group/README.md +++ b/tests/eks-managed-node-group/README.md @@ -17,14 +17,14 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | -| [aws](#requirement\_aws) | >= 5.95, < 6.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.95, < 6.0.0 | +| [aws](#provider\_aws) | >= 6.0 | ## Modules diff --git a/tests/eks-managed-node-group/versions.tf b/tests/eks-managed-node-group/versions.tf index 7884c4e1b2..db13b0a8d2 100644 --- a/tests/eks-managed-node-group/versions.tf +++ b/tests/eks-managed-node-group/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.95, < 6.0.0" + version = ">= 6.0" } } } diff --git a/tests/fast-addons/README.md b/tests/fast-addons/README.md index cd1be0dcd6..e09a5cf53b 100644 --- a/tests/fast-addons/README.md +++ b/tests/fast-addons/README.md @@ -21,14 +21,14 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | -| [aws](#requirement\_aws) | >= 5.95, < 6.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.95, < 6.0.0 | +| [aws](#provider\_aws) | >= 6.0 | ## Modules diff --git a/tests/fast-addons/versions.tf b/tests/fast-addons/versions.tf index 7884c4e1b2..db13b0a8d2 100644 --- a/tests/fast-addons/versions.tf +++ b/tests/fast-addons/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.95, < 6.0.0" + version = ">= 6.0" } } } diff --git a/tests/self-managed-node-group/README.md b/tests/self-managed-node-group/README.md index 655025789b..193314aa2c 100644 --- a/tests/self-managed-node-group/README.md +++ b/tests/self-managed-node-group/README.md @@ -17,14 +17,14 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | -| [aws](#requirement\_aws) | >= 5.95, < 6.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.95, < 6.0.0 | +| [aws](#provider\_aws) | >= 6.0 | ## Modules diff --git a/tests/self-managed-node-group/versions.tf b/tests/self-managed-node-group/versions.tf index 7884c4e1b2..db13b0a8d2 100644 --- a/tests/self-managed-node-group/versions.tf +++ b/tests/self-managed-node-group/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.95, < 6.0.0" + version = ">= 6.0" } } } diff --git a/tests/user-data/README.md b/tests/user-data/README.md index 88988ab2f4..684a3a7648 100644 --- a/tests/user-data/README.md +++ b/tests/user-data/README.md @@ -17,7 +17,7 @@ $ terraform apply --auto-approve | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.2 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | | [local](#requirement\_local) | >= 2.4 | ## Providers diff --git a/tests/user-data/versions.tf b/tests/user-data/versions.tf index 31969d6c02..0d69a257f0 100644 --- a/tests/user-data/versions.tf +++ b/tests/user-data/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { local = { diff --git a/versions.tf b/versions.tf index 5024a4995f..52e65ff5b7 100644 --- a/versions.tf +++ b/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.3.2" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.95, < 6.0.0" + version = ">= 6.0" } tls = { source = "hashicorp/tls" From 43f810dd73a16624ae8f085e9249bbb6545e9f53 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Mon, 7 Jul 2025 12:58:43 -0500 Subject: [PATCH 02/25] fix: Remove deprecated arguments in AWS v6.0 provider, upgrade Helm provider to v3.0, bump VPC module to v6.0 --- README.md | 4 ++-- examples/eks-auto-mode/README.md | 2 +- examples/eks-auto-mode/main.tf | 2 +- examples/eks-hybrid-nodes/README.md | 8 ++++---- examples/eks-hybrid-nodes/main.tf | 6 +++--- examples/eks-hybrid-nodes/remote.tf | 2 +- examples/eks-hybrid-nodes/versions.tf | 2 +- examples/eks-managed-node-group/eks-al2023.tf | 5 +++-- .../eks-managed-node-group/eks-bottlerocket.tf | 5 +++-- examples/eks-managed-node-group/main.tf | 2 +- examples/karpenter/README.md | 6 +++--- examples/karpenter/main.tf | 8 ++++---- examples/karpenter/versions.tf | 2 +- examples/self-managed-node-group/eks-al2023.tf | 5 +++-- .../self-managed-node-group/eks-bottlerocket.tf | 5 +++-- examples/self-managed-node-group/main.tf | 2 +- modules/eks-managed-node-group/README.md | 2 -- modules/eks-managed-node-group/main.tf | 16 ---------------- modules/eks-managed-node-group/variables.tf | 12 ------------ modules/self-managed-node-group/README.md | 2 -- modules/self-managed-node-group/main.tf | 16 ---------------- modules/self-managed-node-group/variables.tf | 12 ------------ node_groups.tf | 4 ---- tests/eks-fargate-profile/README.md | 2 +- tests/eks-fargate-profile/main.tf | 2 +- tests/eks-managed-node-group/README.md | 4 ++-- tests/eks-managed-node-group/main.tf | 4 ++-- tests/fast-addons/README.md | 2 +- tests/fast-addons/main.tf | 2 +- tests/self-managed-node-group/README.md | 6 +++--- tests/self-managed-node-group/main.tf | 6 +++--- versions.tf | 2 +- 32 files changed, 50 insertions(+), 110 deletions(-) diff --git a/README.md b/README.md index b76adf1c3c..2ff7661824 100644 --- a/README.md +++ b/README.md @@ -320,7 +320,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [terraform](#requirement\_terraform) | >= 1.5.7 | | [aws](#requirement\_aws) | >= 6.0 | | [time](#requirement\_time) | >= 0.9 | -| [tls](#requirement\_tls) | >= 3.0 | +| [tls](#requirement\_tls) | >= 4.0 | ## Providers @@ -328,7 +328,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple |------|---------| | [aws](#provider\_aws) | >= 6.0 | | [time](#provider\_time) | >= 0.9 | -| [tls](#provider\_tls) | >= 3.0 | +| [tls](#provider\_tls) | >= 4.0 | ## Modules diff --git a/examples/eks-auto-mode/README.md b/examples/eks-auto-mode/README.md index 795a041fac..57da18f875 100644 --- a/examples/eks-auto-mode/README.md +++ b/examples/eks-auto-mode/README.md @@ -39,7 +39,7 @@ Note that this example may create resources which cost money. Run `terraform des |------|--------|---------| | [disabled\_eks](#module\_disabled\_eks) | ../.. | n/a | | [eks](#module\_eks) | ../.. | n/a | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 | ## Resources diff --git a/examples/eks-auto-mode/main.tf b/examples/eks-auto-mode/main.tf index 316b2764d4..aa7bad1cd2 100644 --- a/examples/eks-auto-mode/main.tf +++ b/examples/eks-auto-mode/main.tf @@ -61,7 +61,7 @@ module "disabled_eks" { module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" name = local.name cidr = local.vpc_cidr diff --git a/examples/eks-hybrid-nodes/README.md b/examples/eks-hybrid-nodes/README.md index 3bd23f9f17..94ccb4eb4d 100644 --- a/examples/eks-hybrid-nodes/README.md +++ b/examples/eks-hybrid-nodes/README.md @@ -27,7 +27,7 @@ Note that this example may create resources which cost money. Run `terraform des |------|---------| | [terraform](#requirement\_terraform) | >= 1.5.7 | | [aws](#requirement\_aws) | >= 6.0 | -| [helm](#requirement\_helm) | >= 2.7, < 3.0.0 | +| [helm](#requirement\_helm) | >= 3.0 | | [http](#requirement\_http) | >= 3.4 | | [local](#requirement\_local) | >= 2.5 | | [tls](#requirement\_tls) | >= 4.0 | @@ -38,7 +38,7 @@ Note that this example may create resources which cost money. Run `terraform des |------|---------| | [aws](#provider\_aws) | >= 6.0 | | [aws.remote](#provider\_aws.remote) | >= 6.0 | -| [helm](#provider\_helm) | >= 2.7, < 3.0.0 | +| [helm](#provider\_helm) | >= 3.0 | | [http](#provider\_http) | >= 3.4 | | [local](#provider\_local) | >= 2.5 | @@ -49,8 +49,8 @@ Note that this example may create resources which cost money. Run `terraform des | [eks](#module\_eks) | ../.. | n/a | | [eks\_hybrid\_node\_role](#module\_eks\_hybrid\_node\_role) | ../../modules/hybrid-node-role | n/a | | [key\_pair](#module\_key\_pair) | terraform-aws-modules/key-pair/aws | ~> 2.0 | -| [remote\_node\_vpc](#module\_remote\_node\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | +| [remote\_node\_vpc](#module\_remote\_node\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 | ## Resources diff --git a/examples/eks-hybrid-nodes/main.tf b/examples/eks-hybrid-nodes/main.tf index ffc77e36a2..95d26f8909 100644 --- a/examples/eks-hybrid-nodes/main.tf +++ b/examples/eks-hybrid-nodes/main.tf @@ -3,11 +3,11 @@ provider "aws" { } provider "helm" { - kubernetes { + kubernetes = { host = module.eks.cluster_endpoint cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data) - exec { + exec = { api_version = "client.authentication.k8s.io/v1beta1" command = "aws" # This requires the awscli to be installed locally where Terraform is executed @@ -106,7 +106,7 @@ data "aws_availability_zones" "available" { module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" name = local.name cidr = local.vpc_cidr diff --git a/examples/eks-hybrid-nodes/remote.tf b/examples/eks-hybrid-nodes/remote.tf index 3a44aba523..66baff9eed 100644 --- a/examples/eks-hybrid-nodes/remote.tf +++ b/examples/eks-hybrid-nodes/remote.tf @@ -253,7 +253,7 @@ data "aws_availability_zones" "remote" { module "remote_node_vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" providers = { aws = aws.remote diff --git a/examples/eks-hybrid-nodes/versions.tf b/examples/eks-hybrid-nodes/versions.tf index 057254205e..29273c9ce0 100644 --- a/examples/eks-hybrid-nodes/versions.tf +++ b/examples/eks-hybrid-nodes/versions.tf @@ -8,7 +8,7 @@ terraform { } helm = { source = "hashicorp/helm" - version = ">= 2.7, < 3.0.0" + version = ">= 3.0" } http = { source = "hashicorp/http" diff --git a/examples/eks-managed-node-group/eks-al2023.tf b/examples/eks-managed-node-group/eks-al2023.tf index 93fda067da..b96a94a875 100644 --- a/examples/eks-managed-node-group/eks-al2023.tf +++ b/examples/eks-managed-node-group/eks-al2023.tf @@ -1,6 +1,7 @@ module "eks_al2023" { - source = "terraform-aws-modules/eks/aws" - version = "~> 20.0" + # source = "terraform-aws-modules/eks/aws" + # version = "~> 20.0" + source = "../.." cluster_name = "${local.name}-al2023" cluster_version = "1.33" diff --git a/examples/eks-managed-node-group/eks-bottlerocket.tf b/examples/eks-managed-node-group/eks-bottlerocket.tf index 4d25e5b9c0..f970639967 100644 --- a/examples/eks-managed-node-group/eks-bottlerocket.tf +++ b/examples/eks-managed-node-group/eks-bottlerocket.tf @@ -1,6 +1,7 @@ module "eks_bottlerocket" { - source = "terraform-aws-modules/eks/aws" - version = "~> 20.0" + # source = "terraform-aws-modules/eks/aws" + # version = "~> 20.0" + source = "../.." cluster_name = "${local.name}-bottlerocket" cluster_version = "1.33" diff --git a/examples/eks-managed-node-group/main.tf b/examples/eks-managed-node-group/main.tf index 451bbdb385..3adeaeb4c0 100644 --- a/examples/eks-managed-node-group/main.tf +++ b/examples/eks-managed-node-group/main.tf @@ -30,7 +30,7 @@ locals { module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" name = local.name cidr = local.vpc_cidr diff --git a/examples/karpenter/README.md b/examples/karpenter/README.md index 24951b07be..47cfbf3ae2 100644 --- a/examples/karpenter/README.md +++ b/examples/karpenter/README.md @@ -95,7 +95,7 @@ Note that this example may create resources which cost money. Run `terraform des |------|---------| | [terraform](#requirement\_terraform) | >= 1.5.7 | | [aws](#requirement\_aws) | >= 6.0 | -| [helm](#requirement\_helm) | >= 2.7, < 3.0.0 | +| [helm](#requirement\_helm) | >= 3.0.0 | ## Providers @@ -103,7 +103,7 @@ Note that this example may create resources which cost money. Run `terraform des |------|---------| | [aws](#provider\_aws) | >= 6.0 | | [aws.virginia](#provider\_aws.virginia) | >= 6.0 | -| [helm](#provider\_helm) | >= 2.7, < 3.0.0 | +| [helm](#provider\_helm) | >= 3.0.0 | ## Modules @@ -112,7 +112,7 @@ Note that this example may create resources which cost money. Run `terraform des | [eks](#module\_eks) | ../.. | n/a | | [karpenter](#module\_karpenter) | ../../modules/karpenter | n/a | | [karpenter\_disabled](#module\_karpenter\_disabled) | ../../modules/karpenter | n/a | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 | ## Resources diff --git a/examples/karpenter/main.tf b/examples/karpenter/main.tf index 7006740f47..b4b7fc4fba 100644 --- a/examples/karpenter/main.tf +++ b/examples/karpenter/main.tf @@ -8,11 +8,11 @@ provider "aws" { } provider "helm" { - kubernetes { + kubernetes = { host = module.eks.cluster_endpoint cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data) - exec { + exec = { api_version = "client.authentication.k8s.io/v1beta1" command = "aws" # This requires the awscli to be installed locally where Terraform is executed @@ -140,7 +140,7 @@ resource "helm_release" "karpenter" { repository_username = data.aws_ecrpublic_authorization_token.token.user_name repository_password = data.aws_ecrpublic_authorization_token.token.password chart = "karpenter" - version = "1.1.1" + version = "1.5.2" wait = false values = [ @@ -164,7 +164,7 @@ resource "helm_release" "karpenter" { module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" name = local.name cidr = local.vpc_cidr diff --git a/examples/karpenter/versions.tf b/examples/karpenter/versions.tf index b1d85d5e91..4e81032c58 100644 --- a/examples/karpenter/versions.tf +++ b/examples/karpenter/versions.tf @@ -8,7 +8,7 @@ terraform { } helm = { source = "hashicorp/helm" - version = ">= 2.7, < 3.0.0" + version = ">= 3.0.0" } } } diff --git a/examples/self-managed-node-group/eks-al2023.tf b/examples/self-managed-node-group/eks-al2023.tf index 58ecb3cf66..6154a1f68a 100644 --- a/examples/self-managed-node-group/eks-al2023.tf +++ b/examples/self-managed-node-group/eks-al2023.tf @@ -1,6 +1,7 @@ module "eks_al2023" { - source = "terraform-aws-modules/eks/aws" - version = "~> 20.0" + # source = "terraform-aws-modules/eks/aws" + # version = "~> 20.0" + source = "../.." cluster_name = "${local.name}-al2023" cluster_version = "1.33" diff --git a/examples/self-managed-node-group/eks-bottlerocket.tf b/examples/self-managed-node-group/eks-bottlerocket.tf index adb3462b82..c1634fdd1d 100644 --- a/examples/self-managed-node-group/eks-bottlerocket.tf +++ b/examples/self-managed-node-group/eks-bottlerocket.tf @@ -1,6 +1,7 @@ module "eks_bottlerocket" { - source = "terraform-aws-modules/eks/aws" - version = "~> 20.0" + # source = "terraform-aws-modules/eks/aws" + # version = "~> 20.0" + source = "../.." cluster_name = "${local.name}-bottlerocket" cluster_version = "1.33" diff --git a/examples/self-managed-node-group/main.tf b/examples/self-managed-node-group/main.tf index f8efaeb389..903ee577b9 100644 --- a/examples/self-managed-node-group/main.tf +++ b/examples/self-managed-node-group/main.tf @@ -30,7 +30,7 @@ locals { module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" name = local.name cidr = local.vpc_cidr diff --git a/modules/eks-managed-node-group/README.md b/modules/eks-managed-node-group/README.md index a69c6d31fc..3c1ea95d76 100644 --- a/modules/eks-managed-node-group/README.md +++ b/modules/eks-managed-node-group/README.md @@ -133,8 +133,6 @@ module "eks_managed_node_group" { | [disk\_size](#input\_disk\_size) | Disk size in GiB for nodes. Defaults to `20`. Only valid when `use_custom_launch_template` = `false` | `number` | `null` | no | | [ebs\_optimized](#input\_ebs\_optimized) | If true, the launched EC2 instance(s) will be EBS-optimized | `bool` | `null` | no | | [efa\_indices](#input\_efa\_indices) | The indices of the network interfaces that should be EFA-enabled. Only valid when `enable_efa_support` = `true` | `list(number)` |
[
0
]
| no | -| [elastic\_gpu\_specifications](#input\_elastic\_gpu\_specifications) | The elastic GPU to attach to the instance | `any` | `{}` | no | -| [elastic\_inference\_accelerator](#input\_elastic\_inference\_accelerator) | Configuration block containing an Elastic Inference Accelerator to attach to the instance | `map(string)` | `{}` | no | | [enable\_bootstrap\_user\_data](#input\_enable\_bootstrap\_user\_data) | Determines whether the bootstrap configurations are populated within the user data template. Only valid when using a custom AMI via `ami_id` | `bool` | `false` | no | | [enable\_efa\_only](#input\_enable\_efa\_only) | Determines whether to enable EFA (`false`, default) or EFA and EFA-only (`true`) network interfaces. Note: requires vpc-cni version `v1.18.4` or later | `bool` | `false` | no | | [enable\_efa\_support](#input\_enable\_efa\_support) | Determines whether to enable Elastic Fabric Adapter (EFA) support | `bool` | `false` | no | diff --git a/modules/eks-managed-node-group/main.tf b/modules/eks-managed-node-group/main.tf index b9c9ba0e87..e2a2955dc3 100644 --- a/modules/eks-managed-node-group/main.tf +++ b/modules/eks-managed-node-group/main.tf @@ -137,22 +137,6 @@ resource "aws_launch_template" "this" { disable_api_termination = var.disable_api_termination ebs_optimized = var.ebs_optimized - dynamic "elastic_gpu_specifications" { - for_each = var.elastic_gpu_specifications - - content { - type = elastic_gpu_specifications.value.type - } - } - - dynamic "elastic_inference_accelerator" { - for_each = length(var.elastic_inference_accelerator) > 0 ? [var.elastic_inference_accelerator] : [] - - content { - type = elastic_inference_accelerator.value.type - } - } - dynamic "enclave_options" { for_each = length(var.enclave_options) > 0 ? [var.enclave_options] : [] diff --git a/modules/eks-managed-node-group/variables.tf b/modules/eks-managed-node-group/variables.tf index 54338542c9..db4c78128b 100644 --- a/modules/eks-managed-node-group/variables.tf +++ b/modules/eks-managed-node-group/variables.tf @@ -227,18 +227,6 @@ variable "credit_specification" { default = {} } -variable "elastic_gpu_specifications" { - description = "The elastic GPU to attach to the instance" - type = any - default = {} -} - -variable "elastic_inference_accelerator" { - description = "Configuration block containing an Elastic Inference Accelerator to attach to the instance" - type = map(string) - default = {} -} - variable "enclave_options" { description = "Enable Nitro Enclaves on launched instances" type = map(string) diff --git a/modules/self-managed-node-group/README.md b/modules/self-managed-node-group/README.md index 1dbf618036..0841fd9685 100644 --- a/modules/self-managed-node-group/README.md +++ b/modules/self-managed-node-group/README.md @@ -121,8 +121,6 @@ module "self_managed_node_group" { | [disable\_api\_termination](#input\_disable\_api\_termination) | If true, enables EC2 instance termination protection | `bool` | `null` | no | | [ebs\_optimized](#input\_ebs\_optimized) | If true, the launched EC2 instance will be EBS-optimized | `bool` | `null` | no | | [efa\_indices](#input\_efa\_indices) | The indices of the network interfaces that should be EFA-enabled. Only valid when `enable_efa_support` = `true` | `list(number)` |
[
0
]
| no | -| [elastic\_gpu\_specifications](#input\_elastic\_gpu\_specifications) | The elastic GPU to attach to the instance | `any` | `{}` | no | -| [elastic\_inference\_accelerator](#input\_elastic\_inference\_accelerator) | Configuration block containing an Elastic Inference Accelerator to attach to the instance | `map(string)` | `{}` | no | | [enable\_efa\_only](#input\_enable\_efa\_only) | Determines whether to enable EFA (`false`, default) or EFA and EFA-only (`true`) network interfaces. Note: requires vpc-cni version `v1.18.4` or later | `bool` | `false` | no | | [enable\_efa\_support](#input\_enable\_efa\_support) | Determines whether to enable Elastic Fabric Adapter (EFA) support | `bool` | `false` | no | | [enable\_monitoring](#input\_enable\_monitoring) | Enables/disables detailed monitoring | `bool` | `true` | no | diff --git a/modules/self-managed-node-group/main.tf b/modules/self-managed-node-group/main.tf index 24454ef74d..328505ad78 100644 --- a/modules/self-managed-node-group/main.tf +++ b/modules/self-managed-node-group/main.tf @@ -200,22 +200,6 @@ resource "aws_launch_template" "this" { disable_api_termination = var.disable_api_termination ebs_optimized = var.ebs_optimized - dynamic "elastic_gpu_specifications" { - for_each = var.elastic_gpu_specifications - - content { - type = elastic_gpu_specifications.value.type - } - } - - dynamic "elastic_inference_accelerator" { - for_each = length(var.elastic_inference_accelerator) > 0 ? [var.elastic_inference_accelerator] : [] - - content { - type = elastic_inference_accelerator.value.type - } - } - dynamic "enclave_options" { for_each = length(var.enclave_options) > 0 ? [var.enclave_options] : [] diff --git a/modules/self-managed-node-group/variables.tf b/modules/self-managed-node-group/variables.tf index 9076dab5af..dbbc68e6a6 100644 --- a/modules/self-managed-node-group/variables.tf +++ b/modules/self-managed-node-group/variables.tf @@ -202,18 +202,6 @@ variable "credit_specification" { default = {} } -variable "elastic_gpu_specifications" { - description = "The elastic GPU to attach to the instance" - type = any - default = {} -} - -variable "elastic_inference_accelerator" { - description = "Configuration block containing an Elastic Inference Accelerator to attach to the instance" - type = map(string) - default = {} -} - variable "enclave_options" { description = "Enable Nitro Enclaves on launched instances" type = map(string) diff --git a/node_groups.tf b/node_groups.tf index de7411f226..14148525fb 100644 --- a/node_groups.tf +++ b/node_groups.tf @@ -367,8 +367,6 @@ module "eks_managed_node_group" { capacity_reservation_specification = try(each.value.capacity_reservation_specification, var.eks_managed_node_group_defaults.capacity_reservation_specification, {}) cpu_options = try(each.value.cpu_options, var.eks_managed_node_group_defaults.cpu_options, {}) credit_specification = try(each.value.credit_specification, var.eks_managed_node_group_defaults.credit_specification, {}) - elastic_gpu_specifications = try(each.value.elastic_gpu_specifications, var.eks_managed_node_group_defaults.elastic_gpu_specifications, {}) - elastic_inference_accelerator = try(each.value.elastic_inference_accelerator, var.eks_managed_node_group_defaults.elastic_inference_accelerator, {}) enclave_options = try(each.value.enclave_options, var.eks_managed_node_group_defaults.enclave_options, {}) instance_market_options = try(each.value.instance_market_options, var.eks_managed_node_group_defaults.instance_market_options, {}) license_specifications = try(each.value.license_specifications, var.eks_managed_node_group_defaults.license_specifications, {}) @@ -519,8 +517,6 @@ module "self_managed_node_group" { capacity_reservation_specification = try(each.value.capacity_reservation_specification, var.self_managed_node_group_defaults.capacity_reservation_specification, {}) cpu_options = try(each.value.cpu_options, var.self_managed_node_group_defaults.cpu_options, {}) credit_specification = try(each.value.credit_specification, var.self_managed_node_group_defaults.credit_specification, {}) - elastic_gpu_specifications = try(each.value.elastic_gpu_specifications, var.self_managed_node_group_defaults.elastic_gpu_specifications, {}) - elastic_inference_accelerator = try(each.value.elastic_inference_accelerator, var.self_managed_node_group_defaults.elastic_inference_accelerator, {}) enclave_options = try(each.value.enclave_options, var.self_managed_node_group_defaults.enclave_options, {}) hibernation_options = try(each.value.hibernation_options, var.self_managed_node_group_defaults.hibernation_options, {}) instance_requirements = try(each.value.instance_requirements, var.self_managed_node_group_defaults.instance_requirements, {}) diff --git a/tests/eks-fargate-profile/README.md b/tests/eks-fargate-profile/README.md index 397d96228d..2696041cea 100644 --- a/tests/eks-fargate-profile/README.md +++ b/tests/eks-fargate-profile/README.md @@ -33,7 +33,7 @@ Note that this example may create resources which cost money. Run `terraform des | [disabled\_fargate\_profile](#module\_disabled\_fargate\_profile) | ../../modules/fargate-profile | n/a | | [eks](#module\_eks) | ../.. | n/a | | [fargate\_profile](#module\_fargate\_profile) | ../../modules/fargate-profile | n/a | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 | ## Resources diff --git a/tests/eks-fargate-profile/main.tf b/tests/eks-fargate-profile/main.tf index bf91d522a8..7ec4e9f414 100644 --- a/tests/eks-fargate-profile/main.tf +++ b/tests/eks-fargate-profile/main.tf @@ -125,7 +125,7 @@ module "disabled_fargate_profile" { module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" name = local.name cidr = local.vpc_cidr diff --git a/tests/eks-managed-node-group/README.md b/tests/eks-managed-node-group/README.md index 9a8cac3a60..be01e4bf7e 100644 --- a/tests/eks-managed-node-group/README.md +++ b/tests/eks-managed-node-group/README.md @@ -33,11 +33,11 @@ Note that this example may create resources which cost money. Run `terraform des | [aws\_vpc\_cni\_ipv6\_pod\_identity](#module\_aws\_vpc\_cni\_ipv6\_pod\_identity) | terraform-aws-modules/eks-pod-identity/aws | ~> 1.6 | | [disabled\_eks](#module\_disabled\_eks) | ../.. | n/a | | [disabled\_eks\_managed\_node\_group](#module\_disabled\_eks\_managed\_node\_group) | ../../modules/eks-managed-node-group | n/a | -| [ebs\_kms\_key](#module\_ebs\_kms\_key) | terraform-aws-modules/kms/aws | ~> 2.1 | +| [ebs\_kms\_key](#module\_ebs\_kms\_key) | terraform-aws-modules/kms/aws | ~> 3.0 | | [eks](#module\_eks) | ../.. | n/a | | [eks\_managed\_node\_group](#module\_eks\_managed\_node\_group) | ../../modules/eks-managed-node-group | n/a | | [key\_pair](#module\_key\_pair) | terraform-aws-modules/key-pair/aws | ~> 2.0 | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 | ## Resources diff --git a/tests/eks-managed-node-group/main.tf b/tests/eks-managed-node-group/main.tf index 010a55fa1b..df059b872e 100644 --- a/tests/eks-managed-node-group/main.tf +++ b/tests/eks-managed-node-group/main.tf @@ -476,7 +476,7 @@ module "disabled_eks_managed_node_group" { module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" name = local.name cidr = local.vpc_cidr @@ -523,7 +523,7 @@ module "aws_vpc_cni_ipv6_pod_identity" { module "ebs_kms_key" { source = "terraform-aws-modules/kms/aws" - version = "~> 2.1" + version = "~> 3.0" description = "Customer managed key to encrypt EKS managed node group volumes" diff --git a/tests/fast-addons/README.md b/tests/fast-addons/README.md index e09a5cf53b..bfc3c6ec58 100644 --- a/tests/fast-addons/README.md +++ b/tests/fast-addons/README.md @@ -35,7 +35,7 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Source | Version | |------|--------|---------| | [eks](#module\_eks) | ../.. | n/a | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 | ## Resources diff --git a/tests/fast-addons/main.tf b/tests/fast-addons/main.tf index e7a5b9cc55..2e91fac7d8 100644 --- a/tests/fast-addons/main.tf +++ b/tests/fast-addons/main.tf @@ -93,7 +93,7 @@ locals { module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" name = local.name cidr = local.vpc_cidr diff --git a/tests/self-managed-node-group/README.md b/tests/self-managed-node-group/README.md index 193314aa2c..d540b58b8d 100644 --- a/tests/self-managed-node-group/README.md +++ b/tests/self-managed-node-group/README.md @@ -32,11 +32,11 @@ Note that this example may create resources which cost money. Run `terraform des |------|--------|---------| | [aws\_vpc\_cni\_ipv4\_pod\_identity](#module\_aws\_vpc\_cni\_ipv4\_pod\_identity) | terraform-aws-modules/eks-pod-identity/aws | ~> 1.6 | | [disabled\_self\_managed\_node\_group](#module\_disabled\_self\_managed\_node\_group) | ../../modules/self-managed-node-group | n/a | -| [ebs\_kms\_key](#module\_ebs\_kms\_key) | terraform-aws-modules/kms/aws | ~> 2.0 | +| [ebs\_kms\_key](#module\_ebs\_kms\_key) | terraform-aws-modules/kms/aws | ~> 3.0 | | [eks](#module\_eks) | ../.. | n/a | | [key\_pair](#module\_key\_pair) | terraform-aws-modules/key-pair/aws | ~> 2.0 | -| [kms](#module\_kms) | terraform-aws-modules/kms/aws | ~> 2.1 | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | +| [kms](#module\_kms) | terraform-aws-modules/kms/aws | ~> 3.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 | ## Resources diff --git a/tests/self-managed-node-group/main.tf b/tests/self-managed-node-group/main.tf index 351985f359..2331d33685 100644 --- a/tests/self-managed-node-group/main.tf +++ b/tests/self-managed-node-group/main.tf @@ -378,7 +378,7 @@ module "disabled_self_managed_node_group" { module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" name = local.name cidr = local.vpc_cidr @@ -446,7 +446,7 @@ module "key_pair" { module "ebs_kms_key" { source = "terraform-aws-modules/kms/aws" - version = "~> 2.0" + version = "~> 3.0" description = "Customer managed key to encrypt EKS managed node group volumes" @@ -470,7 +470,7 @@ module "ebs_kms_key" { module "kms" { source = "terraform-aws-modules/kms/aws" - version = "~> 2.1" + version = "~> 3.0" aliases = ["eks/${local.name}"] description = "${local.name} cluster encryption key" diff --git a/versions.tf b/versions.tf index 52e65ff5b7..71efea2e03 100644 --- a/versions.tf +++ b/versions.tf @@ -8,7 +8,7 @@ terraform { } tls = { source = "hashicorp/tls" - version = ">= 3.0" + version = ">= 4.0" } time = { source = "hashicorp/time" From 14a356115e8acd14654d5193986584b3d0216407 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Mon, 7 Jul 2025 12:59:55 -0500 Subject: [PATCH 03/25] fix: Remove `aws-auth` sub-module --- modules/aws-auth/README.md | 81 ----------------------------------- modules/aws-auth/main.tf | 47 -------------------- modules/aws-auth/outputs.tf | 0 modules/aws-auth/variables.tf | 39 ----------------- modules/aws-auth/versions.tf | 10 ----- 5 files changed, 177 deletions(-) delete mode 100644 modules/aws-auth/README.md delete mode 100644 modules/aws-auth/main.tf delete mode 100644 modules/aws-auth/outputs.tf delete mode 100644 modules/aws-auth/variables.tf delete mode 100644 modules/aws-auth/versions.tf diff --git a/modules/aws-auth/README.md b/modules/aws-auth/README.md deleted file mode 100644 index dffb4525c8..0000000000 --- a/modules/aws-auth/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# `aws-auth` Module - -Configuration in this directory creates/updates the `aws-auth` ConfigMap. - -```hcl -module "eks" { - source = "terraform-aws-modules/eks/aws//modules/aws-auth" - version = "~> 20.0" - - manage_aws_auth_configmap = true - - aws_auth_roles = [ - { - rolearn = "arn:aws:iam::66666666666:role/role1" - username = "role1" - groups = ["system:masters"] - }, - ] - - aws_auth_users = [ - { - userarn = "arn:aws:iam::66666666666:user/user1" - username = "user1" - groups = ["system:masters"] - }, - { - userarn = "arn:aws:iam::66666666666:user/user2" - username = "user2" - groups = ["system:masters"] - }, - ] - - aws_auth_accounts = [ - "777777777777", - "888888888888", - ] -} -``` - -## Usage - - -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 1.5.7 | -| [kubernetes](#requirement\_kubernetes) | >= 2.20 | - -## Providers - -| Name | Version | -|------|---------| -| [kubernetes](#provider\_kubernetes) | >= 2.20 | - -## Modules - -No modules. - -## Resources - -| Name | Type | -|------|------| -| [kubernetes_config_map.aws_auth](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/config_map) | resource | -| [kubernetes_config_map_v1_data.aws_auth](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/config_map_v1_data) | resource | - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [aws\_auth\_accounts](#input\_aws\_auth\_accounts) | List of account maps to add to the aws-auth configmap | `list(any)` | `[]` | no | -| [aws\_auth\_roles](#input\_aws\_auth\_roles) | List of role maps to add to the aws-auth configmap | `list(any)` | `[]` | no | -| [aws\_auth\_users](#input\_aws\_auth\_users) | List of user maps to add to the aws-auth configmap | `list(any)` | `[]` | no | -| [create](#input\_create) | Controls if resources should be created (affects all resources) | `bool` | `true` | no | -| [create\_aws\_auth\_configmap](#input\_create\_aws\_auth\_configmap) | Determines whether to create the aws-auth configmap. NOTE - this is only intended for scenarios where the configmap does not exist (i.e. - when using only self-managed node groups). Most users should use `manage_aws_auth_configmap` | `bool` | `false` | no | -| [manage\_aws\_auth\_configmap](#input\_manage\_aws\_auth\_configmap) | Determines whether to manage the aws-auth configmap | `bool` | `true` | no | - -## Outputs - -No outputs. - diff --git a/modules/aws-auth/main.tf b/modules/aws-auth/main.tf deleted file mode 100644 index 2f7e9694a7..0000000000 --- a/modules/aws-auth/main.tf +++ /dev/null @@ -1,47 +0,0 @@ - -################################################################################ -# aws-auth configmap -################################################################################ - -locals { - aws_auth_configmap_data = { - mapRoles = yamlencode(var.aws_auth_roles) - mapUsers = yamlencode(var.aws_auth_users) - mapAccounts = yamlencode(var.aws_auth_accounts) - } -} - -resource "kubernetes_config_map" "aws_auth" { - count = var.create && var.create_aws_auth_configmap ? 1 : 0 - - metadata { - name = "aws-auth" - namespace = "kube-system" - } - - data = local.aws_auth_configmap_data - - lifecycle { - # We are ignoring the data here since we will manage it with the resource below - # This is only intended to be used in scenarios where the configmap does not exist - ignore_changes = [data, metadata[0].labels, metadata[0].annotations] - } -} - -resource "kubernetes_config_map_v1_data" "aws_auth" { - count = var.create && var.manage_aws_auth_configmap ? 1 : 0 - - force = true - - metadata { - name = "aws-auth" - namespace = "kube-system" - } - - data = local.aws_auth_configmap_data - - depends_on = [ - # Required for instances where the configmap does not exist yet to avoid race condition - kubernetes_config_map.aws_auth, - ] -} diff --git a/modules/aws-auth/outputs.tf b/modules/aws-auth/outputs.tf deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/modules/aws-auth/variables.tf b/modules/aws-auth/variables.tf deleted file mode 100644 index 3aaeb023e3..0000000000 --- a/modules/aws-auth/variables.tf +++ /dev/null @@ -1,39 +0,0 @@ -variable "create" { - description = "Controls if resources should be created (affects all resources)" - type = bool - default = true -} - -################################################################################ -# aws-auth ConfigMap -################################################################################ - -variable "create_aws_auth_configmap" { - description = "Determines whether to create the aws-auth configmap. NOTE - this is only intended for scenarios where the configmap does not exist (i.e. - when using only self-managed node groups). Most users should use `manage_aws_auth_configmap`" - type = bool - default = false -} - -variable "manage_aws_auth_configmap" { - description = "Determines whether to manage the aws-auth configmap" - type = bool - default = true -} - -variable "aws_auth_roles" { - description = "List of role maps to add to the aws-auth configmap" - type = list(any) - default = [] -} - -variable "aws_auth_users" { - description = "List of user maps to add to the aws-auth configmap" - type = list(any) - default = [] -} - -variable "aws_auth_accounts" { - description = "List of account maps to add to the aws-auth configmap" - type = list(any) - default = [] -} diff --git a/modules/aws-auth/versions.tf b/modules/aws-auth/versions.tf deleted file mode 100644 index 3b2df08b05..0000000000 --- a/modules/aws-auth/versions.tf +++ /dev/null @@ -1,10 +0,0 @@ -terraform { - required_version = ">= 1.5.7" - - required_providers { - kubernetes = { - source = "hashicorp/kubernetes" - version = ">= 2.20" - } - } -} From 200d7fbf50c054dc05d4443d9bfc44e2be8620ba Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Mon, 7 Jul 2025 14:06:01 -0500 Subject: [PATCH 04/25] fix: Remove `platform` and `cluster_service_ipv4_cidr` variables from `user-data` sub-module --- modules/_user_data/README.md | 7 +- modules/_user_data/main.tf | 97 ++++++++----------- modules/_user_data/outputs.tf | 7 +- modules/_user_data/variables.tf | 15 +-- modules/eks-managed-node-group/README.md | 5 +- modules/eks-managed-node-group/main.tf | 3 +- modules/eks-managed-node-group/outputs.tf | 9 -- modules/eks-managed-node-group/variables.tf | 15 +-- modules/self-managed-node-group/README.md | 4 +- modules/self-managed-node-group/main.tf | 1 - modules/self-managed-node-group/outputs.tf | 5 - modules/self-managed-node-group/variables.tf | 14 +-- node_groups.tf | 8 +- ...{linux_user_data.tpl => al2_user_data.tpl} | 0 tests/user-data/main.tf | 15 ++- 15 files changed, 67 insertions(+), 138 deletions(-) rename templates/{linux_user_data.tpl => al2_user_data.tpl} (100%) diff --git a/modules/_user_data/README.md b/modules/_user_data/README.md index bfc623cff3..610051bc9c 100644 --- a/modules/_user_data/README.md +++ b/modules/_user_data/README.md @@ -30,14 +30,14 @@ No modules. |------|------| | [null_resource.validate_cluster_service_cidr](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | | [cloudinit_config.al2023_eks_managed_node_group](https://registry.terraform.io/providers/hashicorp/cloudinit/latest/docs/data-sources/config) | data source | -| [cloudinit_config.linux_eks_managed_node_group](https://registry.terraform.io/providers/hashicorp/cloudinit/latest/docs/data-sources/config) | data source | +| [cloudinit_config.al2_eks_managed_node_group](https://registry.terraform.io/providers/hashicorp/cloudinit/latest/docs/data-sources/config) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [additional\_cluster\_dns\_ips](#input\_additional\_cluster\_dns\_ips) | Additional DNS IP addresses to use for the cluster. Only used when `ami_type` = `BOTTLEROCKET_*` | `list(string)` | `[]` | no | -| [ami\_type](#input\_ami\_type) | Type of Amazon Machine Image (AMI) associated with the EKS Node Group. See the [AWS documentation](https://docs.aws.amazon.com/eks/latest/APIReference/API_Nodegroup.html#AmazonEKS-Type-Nodegroup-amiType) for valid values | `string` | `null` | no | +| [ami\_type](#input\_ami\_type) | Type of Amazon Machine Image (AMI) associated with the EKS Node Group. See the [AWS documentation](https://docs.aws.amazon.com/eks/latest/APIReference/API_Nodegroup.html#AmazonEKS-Type-Nodegroup-amiType) for valid values | `string` | `"AL2023_x86_64_STANDARD"` | no | | [bootstrap\_extra\_args](#input\_bootstrap\_extra\_args) | Additional arguments passed to the bootstrap script. When `ami_type` = `BOTTLEROCKET_*`; these are additional [settings](https://github.com/bottlerocket-os/bottlerocket#settings) that are provided to the Bottlerocket user data | `string` | `""` | no | | [cloudinit\_post\_nodeadm](#input\_cloudinit\_post\_nodeadm) | Array of cloud-init document parts that are created after the nodeadm document part |
list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
}))
| `[]` | no | | [cloudinit\_pre\_nodeadm](#input\_cloudinit\_pre\_nodeadm) | Array of cloud-init document parts that are created before the nodeadm document part |
list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
}))
| `[]` | no | @@ -46,11 +46,9 @@ No modules. | [cluster\_ip\_family](#input\_cluster\_ip\_family) | The IP family used to assign Kubernetes pod and service addresses. Valid values are `ipv4` (default) and `ipv6` | `string` | `"ipv4"` | no | | [cluster\_name](#input\_cluster\_name) | Name of the EKS cluster | `string` | `""` | no | | [cluster\_service\_cidr](#input\_cluster\_service\_cidr) | The CIDR block (IPv4 or IPv6) used by the cluster to assign Kubernetes service IP addresses. This is derived from the cluster itself | `string` | `""` | no | -| [cluster\_service\_ipv4\_cidr](#input\_cluster\_service\_ipv4\_cidr) | [Deprecated] The CIDR block to assign Kubernetes service IP addresses from. If you don't specify a block, Kubernetes assigns addresses from either the 10.100.0.0/16 or 172.20.0.0/16 CIDR blocks | `string` | `null` | no | | [create](#input\_create) | Determines whether to create user-data or not | `bool` | `true` | no | | [enable\_bootstrap\_user\_data](#input\_enable\_bootstrap\_user\_data) | Determines whether the bootstrap configurations are populated within the user data template | `bool` | `false` | no | | [is\_eks\_managed\_node\_group](#input\_is\_eks\_managed\_node\_group) | Determines whether the user data is used on nodes in an EKS managed node group. Used to determine if user data will be appended or not | `bool` | `true` | no | -| [platform](#input\_platform) | [DEPRECATED - use `ami_type` instead. Will be removed in `v21.0`] Identifies the OS platform as `bottlerocket`, `linux` (AL2), `al2023`, or `windows` | `string` | `"linux"` | no | | [post\_bootstrap\_user\_data](#input\_post\_bootstrap\_user\_data) | User data that is appended to the user data script after of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | | [pre\_bootstrap\_user\_data](#input\_pre\_bootstrap\_user\_data) | User data that is injected into the user data script ahead of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | | [user\_data\_template\_path](#input\_user\_data\_template\_path) | Path to a local, custom user data template file to use when rendering user data | `string` | `""` | no | @@ -59,6 +57,5 @@ No modules. | Name | Description | |------|-------------| -| [platform](#output\_platform) | [DEPRECATED - Will be removed in `v21.0`] Identifies the OS platform as `bottlerocket`, `linux` (AL2), `al2023, or `windows | | [user\_data](#output\_user\_data) | Base64 encoded user data rendered for the provided inputs | diff --git a/modules/_user_data/main.tf b/modules/_user_data/main.tf index c24074af15..a665b31eec 100644 --- a/modules/_user_data/main.tf +++ b/modules/_user_data/main.tf @@ -7,51 +7,47 @@ resource "null_resource" "validate_cluster_service_cidr" { precondition { # The length 6 is currently arbitrary, but it's a safe bet that the CIDR will be longer than that # The main point is that a value needs to be provided when `create = true` - condition = var.create ? length(local.cluster_service_cidr) > 6 : true + condition = var.create ? length(var.cluster_service_cidr) > 6 : true error_message = "`cluster_service_cidr` is required when `create = true`." } } } locals { - # Converts AMI type into user data type that represents the underlying format (bash, toml, PS1, nodeadm) - # TODO - platform will be removed in v21.0 and only `ami_type` will be valid - ami_type_to_user_data_type = { - AL2_x86_64 = "linux" - AL2_x86_64_GPU = "linux" - AL2_ARM_64 = "linux" - BOTTLEROCKET_ARM_64 = "bottlerocket" - BOTTLEROCKET_x86_64 = "bottlerocket" - BOTTLEROCKET_ARM_64_FIPS = "bottlerocket" - BOTTLEROCKET_x86_64_FIPS = "bottlerocket" - BOTTLEROCKET_ARM_64_NVIDIA = "bottlerocket" - BOTTLEROCKET_x86_64_NVIDIA = "bottlerocket" - WINDOWS_CORE_2019_x86_64 = "windows" - WINDOWS_FULL_2019_x86_64 = "windows" - WINDOWS_CORE_2022_x86_64 = "windows" - WINDOWS_FULL_2022_x86_64 = "windows" - AL2023_x86_64_STANDARD = "al2023" - AL2023_ARM_64_STANDARD = "al2023" - AL2023_x86_64_NEURON = "al2023" - AL2023_x86_64_NVIDIA = "al2023" - AL2023_ARM_64_NVIDIA = "al2023" - } - # Try to use `ami_type` first, but fall back to current, default behavior - # TODO - will be removed in v21.0 - user_data_type = try(local.ami_type_to_user_data_type[var.ami_type], var.platform) - - template_path = { - al2023 = "${path.module}/../../templates/al2023_user_data.tpl" - bottlerocket = "${path.module}/../../templates/bottlerocket_user_data.tpl" - linux = "${path.module}/../../templates/linux_user_data.tpl" - windows = "${path.module}/../../templates/windows_user_data.tpl" + is_al2 = startswith(var.ami_type, "AL2_") + is_al2023 = startswith(var.ami_type, "AL2023_") + + # Converts AMI type into user data template path + ami_type_to_user_data_path = { + AL2_ARM_64 = "${path.module}/../../templates/al2_user_data.tpl" + AL2_x86_64 = "${path.module}/../../templates/al2_user_data.tpl" + AL2_x86_64_GPU = "${path.module}/../../templates/al2_user_data.tpl" + + AL2023_x86_64_STANDARD = "${path.module}/../../templates/al2023_user_data.tpl" + AL2023_ARM_64_STANDARD = "${path.module}/../../templates/al2023_user_data.tpl" + AL2023_x86_64_NEURON = "${path.module}/../../templates/al2023_user_data.tpl" + AL2023_x86_64_NVIDIA = "${path.module}/../../templates/al2023_user_data.tpl" + AL2023_ARM_64_NVIDIA = "${path.module}/../../templates/al2023_user_data.tpl" + + BOTTLEROCKET_ARM_64 = "${path.module}/../../templates/bottlerocket_user_data.tpl" + BOTTLEROCKET_x86_64 = "${path.module}/../../templates/bottlerocket_user_data.tpl" + BOTTLEROCKET_ARM_64_FIPS = "${path.module}/../../templates/bottlerocket_user_data.tpl" + BOTTLEROCKET_x86_64_FIPS = "${path.module}/../../templates/bottlerocket_user_data.tpl" + BOTTLEROCKET_ARM_64_NVIDIA = "${path.module}/../../templates/bottlerocket_user_data.tpl" + BOTTLEROCKET_x86_64_NVIDIA = "${path.module}/../../templates/bottlerocket_user_data.tpl" + + WINDOWS_CORE_2019_x86_64 = "${path.module}/../../templates/windows_user_data.tpl" + WINDOWS_FULL_2019_x86_64 = "${path.module}/../../templates/windows_user_data.tpl" + WINDOWS_CORE_2022_x86_64 = "${path.module}/../../templates/windows_user_data.tpl" + WINDOWS_FULL_2022_x86_64 = "${path.module}/../../templates/windows_user_data.tpl" + + CUSTOM = var.user_data_template_path } + user_data_path = coalesce(var.user_data_template_path, local.ami_type_to_user_data_path[var.ami_type]) - cluster_service_cidr = try(coalesce(var.cluster_service_ipv4_cidr, var.cluster_service_cidr), "") - cluster_dns_ips = flatten(concat([try(cidrhost(local.cluster_service_cidr, 10), "")], var.additional_cluster_dns_ips)) + cluster_dns_ips = flatten(concat([try(cidrhost(var.cluster_service_cidr, 10), "")], var.additional_cluster_dns_ips)) - user_data = base64encode(templatefile( - coalesce(var.user_data_template_path, local.template_path[local.user_data_type]), + user_data = var.ami_type != "" ? base64encode(templatefile(local.user_data_path, { # https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-custom-ami enable_bootstrap_user_data = var.enable_bootstrap_user_data @@ -61,7 +57,7 @@ locals { cluster_endpoint = var.cluster_endpoint cluster_auth_base64 = var.cluster_auth_base64 - cluster_service_cidr = local.cluster_service_cidr + cluster_service_cidr = var.cluster_service_cidr cluster_ip_family = var.cluster_ip_family # Bottlerocket @@ -72,22 +68,13 @@ locals { pre_bootstrap_user_data = var.pre_bootstrap_user_data post_bootstrap_user_data = var.post_bootstrap_user_data } - )) + )) : "" - user_data_type_to_rendered = { - al2023 = { - user_data = var.create ? try(data.cloudinit_config.al2023_eks_managed_node_group[0].rendered, local.user_data) : "" - } - bottlerocket = { - user_data = var.create && local.user_data_type == "bottlerocket" && (var.enable_bootstrap_user_data || var.user_data_template_path != "" || var.bootstrap_extra_args != "") ? local.user_data : "" - } - linux = { - user_data = var.create ? try(data.cloudinit_config.linux_eks_managed_node_group[0].rendered, local.user_data) : "" - } - windows = { - user_data = var.create && local.user_data_type == "windows" && (var.enable_bootstrap_user_data || var.user_data_template_path != "" || var.pre_bootstrap_user_data != "") ? local.user_data : "" - } - } + user_data_type_to_rendered = try(coalesce( + local.is_al2 ? try(data.cloudinit_config.al2_eks_managed_node_group[0].rendered, local.user_data) : null, + local.is_al2023 ? try(data.cloudinit_config.al2023_eks_managed_node_group[0].rendered, local.user_data) : null, + local.user_data, + ), "") } # https://github.com/aws/containers-roadmap/issues/596#issuecomment-675097667 @@ -97,8 +84,8 @@ locals { # this merging will NOT happen and you are responsible for nodes joining the cluster. # See docs for more details -> https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-user-data -data "cloudinit_config" "linux_eks_managed_node_group" { - count = var.create && local.user_data_type == "linux" && var.is_eks_managed_node_group && !var.enable_bootstrap_user_data && var.pre_bootstrap_user_data != "" && var.user_data_template_path == "" ? 1 : 0 +data "cloudinit_config" "al2_eks_managed_node_group" { + count = var.create && local.is_al2 && var.is_eks_managed_node_group && !var.enable_bootstrap_user_data && var.pre_bootstrap_user_data != "" && var.user_data_template_path == "" ? 1 : 0 base64_encode = true gzip = false @@ -129,7 +116,7 @@ locals { } data "cloudinit_config" "al2023_eks_managed_node_group" { - count = var.create && local.user_data_type == "al2023" && length(local.nodeadm_cloudinit) > 0 ? 1 : 0 + count = var.create && local.is_al2023 && length(local.nodeadm_cloudinit) > 0 ? 1 : 0 base64_encode = true gzip = false diff --git a/modules/_user_data/outputs.tf b/modules/_user_data/outputs.tf index 7bebb3f218..40c1d82a4e 100644 --- a/modules/_user_data/outputs.tf +++ b/modules/_user_data/outputs.tf @@ -1,9 +1,4 @@ output "user_data" { description = "Base64 encoded user data rendered for the provided inputs" - value = try(local.user_data_type_to_rendered[local.user_data_type].user_data, null) -} - -output "platform" { - description = "[DEPRECATED - Will be removed in `v21.0`] Identifies the OS platform as `bottlerocket`, `linux` (AL2), `al2023, or `windows`" - value = local.user_data_type + value = var.create ? local.user_data_type_to_rendered : "" } diff --git a/modules/_user_data/variables.tf b/modules/_user_data/variables.tf index d5a1ef1bd3..ea3ad3620c 100644 --- a/modules/_user_data/variables.tf +++ b/modules/_user_data/variables.tf @@ -4,16 +4,10 @@ variable "create" { default = true } -variable "platform" { - description = "[DEPRECATED - use `ami_type` instead. Will be removed in `v21.0`] Identifies the OS platform as `bottlerocket`, `linux` (AL2), `al2023`, or `windows`" - type = string - default = "linux" -} - variable "ami_type" { description = "Type of Amazon Machine Image (AMI) associated with the EKS Node Group. See the [AWS documentation](https://docs.aws.amazon.com/eks/latest/APIReference/API_Nodegroup.html#AmazonEKS-Type-Nodegroup-amiType) for valid values" type = string - default = null + default = "AL2023_x86_64_STANDARD" } variable "enable_bootstrap_user_data" { @@ -64,13 +58,6 @@ variable "additional_cluster_dns_ips" { default = [] } -# TODO - remove at next breaking change -variable "cluster_service_ipv4_cidr" { - description = "[Deprecated] The CIDR block to assign Kubernetes service IP addresses from. If you don't specify a block, Kubernetes assigns addresses from either the 10.100.0.0/16 or 172.20.0.0/16 CIDR blocks" - type = string - default = null -} - variable "pre_bootstrap_user_data" { description = "User data that is injected into the user data script ahead of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*`" type = string diff --git a/modules/eks-managed-node-group/README.md b/modules/eks-managed-node-group/README.md index 3c1ea95d76..c7726185aa 100644 --- a/modules/eks-managed-node-group/README.md +++ b/modules/eks-managed-node-group/README.md @@ -105,7 +105,7 @@ module "eks_managed_node_group" { |------|-------------|------|---------|:--------:| | [ami\_id](#input\_ami\_id) | The AMI from which to launch the instance. If not supplied, EKS will use its own default image | `string` | `""` | no | | [ami\_release\_version](#input\_ami\_release\_version) | The AMI version. Defaults to latest AMI release version for the given Kubernetes version and AMI type | `string` | `null` | no | -| [ami\_type](#input\_ami\_type) | Type of Amazon Machine Image (AMI) associated with the EKS Node Group. See the [AWS documentation](https://docs.aws.amazon.com/eks/latest/APIReference/API_Nodegroup.html#AmazonEKS-Type-Nodegroup-amiType) for valid values | `string` | `null` | no | +| [ami\_type](#input\_ami\_type) | Type of Amazon Machine Image (AMI) associated with the EKS Node Group. See the [AWS documentation](https://docs.aws.amazon.com/eks/latest/APIReference/API_Nodegroup.html#AmazonEKS-Type-Nodegroup-amiType) for valid values | `string` | `"AL2023_x86_64_STANDARD"` | no | | [block\_device\_mappings](#input\_block\_device\_mappings) | Specify volumes to attach to the instance besides the volumes specified by the AMI | `any` | `{}` | no | | [bootstrap\_extra\_args](#input\_bootstrap\_extra\_args) | Additional arguments passed to the bootstrap script. When `ami_type` = `BOTTLEROCKET_*`; these are additional [settings](https://github.com/bottlerocket-os/bottlerocket#settings) that are provided to the Bottlerocket user data | `string` | `""` | no | | [capacity\_reservation\_specification](#input\_capacity\_reservation\_specification) | Targeting for EC2 capacity reservations | `any` | `{}` | no | @@ -118,7 +118,6 @@ module "eks_managed_node_group" { | [cluster\_name](#input\_cluster\_name) | Name of associated EKS cluster | `string` | `null` | no | | [cluster\_primary\_security\_group\_id](#input\_cluster\_primary\_security\_group\_id) | The ID of the EKS cluster primary security group to associate with the instance(s). This is the security group that is automatically created by the EKS service | `string` | `null` | no | | [cluster\_service\_cidr](#input\_cluster\_service\_cidr) | The CIDR block (IPv4 or IPv6) used by the cluster to assign Kubernetes service IP addresses. This is derived from the cluster itself | `string` | `""` | no | -| [cluster\_service\_ipv4\_cidr](#input\_cluster\_service\_ipv4\_cidr) | [Deprecated] The CIDR block to assign Kubernetes service IP addresses from. If you don't specify a block, Kubernetes assigns addresses from either the 10.100.0.0/16 or 172.20.0.0/16 CIDR blocks | `string` | `null` | no | | [cluster\_version](#input\_cluster\_version) | Kubernetes version. Defaults to EKS Cluster Kubernetes version | `string` | `null` | no | | [cpu\_options](#input\_cpu\_options) | The CPU options for the instance | `map(string)` | `{}` | no | | [create](#input\_create) | Determines whether to create EKS managed node group or not | `bool` | `true` | no | @@ -172,7 +171,6 @@ module "eks_managed_node_group" { | [placement](#input\_placement) | The placement of the instance | `map(string)` | `{}` | no | | [placement\_group\_az](#input\_placement\_group\_az) | Availability zone where placement group is created (ex. `eu-west-1c`) | `string` | `null` | no | | [placement\_group\_strategy](#input\_placement\_group\_strategy) | The placement group strategy | `string` | `"cluster"` | no | -| [platform](#input\_platform) | [DEPRECATED - use `ami_type` instead. Will be removed in `v21.0`] Identifies the OS platform as `bottlerocket`, `linux` (AL2), `al2023`, or `windows` | `string` | `"linux"` | no | | [post\_bootstrap\_user\_data](#input\_post\_bootstrap\_user\_data) | User data that is appended to the user data script after of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | | [pre\_bootstrap\_user\_data](#input\_pre\_bootstrap\_user\_data) | User data that is injected into the user data script ahead of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | | [private\_dns\_name\_options](#input\_private\_dns\_name\_options) | The options for the instance hostname. The default values are inherited from the subnet | `map(string)` | `{}` | no | @@ -211,5 +209,4 @@ module "eks_managed_node_group" { | [node\_group\_resources](#output\_node\_group\_resources) | List of objects containing information about underlying resources | | [node\_group\_status](#output\_node\_group\_status) | Status of the EKS Node Group | | [node\_group\_taints](#output\_node\_group\_taints) | List of objects containing information about taints applied to the node group | -| [platform](#output\_platform) | [DEPRECATED - Will be removed in `v21.0`] Identifies the OS platform as `bottlerocket`, `linux` (AL2), `al2023`, or `windows` | diff --git a/modules/eks-managed-node-group/main.tf b/modules/eks-managed-node-group/main.tf index e2a2955dc3..2d37bc352a 100644 --- a/modules/eks-managed-node-group/main.tf +++ b/modules/eks-managed-node-group/main.tf @@ -9,14 +9,13 @@ module "user_data" { source = "../_user_data" create = var.create - platform = var.platform ami_type = var.ami_type cluster_name = var.cluster_name cluster_endpoint = var.cluster_endpoint cluster_auth_base64 = var.cluster_auth_base64 cluster_ip_family = var.cluster_ip_family - cluster_service_cidr = try(coalesce(var.cluster_service_cidr, var.cluster_service_ipv4_cidr), "") + cluster_service_cidr = var.cluster_service_cidr enable_bootstrap_user_data = var.enable_bootstrap_user_data pre_bootstrap_user_data = var.pre_bootstrap_user_data diff --git a/modules/eks-managed-node-group/outputs.tf b/modules/eks-managed-node-group/outputs.tf index 8cab6e2c13..012cd46f4e 100644 --- a/modules/eks-managed-node-group/outputs.tf +++ b/modules/eks-managed-node-group/outputs.tf @@ -88,12 +88,3 @@ output "iam_role_unique_id" { description = "Stable and unique string identifying the IAM role" value = try(aws_iam_role.this[0].unique_id, null) } - -################################################################################ -# Additional -################################################################################ - -output "platform" { - description = "[DEPRECATED - Will be removed in `v21.0`] Identifies the OS platform as `bottlerocket`, `linux` (AL2), `al2023`, or `windows`" - value = module.user_data.platform -} diff --git a/modules/eks-managed-node-group/variables.tf b/modules/eks-managed-node-group/variables.tf index db4c78128b..a5f5642abf 100644 --- a/modules/eks-managed-node-group/variables.tf +++ b/modules/eks-managed-node-group/variables.tf @@ -10,12 +10,6 @@ variable "tags" { default = {} } -variable "platform" { - description = "[DEPRECATED - use `ami_type` instead. Will be removed in `v21.0`] Identifies the OS platform as `bottlerocket`, `linux` (AL2), `al2023`, or `windows`" - type = string - default = "linux" -} - ################################################################################ # User Data ################################################################################ @@ -50,13 +44,6 @@ variable "cluster_service_cidr" { default = "" } -# TODO - remove at next breaking change -variable "cluster_service_ipv4_cidr" { - description = "[Deprecated] The CIDR block to assign Kubernetes service IP addresses from. If you don't specify a block, Kubernetes assigns addresses from either the 10.100.0.0/16 or 172.20.0.0/16 CIDR blocks" - type = string - default = null -} - variable "pre_bootstrap_user_data" { description = "User data that is injected into the user data script ahead of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*`" type = string @@ -379,7 +366,7 @@ variable "use_name_prefix" { variable "ami_type" { description = "Type of Amazon Machine Image (AMI) associated with the EKS Node Group. See the [AWS documentation](https://docs.aws.amazon.com/eks/latest/APIReference/API_Nodegroup.html#AmazonEKS-Type-Nodegroup-amiType) for valid values" type = string - default = null + default = "AL2023_x86_64_STANDARD" } variable "ami_release_version" { diff --git a/modules/self-managed-node-group/README.md b/modules/self-managed-node-group/README.md index 0841fd9685..3821028284 100644 --- a/modules/self-managed-node-group/README.md +++ b/modules/self-managed-node-group/README.md @@ -86,7 +86,7 @@ module "self_managed_node_group" { |------|-------------|------|---------|:--------:| | [additional\_cluster\_dns\_ips](#input\_additional\_cluster\_dns\_ips) | Additional DNS IP addresses to use for the cluster. Only used when `ami_type` = `BOTTLEROCKET_*` | `list(string)` | `[]` | no | | [ami\_id](#input\_ami\_id) | The AMI from which to launch the instance | `string` | `""` | no | -| [ami\_type](#input\_ami\_type) | Type of Amazon Machine Image (AMI) associated with the node group. See the [AWS documentation](https://docs.aws.amazon.com/eks/latest/APIReference/API_Nodegroup.html#AmazonEKS-Type-Nodegroup-amiType) for valid values | `string` | `"AL2_x86_64"` | no | +| [ami\_type](#input\_ami\_type) | Type of Amazon Machine Image (AMI) associated with the node group. See the [AWS documentation](https://docs.aws.amazon.com/eks/latest/APIReference/API_Nodegroup.html#AmazonEKS-Type-Nodegroup-amiType) for valid values | `string` | `"AL2023_x86_64_STANDARD"` | no | | [autoscaling\_group\_tags](#input\_autoscaling\_group\_tags) | A map of additional tags to add to the autoscaling group created. Tags are applied to the autoscaling group only and are NOT propagated to instances | `map(string)` | `{}` | no | | [availability\_zones](#input\_availability\_zones) | A list of one or more availability zones for the group. Used for EC2-Classic and default subnets when not specified with `subnet_ids` argument. Conflicts with `subnet_ids` | `list(string)` | `null` | no | | [block\_device\_mappings](#input\_block\_device\_mappings) | Specify volumes to attach to the instance besides the volumes specified by the AMI | `any` | `{}` | no | @@ -173,7 +173,6 @@ module "self_managed_node_group" { | [placement](#input\_placement) | The placement of the instance | `map(string)` | `{}` | no | | [placement\_group](#input\_placement\_group) | The name of the placement group into which you'll launch your instances, if any | `string` | `null` | no | | [placement\_group\_az](#input\_placement\_group\_az) | Availability zone where placement group is created (ex. `eu-west-1c`) | `string` | `null` | no | -| [platform](#input\_platform) | [DEPRECATED - must use `ami_type` instead. Will be removed in `v21.0`] | `string` | `null` | no | | [post\_bootstrap\_user\_data](#input\_post\_bootstrap\_user\_data) | User data that is appended to the user data script after of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | | [pre\_bootstrap\_user\_data](#input\_pre\_bootstrap\_user\_data) | User data that is injected into the user data script ahead of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | | [private\_dns\_name\_options](#input\_private\_dns\_name\_options) | The options for the instance hostname. The default values are inherited from the subnet | `map(string)` | `{}` | no | @@ -224,6 +223,5 @@ module "self_managed_node_group" { | [launch\_template\_id](#output\_launch\_template\_id) | The ID of the launch template | | [launch\_template\_latest\_version](#output\_launch\_template\_latest\_version) | The latest version of the launch template | | [launch\_template\_name](#output\_launch\_template\_name) | The name of the launch template | -| [platform](#output\_platform) | [DEPRECATED - Will be removed in `v21.0`] Identifies the OS platform as `bottlerocket`, `linux` (AL2), `al2023`, or `windows` | | [user\_data](#output\_user\_data) | Base64 encoded user data | diff --git a/modules/self-managed-node-group/main.tf b/modules/self-managed-node-group/main.tf index 328505ad78..31dd5f4dbc 100644 --- a/modules/self-managed-node-group/main.tf +++ b/modules/self-managed-node-group/main.tf @@ -70,7 +70,6 @@ module "user_data" { source = "../_user_data" create = var.create - platform = local.user_data_type ami_type = var.ami_type is_eks_managed_node_group = false diff --git a/modules/self-managed-node-group/outputs.tf b/modules/self-managed-node-group/outputs.tf index 9607810ac3..bf3564cb25 100644 --- a/modules/self-managed-node-group/outputs.tf +++ b/modules/self-managed-node-group/outputs.tf @@ -141,11 +141,6 @@ output "autoscaling_group_schedule_arns" { # Additional ################################################################################ -output "platform" { - description = "[DEPRECATED - Will be removed in `v21.0`] Identifies the OS platform as `bottlerocket`, `linux` (AL2), `al2023`, or `windows`" - value = module.user_data.platform -} - output "image_id" { description = "ID of the image" value = try(aws_launch_template.this[0].image_id, null) diff --git a/modules/self-managed-node-group/variables.tf b/modules/self-managed-node-group/variables.tf index dbbc68e6a6..7ded12ca34 100644 --- a/modules/self-managed-node-group/variables.tf +++ b/modules/self-managed-node-group/variables.tf @@ -10,18 +10,6 @@ variable "tags" { default = {} } -# tflint-ignore: terraform_unused_declarations -variable "platform" { - description = "[DEPRECATED - must use `ami_type` instead. Will be removed in `v21.0`]" - type = string - default = null - - validation { - condition = var.platform == null - error_message = "`platform` is no longer valid due to the number of OS choices. Please provide an [`ami_type`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-nodegroup.html#cfn-eks-nodegroup-amitype) instead." - } -} - ################################################################################ # User Data ################################################################################ @@ -271,7 +259,7 @@ variable "ami_id" { variable "ami_type" { description = "Type of Amazon Machine Image (AMI) associated with the node group. See the [AWS documentation](https://docs.aws.amazon.com/eks/latest/APIReference/API_Nodegroup.html#AmazonEKS-Type-Nodegroup-amiType) for valid values" type = string - default = "AL2_x86_64" + default = "AL2023_x86_64_STANDARD" } variable "cluster_version" { diff --git a/node_groups.tf b/node_groups.tf index 14148525fb..b6f4f22826 100644 --- a/node_groups.tf +++ b/node_groups.tf @@ -314,7 +314,7 @@ module "eks_managed_node_group" { desired_size = try(each.value.desired_size, var.eks_managed_node_group_defaults.desired_size, 1) ami_id = try(each.value.ami_id, var.eks_managed_node_group_defaults.ami_id, "") - ami_type = try(each.value.ami_type, var.eks_managed_node_group_defaults.ami_type, null) + ami_type = try(each.value.ami_type, var.eks_managed_node_group_defaults.ami_type, "AL2023_x86_64_STANDARD") ami_release_version = try(each.value.ami_release_version, var.eks_managed_node_group_defaults.ami_release_version, null) use_latest_ami_release_version = try(each.value.use_latest_ami_release_version, var.eks_managed_node_group_defaults.use_latest_ami_release_version, false) @@ -330,10 +330,8 @@ module "eks_managed_node_group" { timeouts = try(each.value.timeouts, var.eks_managed_node_group_defaults.timeouts, {}) # User data - platform = try(each.value.platform, var.eks_managed_node_group_defaults.platform, "linux") cluster_endpoint = try(time_sleep.this[0].triggers["cluster_endpoint"], "") cluster_auth_base64 = try(time_sleep.this[0].triggers["cluster_certificate_authority_data"], "") - cluster_service_ipv4_cidr = var.cluster_service_ipv4_cidr cluster_ip_family = var.cluster_ip_family cluster_service_cidr = try(time_sleep.this[0].triggers["cluster_service_cidr"], "") enable_bootstrap_user_data = try(each.value.enable_bootstrap_user_data, var.eks_managed_node_group_defaults.enable_bootstrap_user_data, false) @@ -475,9 +473,7 @@ module "self_managed_node_group" { autoscaling_group_tags = try(each.value.autoscaling_group_tags, var.self_managed_node_group_defaults.autoscaling_group_tags, {}) # User data - platform = try(each.value.platform, var.self_managed_node_group_defaults.platform, null) - # TODO - update this when `var.platform` is removed in v21.0 - ami_type = try(each.value.ami_type, var.self_managed_node_group_defaults.ami_type, "AL2_x86_64") + ami_type = try(each.value.ami_type, var.self_managed_node_group_defaults.ami_type, "AL2023_x86_64_STANDARD") cluster_endpoint = try(time_sleep.this[0].triggers["cluster_endpoint"], "") cluster_auth_base64 = try(time_sleep.this[0].triggers["cluster_certificate_authority_data"], "") cluster_service_cidr = try(time_sleep.this[0].triggers["cluster_service_cidr"], "") diff --git a/templates/linux_user_data.tpl b/templates/al2_user_data.tpl similarity index 100% rename from templates/linux_user_data.tpl rename to templates/al2_user_data.tpl diff --git a/tests/user-data/main.tf b/tests/user-data/main.tf index 9a55b3cf77..835d9fc347 100644 --- a/tests/user-data/main.tf +++ b/tests/user-data/main.tf @@ -15,13 +15,15 @@ locals { module "eks_mng_al2_disabled" { source = "../../modules/_user_data" - create = false + ami_type = "AL2_x86_64" + create = false } module "eks_mng_al2_no_op" { source = "../../modules/_user_data" # Hard requirement + ami_type = "AL2_x86_64" cluster_service_cidr = local.cluster_service_cidr } @@ -29,6 +31,7 @@ module "eks_mng_al2_additional" { source = "../../modules/_user_data" # Hard requirement + ami_type = "AL2_x86_64" cluster_service_cidr = local.cluster_service_cidr pre_bootstrap_user_data = <<-EOT @@ -39,6 +42,7 @@ module "eks_mng_al2_additional" { module "eks_mng_al2_custom_ami" { source = "../../modules/_user_data" + ami_type = "AL2_x86_64" cluster_name = local.name cluster_endpoint = local.cluster_endpoint cluster_auth_base64 = local.cluster_auth_base64 @@ -60,6 +64,7 @@ module "eks_mng_al2_custom_ami" { module "eks_mng_al2_custom_ami_ipv6" { source = "../../modules/_user_data" + ami_type = "AL2_x86_64" cluster_name = local.name cluster_endpoint = local.cluster_endpoint cluster_auth_base64 = local.cluster_auth_base64 @@ -82,6 +87,7 @@ module "eks_mng_al2_custom_ami_ipv6" { module "eks_mng_al2_custom_template" { source = "../../modules/_user_data" + ami_type = "AL2_x86_64" cluster_name = local.name cluster_endpoint = local.cluster_endpoint cluster_auth_base64 = local.cluster_auth_base64 @@ -364,12 +370,15 @@ module "self_mng_al2_no_op" { is_eks_managed_node_group = false # Hard requirement + ami_type = "AL2_x86_64" cluster_service_cidr = local.cluster_service_cidr } module "self_mng_al2_bootstrap" { source = "../../modules/_user_data" + ami_type = "AL2_x86_64" + enable_bootstrap_user_data = true is_eks_managed_node_group = false @@ -393,6 +402,8 @@ module "self_mng_al2_bootstrap" { module "self_mng_al2_bootstrap_ipv6" { source = "../../modules/_user_data" + ami_type = "AL2_x86_64" + enable_bootstrap_user_data = true is_eks_managed_node_group = false @@ -417,6 +428,8 @@ module "self_mng_al2_bootstrap_ipv6" { module "self_mng_al2_custom_template" { source = "../../modules/_user_data" + ami_type = "AL2_x86_64" + enable_bootstrap_user_data = true is_eks_managed_node_group = false From 7bee6c5a82bf94926cae730dd4d74a52d325f0b5 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Mon, 7 Jul 2025 14:23:01 -0500 Subject: [PATCH 05/25] fix: Resolve all marked `todos` that have been accumulated --- README.md | 2 - examples/karpenter/main.tf | 3 +- main.tf | 44 +-- modules/eks-managed-node-group/README.md | 7 +- modules/eks-managed-node-group/main.tf | 56 +-- modules/eks-managed-node-group/variables.tf | 13 +- modules/karpenter/README.md | 5 +- modules/karpenter/main.tf | 6 - modules/karpenter/policy.tf | 355 +------------------ modules/karpenter/variables.tf | 11 +- modules/self-managed-node-group/README.md | 5 +- modules/self-managed-node-group/main.tf | 82 +---- modules/self-managed-node-group/variables.tf | 9 +- node_groups.tf | 2 - tests/fast-addons/README.md | 92 ----- tests/fast-addons/main.tf | 159 --------- tests/fast-addons/outputs.tf | 226 ------------ tests/fast-addons/variables.tf | 0 tests/fast-addons/versions.tf | 10 - variables.tf | 14 - 20 files changed, 24 insertions(+), 1077 deletions(-) delete mode 100644 tests/fast-addons/README.md delete mode 100644 tests/fast-addons/main.tf delete mode 100644 tests/fast-addons/outputs.tf delete mode 100644 tests/fast-addons/variables.tf delete mode 100644 tests/fast-addons/versions.tf diff --git a/README.md b/README.md index 2ff7661824..de2d3a9b64 100644 --- a/README.md +++ b/README.md @@ -385,7 +385,6 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [access\_entries](#input\_access\_entries) | Map of access entries to add to the cluster | `any` | `{}` | no | | [attach\_cluster\_encryption\_policy](#input\_attach\_cluster\_encryption\_policy) | Indicates whether or not to attach an additional policy for the cluster IAM role to utilize the encryption key provided | `bool` | `true` | no | | [authentication\_mode](#input\_authentication\_mode) | The authentication mode for the cluster. Valid values are `CONFIG_MAP`, `API` or `API_AND_CONFIG_MAP` | `string` | `"API_AND_CONFIG_MAP"` | no | -| [bootstrap\_self\_managed\_addons](#input\_bootstrap\_self\_managed\_addons) | Indicates whether or not to bootstrap self-managed addons after the cluster has been created | `bool` | `null` | no | | [cloudwatch\_log\_group\_class](#input\_cloudwatch\_log\_group\_class) | Specified the log class of the log group. Possible values are: `STANDARD` or `INFREQUENT_ACCESS` | `string` | `null` | no | | [cloudwatch\_log\_group\_kms\_key\_id](#input\_cloudwatch\_log\_group\_kms\_key\_id) | If a KMS Key ARN is set, this key will be used to encrypt the corresponding log group. Please be sure that the KMS Key has an appropriate key policy (https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/encrypt-log-data-kms.html) | `string` | `null` | no | | [cloudwatch\_log\_group\_retention\_in\_days](#input\_cloudwatch\_log\_group\_retention\_in\_days) | Number of days to retain log events. Default retention - 90 days | `number` | `90` | no | @@ -441,7 +440,6 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [enable\_efa\_support](#input\_enable\_efa\_support) | Determines whether to enable Elastic Fabric Adapter (EFA) support | `bool` | `false` | no | | [enable\_irsa](#input\_enable\_irsa) | Determines whether to create an OpenID Connect Provider for EKS to enable IRSA | `bool` | `true` | no | | [enable\_kms\_key\_rotation](#input\_enable\_kms\_key\_rotation) | Specifies whether key rotation is enabled | `bool` | `true` | no | -| [enable\_security\_groups\_for\_pods](#input\_enable\_security\_groups\_for\_pods) | Determines whether to add the necessary IAM permission policy for security groups for pods | `bool` | `true` | no | | [fargate\_profile\_defaults](#input\_fargate\_profile\_defaults) | Map of Fargate Profile default configurations | `any` | `{}` | no | | [fargate\_profiles](#input\_fargate\_profiles) | Map of Fargate Profile definitions to create | `any` | `{}` | no | | [iam\_role\_additional\_policies](#input\_iam\_role\_additional\_policies) | Additional policies to be added to the IAM role | `map(string)` | `{}` | no | diff --git a/examples/karpenter/main.tf b/examples/karpenter/main.tf index b4b7fc4fba..de205e3854 100644 --- a/examples/karpenter/main.tf +++ b/examples/karpenter/main.tf @@ -106,8 +106,7 @@ module "eks" { module "karpenter" { source = "../../modules/karpenter" - cluster_name = module.eks.cluster_name - enable_v1_permissions = true + cluster_name = module.eks.cluster_name # Name needs to match role name passed to the EC2NodeClass node_iam_role_use_name_prefix = false diff --git a/main.tf b/main.tf index c10d79608d..da48f3672c 100644 --- a/main.tf +++ b/main.tf @@ -39,7 +39,7 @@ resource "aws_eks_cluster" "this" { role_arn = local.cluster_role version = var.cluster_version enabled_cluster_log_types = var.cluster_enabled_log_types - bootstrap_self_managed_addons = local.auto_mode_enabled ? coalesce(var.bootstrap_self_managed_addons, false) : var.bootstrap_self_managed_addons + bootstrap_self_managed_addons = false force_update_version = var.cluster_force_update_version access_config { @@ -459,11 +459,6 @@ locals { eks_outpost_iam_role_policies = { for k, v in { AmazonEKSClusterPolicy = "${local.iam_role_policy_prefix}/AmazonEKSLocalOutpostClusterPolicy" } : k => v if local.create_outposts_local_cluster && !local.auto_mode_enabled } - - # Security groups for pods - eks_sgpp_iam_role_policies = { for k, v in { - AmazonEKSVPCResourceController = "${local.iam_role_policy_prefix}/AmazonEKSVPCResourceController" - } : k => v if var.enable_security_groups_for_pods && !local.create_outposts_local_cluster && !local.auto_mode_enabled } } data "aws_iam_policy_document" "assume_role_policy" { @@ -513,7 +508,6 @@ resource "aws_iam_role_policy_attachment" "this" { local.eks_standard_iam_role_policies, local.eks_auto_mode_iam_role_policies, local.eks_outpost_iam_role_policies, - local.eks_sgpp_iam_role_policies, ) : k => v if local.create_iam_role } policy_arn = each.value @@ -722,18 +716,12 @@ resource "aws_iam_role_policy_attachment" "custom" { # EKS Addons ################################################################################ -locals { - # TODO - Set to `NONE` on next breaking change when default addons are disabled - resolve_conflicts_on_create_default = coalesce(var.bootstrap_self_managed_addons, true) ? "OVERWRITE" : "NONE" -} - data "aws_eks_addon_version" "this" { for_each = { for k, v in var.cluster_addons : k => v if local.create && !local.create_outposts_local_cluster } addon_name = try(each.value.name, each.key) kubernetes_version = coalesce(var.cluster_version, aws_eks_cluster.this[0].version) - # TODO - Set default fallback to `true` on next breaking change - most_recent = try(each.value.most_recent, null) + most_recent = try(each.value.most_recent, true) } resource "aws_eks_addon" "this" { @@ -755,9 +743,8 @@ resource "aws_eks_addon" "this" { } } - preserve = try(each.value.preserve, true) - # TODO - Set to `NONE` on next breaking change when default addons are disabled - resolve_conflicts_on_create = try(each.value.resolve_conflicts_on_create, local.resolve_conflicts_on_create_default) + preserve = try(each.value.preserve, true) + resolve_conflicts_on_create = try(each.value.resolve_conflicts_on_create, "NONE") resolve_conflicts_on_update = try(each.value.resolve_conflicts_on_update, "OVERWRITE") service_account_role_arn = try(each.value.service_account_role_arn, null) @@ -795,9 +782,8 @@ resource "aws_eks_addon" "before_compute" { } } - preserve = try(each.value.preserve, true) - # TODO - Set to `NONE` on next breaking change when default addons are disabled - resolve_conflicts_on_create = try(each.value.resolve_conflicts_on_create, local.resolve_conflicts_on_create_default) + preserve = try(each.value.preserve, true) + resolve_conflicts_on_create = try(each.value.resolve_conflicts_on_create, "NONE") resolve_conflicts_on_update = try(each.value.resolve_conflicts_on_update, "OVERWRITE") service_account_role_arn = try(each.value.service_account_role_arn, null) @@ -815,15 +801,6 @@ resource "aws_eks_addon" "before_compute" { # Note - this is different from IRSA ################################################################################ -locals { - # Maintain current behavior for <= 1.29, remove default for >= 1.30 - # `null` will return the latest Kubernetes version from the EKS API, which at time of writing is 1.30 - # https://github.com/kubernetes/kubernetes/pull/123561 - # TODO - remove on next breaking change in conjunction with issuer URL change below - idpc_backwards_compat_version = contains(["1.21", "1.22", "1.23", "1.24", "1.25", "1.26", "1.27", "1.28", "1.29"], coalesce(var.cluster_version, "1.30")) - idpc_issuer_url = local.idpc_backwards_compat_version ? try(aws_eks_cluster.this[0].identity[0].oidc[0].issuer, null) : null -} - resource "aws_eks_identity_provider_config" "this" { for_each = { for k, v in var.cluster_identity_providers : k => v if local.create && !local.create_outposts_local_cluster } @@ -834,11 +811,10 @@ resource "aws_eks_identity_provider_config" "this" { groups_claim = lookup(each.value, "groups_claim", null) groups_prefix = lookup(each.value, "groups_prefix", null) identity_provider_config_name = try(each.value.identity_provider_config_name, each.key) - # TODO - make argument explicitly required on next breaking change - issuer_url = try(each.value.issuer_url, local.idpc_issuer_url) - required_claims = lookup(each.value, "required_claims", null) - username_claim = lookup(each.value, "username_claim", null) - username_prefix = lookup(each.value, "username_prefix", null) + issuer_url = each.value.issuer_url + required_claims = lookup(each.value, "required_claims", null) + username_claim = lookup(each.value, "username_claim", null) + username_prefix = lookup(each.value, "username_prefix", null) } tags = merge(var.tags, try(each.value.tags, {})) diff --git a/modules/eks-managed-node-group/README.md b/modules/eks-managed-node-group/README.md index c7726185aa..bd18309167 100644 --- a/modules/eks-managed-node-group/README.md +++ b/modules/eks-managed-node-group/README.md @@ -92,12 +92,10 @@ module "eks_managed_node_group" { | [aws_placement_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/placement_group) | resource | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_ec2_instance_type.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_instance_type) | data source | -| [aws_ec2_instance_type_offerings.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_instance_type_offerings) | data source | | [aws_iam_policy_document.assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | | [aws_ssm_parameter.ami](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | -| [aws_subnets.placement_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnets) | data source | ## Inputs @@ -133,9 +131,9 @@ module "eks_managed_node_group" { | [ebs\_optimized](#input\_ebs\_optimized) | If true, the launched EC2 instance(s) will be EBS-optimized | `bool` | `null` | no | | [efa\_indices](#input\_efa\_indices) | The indices of the network interfaces that should be EFA-enabled. Only valid when `enable_efa_support` = `true` | `list(number)` |
[
0
]
| no | | [enable\_bootstrap\_user\_data](#input\_enable\_bootstrap\_user\_data) | Determines whether the bootstrap configurations are populated within the user data template. Only valid when using a custom AMI via `ami_id` | `bool` | `false` | no | -| [enable\_efa\_only](#input\_enable\_efa\_only) | Determines whether to enable EFA (`false`, default) or EFA and EFA-only (`true`) network interfaces. Note: requires vpc-cni version `v1.18.4` or later | `bool` | `false` | no | +| [enable\_efa\_only](#input\_enable\_efa\_only) | Determines whether to enable EFA (`false`, default) or EFA and EFA-only (`true`) network interfaces. Note: requires vpc-cni version `v1.18.4` or later | `bool` | `true` | no | | [enable\_efa\_support](#input\_enable\_efa\_support) | Determines whether to enable Elastic Fabric Adapter (EFA) support | `bool` | `false` | no | -| [enable\_monitoring](#input\_enable\_monitoring) | Enables/disables detailed monitoring | `bool` | `true` | no | +| [enable\_monitoring](#input\_enable\_monitoring) | Enables/disables detailed monitoring | `bool` | `false` | no | | [enclave\_options](#input\_enclave\_options) | Enable Nitro Enclaves on launched instances | `map(string)` | `{}` | no | | [force\_update\_version](#input\_force\_update\_version) | Force version update if existing pods are unable to be drained due to a pod disruption budget issue | `bool` | `null` | no | | [iam\_role\_additional\_policies](#input\_iam\_role\_additional\_policies) | Additional policies to be added to the IAM role | `map(string)` | `{}` | no | @@ -169,7 +167,6 @@ module "eks_managed_node_group" { | [network\_interfaces](#input\_network\_interfaces) | Customize network interfaces to be attached at instance boot time | `list(any)` | `[]` | no | | [node\_repair\_config](#input\_node\_repair\_config) | The node auto repair configuration for the node group |
object({
enabled = optional(bool, true)
})
| `null` | no | | [placement](#input\_placement) | The placement of the instance | `map(string)` | `{}` | no | -| [placement\_group\_az](#input\_placement\_group\_az) | Availability zone where placement group is created (ex. `eu-west-1c`) | `string` | `null` | no | | [placement\_group\_strategy](#input\_placement\_group\_strategy) | The placement group strategy | `string` | `"cluster"` | no | | [post\_bootstrap\_user\_data](#input\_post\_bootstrap\_user\_data) | User data that is appended to the user data script after of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | | [pre\_bootstrap\_user\_data](#input\_pre\_bootstrap\_user\_data) | User data that is injected into the user data script ahead of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | diff --git a/modules/eks-managed-node-group/main.tf b/modules/eks-managed-node-group/main.tf index 2d37bc352a..5a5e539f4e 100644 --- a/modules/eks-managed-node-group/main.tf +++ b/modules/eks-managed-node-group/main.tf @@ -381,7 +381,7 @@ resource "aws_eks_node_group" "this" { # Required cluster_name = var.cluster_name node_role_arn = var.create_iam_role ? aws_iam_role.this[0].arn : var.iam_role_arn - subnet_ids = local.create_placement_group ? data.aws_subnets.placement_group[0].ids : var.subnet_ids + subnet_ids = var.subnet_ids scaling_config { min_size = var.min_size @@ -617,60 +617,6 @@ resource "aws_placement_group" "this" { tags = var.tags } -################################################################################ -# Instance AZ Lookup - -# Instances usually used in placement groups w/ EFA are only available in -# select availability zones. These data sources will cross reference the availability -# zones supported by the instance type with the subnets provided to ensure only -# AZs/subnets that are supported are used. -################################################################################ - -# Find the availability zones supported by the instance type -# TODO - remove at next breaking change -# Force users to be explicit about which AZ to use when using placement groups, -# with or without EFA support -data "aws_ec2_instance_type_offerings" "this" { - count = local.enable_efa_support ? 1 : 0 - - filter { - name = "instance-type" - values = [local.efa_instance_type] - } - - location_type = "availability-zone-id" -} - -# Reverse the lookup to find one of the subnets provided based on the availability -# availability zone ID of the queried instance type (supported) -data "aws_subnets" "placement_group" { - count = local.create_placement_group ? 1 : 0 - - filter { - name = "subnet-id" - values = var.subnet_ids - } - - # The data source can lookup the first available AZ or you can specify an AZ (next filter) - dynamic "filter" { - for_each = var.enable_efa_support && var.placement_group_az == null ? [1] : [] - - content { - name = "availability-zone-id" - values = data.aws_ec2_instance_type_offerings.this[0].locations - } - } - - dynamic "filter" { - for_each = var.placement_group_az != null ? [var.placement_group_az] : [] - - content { - name = "availability-zone" - values = [filter.value] - } - } -} - ################################################################################ # Autoscaling Group Schedule ################################################################################ diff --git a/modules/eks-managed-node-group/variables.tf b/modules/eks-managed-node-group/variables.tf index a5f5642abf..0e590e42f0 100644 --- a/modules/eks-managed-node-group/variables.tf +++ b/modules/eks-managed-node-group/variables.tf @@ -248,11 +248,10 @@ variable "metadata_options" { } } -# TODO - make this false by default at next breaking change variable "enable_monitoring" { description = "Enables/disables detailed monitoring" type = bool - default = true + default = false } variable "enable_efa_support" { @@ -261,11 +260,10 @@ variable "enable_efa_support" { default = false } -# TODO - make this true by default at next breaking change (remove variable, only pass indices) variable "enable_efa_only" { description = "Determines whether to enable EFA (`false`, default) or EFA and EFA-only (`true`) network interfaces. Note: requires vpc-cni version `v1.18.4` or later" type = bool - default = false + default = true } variable "efa_indices" { @@ -292,7 +290,6 @@ variable "create_placement_group" { default = false } -# TODO - remove at next breaking change variable "placement_group_strategy" { description = "The placement group strategy" type = string @@ -327,12 +324,6 @@ variable "subnet_ids" { default = null } -variable "placement_group_az" { - description = "Availability zone where placement group is created (ex. `eu-west-1c`)" - type = string - default = null -} - variable "min_size" { description = "Minimum number of instances/nodes" type = number diff --git a/modules/karpenter/README.md b/modules/karpenter/README.md index 8ce6f3a100..679ebab4f8 100644 --- a/modules/karpenter/README.md +++ b/modules/karpenter/README.md @@ -121,8 +121,6 @@ No modules. | [aws_iam_policy_document.controller_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.node_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.queue](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.v033](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.v1](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | @@ -139,11 +137,10 @@ No modules. | [create\_iam\_role](#input\_create\_iam\_role) | Determines whether an IAM role is created | `bool` | `true` | no | | [create\_instance\_profile](#input\_create\_instance\_profile) | Whether to create an IAM instance profile | `bool` | `false` | no | | [create\_node\_iam\_role](#input\_create\_node\_iam\_role) | Determines whether an IAM role is created or to use an existing IAM role | `bool` | `true` | no | -| [create\_pod\_identity\_association](#input\_create\_pod\_identity\_association) | Determines whether to create pod identity association | `bool` | `false` | no | +| [create\_pod\_identity\_association](#input\_create\_pod\_identity\_association) | Determines whether to create pod identity association | `bool` | `true` | no | | [enable\_irsa](#input\_enable\_irsa) | Determines whether to enable support for IAM role for service accounts | `bool` | `false` | no | | [enable\_pod\_identity](#input\_enable\_pod\_identity) | Determines whether to enable support for EKS pod identity | `bool` | `true` | no | | [enable\_spot\_termination](#input\_enable\_spot\_termination) | Determines whether to enable native spot termination handling | `bool` | `true` | no | -| [enable\_v1\_permissions](#input\_enable\_v1\_permissions) | Determines whether to enable permissions suitable for v1+ (`true`) or for v0.33.x-v0.37.x (`false`) | `bool` | `false` | no | | [iam\_policy\_description](#input\_iam\_policy\_description) | IAM policy description | `string` | `"Karpenter controller IAM policy"` | no | | [iam\_policy\_name](#input\_iam\_policy\_name) | Name of the IAM policy | `string` | `"KarpenterController"` | no | | [iam\_policy\_path](#input\_iam\_policy\_path) | Path of the IAM policy | `string` | `"/"` | no | diff --git a/modules/karpenter/main.tf b/modules/karpenter/main.tf index d03dfa49f8..7e4a73d0de 100644 --- a/modules/karpenter/main.tf +++ b/modules/karpenter/main.tf @@ -82,12 +82,6 @@ resource "aws_iam_role" "controller" { tags = merge(var.tags, var.iam_role_tags) } -data "aws_iam_policy_document" "controller" { - count = local.create_iam_role ? 1 : 0 - - source_policy_documents = var.enable_v1_permissions ? [data.aws_iam_policy_document.v1[0].json] : [data.aws_iam_policy_document.v033[0].json] -} - resource "aws_iam_policy" "controller" { count = local.create_iam_role ? 1 : 0 diff --git a/modules/karpenter/policy.tf b/modules/karpenter/policy.tf index b9068d7b60..564b1a0907 100644 --- a/modules/karpenter/policy.tf +++ b/modules/karpenter/policy.tf @@ -1,357 +1,4 @@ -################################################################################ -# v0.33.x - v0.37.x Controller IAM Policy -################################################################################ - -data "aws_iam_policy_document" "v033" { - count = local.create_iam_role ? 1 : 0 - - statement { - sid = "AllowScopedEC2InstanceActions" - resources = [ - "arn:${local.partition}:ec2:*::image/*", - "arn:${local.partition}:ec2:*::snapshot/*", - "arn:${local.partition}:ec2:*:*:spot-instances-request/*", - "arn:${local.partition}:ec2:*:*:security-group/*", - "arn:${local.partition}:ec2:*:*:subnet/*", - "arn:${local.partition}:ec2:*:*:launch-template/*", - ] - - actions = [ - "ec2:RunInstances", - "ec2:CreateFleet" - ] - } - - statement { - sid = "AllowScopedEC2InstanceActionsWithTags" - resources = [ - "arn:${local.partition}:ec2:*:*:fleet/*", - "arn:${local.partition}:ec2:*:*:instance/*", - "arn:${local.partition}:ec2:*:*:volume/*", - "arn:${local.partition}:ec2:*:*:network-interface/*", - "arn:${local.partition}:ec2:*:*:launch-template/*", - "arn:${local.partition}:ec2:*:*:spot-instances-request/*", - ] - actions = [ - "ec2:RunInstances", - "ec2:CreateFleet", - "ec2:CreateLaunchTemplate" - ] - - condition { - test = "StringEquals" - variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}" - values = ["owned"] - } - - condition { - test = "StringLike" - variable = "aws:RequestTag/karpenter.sh/nodepool" - values = ["*"] - } - } - - statement { - sid = "AllowScopedResourceCreationTagging" - resources = [ - "arn:${local.partition}:ec2:*:*:fleet/*", - "arn:${local.partition}:ec2:*:*:instance/*", - "arn:${local.partition}:ec2:*:*:volume/*", - "arn:${local.partition}:ec2:*:*:network-interface/*", - "arn:${local.partition}:ec2:*:*:launch-template/*", - "arn:${local.partition}:ec2:*:*:spot-instances-request/*", - ] - actions = ["ec2:CreateTags"] - - condition { - test = "StringEquals" - variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}" - values = ["owned"] - } - - condition { - test = "StringEquals" - variable = "ec2:CreateAction" - values = [ - "RunInstances", - "CreateFleet", - "CreateLaunchTemplate", - ] - } - - condition { - test = "StringLike" - variable = "aws:RequestTag/karpenter.sh/nodepool" - values = ["*"] - } - } - - statement { - sid = "AllowScopedResourceTagging" - resources = ["arn:${local.partition}:ec2:*:*:instance/*"] - actions = ["ec2:CreateTags"] - - condition { - test = "StringEquals" - variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}" - values = ["owned"] - } - - condition { - test = "StringLike" - variable = "aws:ResourceTag/karpenter.sh/nodepool" - values = ["*"] - } - - condition { - test = "ForAllValues:StringEquals" - variable = "aws:TagKeys" - values = [ - "karpenter.sh/nodeclaim", - "Name", - ] - } - } - - statement { - sid = "AllowScopedDeletion" - resources = [ - "arn:${local.partition}:ec2:*:*:instance/*", - "arn:${local.partition}:ec2:*:*:launch-template/*" - ] - - actions = [ - "ec2:TerminateInstances", - "ec2:DeleteLaunchTemplate" - ] - - condition { - test = "StringEquals" - variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}" - values = ["owned"] - } - - condition { - test = "StringLike" - variable = "aws:ResourceTag/karpenter.sh/nodepool" - values = ["*"] - } - } - - statement { - sid = "AllowRegionalReadActions" - resources = ["*"] - actions = [ - "ec2:DescribeAvailabilityZones", - "ec2:DescribeImages", - "ec2:DescribeInstances", - "ec2:DescribeInstanceTypeOfferings", - "ec2:DescribeInstanceTypes", - "ec2:DescribeLaunchTemplates", - "ec2:DescribeSecurityGroups", - "ec2:DescribeSpotPriceHistory", - "ec2:DescribeSubnets" - ] - - condition { - test = "StringEquals" - variable = "aws:RequestedRegion" - values = [local.region] - } - } - - statement { - sid = "AllowSSMReadActions" - resources = coalescelist(var.ami_id_ssm_parameter_arns, ["arn:${local.partition}:ssm:${local.region}::parameter/aws/service/*"]) - actions = ["ssm:GetParameter"] - } - - statement { - sid = "AllowPricingReadActions" - resources = ["*"] - actions = ["pricing:GetProducts"] - } - - dynamic "statement" { - for_each = local.enable_spot_termination ? [1] : [] - - content { - sid = "AllowInterruptionQueueActions" - resources = [try(aws_sqs_queue.this[0].arn, null)] - actions = [ - "sqs:DeleteMessage", - "sqs:GetQueueAttributes", - "sqs:GetQueueUrl", - "sqs:ReceiveMessage" - ] - } - } - - statement { - sid = "AllowPassingInstanceRole" - resources = var.create_node_iam_role ? [aws_iam_role.node[0].arn] : [var.node_iam_role_arn] - actions = ["iam:PassRole"] - - condition { - test = "StringEquals" - variable = "iam:PassedToService" - values = ["ec2.${local.dns_suffix}"] - } - } - - statement { - sid = "AllowScopedInstanceProfileCreationActions" - resources = ["*"] - actions = ["iam:CreateInstanceProfile"] - - condition { - test = "StringEquals" - variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}" - values = ["owned"] - } - - condition { - test = "StringEquals" - variable = "aws:RequestTag/topology.kubernetes.io/region" - values = [local.region] - } - - condition { - test = "StringLike" - variable = "aws:RequestTag/karpenter.k8s.aws/ec2nodeclass" - values = ["*"] - } - } - - statement { - sid = "AllowScopedInstanceProfileTagActions" - resources = ["*"] - actions = ["iam:TagInstanceProfile"] - - condition { - test = "StringEquals" - variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}" - values = ["owned"] - } - - condition { - test = "StringEquals" - variable = "aws:ResourceTag/topology.kubernetes.io/region" - values = [local.region] - } - - condition { - test = "StringEquals" - variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}" - values = ["owned"] - } - - condition { - test = "StringEquals" - variable = "aws:ResourceTag/topology.kubernetes.io/region" - values = [local.region] - } - - condition { - test = "StringLike" - variable = "aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass" - values = ["*"] - } - - condition { - test = "StringLike" - variable = "aws:RequestTag/karpenter.k8s.aws/ec2nodeclass" - values = ["*"] - } - } - - statement { - sid = "AllowScopedInstanceProfileActions" - resources = ["*"] - actions = [ - "iam:AddRoleToInstanceProfile", - "iam:RemoveRoleFromInstanceProfile", - "iam:DeleteInstanceProfile" - ] - - condition { - test = "StringEquals" - variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}" - values = ["owned"] - } - - condition { - test = "StringEquals" - variable = "aws:ResourceTag/topology.kubernetes.io/region" - values = [local.region] - } - - condition { - test = "StringLike" - variable = "aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass" - values = ["*"] - } - } - - statement { - sid = "AllowInstanceProfileReadActions" - resources = ["*"] - actions = ["iam:GetInstanceProfile"] - } - - statement { - sid = "AllowAPIServerEndpointDiscovery" - resources = ["arn:${local.partition}:eks:${local.region}:${local.account_id}:cluster/${var.cluster_name}"] - actions = ["eks:DescribeCluster"] - } - - dynamic "statement" { - for_each = var.iam_policy_statements - - content { - sid = try(statement.value.sid, null) - actions = try(statement.value.actions, null) - not_actions = try(statement.value.not_actions, null) - effect = try(statement.value.effect, null) - resources = try(statement.value.resources, null) - not_resources = try(statement.value.not_resources, null) - - dynamic "principals" { - for_each = try(statement.value.principals, []) - - content { - type = principals.value.type - identifiers = principals.value.identifiers - } - } - - dynamic "not_principals" { - for_each = try(statement.value.not_principals, []) - - content { - type = not_principals.value.type - identifiers = not_principals.value.identifiers - } - } - - dynamic "condition" { - for_each = try(statement.value.conditions, []) - - content { - test = condition.value.test - values = condition.value.values - variable = condition.value.variable - } - } - } - } -} - -################################################################################ -# v1.0.x Controller IAM Policy -################################################################################ - -data "aws_iam_policy_document" "v1" { +data "aws_iam_policy_document" "controller" { count = local.create_iam_role ? 1 : 0 statement { diff --git a/modules/karpenter/variables.tf b/modules/karpenter/variables.tf index 71b2cbdf38..50cd58a6da 100644 --- a/modules/karpenter/variables.tf +++ b/modules/karpenter/variables.tf @@ -116,13 +116,6 @@ variable "enable_pod_identity" { default = true } -# TODO - make v1 permssions the default policy at next breaking change -variable "enable_v1_permissions" { - description = "Determines whether to enable permissions suitable for v1+ (`true`) or for v0.33.x-v0.37.x (`false`)" - type = bool - default = false -} - ################################################################################ # IAM Role for Service Account (IRSA) ################################################################################ @@ -154,11 +147,11 @@ variable "irsa_assume_role_condition_test" { ################################################################################ # Pod Identity Association ################################################################################ -# TODO - Change default to `true` at next breaking change + variable "create_pod_identity_association" { description = "Determines whether to create pod identity association" type = bool - default = false + default = true } variable "namespace" { diff --git a/modules/self-managed-node-group/README.md b/modules/self-managed-node-group/README.md index 3821028284..ddd0d103e7 100644 --- a/modules/self-managed-node-group/README.md +++ b/modules/self-managed-node-group/README.md @@ -73,12 +73,10 @@ module "self_managed_node_group" { | [aws_placement_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/placement_group) | resource | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_ec2_instance_type.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_instance_type) | data source | -| [aws_ec2_instance_type_offerings.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_instance_type_offerings) | data source | | [aws_iam_policy_document.assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | | [aws_ssm_parameter.ami](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | -| [aws_subnets.placement_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnets) | data source | ## Inputs @@ -121,7 +119,7 @@ module "self_managed_node_group" { | [disable\_api\_termination](#input\_disable\_api\_termination) | If true, enables EC2 instance termination protection | `bool` | `null` | no | | [ebs\_optimized](#input\_ebs\_optimized) | If true, the launched EC2 instance will be EBS-optimized | `bool` | `null` | no | | [efa\_indices](#input\_efa\_indices) | The indices of the network interfaces that should be EFA-enabled. Only valid when `enable_efa_support` = `true` | `list(number)` |
[
0
]
| no | -| [enable\_efa\_only](#input\_enable\_efa\_only) | Determines whether to enable EFA (`false`, default) or EFA and EFA-only (`true`) network interfaces. Note: requires vpc-cni version `v1.18.4` or later | `bool` | `false` | no | +| [enable\_efa\_only](#input\_enable\_efa\_only) | Determines whether to enable EFA (`false`, default) or EFA and EFA-only (`true`) network interfaces. Note: requires vpc-cni version `v1.18.4` or later | `bool` | `true` | no | | [enable\_efa\_support](#input\_enable\_efa\_support) | Determines whether to enable Elastic Fabric Adapter (EFA) support | `bool` | `false` | no | | [enable\_monitoring](#input\_enable\_monitoring) | Enables/disables detailed monitoring | `bool` | `true` | no | | [enabled\_metrics](#input\_enabled\_metrics) | A list of metrics to collect. The allowed values are `GroupDesiredCapacity`, `GroupInServiceCapacity`, `GroupPendingCapacity`, `GroupMinSize`, `GroupMaxSize`, `GroupInServiceInstances`, `GroupPendingInstances`, `GroupStandbyInstances`, `GroupStandbyCapacity`, `GroupTerminatingCapacity`, `GroupTerminatingInstances`, `GroupTotalCapacity`, `GroupTotalInstances` | `list(string)` | `[]` | no | @@ -172,7 +170,6 @@ module "self_managed_node_group" { | [network\_interfaces](#input\_network\_interfaces) | Customize network interfaces to be attached at instance boot time | `list(any)` | `[]` | no | | [placement](#input\_placement) | The placement of the instance | `map(string)` | `{}` | no | | [placement\_group](#input\_placement\_group) | The name of the placement group into which you'll launch your instances, if any | `string` | `null` | no | -| [placement\_group\_az](#input\_placement\_group\_az) | Availability zone where placement group is created (ex. `eu-west-1c`) | `string` | `null` | no | | [post\_bootstrap\_user\_data](#input\_post\_bootstrap\_user\_data) | User data that is appended to the user data script after of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | | [pre\_bootstrap\_user\_data](#input\_pre\_bootstrap\_user\_data) | User data that is injected into the user data script ahead of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | | [private\_dns\_name\_options](#input\_private\_dns\_name\_options) | The options for the instance hostname. The default values are inherited from the subnet | `map(string)` | `{}` | no | diff --git a/modules/self-managed-node-group/main.tf b/modules/self-managed-node-group/main.tf index 31dd5f4dbc..7cadc42ea4 100644 --- a/modules/self-managed-node-group/main.tf +++ b/modules/self-managed-node-group/main.tf @@ -9,30 +9,6 @@ locals { # Just to ensure templating doesn't fail when values are not provided ssm_cluster_version = var.cluster_version != null ? var.cluster_version : "" - # TODO - Temporary stopgap for backwards compatibility until v21.0 - ami_type_to_user_data_type = { - AL2_x86_64 = "linux" - AL2_x86_64_GPU = "linux" - AL2_ARM_64 = "linux" - BOTTLEROCKET_ARM_64 = "bottlerocket" - BOTTLEROCKET_x86_64 = "bottlerocket" - BOTTLEROCKET_ARM_64_FIPS = "bottlerocket" - BOTTLEROCKET_x86_64_FIPS = "bottlerocket" - BOTTLEROCKET_ARM_64_NVIDIA = "bottlerocket" - BOTTLEROCKET_x86_64_NVIDIA = "bottlerocket" - WINDOWS_CORE_2019_x86_64 = "windows" - WINDOWS_FULL_2019_x86_64 = "windows" - WINDOWS_CORE_2022_x86_64 = "windows" - WINDOWS_FULL_2022_x86_64 = "windows" - AL2023_x86_64_STANDARD = "al2023" - AL2023_ARM_64_STANDARD = "al2023" - AL2023_x86_64_NEURON = "al2023" - AL2023_x86_64_NVIDIA = "al2023" - AL2023_ARM_64_NVIDIA = "al2023" - } - - user_data_type = local.ami_type_to_user_data_type[var.ami_type] - # Map the AMI type to the respective SSM param path ami_type_to_ssm_param = { AL2_x86_64 = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2/recommended/image_id" @@ -741,7 +717,7 @@ resource "aws_autoscaling_group" "this" { target_group_arns = var.target_group_arns termination_policies = var.termination_policies - vpc_zone_identifier = local.enable_efa_support ? data.aws_subnets.placement_group[0].ids : var.subnet_ids + vpc_zone_identifier = var.subnet_ids wait_for_capacity_timeout = var.wait_for_capacity_timeout wait_for_elb_capacity = var.wait_for_elb_capacity @@ -939,60 +915,6 @@ resource "aws_placement_group" "this" { tags = var.tags } -################################################################################ -# Instance AZ Lookup - -# Instances usually used in placement groups w/ EFA are only available in -# select availability zones. These data sources will cross reference the availability -# zones supported by the instance type with the subnets provided to ensure only -# AZs/subnets that are supported are used. -################################################################################ - -# Find the availability zones supported by the instance type -# TODO - remove at next breaking change -# Force users to be explicit about which AZ to use when using placement groups, -# with or without EFA support -data "aws_ec2_instance_type_offerings" "this" { - count = local.enable_efa_support ? 1 : 0 - - filter { - name = "instance-type" - values = [var.instance_type] - } - - location_type = "availability-zone-id" -} - -# Reverse the lookup to find one of the subnets provided based on the availability -# availability zone ID of the queried instance type (supported) -data "aws_subnets" "placement_group" { - count = local.create_placement_group ? 1 : 0 - - filter { - name = "subnet-id" - values = var.subnet_ids - } - - # The data source can lookup the first available AZ or you can specify an AZ (next filter) - dynamic "filter" { - for_each = local.create_placement_group && var.placement_group_az == null ? [1] : [] - - content { - name = "availability-zone-id" - values = data.aws_ec2_instance_type_offerings.this[0].locations - } - } - - dynamic "filter" { - for_each = var.placement_group_az != null ? [var.placement_group_az] : [] - - content { - name = "availability-zone" - values = [filter.value] - } - } -} - ################################################################################ # Access Entry ################################################################################ @@ -1002,7 +924,7 @@ resource "aws_eks_access_entry" "this" { cluster_name = var.cluster_name principal_arn = var.create_iam_instance_profile ? aws_iam_role.this[0].arn : var.iam_role_arn - type = local.user_data_type == "windows" ? "EC2_WINDOWS" : "EC2_LINUX" + type = startswith(var.ami_type, "WINDOWS_") ? "EC2_WINDOWS" : "EC2_LINUX" tags = var.tags } diff --git a/modules/self-managed-node-group/variables.tf b/modules/self-managed-node-group/variables.tf index 7ded12ca34..7c1eaef882 100644 --- a/modules/self-managed-node-group/variables.tf +++ b/modules/self-managed-node-group/variables.tf @@ -310,11 +310,10 @@ variable "enable_efa_support" { default = false } -# TODO - make this true by default at next breaking change (remove variable, only pass indices) variable "enable_efa_only" { description = "Determines whether to enable EFA (`false`, default) or EFA and EFA-only (`true`) network interfaces. Note: requires vpc-cni version `v1.18.4` or later" type = bool - default = false + default = true } variable "efa_indices" { @@ -379,12 +378,6 @@ variable "availability_zones" { default = null } -variable "placement_group_az" { - description = "Availability zone where placement group is created (ex. `eu-west-1c`)" - type = string - default = null -} - variable "subnet_ids" { description = "A list of subnet IDs to launch resources in. Subnets automatically determine which availability zones the group will reside. Conflicts with `availability_zones`" type = list(string) diff --git a/node_groups.tf b/node_groups.tf index b6f4f22826..730b8307de 100644 --- a/node_groups.tf +++ b/node_groups.tf @@ -375,7 +375,6 @@ module "eks_managed_node_group" { efa_indices = try(each.value.efa_indices, var.eks_managed_node_group_defaults.efa_indices, [0]) create_placement_group = try(each.value.create_placement_group, var.eks_managed_node_group_defaults.create_placement_group, false) placement = try(each.value.placement, var.eks_managed_node_group_defaults.placement, {}) - placement_group_az = try(each.value.placement_group_az, var.eks_managed_node_group_defaults.placement_group_az, null) placement_group_strategy = try(each.value.placement_group_strategy, var.eks_managed_node_group_defaults.placement_group_strategy, "cluster") network_interfaces = try(each.value.network_interfaces, var.eks_managed_node_group_defaults.network_interfaces, []) maintenance_options = try(each.value.maintenance_options, var.eks_managed_node_group_defaults.maintenance_options, {}) @@ -446,7 +445,6 @@ module "self_managed_node_group" { target_group_arns = try(each.value.target_group_arns, var.self_managed_node_group_defaults.target_group_arns, []) create_placement_group = try(each.value.create_placement_group, var.self_managed_node_group_defaults.create_placement_group, false) placement_group = try(each.value.placement_group, var.self_managed_node_group_defaults.placement_group, null) - placement_group_az = try(each.value.placement_group_az, var.self_managed_node_group_defaults.placement_group_az, null) health_check_type = try(each.value.health_check_type, var.self_managed_node_group_defaults.health_check_type, null) health_check_grace_period = try(each.value.health_check_grace_period, var.self_managed_node_group_defaults.health_check_grace_period, null) diff --git a/tests/fast-addons/README.md b/tests/fast-addons/README.md deleted file mode 100644 index bfc3c6ec58..0000000000 --- a/tests/fast-addons/README.md +++ /dev/null @@ -1,92 +0,0 @@ -# Fast Addons - -Refer to https://github.com/terraform-aws-modules/terraform-aws-eks/pull/3214 for additional information. - - - -## Usage - -To provision the provided configurations you need to execute: - -```bash -$ terraform init -$ terraform plan -$ terraform apply --auto-approve -``` - -Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources. - - -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 1.5.7 | -| [aws](#requirement\_aws) | >= 6.0 | - -## Providers - -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | >= 6.0 | - -## Modules - -| Name | Source | Version | -|------|--------|---------| -| [eks](#module\_eks) | ../.. | n/a | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 | - -## Resources - -| Name | Type | -|------|------| -| [aws_route_table_association.custom_network](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association) | resource | -| [aws_subnet.custom_network](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource | -| [aws_vpc_ipv4_cidr_block_association.custom_network](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipv4_cidr_block_association) | resource | -| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | - -## Inputs - -No inputs. - -## Outputs - -| Name | Description | -|------|-------------| -| [access\_entries](#output\_access\_entries) | Map of access entries created and their attributes | -| [cloudwatch\_log\_group\_arn](#output\_cloudwatch\_log\_group\_arn) | Arn of cloudwatch log group created | -| [cloudwatch\_log\_group\_name](#output\_cloudwatch\_log\_group\_name) | Name of cloudwatch log group created | -| [cluster\_addons](#output\_cluster\_addons) | Map of attribute maps for all EKS cluster addons enabled | -| [cluster\_arn](#output\_cluster\_arn) | The Amazon Resource Name (ARN) of the cluster | -| [cluster\_certificate\_authority\_data](#output\_cluster\_certificate\_authority\_data) | Base64 encoded certificate data required to communicate with the cluster | -| [cluster\_dualstack\_oidc\_issuer\_url](#output\_cluster\_dualstack\_oidc\_issuer\_url) | Dual-stack compatible URL on the EKS cluster for the OpenID Connect identity provider | -| [cluster\_endpoint](#output\_cluster\_endpoint) | Endpoint for your Kubernetes API server | -| [cluster\_iam\_role\_arn](#output\_cluster\_iam\_role\_arn) | IAM role ARN of the EKS cluster | -| [cluster\_iam\_role\_name](#output\_cluster\_iam\_role\_name) | IAM role name of the EKS cluster | -| [cluster\_iam\_role\_unique\_id](#output\_cluster\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role | -| [cluster\_id](#output\_cluster\_id) | The ID of the EKS cluster. Note: currently a value is returned only for local EKS clusters created on Outposts | -| [cluster\_identity\_providers](#output\_cluster\_identity\_providers) | Map of attribute maps for all EKS identity providers enabled | -| [cluster\_ip\_family](#output\_cluster\_ip\_family) | The IP family used by the cluster (e.g. `ipv4` or `ipv6`) | -| [cluster\_name](#output\_cluster\_name) | The name of the EKS cluster | -| [cluster\_oidc\_issuer\_url](#output\_cluster\_oidc\_issuer\_url) | The URL on the EKS cluster for the OpenID Connect identity provider | -| [cluster\_platform\_version](#output\_cluster\_platform\_version) | Platform version for the cluster | -| [cluster\_primary\_security\_group\_id](#output\_cluster\_primary\_security\_group\_id) | Cluster security group that was created by Amazon EKS for the cluster. Managed node groups use this security group for control-plane-to-data-plane communication. Referred to as 'Cluster security group' in the EKS console | -| [cluster\_security\_group\_arn](#output\_cluster\_security\_group\_arn) | Amazon Resource Name (ARN) of the cluster security group | -| [cluster\_security\_group\_id](#output\_cluster\_security\_group\_id) | ID of the cluster security group | -| [cluster\_service\_cidr](#output\_cluster\_service\_cidr) | The CIDR block where Kubernetes pod and service IP addresses are assigned from | -| [cluster\_status](#output\_cluster\_status) | Status of the EKS cluster. One of `CREATING`, `ACTIVE`, `DELETING`, `FAILED` | -| [cluster\_tls\_certificate\_sha1\_fingerprint](#output\_cluster\_tls\_certificate\_sha1\_fingerprint) | The SHA1 fingerprint of the public key of the cluster's certificate | -| [eks\_managed\_node\_groups](#output\_eks\_managed\_node\_groups) | Map of attribute maps for all EKS managed node groups created | -| [eks\_managed\_node\_groups\_autoscaling\_group\_names](#output\_eks\_managed\_node\_groups\_autoscaling\_group\_names) | List of the autoscaling group names created by EKS managed node groups | -| [fargate\_profiles](#output\_fargate\_profiles) | Map of attribute maps for all EKS Fargate Profiles created | -| [kms\_key\_arn](#output\_kms\_key\_arn) | The Amazon Resource Name (ARN) of the key | -| [kms\_key\_id](#output\_kms\_key\_id) | The globally unique identifier for the key | -| [kms\_key\_policy](#output\_kms\_key\_policy) | The IAM resource policy set on the key | -| [node\_security\_group\_arn](#output\_node\_security\_group\_arn) | Amazon Resource Name (ARN) of the node shared security group | -| [node\_security\_group\_id](#output\_node\_security\_group\_id) | ID of the node shared security group | -| [oidc\_provider](#output\_oidc\_provider) | The OpenID Connect identity provider (issuer URL without leading `https://`) | -| [oidc\_provider\_arn](#output\_oidc\_provider\_arn) | The ARN of the OIDC Provider if `enable_irsa = true` | -| [self\_managed\_node\_groups](#output\_self\_managed\_node\_groups) | Map of attribute maps for all self managed node groups created | -| [self\_managed\_node\_groups\_autoscaling\_group\_names](#output\_self\_managed\_node\_groups\_autoscaling\_group\_names) | List of the autoscaling group names created by self-managed node groups | - diff --git a/tests/fast-addons/main.tf b/tests/fast-addons/main.tf deleted file mode 100644 index 2e91fac7d8..0000000000 --- a/tests/fast-addons/main.tf +++ /dev/null @@ -1,159 +0,0 @@ -provider "aws" { - region = local.region -} - -locals { - name = "ex-${basename(path.cwd)}" - cluster_version = "1.33" - region = "eu-west-1" - - tags = { - Test = local.name - GithubRepo = "terraform-aws-eks" - GithubOrg = "terraform-aws-modules" - } -} - -################################################################################ -# EKS Module -################################################################################ - -module "eks" { - source = "../.." - - cluster_name = local.name - cluster_version = local.cluster_version - cluster_endpoint_public_access = true - - enable_cluster_creator_admin_permissions = true - - # Disable the default self-managed addons to avoid the penalty of adopting them later - bootstrap_self_managed_addons = false - - # Addons will be provisioned net new via the EKS addon API - cluster_addons = { - coredns = { - most_recent = true - } - eks-pod-identity-agent = { - before_compute = true - most_recent = true - } - kube-proxy = { - most_recent = true - } - vpc-cni = { - most_recent = true - before_compute = true - configuration_values = jsonencode({ - env = { - # Use subnet tags to avoid the need to inject the ENIConfig - # which requires a live API server endpoint which leads to a dependency of: - # Control plane -> API request to create ENIConfig -> VPC CNI addon -> nodes/compute - # With the subnet discovery feature, we can avoid this dependency: - # Control plane -> VPC CNI addon -> nodes/compute - ENABLE_SUBNET_DISCOVERY = "true" - } - }) - } - } - - vpc_id = module.vpc.vpc_id - subnet_ids = module.vpc.private_subnets - - eks_managed_node_groups = { - example = { - instance_types = ["m6i.large"] - - min_size = 2 - max_size = 5 - desired_size = 2 - } - } - - tags = local.tags -} - -################################################################################ -# VPC -################################################################################ - -data "aws_availability_zones" "available" { - # Exclude local zones - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} - -locals { - vpc_cidr = "10.0.0.0/16" - azs = slice(data.aws_availability_zones.available.names, 0, 3) -} - -module "vpc" { - source = "terraform-aws-modules/vpc/aws" - version = "~> 6.0" - - name = local.name - cidr = local.vpc_cidr - - azs = local.azs - private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 4, k)] - public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 48)] - - enable_nat_gateway = true - single_nat_gateway = true - - public_subnet_tags = { - "kubernetes.io/role/elb" = 1 - } - - tags = local.tags -} - -################################################################################ -# Custom Networking -################################################################################ - -locals { - custom_network_vpc_cidr = "10.99.0.0/16" - - custom_network_subnets = [for k, v in local.azs : cidrsubnet(local.custom_network_vpc_cidr, 4, k)] -} - -resource "aws_vpc_ipv4_cidr_block_association" "custom_network" { - vpc_id = module.vpc.vpc_id - cidr_block = local.custom_network_vpc_cidr -} - -resource "aws_subnet" "custom_network" { - count = length(local.custom_network_subnets) - - vpc_id = module.vpc.vpc_id - cidr_block = element(local.custom_network_subnets, count.index) - - tags = merge( - local.tags, - { - # Tag for subnet discovery - "kubernetes.io/role/cni" = 1 - "kubernetes.io/role/internal-elb" = 1 - } - ) - - depends_on = [ - aws_vpc_ipv4_cidr_block_association.custom_network - ] -} - -resource "aws_route_table_association" "custom_network" { - count = length(local.custom_network_subnets) - - subnet_id = element(aws_subnet.custom_network[*].id, count.index) - route_table_id = element(module.vpc.private_route_table_ids, 0) - - depends_on = [ - aws_vpc_ipv4_cidr_block_association.custom_network - ] -} diff --git a/tests/fast-addons/outputs.tf b/tests/fast-addons/outputs.tf deleted file mode 100644 index 9357464c29..0000000000 --- a/tests/fast-addons/outputs.tf +++ /dev/null @@ -1,226 +0,0 @@ -################################################################################ -# Cluster -################################################################################ - -output "cluster_arn" { - description = "The Amazon Resource Name (ARN) of the cluster" - value = module.eks.cluster_arn -} - -output "cluster_certificate_authority_data" { - description = "Base64 encoded certificate data required to communicate with the cluster" - value = module.eks.cluster_certificate_authority_data -} - -output "cluster_endpoint" { - description = "Endpoint for your Kubernetes API server" - value = module.eks.cluster_endpoint -} - -output "cluster_id" { - description = "The ID of the EKS cluster. Note: currently a value is returned only for local EKS clusters created on Outposts" - value = module.eks.cluster_id -} - -output "cluster_name" { - description = "The name of the EKS cluster" - value = module.eks.cluster_name -} - -output "cluster_oidc_issuer_url" { - description = "The URL on the EKS cluster for the OpenID Connect identity provider" - value = module.eks.cluster_oidc_issuer_url -} - -output "cluster_dualstack_oidc_issuer_url" { - description = "Dual-stack compatible URL on the EKS cluster for the OpenID Connect identity provider" - value = module.eks.cluster_dualstack_oidc_issuer_url -} - -output "cluster_platform_version" { - description = "Platform version for the cluster" - value = module.eks.cluster_platform_version -} - -output "cluster_status" { - description = "Status of the EKS cluster. One of `CREATING`, `ACTIVE`, `DELETING`, `FAILED`" - value = module.eks.cluster_status -} - -output "cluster_primary_security_group_id" { - description = "Cluster security group that was created by Amazon EKS for the cluster. Managed node groups use this security group for control-plane-to-data-plane communication. Referred to as 'Cluster security group' in the EKS console" - value = module.eks.cluster_primary_security_group_id -} - -output "cluster_service_cidr" { - description = "The CIDR block where Kubernetes pod and service IP addresses are assigned from" - value = module.eks.cluster_service_cidr -} - -output "cluster_ip_family" { - description = "The IP family used by the cluster (e.g. `ipv4` or `ipv6`)" - value = module.eks.cluster_ip_family -} - -################################################################################ -# Access Entry -################################################################################ - -output "access_entries" { - description = "Map of access entries created and their attributes" - value = module.eks.access_entries -} - -################################################################################ -# KMS Key -################################################################################ - -output "kms_key_arn" { - description = "The Amazon Resource Name (ARN) of the key" - value = module.eks.kms_key_arn -} - -output "kms_key_id" { - description = "The globally unique identifier for the key" - value = module.eks.kms_key_id -} - -output "kms_key_policy" { - description = "The IAM resource policy set on the key" - value = module.eks.kms_key_policy -} - -################################################################################ -# Security Group -################################################################################ - -output "cluster_security_group_arn" { - description = "Amazon Resource Name (ARN) of the cluster security group" - value = module.eks.cluster_security_group_arn -} - -output "cluster_security_group_id" { - description = "ID of the cluster security group" - value = module.eks.cluster_security_group_id -} - -################################################################################ -# Node Security Group -################################################################################ - -output "node_security_group_arn" { - description = "Amazon Resource Name (ARN) of the node shared security group" - value = module.eks.node_security_group_arn -} - -output "node_security_group_id" { - description = "ID of the node shared security group" - value = module.eks.node_security_group_id -} - -################################################################################ -# IRSA -################################################################################ - -output "oidc_provider" { - description = "The OpenID Connect identity provider (issuer URL without leading `https://`)" - value = module.eks.oidc_provider -} - -output "oidc_provider_arn" { - description = "The ARN of the OIDC Provider if `enable_irsa = true`" - value = module.eks.oidc_provider_arn -} - -output "cluster_tls_certificate_sha1_fingerprint" { - description = "The SHA1 fingerprint of the public key of the cluster's certificate" - value = module.eks.cluster_tls_certificate_sha1_fingerprint -} - -################################################################################ -# IAM Role -################################################################################ - -output "cluster_iam_role_name" { - description = "IAM role name of the EKS cluster" - value = module.eks.cluster_iam_role_name -} - -output "cluster_iam_role_arn" { - description = "IAM role ARN of the EKS cluster" - value = module.eks.cluster_iam_role_arn -} - -output "cluster_iam_role_unique_id" { - description = "Stable and unique string identifying the IAM role" - value = module.eks.cluster_iam_role_unique_id -} - -################################################################################ -# EKS Addons -################################################################################ - -output "cluster_addons" { - description = "Map of attribute maps for all EKS cluster addons enabled" - value = module.eks.cluster_addons -} - -################################################################################ -# EKS Identity Provider -################################################################################ - -output "cluster_identity_providers" { - description = "Map of attribute maps for all EKS identity providers enabled" - value = module.eks.cluster_identity_providers -} - -################################################################################ -# CloudWatch Log Group -################################################################################ - -output "cloudwatch_log_group_name" { - description = "Name of cloudwatch log group created" - value = module.eks.cloudwatch_log_group_name -} - -output "cloudwatch_log_group_arn" { - description = "Arn of cloudwatch log group created" - value = module.eks.cloudwatch_log_group_arn -} - -################################################################################ -# Fargate Profile -################################################################################ - -output "fargate_profiles" { - description = "Map of attribute maps for all EKS Fargate Profiles created" - value = module.eks.fargate_profiles -} - -################################################################################ -# EKS Managed Node Group -################################################################################ - -output "eks_managed_node_groups" { - description = "Map of attribute maps for all EKS managed node groups created" - value = module.eks.eks_managed_node_groups -} - -output "eks_managed_node_groups_autoscaling_group_names" { - description = "List of the autoscaling group names created by EKS managed node groups" - value = module.eks.eks_managed_node_groups_autoscaling_group_names -} - -################################################################################ -# Self Managed Node Group -################################################################################ - -output "self_managed_node_groups" { - description = "Map of attribute maps for all self managed node groups created" - value = module.eks.self_managed_node_groups -} - -output "self_managed_node_groups_autoscaling_group_names" { - description = "List of the autoscaling group names created by self-managed node groups" - value = module.eks.self_managed_node_groups_autoscaling_group_names -} diff --git a/tests/fast-addons/variables.tf b/tests/fast-addons/variables.tf deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/fast-addons/versions.tf b/tests/fast-addons/versions.tf deleted file mode 100644 index db13b0a8d2..0000000000 --- a/tests/fast-addons/versions.tf +++ /dev/null @@ -1,10 +0,0 @@ -terraform { - required_version = ">= 1.5.7" - - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 6.0" - } - } -} diff --git a/variables.tf b/variables.tf index b4881b2988..ccb27f387c 100644 --- a/variables.tf +++ b/variables.tf @@ -166,13 +166,6 @@ variable "cluster_timeouts" { default = {} } -# TODO - hard code to false on next breaking change -variable "bootstrap_self_managed_addons" { - description = "Indicates whether or not to bootstrap self-managed addons after the cluster has been created" - type = bool - default = null -} - ################################################################################ # Access Entry ################################################################################ @@ -499,13 +492,6 @@ variable "iam_role_additional_policies" { default = {} } -# TODO - will be removed in next breaking change; user can add the policy on their own when needed -variable "enable_security_groups_for_pods" { - description = "Determines whether to add the necessary IAM permission policy for security groups for pods" - type = bool - default = true -} - variable "iam_role_tags" { description = "A map of additional tags to add to the IAM role created" type = map(string) From 80d227314dcf45147e0337828c6998fb789d4431 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Mon, 7 Jul 2025 14:26:31 -0500 Subject: [PATCH 06/25] fix: Set default `http_put_response_hop_limit` to `1` --- modules/eks-managed-node-group/README.md | 2 +- modules/eks-managed-node-group/variables.tf | 2 +- modules/self-managed-node-group/README.md | 2 +- modules/self-managed-node-group/variables.tf | 2 +- node_groups.tf | 2 +- tests/eks-managed-node-group/main.tf | 2 +- tests/self-managed-node-group/main.tf | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/eks-managed-node-group/README.md b/modules/eks-managed-node-group/README.md index bd18309167..1dbf4a8087 100644 --- a/modules/eks-managed-node-group/README.md +++ b/modules/eks-managed-node-group/README.md @@ -161,7 +161,7 @@ module "eks_managed_node_group" { | [license\_specifications](#input\_license\_specifications) | A map of license specifications to associate with | `any` | `{}` | no | | [maintenance\_options](#input\_maintenance\_options) | The maintenance options for the instance | `any` | `{}` | no | | [max\_size](#input\_max\_size) | Maximum number of instances/nodes | `number` | `3` | no | -| [metadata\_options](#input\_metadata\_options) | Customize the metadata options for the instance | `map(string)` |
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 2,
"http_tokens": "required"
}
| no | +| [metadata\_options](#input\_metadata\_options) | Customize the metadata options for the instance | `map(string)` |
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 1,
"http_tokens": "required"
}
| no | | [min\_size](#input\_min\_size) | Minimum number of instances/nodes | `number` | `0` | no | | [name](#input\_name) | Name of the EKS managed node group | `string` | `""` | no | | [network\_interfaces](#input\_network\_interfaces) | Customize network interfaces to be attached at instance boot time | `list(any)` | `[]` | no | diff --git a/modules/eks-managed-node-group/variables.tf b/modules/eks-managed-node-group/variables.tf index 0e590e42f0..4fb148c590 100644 --- a/modules/eks-managed-node-group/variables.tf +++ b/modules/eks-managed-node-group/variables.tf @@ -244,7 +244,7 @@ variable "metadata_options" { default = { http_endpoint = "enabled" http_tokens = "required" - http_put_response_hop_limit = 2 + http_put_response_hop_limit = 1 } } diff --git a/modules/self-managed-node-group/README.md b/modules/self-managed-node-group/README.md index ddd0d103e7..9193a6d129 100644 --- a/modules/self-managed-node-group/README.md +++ b/modules/self-managed-node-group/README.md @@ -161,7 +161,7 @@ module "self_managed_node_group" { | [maintenance\_options](#input\_maintenance\_options) | The maintenance options for the instance | `any` | `{}` | no | | [max\_instance\_lifetime](#input\_max\_instance\_lifetime) | The maximum amount of time, in seconds, that an instance can be in service, values must be either equal to 0 or between 604800 and 31536000 seconds | `number` | `null` | no | | [max\_size](#input\_max\_size) | The maximum size of the autoscaling group | `number` | `3` | no | -| [metadata\_options](#input\_metadata\_options) | Customize the metadata options for the instance | `map(string)` |
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 2,
"http_tokens": "required"
}
| no | +| [metadata\_options](#input\_metadata\_options) | Customize the metadata options for the instance | `map(string)` |
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 1,
"http_tokens": "required"
}
| no | | [metrics\_granularity](#input\_metrics\_granularity) | The granularity to associate with the metrics to collect. The only valid value is `1Minute` | `string` | `null` | no | | [min\_elb\_capacity](#input\_min\_elb\_capacity) | Setting this causes Terraform to wait for this number of instances to show up healthy in the ELB only on creation. Updates will not wait on ELB instance number changes | `number` | `null` | no | | [min\_size](#input\_min\_size) | The minimum size of the autoscaling group | `number` | `0` | no | diff --git a/modules/self-managed-node-group/variables.tf b/modules/self-managed-node-group/variables.tf index 7c1eaef882..0afe3177a2 100644 --- a/modules/self-managed-node-group/variables.tf +++ b/modules/self-managed-node-group/variables.tf @@ -328,7 +328,7 @@ variable "metadata_options" { default = { http_endpoint = "enabled" http_tokens = "required" - http_put_response_hop_limit = 2 + http_put_response_hop_limit = 1 } } diff --git a/node_groups.tf b/node_groups.tf index 730b8307de..45039e5d42 100644 --- a/node_groups.tf +++ b/node_groups.tf @@ -2,7 +2,7 @@ locals { metadata_options = { http_endpoint = "enabled" http_tokens = "required" - http_put_response_hop_limit = 2 + http_put_response_hop_limit = 1 } # EKS managed node group diff --git a/tests/eks-managed-node-group/main.tf b/tests/eks-managed-node-group/main.tf index df059b872e..e1f263b4a9 100644 --- a/tests/eks-managed-node-group/main.tf +++ b/tests/eks-managed-node-group/main.tf @@ -288,7 +288,7 @@ module "eks" { metadata_options = { http_endpoint = "enabled" http_tokens = "required" - http_put_response_hop_limit = 2 + http_put_response_hop_limit = 1 instance_metadata_tags = "disabled" } diff --git a/tests/self-managed-node-group/main.tf b/tests/self-managed-node-group/main.tf index 2331d33685..2560da9bf2 100644 --- a/tests/self-managed-node-group/main.tf +++ b/tests/self-managed-node-group/main.tf @@ -284,7 +284,7 @@ module "eks" { metadata_options = { http_endpoint = "enabled" http_tokens = "required" - http_put_response_hop_limit = 2 + http_put_response_hop_limit = 1 instance_metadata_tags = "disabled" } From c3c677243941e2b464374c91a162ef4007f8bfc7 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Mon, 7 Jul 2025 14:29:56 -0500 Subject: [PATCH 07/25] fix: Remove IRSA support from Karpenter sub-module --- modules/karpenter/README.md | 4 --- modules/karpenter/main.tf | 52 ++++++++++------------------------ modules/karpenter/variables.tf | 28 ------------------ 3 files changed, 15 insertions(+), 69 deletions(-) diff --git a/modules/karpenter/README.md b/modules/karpenter/README.md index 679ebab4f8..aace65630e 100644 --- a/modules/karpenter/README.md +++ b/modules/karpenter/README.md @@ -138,7 +138,6 @@ No modules. | [create\_instance\_profile](#input\_create\_instance\_profile) | Whether to create an IAM instance profile | `bool` | `false` | no | | [create\_node\_iam\_role](#input\_create\_node\_iam\_role) | Determines whether an IAM role is created or to use an existing IAM role | `bool` | `true` | no | | [create\_pod\_identity\_association](#input\_create\_pod\_identity\_association) | Determines whether to create pod identity association | `bool` | `true` | no | -| [enable\_irsa](#input\_enable\_irsa) | Determines whether to enable support for IAM role for service accounts | `bool` | `false` | no | | [enable\_pod\_identity](#input\_enable\_pod\_identity) | Determines whether to enable support for EKS pod identity | `bool` | `true` | no | | [enable\_spot\_termination](#input\_enable\_spot\_termination) | Determines whether to enable native spot termination handling | `bool` | `true` | no | | [iam\_policy\_description](#input\_iam\_policy\_description) | IAM policy description | `string` | `"Karpenter controller IAM policy"` | no | @@ -154,9 +153,6 @@ No modules. | [iam\_role\_policies](#input\_iam\_role\_policies) | Policies to attach to the IAM role in `{'static_name' = 'policy_arn'}` format | `map(string)` | `{}` | no | | [iam\_role\_tags](#input\_iam\_role\_tags) | A map of additional tags to add the the IAM role | `map(any)` | `{}` | no | | [iam\_role\_use\_name\_prefix](#input\_iam\_role\_use\_name\_prefix) | Determines whether the name of the IAM role (`iam_role_name`) is used as a prefix | `bool` | `true` | no | -| [irsa\_assume\_role\_condition\_test](#input\_irsa\_assume\_role\_condition\_test) | Name of the [IAM condition operator](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html) to evaluate when assuming the role | `string` | `"StringEquals"` | no | -| [irsa\_namespace\_service\_accounts](#input\_irsa\_namespace\_service\_accounts) | List of `namespace:serviceaccount`pairs to use in trust policy for IAM role for service accounts | `list(string)` |
[
"karpenter:karpenter"
]
| no | -| [irsa\_oidc\_provider\_arn](#input\_irsa\_oidc\_provider\_arn) | OIDC provider arn used in trust policy for IAM role for service accounts | `string` | `""` | no | | [namespace](#input\_namespace) | Namespace to associate with the Karpenter Pod Identity | `string` | `"kube-system"` | no | | [node\_iam\_role\_additional\_policies](#input\_node\_iam\_role\_additional\_policies) | Additional policies to be added to the IAM role | `map(string)` | `{}` | no | | [node\_iam\_role\_arn](#input\_node\_iam\_role\_arn) | Existing IAM role ARN for the IAM instance profile. Required if `create_iam_role` is set to `false` | `string` | `null` | no | diff --git a/modules/karpenter/main.tf b/modules/karpenter/main.tf index 7e4a73d0de..11606c97e2 100644 --- a/modules/karpenter/main.tf +++ b/modules/karpenter/main.tf @@ -1,12 +1,18 @@ -data "aws_region" "current" {} -data "aws_partition" "current" {} -data "aws_caller_identity" "current" {} +data "aws_region" "current" { + count = var.create ? 1 : 0 +} +data "aws_partition" "current" { + count = var.create ? 1 : 0 +} +data "aws_caller_identity" "current" { + count = var.create ? 1 : 0 +} locals { - account_id = data.aws_caller_identity.current.account_id - dns_suffix = data.aws_partition.current.dns_suffix - partition = data.aws_partition.current.partition - region = data.aws_region.current.name + account_id = try(data.aws_caller_identity.current[0].account_id, "") + dns_suffix = try(data.aws_partition.current[0].dns_suffix, "") + partition = try(data.aws_partition.current[0].partition, "") + region = try(data.aws_region.current[0].region, "") } ################################################################################ @@ -14,8 +20,7 @@ locals { ################################################################################ locals { - create_iam_role = var.create && var.create_iam_role - irsa_oidc_provider_url = replace(var.irsa_oidc_provider_arn, "/^(.*provider/)/", "") + create_iam_role = var.create && var.create_iam_role } data "aws_iam_policy_document" "controller_assume_role" { @@ -37,33 +42,6 @@ data "aws_iam_policy_document" "controller_assume_role" { } } } - - # IAM Roles for Service Accounts (IRSA) - dynamic "statement" { - for_each = var.enable_irsa ? [1] : [] - - content { - actions = ["sts:AssumeRoleWithWebIdentity"] - - principals { - type = "Federated" - identifiers = [var.irsa_oidc_provider_arn] - } - - condition { - test = var.irsa_assume_role_condition_test - variable = "${local.irsa_oidc_provider_url}:sub" - values = [for sa in var.irsa_namespace_service_accounts : "system:serviceaccount:${sa}"] - } - - # https://aws.amazon.com/premiumsupport/knowledge-center/eks-troubleshoot-oidc-and-irsa/?nc1=h_ls - condition { - test = var.irsa_assume_role_condition_test - variable = "${local.irsa_oidc_provider_url}:aud" - values = ["sts.amazonaws.com"] - } - } - } } resource "aws_iam_role" "controller" { @@ -268,7 +246,7 @@ locals { AmazonEKS_CNI_Policy = "${local.node_iam_role_policy_prefix}/AmazonEKS_CNI_Policy" } : k => v if var.node_iam_role_attach_cni_policy && var.cluster_ip_family == "ipv4" } ipv6_cni_policy = { for k, v in { - AmazonEKS_CNI_IPv6_Policy = "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:policy/AmazonEKS_CNI_IPv6_Policy" + AmazonEKS_CNI_IPv6_Policy = "arn:${local.partition}:iam::${local.account_id}:policy/AmazonEKS_CNI_IPv6_Policy" } : k => v if var.node_iam_role_attach_cni_policy && var.cluster_ip_family == "ipv6" } } diff --git a/modules/karpenter/variables.tf b/modules/karpenter/variables.tf index 50cd58a6da..a403eba995 100644 --- a/modules/karpenter/variables.tf +++ b/modules/karpenter/variables.tf @@ -116,34 +116,6 @@ variable "enable_pod_identity" { default = true } -################################################################################ -# IAM Role for Service Account (IRSA) -################################################################################ - -variable "enable_irsa" { - description = "Determines whether to enable support for IAM role for service accounts" - type = bool - default = false -} - -variable "irsa_oidc_provider_arn" { - description = "OIDC provider arn used in trust policy for IAM role for service accounts" - type = string - default = "" -} - -variable "irsa_namespace_service_accounts" { - description = "List of `namespace:serviceaccount`pairs to use in trust policy for IAM role for service accounts" - type = list(string) - default = ["karpenter:karpenter"] -} - -variable "irsa_assume_role_condition_test" { - description = "Name of the [IAM condition operator](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html) to evaluate when assuming the role" - type = string - default = "StringEquals" -} - ################################################################################ # Pod Identity Association ################################################################################ From 2d79dc21eb3358c9af21cd2573f97c05dff50ed1 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Mon, 7 Jul 2025 14:48:08 -0500 Subject: [PATCH 08/25] fix: Avoid making GET requests from data sources unless absolutely necessary --- main.tf | 3 ++- modules/eks-managed-node-group/README.md | 2 ++ modules/eks-managed-node-group/main.tf | 17 ++++++++++---- modules/eks-managed-node-group/variables.tf | 12 ++++++++++ modules/fargate-profile/README.md | 2 ++ modules/fargate-profile/main.tf | 24 +++++++++++++++----- modules/fargate-profile/variables.tf | 12 ++++++++++ modules/hybrid-node-role/main.tf | 3 +-- modules/self-managed-node-group/README.md | 2 ++ modules/self-managed-node-group/main.tf | 17 ++++++++++---- modules/self-managed-node-group/variables.tf | 12 ++++++++++ node_groups.tf | 12 ++++++++++ 12 files changed, 101 insertions(+), 17 deletions(-) diff --git a/main.tf b/main.tf index da48f3672c..63891561d2 100644 --- a/main.tf +++ b/main.tf @@ -18,7 +18,8 @@ data "aws_iam_session_context" "current" { locals { create = var.create && var.putin_khuylo - partition = try(data.aws_partition.current[0].partition, "") + account_id = try(data.aws_caller_identity.current[0].account_id, "") + partition = try(data.aws_partition.current[0].partition, "") cluster_role = try(aws_iam_role.this[0].arn, var.iam_role_arn) diff --git a/modules/eks-managed-node-group/README.md b/modules/eks-managed-node-group/README.md index 1dbf4a8087..f834a5ceed 100644 --- a/modules/eks-managed-node-group/README.md +++ b/modules/eks-managed-node-group/README.md @@ -101,6 +101,7 @@ module "eks_managed_node_group" { | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [account\_id](#input\_account\_id) | The AWS account ID - pass through value to reduce number of GET requests from data sources | `string` | `""` | no | | [ami\_id](#input\_ami\_id) | The AMI from which to launch the instance. If not supplied, EKS will use its own default image | `string` | `""` | no | | [ami\_release\_version](#input\_ami\_release\_version) | The AMI version. Defaults to latest AMI release version for the given Kubernetes version and AMI type | `string` | `null` | no | | [ami\_type](#input\_ami\_type) | Type of Amazon Machine Image (AMI) associated with the EKS Node Group. See the [AWS documentation](https://docs.aws.amazon.com/eks/latest/APIReference/API_Nodegroup.html#AmazonEKS-Type-Nodegroup-amiType) for valid values | `string` | `"AL2023_x86_64_STANDARD"` | no | @@ -166,6 +167,7 @@ module "eks_managed_node_group" { | [name](#input\_name) | Name of the EKS managed node group | `string` | `""` | no | | [network\_interfaces](#input\_network\_interfaces) | Customize network interfaces to be attached at instance boot time | `list(any)` | `[]` | no | | [node\_repair\_config](#input\_node\_repair\_config) | The node auto repair configuration for the node group |
object({
enabled = optional(bool, true)
})
| `null` | no | +| [partition](#input\_partition) | The AWS partition - pass through value to reduce number of GET requests from data sources | `string` | `""` | no | | [placement](#input\_placement) | The placement of the instance | `map(string)` | `{}` | no | | [placement\_group\_strategy](#input\_placement\_group\_strategy) | The placement group strategy | `string` | `"cluster"` | no | | [post\_bootstrap\_user\_data](#input\_post\_bootstrap\_user\_data) | User data that is appended to the user data script after of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | diff --git a/modules/eks-managed-node-group/main.tf b/modules/eks-managed-node-group/main.tf index 5a5e539f4e..b85e1f2652 100644 --- a/modules/eks-managed-node-group/main.tf +++ b/modules/eks-managed-node-group/main.tf @@ -1,5 +1,14 @@ -data "aws_partition" "current" {} -data "aws_caller_identity" "current" {} +data "aws_partition" "current" { + count = var.create && var.partition == "" ? 1 : 0 +} +data "aws_caller_identity" "current" { + count = var.create && var.account_id == "" ? 1 : 0 +} + +locals { + partition = try(data.aws_partition.current[0].partition, var.partition) + account_id = try(data.aws_caller_identity.current[0].account_id, var.account_id) +} ################################################################################ # User Data @@ -477,13 +486,13 @@ locals { create_iam_role = var.create && var.create_iam_role iam_role_name = coalesce(var.iam_role_name, "${var.name}-eks-node-group") - iam_role_policy_prefix = "arn:${data.aws_partition.current.partition}:iam::aws:policy" + iam_role_policy_prefix = "arn:${local.partition}:iam::aws:policy" ipv4_cni_policy = { for k, v in { AmazonEKS_CNI_Policy = "${local.iam_role_policy_prefix}/AmazonEKS_CNI_Policy" } : k => v if var.iam_role_attach_cni_policy && var.cluster_ip_family == "ipv4" } ipv6_cni_policy = { for k, v in { - AmazonEKS_CNI_IPv6_Policy = "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:policy/AmazonEKS_CNI_IPv6_Policy" + AmazonEKS_CNI_IPv6_Policy = "arn:${local.partition}:iam::${local.account_id}:policy/AmazonEKS_CNI_IPv6_Policy" } : k => v if var.iam_role_attach_cni_policy && var.cluster_ip_family == "ipv6" } } diff --git a/modules/eks-managed-node-group/variables.tf b/modules/eks-managed-node-group/variables.tf index 4fb148c590..96fa7d75b5 100644 --- a/modules/eks-managed-node-group/variables.tf +++ b/modules/eks-managed-node-group/variables.tf @@ -10,6 +10,18 @@ variable "tags" { default = {} } +variable "partition" { + description = "The AWS partition - pass through value to reduce number of GET requests from data sources" + type = string + default = "" +} + +variable "account_id" { + description = "The AWS account ID - pass through value to reduce number of GET requests from data sources" + type = string + default = "" +} + ################################################################################ # User Data ################################################################################ diff --git a/modules/fargate-profile/README.md b/modules/fargate-profile/README.md index 0d1b40344d..cf29596788 100644 --- a/modules/fargate-profile/README.md +++ b/modules/fargate-profile/README.md @@ -60,6 +60,7 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [account\_id](#input\_account\_id) | The AWS account ID - pass through value to reduce number of GET requests from data sources | `string` | `null` | no | | [cluster\_ip\_family](#input\_cluster\_ip\_family) | The IP family used to assign Kubernetes pod and service addresses. Valid values are `ipv4` (default) and `ipv6` | `string` | `"ipv4"` | no | | [cluster\_name](#input\_cluster\_name) | Name of the EKS cluster | `string` | `null` | no | | [create](#input\_create) | Determines whether to create Fargate profile or not | `bool` | `true` | no | @@ -76,6 +77,7 @@ No modules. | [iam\_role\_tags](#input\_iam\_role\_tags) | A map of additional tags to add to the IAM role created | `map(string)` | `{}` | no | | [iam\_role\_use\_name\_prefix](#input\_iam\_role\_use\_name\_prefix) | Determines whether the IAM role name (`iam_role_name`) is used as a prefix | `bool` | `true` | no | | [name](#input\_name) | Name of the EKS Fargate Profile | `string` | `""` | no | +| [partition](#input\_partition) | The AWS partition - pass through value to reduce number of GET requests from data sources | `string` | `null` | no | | [selectors](#input\_selectors) | Configuration block(s) for selecting Kubernetes Pods to execute with this Fargate Profile | `any` | `[]` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs for the EKS Fargate Profile | `list(string)` | `[]` | no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | diff --git a/modules/fargate-profile/main.tf b/modules/fargate-profile/main.tf index ffbbfb8294..3e124282dc 100644 --- a/modules/fargate-profile/main.tf +++ b/modules/fargate-profile/main.tf @@ -1,18 +1,30 @@ -data "aws_partition" "current" {} -data "aws_caller_identity" "current" {} -data "aws_region" "current" {} +data "aws_region" "current" { + count = var.create ? 1 : 0 +} +data "aws_partition" "current" { + count = var.create && var.partition == "" ? 1 : 0 +} +data "aws_caller_identity" "current" { + count = var.create && var.account_id == "" ? 1 : 0 +} + +locals { + account_id = try(data.aws_caller_identity.current[0].account_id, var.account_id) + partition = try(data.aws_partition.current[0].partition, var.partition) + region = try(data.aws_region.current[0].region, "") +} locals { create_iam_role = var.create && var.create_iam_role iam_role_name = coalesce(var.iam_role_name, var.name, "fargate-profile") - iam_role_policy_prefix = "arn:${data.aws_partition.current.partition}:iam::aws:policy" + iam_role_policy_prefix = "arn:${local.partition}:iam::aws:policy" ipv4_cni_policy = { for k, v in { AmazonEKS_CNI_Policy = "${local.iam_role_policy_prefix}/AmazonEKS_CNI_Policy" } : k => v if var.iam_role_attach_cni_policy && var.cluster_ip_family == "ipv4" } ipv6_cni_policy = { for k, v in { - AmazonEKS_CNI_IPv6_Policy = "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:policy/AmazonEKS_CNI_IPv6_Policy" + AmazonEKS_CNI_IPv6_Policy = "arn:${local.partition}:iam::${local.account_id}:policy/AmazonEKS_CNI_IPv6_Policy" } : k => v if var.iam_role_attach_cni_policy && var.cluster_ip_family == "ipv6" } } @@ -37,7 +49,7 @@ data "aws_iam_policy_document" "assume_role_policy" { variable = "aws:SourceArn" values = [ - "arn:${data.aws_partition.current.partition}:eks:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:fargateprofile/${var.cluster_name}/*", + "arn:${local.partition}:eks:${local.region}:${local.account_id}:fargateprofile/${var.cluster_name}/*", ] } } diff --git a/modules/fargate-profile/variables.tf b/modules/fargate-profile/variables.tf index 3e37b8c151..cd2db7ac6a 100644 --- a/modules/fargate-profile/variables.tf +++ b/modules/fargate-profile/variables.tf @@ -10,6 +10,18 @@ variable "tags" { default = {} } +variable "partition" { + description = "The AWS partition - pass through value to reduce number of GET requests from data sources" + type = string + default = null +} + +variable "account_id" { + description = "The AWS account ID - pass through value to reduce number of GET requests from data sources" + type = string + default = null +} + ################################################################################ # IAM Role ################################################################################ diff --git a/modules/hybrid-node-role/main.tf b/modules/hybrid-node-role/main.tf index 5a2473f29b..7ef874c6b3 100644 --- a/modules/hybrid-node-role/main.tf +++ b/modules/hybrid-node-role/main.tf @@ -1,9 +1,8 @@ data "aws_partition" "current" { count = var.create ? 1 : 0 } - locals { - partition = try(data.aws_partition.current[0].partition, "aws") + partition = try(data.aws_partition.current[0].partition, "") } ################################################################################ diff --git a/modules/self-managed-node-group/README.md b/modules/self-managed-node-group/README.md index 9193a6d129..e4c7bbac50 100644 --- a/modules/self-managed-node-group/README.md +++ b/modules/self-managed-node-group/README.md @@ -82,6 +82,7 @@ module "self_managed_node_group" { | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [account\_id](#input\_account\_id) | The AWS account ID - pass through value to reduce number of GET requests from data sources | `string` | `""` | no | | [additional\_cluster\_dns\_ips](#input\_additional\_cluster\_dns\_ips) | Additional DNS IP addresses to use for the cluster. Only used when `ami_type` = `BOTTLEROCKET_*` | `list(string)` | `[]` | no | | [ami\_id](#input\_ami\_id) | The AMI from which to launch the instance | `string` | `""` | no | | [ami\_type](#input\_ami\_type) | Type of Amazon Machine Image (AMI) associated with the node group. See the [AWS documentation](https://docs.aws.amazon.com/eks/latest/APIReference/API_Nodegroup.html#AmazonEKS-Type-Nodegroup-amiType) for valid values | `string` | `"AL2023_x86_64_STANDARD"` | no | @@ -168,6 +169,7 @@ module "self_managed_node_group" { | [mixed\_instances\_policy](#input\_mixed\_instances\_policy) | Configuration block containing settings to define launch targets for Auto Scaling groups | `any` | `null` | no | | [name](#input\_name) | Name of the Self managed Node Group | `string` | `""` | no | | [network\_interfaces](#input\_network\_interfaces) | Customize network interfaces to be attached at instance boot time | `list(any)` | `[]` | no | +| [partition](#input\_partition) | The AWS partition - pass through value to reduce number of GET requests from data sources | `string` | `""` | no | | [placement](#input\_placement) | The placement of the instance | `map(string)` | `{}` | no | | [placement\_group](#input\_placement\_group) | The name of the placement group into which you'll launch your instances, if any | `string` | `null` | no | | [post\_bootstrap\_user\_data](#input\_post\_bootstrap\_user\_data) | User data that is appended to the user data script after of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | diff --git a/modules/self-managed-node-group/main.tf b/modules/self-managed-node-group/main.tf index 7cadc42ea4..d1f693cc06 100644 --- a/modules/self-managed-node-group/main.tf +++ b/modules/self-managed-node-group/main.tf @@ -1,5 +1,14 @@ -data "aws_partition" "current" {} -data "aws_caller_identity" "current" {} +data "aws_partition" "current" { + count = var.create && var.partition == "" ? 1 : 0 +} +data "aws_caller_identity" "current" { + count = var.create && var.account_id == "" ? 1 : 0 +} + +locals { + partition = try(data.aws_partition.current[0].partition, var.partition) + account_id = try(data.aws_caller_identity.current[0].account_id, var.account_id) +} ################################################################################ # AMI SSM Parameter @@ -759,13 +768,13 @@ locals { create_iam_instance_profile = var.create && var.create_iam_instance_profile iam_role_name = coalesce(var.iam_role_name, "${var.name}-node-group") - iam_role_policy_prefix = "arn:${data.aws_partition.current.partition}:iam::aws:policy" + iam_role_policy_prefix = "arn:${local.partition}:iam::aws:policy" ipv4_cni_policy = { for k, v in { AmazonEKS_CNI_Policy = "${local.iam_role_policy_prefix}/AmazonEKS_CNI_Policy" } : k => v if var.iam_role_attach_cni_policy && var.cluster_ip_family == "ipv4" } ipv6_cni_policy = { for k, v in { - AmazonEKS_CNI_IPv6_Policy = "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:policy/AmazonEKS_CNI_IPv6_Policy" + AmazonEKS_CNI_IPv6_Policy = "arn:${local.partition}:iam::${local.account_id}:policy/AmazonEKS_CNI_IPv6_Policy" } : k => v if var.iam_role_attach_cni_policy && var.cluster_ip_family == "ipv6" } } diff --git a/modules/self-managed-node-group/variables.tf b/modules/self-managed-node-group/variables.tf index 0afe3177a2..48168a96e6 100644 --- a/modules/self-managed-node-group/variables.tf +++ b/modules/self-managed-node-group/variables.tf @@ -10,6 +10,18 @@ variable "tags" { default = {} } +variable "partition" { + description = "The AWS partition - pass through value to reduce number of GET requests from data sources" + type = string + default = "" +} + +variable "account_id" { + description = "The AWS account ID - pass through value to reduce number of GET requests from data sources" + type = string + default = "" +} + ################################################################################ # User Data ################################################################################ diff --git a/node_groups.tf b/node_groups.tf index 45039e5d42..df39d793d7 100644 --- a/node_groups.tf +++ b/node_groups.tf @@ -262,6 +262,10 @@ module "fargate_profile" { create = try(each.value.create, true) + # Pass through values to reduce GET requests from data sources + partition = local.partition + account_id = local.account_id + # Fargate Profile cluster_name = time_sleep.this[0].triggers["cluster_name"] cluster_ip_family = var.cluster_ip_family @@ -300,6 +304,10 @@ module "eks_managed_node_group" { create = try(each.value.create, true) + # Pass through values to reduce GET requests from data sources + partition = local.partition + account_id = local.account_id + cluster_name = time_sleep.this[0].triggers["cluster_name"] cluster_version = try(each.value.cluster_version, var.eks_managed_node_group_defaults.cluster_version, time_sleep.this[0].triggers["cluster_version"]) @@ -418,6 +426,10 @@ module "self_managed_node_group" { create = try(each.value.create, true) + # Pass through values to reduce GET requests from data sources + partition = local.partition + account_id = local.account_id + cluster_name = time_sleep.this[0].triggers["cluster_name"] # Autoscaling Group From 200a712b6c78b03267cbb2aeba46fcf4786c9559 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Tue, 8 Jul 2025 15:00:04 -0500 Subject: [PATCH 09/25] feat: Add variable optional attribute definitions --- README.md | 12 +- modules/_user_data/main.tf | 2 +- modules/_user_data/outputs.tf | 2 +- modules/eks-managed-node-group/README.md | 41 +- modules/eks-managed-node-group/main.tf | 255 ++-- modules/eks-managed-node-group/outputs.tf | 9 - modules/eks-managed-node-group/variables.tf | 219 ++- modules/fargate-profile/README.md | 6 +- modules/fargate-profile/main.tf | 33 +- modules/fargate-profile/variables.tf | 38 +- modules/hybrid-node-role/README.md | 8 +- modules/hybrid-node-role/main.tf | 43 +- modules/hybrid-node-role/variables.tf | 59 +- modules/karpenter/README.md | 4 +- modules/karpenter/policy.tf | 20 +- modules/karpenter/variables.tf | 26 +- modules/self-managed-node-group/README.md | 58 +- modules/self-managed-node-group/main.tf | 569 ++++---- modules/self-managed-node-group/outputs.tf | 9 - modules/self-managed-node-group/variables.tf | 393 ++++- node_groups.tf | 302 ++-- scratch/main.tf | 20 + tests/self-managed-node-group/main.tf | 50 +- variables.tf | 1365 +++++++++++++++++- 24 files changed, 2676 insertions(+), 867 deletions(-) create mode 100644 scratch/main.tf diff --git a/README.md b/README.md index de2d3a9b64..f9e8bcac1a 100644 --- a/README.md +++ b/README.md @@ -433,15 +433,15 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [create\_node\_security\_group](#input\_create\_node\_security\_group) | Determines whether to create a security group for the node groups or use the existing `node_security_group_id` | `bool` | `true` | no | | [custom\_oidc\_thumbprints](#input\_custom\_oidc\_thumbprints) | Additional list of server certificate thumbprints for the OpenID Connect (OIDC) identity provider's server certificate(s) | `list(string)` | `[]` | no | | [dataplane\_wait\_duration](#input\_dataplane\_wait\_duration) | Duration to wait after the EKS cluster has become active before creating the dataplane components (EKS managed node group(s), self-managed node group(s), Fargate profile(s)) | `string` | `"30s"` | no | -| [eks\_managed\_node\_group\_defaults](#input\_eks\_managed\_node\_group\_defaults) | Map of EKS managed node group default configurations | `any` | `{}` | no | -| [eks\_managed\_node\_groups](#input\_eks\_managed\_node\_groups) | Map of EKS managed node group definitions to create | `any` | `{}` | no | +| [eks\_managed\_node\_group\_defaults](#input\_eks\_managed\_node\_group\_defaults) | Map of EKS managed node group default configurations |
object({
create = optional(bool)
cluster_version = optional(string)

# EKS Managed Node Group
use_name_prefix = optional(bool)
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
ami_id = optional(string)
ami_type = optional(string)
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool)
capacity_type = optional(string)
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}))
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool)
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
create_placement_group = optional(bool)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string))
cluster_primary_security_group_id = optional(string)

tags = optional(map(string), {})
})
| `{}` | no | +| [eks\_managed\_node\_groups](#input\_eks\_managed\_node\_groups) | Map of EKS managed node group definitions to create |
map(object({
create = optional(bool, true)
cluster_version = optional(string)

# EKS Managed Node Group
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
ami_id = optional(string, "")
ami_type = optional(string, "AL2023_x86_64_STANDARD")
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool, true)
capacity_type = optional(string, "ON_DEMAND")
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool, true)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}), {
max_unavailable_percentage = 33
})
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool, false)
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
create_placement_group = optional(bool, false)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool, true)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "EKS managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string), [])
cluster_primary_security_group_id = optional(string)

tags = optional(map(string), {})
}))
| `{}` | no | | [enable\_auto\_mode\_custom\_tags](#input\_enable\_auto\_mode\_custom\_tags) | Determines whether to enable permissions for custom tags resources created by EKS Auto Mode | `bool` | `true` | no | | [enable\_cluster\_creator\_admin\_permissions](#input\_enable\_cluster\_creator\_admin\_permissions) | Indicates whether or not to add the cluster creator (the identity used by Terraform) as an administrator via access entry | `bool` | `false` | no | | [enable\_efa\_support](#input\_enable\_efa\_support) | Determines whether to enable Elastic Fabric Adapter (EFA) support | `bool` | `false` | no | | [enable\_irsa](#input\_enable\_irsa) | Determines whether to create an OpenID Connect Provider for EKS to enable IRSA | `bool` | `true` | no | | [enable\_kms\_key\_rotation](#input\_enable\_kms\_key\_rotation) | Specifies whether key rotation is enabled | `bool` | `true` | no | -| [fargate\_profile\_defaults](#input\_fargate\_profile\_defaults) | Map of Fargate Profile default configurations | `any` | `{}` | no | -| [fargate\_profiles](#input\_fargate\_profiles) | Map of Fargate Profile definitions to create | `any` | `{}` | no | +| [fargate\_profile\_defaults](#input\_fargate\_profile\_defaults) | Map of Fargate Profile default configurations |
object({
create = optional(bool)

# Fargate profile
name = optional(string) # Will fall back to map key
subnet_ids = optional(list(string))
selectors = optional(list(object({
labels = optional(map(string))
namespace = string
})))
timeouts = optional(object({
create = optional(string)
delete = optional(string)
}))

# IAM role
create_iam_role = optional(bool)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
tags = optional(map(string), {})
})
| `{}` | no | +| [fargate\_profiles](#input\_fargate\_profiles) | Map of Fargate Profile definitions to create |
map(object({
create = optional(bool, true)

# Fargate profile
name = optional(string) # Will fall back to map key
subnet_ids = optional(list(string), [])
selectors = optional(list(object({
labels = optional(map(string))
namespace = string
})))
timeouts = optional(object({
create = optional(string)
delete = optional(string)
}))

# IAM role
create_iam_role = optional(bool, true)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Fargate profile IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
tags = optional(map(string), {})
}))
| `{}` | no | | [iam\_role\_additional\_policies](#input\_iam\_role\_additional\_policies) | Additional policies to be added to the IAM role | `map(string)` | `{}` | no | | [iam\_role\_arn](#input\_iam\_role\_arn) | Existing IAM role ARN for the cluster. Required if `create_iam_role` is set to `false` | `string` | `null` | no | | [iam\_role\_description](#input\_iam\_role\_description) | Description of the role | `string` | `null` | no | @@ -479,8 +479,8 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [outpost\_config](#input\_outpost\_config) | Configuration for the AWS Outpost to provision the cluster on | `any` | `{}` | no | | [prefix\_separator](#input\_prefix\_separator) | The separator to use between the prefix and the generated timestamp for resource names | `string` | `"-"` | no | | [putin\_khuylo](#input\_putin\_khuylo) | Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo! | `bool` | `true` | no | -| [self\_managed\_node\_group\_defaults](#input\_self\_managed\_node\_group\_defaults) | Map of self-managed node group default configurations | `any` | `{}` | no | -| [self\_managed\_node\_groups](#input\_self\_managed\_node\_groups) | Map of self-managed node group definitions to create | `any` | `{}` | no | +| [self\_managed\_node\_group\_defaults](#input\_self\_managed\_node\_group\_defaults) | Map of self-managed node group default configurations |
object({
create = optional(bool)
# Autoscaling Group
create_autoscaling_group = optional(bool)
use_name_prefix = optional(bool)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool)
context = optional(string)
target_group_arns = optional(list(string))
create_placement_group = optional(bool)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(number)
force_delete = optional(bool)
force_delete_warm_pool = optional(bool)
termination_policies = optional(list(string))
suspended_processes = optional(list(string))
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string))
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string)
triggers = optional(list(string))
}))
use_mixed_instances_policy = optional(bool)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
warm_pool = optional(object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string))
# User data
ami_type = optional(string)
additional_cluster_dns_ips = optional(list(string))
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string)
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
hibernation_options = optional(object({
configured = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool)
iam_role_arn = optional(string)

tags = optional(map(string))
})
| `{}` | no | +| [self\_managed\_node\_groups](#input\_self\_managed\_node\_groups) | Map of self-managed node group definitions to create |
map(object({
create = optional(bool, true)
# Autoscaling Group
create_autoscaling_group = optional(bool, true)
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool, false)
context = optional(string)
target_group_arns = optional(list(string), [])
create_placement_group = optional(bool, false)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(number)
force_delete = optional(bool)
force_delete_warm_pool = optional(bool)
termination_policies = optional(list(string), [])
suspended_processes = optional(list(string), [])
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string), [])
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number, 66)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string, "Rolling")
triggers = optional(list(string))
}), {
strategy = "Rolling"
preferences = {
min_healthy_percentage = 66
}
})
use_mixed_instances_policy = optional(bool, false)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
warm_pool = optional(object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string), {})
# User data
ami_type = optional(string, "AL2023_x86_64_STANDARD")
additional_cluster_dns_ips = optional(list(string), [])
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string, "m6i.large")
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
hibernation_options = optional(object({
configured = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool, true)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Self managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool, true)
iam_role_arn = optional(string)

tags = optional(map(string), {})
}))
| `{}` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs where the nodes/node groups will be provisioned. If `control_plane_subnet_ids` is not provided, the EKS cluster control plane (ENIs) will be provisioned in these subnets | `list(string)` | `[]` | no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | | [vpc\_id](#input\_vpc\_id) | ID of the VPC where the cluster security group will be provisioned | `string` | `null` | no | diff --git a/modules/_user_data/main.tf b/modules/_user_data/main.tf index a665b31eec..c394421c4c 100644 --- a/modules/_user_data/main.tf +++ b/modules/_user_data/main.tf @@ -47,7 +47,7 @@ locals { cluster_dns_ips = flatten(concat([try(cidrhost(var.cluster_service_cidr, 10), "")], var.additional_cluster_dns_ips)) - user_data = var.ami_type != "" ? base64encode(templatefile(local.user_data_path, + user_data = var.create ? base64encode(templatefile(local.user_data_path, { # https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-custom-ami enable_bootstrap_user_data = var.enable_bootstrap_user_data diff --git a/modules/_user_data/outputs.tf b/modules/_user_data/outputs.tf index 40c1d82a4e..dda4b5195d 100644 --- a/modules/_user_data/outputs.tf +++ b/modules/_user_data/outputs.tf @@ -1,4 +1,4 @@ output "user_data" { description = "Base64 encoded user data rendered for the provided inputs" - value = var.create ? local.user_data_type_to_rendered : "" + value = local.user_data_type_to_rendered } diff --git a/modules/eks-managed-node-group/README.md b/modules/eks-managed-node-group/README.md index f834a5ceed..4f310e5df3 100644 --- a/modules/eks-managed-node-group/README.md +++ b/modules/eks-managed-node-group/README.md @@ -82,7 +82,6 @@ module "eks_managed_node_group" { | Name | Type | |------|------| -| [aws_autoscaling_schedule.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/autoscaling_schedule) | resource | | [aws_eks_node_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource | | [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | @@ -105,9 +104,9 @@ module "eks_managed_node_group" { | [ami\_id](#input\_ami\_id) | The AMI from which to launch the instance. If not supplied, EKS will use its own default image | `string` | `""` | no | | [ami\_release\_version](#input\_ami\_release\_version) | The AMI version. Defaults to latest AMI release version for the given Kubernetes version and AMI type | `string` | `null` | no | | [ami\_type](#input\_ami\_type) | Type of Amazon Machine Image (AMI) associated with the EKS Node Group. See the [AWS documentation](https://docs.aws.amazon.com/eks/latest/APIReference/API_Nodegroup.html#AmazonEKS-Type-Nodegroup-amiType) for valid values | `string` | `"AL2023_x86_64_STANDARD"` | no | -| [block\_device\_mappings](#input\_block\_device\_mappings) | Specify volumes to attach to the instance besides the volumes specified by the AMI | `any` | `{}` | no | +| [block\_device\_mappings](#input\_block\_device\_mappings) | Specify volumes to attach to the instance besides the volumes specified by the AMI |
map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
}))
| `null` | no | | [bootstrap\_extra\_args](#input\_bootstrap\_extra\_args) | Additional arguments passed to the bootstrap script. When `ami_type` = `BOTTLEROCKET_*`; these are additional [settings](https://github.com/bottlerocket-os/bottlerocket#settings) that are provided to the Bottlerocket user data | `string` | `""` | no | -| [capacity\_reservation\_specification](#input\_capacity\_reservation\_specification) | Targeting for EC2 capacity reservations | `any` | `{}` | no | +| [capacity\_reservation\_specification](#input\_capacity\_reservation\_specification) | Targeting for EC2 capacity reservations |
object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
})
| `null` | no | | [capacity\_type](#input\_capacity\_type) | Type of capacity associated with the EKS Node Group. Valid values: `ON_DEMAND`, `SPOT` | `string` | `"ON_DEMAND"` | no | | [cloudinit\_post\_nodeadm](#input\_cloudinit\_post\_nodeadm) | Array of cloud-init document parts that are created after the nodeadm document part |
list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
}))
| `[]` | no | | [cloudinit\_pre\_nodeadm](#input\_cloudinit\_pre\_nodeadm) | Array of cloud-init document parts that are created before the nodeadm document part |
list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
}))
| `[]` | no | @@ -118,14 +117,13 @@ module "eks_managed_node_group" { | [cluster\_primary\_security\_group\_id](#input\_cluster\_primary\_security\_group\_id) | The ID of the EKS cluster primary security group to associate with the instance(s). This is the security group that is automatically created by the EKS service | `string` | `null` | no | | [cluster\_service\_cidr](#input\_cluster\_service\_cidr) | The CIDR block (IPv4 or IPv6) used by the cluster to assign Kubernetes service IP addresses. This is derived from the cluster itself | `string` | `""` | no | | [cluster\_version](#input\_cluster\_version) | Kubernetes version. Defaults to EKS Cluster Kubernetes version | `string` | `null` | no | -| [cpu\_options](#input\_cpu\_options) | The CPU options for the instance | `map(string)` | `{}` | no | +| [cpu\_options](#input\_cpu\_options) | The CPU options for the instance |
object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
})
| `null` | no | | [create](#input\_create) | Determines whether to create EKS managed node group or not | `bool` | `true` | no | | [create\_iam\_role](#input\_create\_iam\_role) | Determines whether an IAM role is created or to use an existing IAM role | `bool` | `true` | no | | [create\_iam\_role\_policy](#input\_create\_iam\_role\_policy) | Determines whether an IAM role policy is created or not | `bool` | `true` | no | | [create\_launch\_template](#input\_create\_launch\_template) | Determines whether to create a launch template or not. If set to `false`, EKS will use its own default launch template | `bool` | `true` | no | | [create\_placement\_group](#input\_create\_placement\_group) | Determines whether a placement group is created & used by the node group | `bool` | `false` | no | -| [create\_schedule](#input\_create\_schedule) | Determines whether to create autoscaling group schedule or not | `bool` | `true` | no | -| [credit\_specification](#input\_credit\_specification) | Customize the credit specification of the instance | `map(string)` | `{}` | no | +| [credit\_specification](#input\_credit\_specification) | Customize the credit specification of the instance |
object({
cpu_credits = optional(string)
})
| `null` | no | | [desired\_size](#input\_desired\_size) | Desired number of instances/nodes | `number` | `1` | no | | [disable\_api\_termination](#input\_disable\_api\_termination) | If true, enables EC2 instance termination protection | `bool` | `null` | no | | [disk\_size](#input\_disk\_size) | Disk size in GiB for nodes. Defaults to `20`. Only valid when `use_custom_launch_template` = `false` | `number` | `null` | no | @@ -135,7 +133,7 @@ module "eks_managed_node_group" { | [enable\_efa\_only](#input\_enable\_efa\_only) | Determines whether to enable EFA (`false`, default) or EFA and EFA-only (`true`) network interfaces. Note: requires vpc-cni version `v1.18.4` or later | `bool` | `true` | no | | [enable\_efa\_support](#input\_enable\_efa\_support) | Determines whether to enable Elastic Fabric Adapter (EFA) support | `bool` | `false` | no | | [enable\_monitoring](#input\_enable\_monitoring) | Enables/disables detailed monitoring | `bool` | `false` | no | -| [enclave\_options](#input\_enclave\_options) | Enable Nitro Enclaves on launched instances | `map(string)` | `{}` | no | +| [enclave\_options](#input\_enclave\_options) | Enable Nitro Enclaves on launched instances |
object({
enabled = optional(bool)
})
| `null` | no | | [force\_update\_version](#input\_force\_update\_version) | Force version update if existing pods are unable to be drained due to a pod disruption budget issue | `bool` | `null` | no | | [iam\_role\_additional\_policies](#input\_iam\_role\_additional\_policies) | Additional policies to be added to the IAM role | `map(string)` | `{}` | no | | [iam\_role\_arn](#input\_iam\_role\_arn) | Existing IAM role ARN for the node group. Required if `create_iam_role` is set to `false` | `string` | `null` | no | @@ -144,10 +142,10 @@ module "eks_managed_node_group" { | [iam\_role\_name](#input\_iam\_role\_name) | Name to use on IAM role created | `string` | `null` | no | | [iam\_role\_path](#input\_iam\_role\_path) | IAM role path | `string` | `null` | no | | [iam\_role\_permissions\_boundary](#input\_iam\_role\_permissions\_boundary) | ARN of the policy that is used to set the permissions boundary for the IAM role | `string` | `null` | no | -| [iam\_role\_policy\_statements](#input\_iam\_role\_policy\_statements) | A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed | `any` | `[]` | no | +| [iam\_role\_policy\_statements](#input\_iam\_role\_policy\_statements) | A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed |
list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
}))
| `null` | no | | [iam\_role\_tags](#input\_iam\_role\_tags) | A map of additional tags to add to the IAM role created | `map(string)` | `{}` | no | | [iam\_role\_use\_name\_prefix](#input\_iam\_role\_use\_name\_prefix) | Determines whether the IAM role name (`iam_role_name`) is used as a prefix | `bool` | `true` | no | -| [instance\_market\_options](#input\_instance\_market\_options) | The market (purchasing) option for the instance | `any` | `{}` | no | +| [instance\_market\_options](#input\_instance\_market\_options) | The market (purchasing) option for the instance |
object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
})
| `null` | no | | [instance\_types](#input\_instance\_types) | Set of instance types associated with the EKS Node Group. Defaults to `["t3.medium"]` | `list(string)` | `null` | no | | [kernel\_id](#input\_kernel\_id) | The kernel ID | `string` | `null` | no | | [key\_name](#input\_key\_name) | The key name that should be used for the instance(s) | `string` | `null` | no | @@ -159,32 +157,30 @@ module "eks_managed_node_group" { | [launch\_template\_tags](#input\_launch\_template\_tags) | A map of additional tags to add to the tag\_specifications of launch template created | `map(string)` | `{}` | no | | [launch\_template\_use\_name\_prefix](#input\_launch\_template\_use\_name\_prefix) | Determines whether to use `launch_template_name` as is or create a unique name beginning with the `launch_template_name` as the prefix | `bool` | `true` | no | | [launch\_template\_version](#input\_launch\_template\_version) | Launch template version number. The default is `$Default` | `string` | `null` | no | -| [license\_specifications](#input\_license\_specifications) | A map of license specifications to associate with | `any` | `{}` | no | -| [maintenance\_options](#input\_maintenance\_options) | The maintenance options for the instance | `any` | `{}` | no | +| [license\_specifications](#input\_license\_specifications) | A list of license specifications to associate with |
list(object({
license_configuration_arn = string
}))
| `null` | no | +| [maintenance\_options](#input\_maintenance\_options) | The maintenance options for the instance |
object({
auto_recovery = optional(string)
})
| `null` | no | | [max\_size](#input\_max\_size) | Maximum number of instances/nodes | `number` | `3` | no | -| [metadata\_options](#input\_metadata\_options) | Customize the metadata options for the instance | `map(string)` |
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 1,
"http_tokens": "required"
}
| no | +| [metadata\_options](#input\_metadata\_options) | Customize the metadata options for the instance |
object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
})
|
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 1,
"http_tokens": "required"
}
| no | | [min\_size](#input\_min\_size) | Minimum number of instances/nodes | `number` | `0` | no | | [name](#input\_name) | Name of the EKS managed node group | `string` | `""` | no | -| [network\_interfaces](#input\_network\_interfaces) | Customize network interfaces to be attached at instance boot time | `list(any)` | `[]` | no | +| [network\_interfaces](#input\_network\_interfaces) | Customize network interfaces to be attached at instance boot time |
list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
}))
| `[]` | no | | [node\_repair\_config](#input\_node\_repair\_config) | The node auto repair configuration for the node group |
object({
enabled = optional(bool, true)
})
| `null` | no | | [partition](#input\_partition) | The AWS partition - pass through value to reduce number of GET requests from data sources | `string` | `""` | no | -| [placement](#input\_placement) | The placement of the instance | `map(string)` | `{}` | no | -| [placement\_group\_strategy](#input\_placement\_group\_strategy) | The placement group strategy | `string` | `"cluster"` | no | +| [placement](#input\_placement) | The placement of the instance |
object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
})
| `{}` | no | | [post\_bootstrap\_user\_data](#input\_post\_bootstrap\_user\_data) | User data that is appended to the user data script after of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | | [pre\_bootstrap\_user\_data](#input\_pre\_bootstrap\_user\_data) | User data that is injected into the user data script ahead of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | -| [private\_dns\_name\_options](#input\_private\_dns\_name\_options) | The options for the instance hostname. The default values are inherited from the subnet | `map(string)` | `{}` | no | +| [private\_dns\_name\_options](#input\_private\_dns\_name\_options) | The options for the instance hostname. The default values are inherited from the subnet |
object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
})
| `null` | no | | [ram\_disk\_id](#input\_ram\_disk\_id) | The ID of the ram disk | `string` | `null` | no | -| [remote\_access](#input\_remote\_access) | Configuration block with remote access settings. Only valid when `use_custom_launch_template` = `false` | `any` | `{}` | no | -| [schedules](#input\_schedules) | Map of autoscaling group schedule to create | `map(any)` | `{}` | no | +| [remote\_access](#input\_remote\_access) | Configuration block with remote access settings. Only valid when `use_custom_launch_template` = `false` |
object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
})
| `null` | no | | [subnet\_ids](#input\_subnet\_ids) | Identifiers of EC2 Subnets to associate with the EKS Node Group. These subnets must have the following resource tag: `kubernetes.io/cluster/CLUSTER_NAME` | `list(string)` | `null` | no | | [tag\_specifications](#input\_tag\_specifications) | The tags to apply to the resources during launch | `list(string)` |
[
"instance",
"volume",
"network-interface"
]
| no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | -| [taints](#input\_taints) | The Kubernetes taints to be applied to the nodes in the node group. Maximum of 50 taints per node group | `any` | `{}` | no | -| [timeouts](#input\_timeouts) | Create, update, and delete timeout configurations for the node group | `map(string)` | `{}` | no | -| [update\_config](#input\_update\_config) | Configuration block of settings for max unavailable resources during node group updates | `map(string)` |
{
"max_unavailable_percentage": 33
}
| no | +| [taints](#input\_taints) | The Kubernetes taints to be applied to the nodes in the node group. Maximum of 50 taints per node group |
map(object({
key = string
value = optional(string)
effect = string
}))
| `null` | no | +| [timeouts](#input\_timeouts) | Create, update, and delete timeout configurations for the node group |
object({
create = optional(string)
update = optional(string)
delete = optional(string)
})
| `null` | no | +| [update\_config](#input\_update\_config) | Configuration block of settings for max unavailable resources during node group updates |
object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
})
|
{
"max_unavailable_percentage": 33
}
| no | | [update\_launch\_template\_default\_version](#input\_update\_launch\_template\_default\_version) | Whether to update the launch templates default version on each update. Conflicts with `launch_template_default_version` | `bool` | `true` | no | | [use\_custom\_launch\_template](#input\_use\_custom\_launch\_template) | Determines whether to use a custom launch template or not. If set to `false`, EKS will use its own default launch template | `bool` | `true` | no | -| [use\_latest\_ami\_release\_version](#input\_use\_latest\_ami\_release\_version) | Determines whether to use the latest AMI release version for the given `ami_type` (except for `CUSTOM`). Note: `ami_type` and `cluster_version` must be supplied in order to enable this feature | `bool` | `false` | no | +| [use\_latest\_ami\_release\_version](#input\_use\_latest\_ami\_release\_version) | Determines whether to use the latest AMI release version for the given `ami_type` (except for `CUSTOM`). Note: `ami_type` and `cluster_version` must be supplied in order to enable this feature | `bool` | `true` | no | | [use\_name\_prefix](#input\_use\_name\_prefix) | Determines whether to use `name` as is or create a unique name beginning with the `name` as the prefix | `bool` | `true` | no | | [user\_data\_template\_path](#input\_user\_data\_template\_path) | Path to a local, custom user data template file to use when rendering user data | `string` | `""` | no | | [vpc\_security\_group\_ids](#input\_vpc\_security\_group\_ids) | A list of security group IDs to associate | `list(string)` | `[]` | no | @@ -193,7 +189,6 @@ module "eks_managed_node_group" { | Name | Description | |------|-------------| -| [autoscaling\_group\_schedule\_arns](#output\_autoscaling\_group\_schedule\_arns) | ARNs of autoscaling group schedules | | [iam\_role\_arn](#output\_iam\_role\_arn) | The Amazon Resource Name (ARN) specifying the IAM role | | [iam\_role\_name](#output\_iam\_role\_name) | The name of the IAM role | | [iam\_role\_unique\_id](#output\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role | diff --git a/modules/eks-managed-node-group/main.tf b/modules/eks-managed-node-group/main.tf index b85e1f2652..90850f0edb 100644 --- a/modules/eks-managed-node-group/main.tf +++ b/modules/eks-managed-node-group/main.tf @@ -73,70 +73,69 @@ locals { locals { launch_template_name = coalesce(var.launch_template_name, "${var.name}-eks-node-group") security_group_ids = compact(concat([var.cluster_primary_security_group_id], var.vpc_security_group_ids)) - - placement = local.create_placement_group ? { group_name = aws_placement_group.this[0].name } : var.placement } resource "aws_launch_template" "this" { count = var.create && var.create_launch_template && var.use_custom_launch_template ? 1 : 0 dynamic "block_device_mappings" { - for_each = var.block_device_mappings + for_each = var.block_device_mappings != null ? var.block_device_mappings : {} content { - device_name = try(block_device_mappings.value.device_name, null) + device_name = block_device_mappings.value.device_name dynamic "ebs" { - for_each = try([block_device_mappings.value.ebs], []) + for_each = block_device_mappings.value.ebs != null ? [block_device_mappings.value.ebs] : [] content { - delete_on_termination = try(ebs.value.delete_on_termination, null) - encrypted = try(ebs.value.encrypted, null) - iops = try(ebs.value.iops, null) - kms_key_id = try(ebs.value.kms_key_id, null) - snapshot_id = try(ebs.value.snapshot_id, null) - throughput = try(ebs.value.throughput, null) - volume_size = try(ebs.value.volume_size, null) - volume_type = try(ebs.value.volume_type, null) + delete_on_termination = ebs.value.delete_on_termination + encrypted = ebs.value.encrypted + iops = ebs.value.iops + kms_key_id = ebs.value.kms_key_id + snapshot_id = ebs.value.snapshot_id + throughput = ebs.value.throughput + volume_initialization_rate = ebs.value.volume_initialization_rate + volume_size = ebs.value.volume_size + volume_type = ebs.value.volume_type } } - no_device = try(block_device_mappings.value.no_device, null) - virtual_name = try(block_device_mappings.value.virtual_name, null) + no_device = block_device_mappings.value.no_device + virtual_name = block_device_mappings.value.virtual_name } } dynamic "capacity_reservation_specification" { - for_each = length(var.capacity_reservation_specification) > 0 ? [var.capacity_reservation_specification] : [] + for_each = var.capacity_reservation_specification != null ? [var.capacity_reservation_specification] : [] content { - capacity_reservation_preference = try(capacity_reservation_specification.value.capacity_reservation_preference, null) + capacity_reservation_preference = capacity_reservation_specification.value.capacity_reservation_preference dynamic "capacity_reservation_target" { - for_each = try([capacity_reservation_specification.value.capacity_reservation_target], []) - + for_each = capacity_reservation_specification.value.capacity_reservation_target != null ? [capacity_reservation_specification.value.capacity_reservation_target] : [] content { - capacity_reservation_id = try(capacity_reservation_target.value.capacity_reservation_id, null) - capacity_reservation_resource_group_arn = try(capacity_reservation_target.value.capacity_reservation_resource_group_arn, null) + capacity_reservation_id = capacity_reservation_target.value.capacity_reservation_id + capacity_reservation_resource_group_arn = capacity_reservation_target.value.capacity_reservation_resource_group_arn } } } } dynamic "cpu_options" { - for_each = length(var.cpu_options) > 0 ? [var.cpu_options] : [] + for_each = var.cpu_options != null ? [var.cpu_options] : [] content { - core_count = try(cpu_options.value.core_count, null) - threads_per_core = try(cpu_options.value.threads_per_core, null) + amd_sev_snp = cpu_options.value.amd_sev_snp + core_count = cpu_options.value.core_count + threads_per_core = cpu_options.value.threads_per_core } } dynamic "credit_specification" { - for_each = length(var.credit_specification) > 0 ? [var.credit_specification] : [] + for_each = var.credit_specification != null ? [var.credit_specification] : [] content { - cpu_credits = try(credit_specification.value.cpu_credits, null) + cpu_credits = credit_specification.value.cpu_credits } } @@ -146,7 +145,7 @@ resource "aws_launch_template" "this" { ebs_optimized = var.ebs_optimized dynamic "enclave_options" { - for_each = length(var.enclave_options) > 0 ? [var.enclave_options] : [] + for_each = var.enclave_options != null ? [var.enclave_options] : [] content { enabled = enclave_options.value.enabled @@ -179,20 +178,20 @@ resource "aws_launch_template" "this" { # instance_initiated_shutdown_behavior = var.instance_initiated_shutdown_behavior dynamic "instance_market_options" { - for_each = length(var.instance_market_options) > 0 ? [var.instance_market_options] : [] + for_each = var.instance_market_options != null ? [var.instance_market_options] : [] content { - market_type = try(instance_market_options.value.market_type, null) + market_type = instance_market_options.value.market_type dynamic "spot_options" { - for_each = try([instance_market_options.value.spot_options], []) + for_each = instance_market_options.value.spot_options != null ? [instance_market_options.value.spot_options] : [] content { - block_duration_minutes = try(spot_options.value.block_duration_minutes, null) - instance_interruption_behavior = try(spot_options.value.instance_interruption_behavior, null) - max_price = try(spot_options.value.max_price, null) - spot_instance_type = try(spot_options.value.spot_instance_type, null) - valid_until = try(spot_options.value.valid_until, null) + block_duration_minutes = spot_options.value.block_duration_minutes + instance_interruption_behavior = spot_options.value.instance_interruption_behavior + max_price = spot_options.value.max_price + spot_instance_type = spot_options.value.spot_instance_type + valid_until = spot_options.value.valid_until } } } @@ -205,7 +204,7 @@ resource "aws_launch_template" "this" { key_name = var.key_name dynamic "license_specification" { - for_each = length(var.license_specifications) > 0 ? var.license_specifications : {} + for_each = var.license_specifications != null ? var.license_specifications : [] content { license_configuration_arn = license_specification.value.license_configuration_arn @@ -213,22 +212,22 @@ resource "aws_launch_template" "this" { } dynamic "maintenance_options" { - for_each = length(var.maintenance_options) > 0 ? [var.maintenance_options] : [] + for_each = var.maintenance_options != null ? [var.maintenance_options] : [] content { - auto_recovery = try(maintenance_options.value.auto_recovery, null) + auto_recovery = maintenance_options.value.auto_recovery } } dynamic "metadata_options" { - for_each = length(var.metadata_options) > 0 ? [var.metadata_options] : [] + for_each = var.metadata_options != null ? [var.metadata_options] : [] content { - http_endpoint = try(metadata_options.value.http_endpoint, null) - http_protocol_ipv6 = try(metadata_options.value.http_protocol_ipv6, null) - http_put_response_hop_limit = try(metadata_options.value.http_put_response_hop_limit, null) - http_tokens = try(metadata_options.value.http_tokens, null) - instance_metadata_tags = try(metadata_options.value.instance_metadata_tags, null) + http_endpoint = metadata_options.value.http_endpoint + http_protocol_ipv6 = metadata_options.value.http_protocol_ipv6 + http_put_response_hop_limit = metadata_options.value.http_put_response_hop_limit + http_tokens = metadata_options.value.http_tokens + instance_metadata_tags = metadata_options.value.instance_metadata_tags } } @@ -244,29 +243,57 @@ resource "aws_launch_template" "this" { name_prefix = var.launch_template_use_name_prefix ? "${local.launch_template_name}-" : null dynamic "network_interfaces" { - for_each = local.network_interfaces + for_each = length(var.network_interfaces) > 0 ? var.network_interfaces : [] content { - associate_carrier_ip_address = try(network_interfaces.value.associate_carrier_ip_address, null) - associate_public_ip_address = try(network_interfaces.value.associate_public_ip_address, null) - delete_on_termination = try(network_interfaces.value.delete_on_termination, null) - description = try(network_interfaces.value.description, null) - device_index = try(network_interfaces.value.device_index, null) - interface_type = try(network_interfaces.value.interface_type, null) - ipv4_address_count = try(network_interfaces.value.ipv4_address_count, null) - ipv4_addresses = try(network_interfaces.value.ipv4_addresses, []) - ipv4_prefix_count = try(network_interfaces.value.ipv4_prefix_count, null) - ipv4_prefixes = try(network_interfaces.value.ipv4_prefixes, null) - ipv6_address_count = try(network_interfaces.value.ipv6_address_count, null) - ipv6_addresses = try(network_interfaces.value.ipv6_addresses, []) - ipv6_prefix_count = try(network_interfaces.value.ipv6_prefix_count, null) - ipv6_prefixes = try(network_interfaces.value.ipv6_prefixes, []) - network_card_index = try(network_interfaces.value.network_card_index, null) - network_interface_id = try(network_interfaces.value.network_interface_id, null) - primary_ipv6 = try(network_interfaces.value.primary_ipv6, null) - private_ip_address = try(network_interfaces.value.private_ip_address, null) + associate_carrier_ip_address = network_interfaces.value.associate_carrier_ip_address + associate_public_ip_address = network_interfaces.value.associate_public_ip_address + + dynamic "connection_tracking_specification" { + for_each = network_interfaces.value.connection_tracking_specification != null ? [network_interfaces.value.connection_tracking_specification] : [] + + content { + tcp_established_timeout = connection_tracking_specification.value.tcp_established_timeout + udp_stream_timeout = connection_tracking_specification.value.udp_stream_timeout + udp_timeout = connection_tracking_specification.value.udp_timeout + } + } + + delete_on_termination = network_interfaces.value.delete_on_termination + description = network_interfaces.value.description + device_index = network_interfaces.value.device_index + + dynamic "ena_srd_specification" { + for_each = network_interfaces.value.ena_srd_specification != null ? [network_interfaces.value.ena_srd_specification] : [] + + content { + ena_srd_enabled = ena_srd_specification.value.ena_srd_enabled + + dynamic "ena_srd_udp_specification" { + for_each = ena_srd_specification.value.ena_srd_udp_specification != null ? [ena_srd_specification.value.ena_srd_udp_specification] : [] + + content { + ena_srd_udp_enabled = ena_srd_udp_specification.value.ena_srd_udp_enabled + } + } + } + } + + interface_type = network_interfaces.value.interface_type + ipv4_address_count = network_interfaces.value.ipv4_address_count + ipv4_addresses = network_interfaces.value.ipv4_addresses + ipv4_prefix_count = network_interfaces.value.ipv4_prefix_count + ipv4_prefixes = network_interfaces.value.ipv4_prefixes + ipv6_address_count = network_interfaces.value.ipv6_address_count + ipv6_addresses = network_interfaces.value.ipv6_addresses + ipv6_prefix_count = network_interfaces.value.ipv6_prefix_count + ipv6_prefixes = network_interfaces.value.ipv6_prefixes + network_card_index = network_interfaces.value.network_card_index + network_interface_id = network_interfaces.value.network_interface_id + primary_ipv6 = network_interfaces.value.primary_ipv6 + private_ip_address = network_interfaces.value.private_ip_address # Ref: https://github.com/hashicorp/terraform-provider-aws/issues/4570 - security_groups = compact(concat(try(network_interfaces.value.security_groups, []), local.security_group_ids)) + security_groups = compact(concat(network_interfaces.value.security_groups, var.security_groups)) # Set on EKS managed node group, will fail if set here # https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-basics # subnet_id = try(network_interfaces.value.subnet_id, null) @@ -274,27 +301,27 @@ resource "aws_launch_template" "this" { } dynamic "placement" { - for_each = length(local.placement) > 0 ? [local.placement] : [] + for_each = length(var.placement) > 0 || local.create_placement_group ? [var.placement] : [] content { - affinity = try(placement.value.affinity, null) - availability_zone = lookup(placement.value, "availability_zone", null) - group_name = lookup(placement.value, "group_name", null) - host_id = lookup(placement.value, "host_id", null) - host_resource_group_arn = lookup(placement.value, "host_resource_group_arn", null) - partition_number = try(placement.value.partition_number, null) - spread_domain = try(placement.value.spread_domain, null) - tenancy = try(placement.value.tenancy, null) + affinity = placement.value.affinity + availability_zone = placement.value.availability_zone + group_name = try(coalesce(aws_placement_group.this[0].name, placement.value.group_name), null) + host_id = placement.value.host_id + host_resource_group_arn = placement.value.host_resource_group_arn + partition_number = placement.value.partition_number + spread_domain = placement.value.spread_domain + tenancy = placement.value.tenancy } } dynamic "private_dns_name_options" { - for_each = length(var.private_dns_name_options) > 0 ? [var.private_dns_name_options] : [] + for_each = var.private_dns_name_options != null ? [var.private_dns_name_options] : [] content { - enable_resource_name_dns_aaaa_record = try(private_dns_name_options.value.enable_resource_name_dns_aaaa_record, null) - enable_resource_name_dns_a_record = try(private_dns_name_options.value.enable_resource_name_dns_a_record, null) - hostname_type = try(private_dns_name_options.value.hostname_type, null) + enable_resource_name_dns_aaaa_record = private_dns_name_options.value.enable_resource_name_dns_aaaa_record + enable_resource_name_dns_a_record = private_dns_name_options.value.enable_resource_name_dns_a_record + hostname_type = private_dns_name_options.value.hostname_type } } @@ -424,30 +451,30 @@ resource "aws_eks_node_group" "this" { } dynamic "remote_access" { - for_each = length(var.remote_access) > 0 ? [var.remote_access] : [] + for_each = var.remote_access != null ? [var.remote_access] : [] content { - ec2_ssh_key = try(remote_access.value.ec2_ssh_key, null) - source_security_group_ids = try(remote_access.value.source_security_group_ids, []) + ec2_ssh_key = remote_access.value.ec2_ssh_key + source_security_group_ids = remote_access.value.source_security_group_ids } } dynamic "taint" { - for_each = var.taints + for_each = var.taints != null ? var.taints : {} content { key = taint.value.key - value = try(taint.value.value, null) + value = taint.value.value effect = taint.value.effect } } dynamic "update_config" { - for_each = length(var.update_config) > 0 ? [var.update_config] : [] + for_each = var.update_config != null ? [var.update_config] : [] content { - max_unavailable_percentage = try(update_config.value.max_unavailable_percentage, null) - max_unavailable = try(update_config.value.max_unavailable, null) + max_unavailable_percentage = update_config.value.max_unavailable_percentage + max_unavailable = update_config.value.max_unavailable } } @@ -459,10 +486,14 @@ resource "aws_eks_node_group" "this" { } } - timeouts { - create = lookup(var.timeouts, "create", null) - update = lookup(var.timeouts, "update", null) - delete = lookup(var.timeouts, "delete", null) + dynamic "timeouts" { + for_each = var.timeouts != null ? [var.timeouts] : [] + + content { + create = var.timeouts.create + update = var.timeouts.update + delete = var.timeouts.delete + } } lifecycle { @@ -552,25 +583,25 @@ resource "aws_iam_role_policy_attachment" "additional" { ################################################################################ locals { - create_iam_role_policy = local.create_iam_role && var.create_iam_role_policy && length(var.iam_role_policy_statements) > 0 + create_iam_role_policy = local.create_iam_role && var.create_iam_role_policy && var.iam_role_policy_statements != null } data "aws_iam_policy_document" "role" { count = local.create_iam_role_policy ? 1 : 0 dynamic "statement" { - for_each = var.iam_role_policy_statements + for_each = var.iam_role_policy_statements != null ? var.iam_role_policy_statements : [] content { - sid = try(statement.value.sid, null) - actions = try(statement.value.actions, null) - not_actions = try(statement.value.not_actions, null) - effect = try(statement.value.effect, null) - resources = try(statement.value.resources, null) - not_resources = try(statement.value.not_resources, null) + sid = statement.value.sid + actions = statement.value.actions + not_actions = statement.value.not_actions + effect = statement.value.effect + resources = statement.value.resources + not_resources = statement.value.not_resources dynamic "principals" { - for_each = try(statement.value.principals, []) + for_each = statement.value.principals != null ? statement.value.principals : [] content { type = principals.value.type @@ -579,7 +610,7 @@ data "aws_iam_policy_document" "role" { } dynamic "not_principals" { - for_each = try(statement.value.not_principals, []) + for_each = statement.value.not_principals != null ? statement.value.not_principals : [] content { type = not_principals.value.type @@ -588,7 +619,7 @@ data "aws_iam_policy_document" "role" { } dynamic "condition" { - for_each = try(statement.value.conditions, []) + for_each = statement.value.condition != null ? statement.value.condition : [] content { test = condition.value.test @@ -621,29 +652,7 @@ resource "aws_placement_group" "this" { count = local.create_placement_group ? 1 : 0 name = "${var.cluster_name}-${var.name}" - strategy = var.placement_group_strategy + strategy = "cluster" tags = var.tags } - -################################################################################ -# Autoscaling Group Schedule -################################################################################ - -resource "aws_autoscaling_schedule" "this" { - for_each = { for k, v in var.schedules : k => v if var.create && var.create_schedule } - - scheduled_action_name = each.key - autoscaling_group_name = aws_eks_node_group.this[0].resources[0].autoscaling_groups[0].name - - min_size = try(each.value.min_size, -1) - max_size = try(each.value.max_size, -1) - desired_capacity = try(each.value.desired_size, -1) - start_time = try(each.value.start_time, null) - end_time = try(each.value.end_time, null) - time_zone = try(each.value.time_zone, null) - - # [Minute] [Hour] [Day_of_Month] [Month_of_Year] [Day_of_Week] - # Cron examples: https://crontab.guru/examples.html - recurrence = try(each.value.recurrence, null) -} diff --git a/modules/eks-managed-node-group/outputs.tf b/modules/eks-managed-node-group/outputs.tf index 012cd46f4e..0475953452 100644 --- a/modules/eks-managed-node-group/outputs.tf +++ b/modules/eks-managed-node-group/outputs.tf @@ -61,15 +61,6 @@ output "node_group_taints" { value = try(aws_eks_node_group.this[0].taint, []) } -################################################################################ -# Autoscaling Group Schedule -################################################################################ - -output "autoscaling_group_schedule_arns" { - description = "ARNs of autoscaling group schedules" - value = { for k, v in aws_autoscaling_schedule.this : k => v.arn } -} - ################################################################################ # IAM Role ################################################################################ diff --git a/modules/eks-managed-node-group/variables.tf b/modules/eks-managed-node-group/variables.tf index 96fa7d75b5..294563dc7b 100644 --- a/modules/eks-managed-node-group/variables.tf +++ b/modules/eks-managed-node-group/variables.tf @@ -204,59 +204,107 @@ variable "ram_disk_id" { variable "block_device_mappings" { description = "Specify volumes to attach to the instance besides the volumes specified by the AMI" - type = any - default = {} + type = map(object({ + device_name = optional(string) + ebs = optional(object({ + delete_on_termination = optional(bool) + encrypted = optional(bool) + iops = optional(number) + kms_key_id = optional(string) + snapshot_id = optional(string) + throughput = optional(number) + volume_initialization_rate = optional(number) + volume_size = optional(number) + volume_type = optional(string) + })) + no_device = optional(string) + virtual_name = optional(string) + })) + default = null } variable "capacity_reservation_specification" { description = "Targeting for EC2 capacity reservations" - type = any - default = {} + type = object({ + capacity_reservation_preference = optional(string) + capacity_reservation_target = optional(object({ + capacity_reservation_id = optional(string) + capacity_reservation_resource_group_arn = optional(string) + })) + }) + default = null } variable "cpu_options" { description = "The CPU options for the instance" - type = map(string) - default = {} + type = object({ + amd_sev_snp = optional(string) + core_count = optional(number) + threads_per_core = optional(number) + }) + default = null } variable "credit_specification" { description = "Customize the credit specification of the instance" - type = map(string) - default = {} + type = object({ + cpu_credits = optional(string) + }) + default = null } variable "enclave_options" { description = "Enable Nitro Enclaves on launched instances" - type = map(string) - default = {} + type = object({ + enabled = optional(bool) + }) + default = null } variable "instance_market_options" { description = "The market (purchasing) option for the instance" - type = any - default = {} + type = object({ + market_type = optional(string) + spot_options = optional(object({ + block_duration_minutes = optional(number) + instance_interruption_behavior = optional(string) + max_price = optional(string) + spot_instance_type = optional(string) + valid_until = optional(string) + })) + }) + default = null } variable "maintenance_options" { description = "The maintenance options for the instance" - type = any - default = {} + type = object({ + auto_recovery = optional(string) + }) + default = null } variable "license_specifications" { - description = "A map of license specifications to associate with" - type = any - default = {} + description = "A list of license specifications to associate with" + type = list(object({ + license_configuration_arn = string + })) + default = null } variable "metadata_options" { description = "Customize the metadata options for the instance" - type = map(string) + type = object({ + http_endpoint = optional(string, "enabled") + http_protocol_ipv6 = optional(string) + http_put_response_hop_limit = optional(number, 1) + http_tokens = optional(string, "required") + instance_metadata_tags = optional(string) + }) default = { http_endpoint = "enabled" - http_tokens = "required" http_put_response_hop_limit = 1 + http_tokens = "required" } } @@ -286,14 +334,55 @@ variable "efa_indices" { variable "network_interfaces" { description = "Customize network interfaces to be attached at instance boot time" - type = list(any) - default = [] + type = list(object({ + associate_carrier_ip_address = optional(bool) + associate_public_ip_address = optional(bool) + connection_tracking_specification = optional(object({ + tcp_established_timeout = optional(number) + udp_stream_timeout = optional(number) + udp_timeout = optional(number) + })) + delete_on_termination = optional(bool) + description = optional(string) + device_index = optional(number) + ena_srd_specification = optional(object({ + ena_srd_enabled = optional(bool) + ena_srd_udp_specification = optional(object({ + ena_srd_udp_enabled = optional(bool) + })) + })) + interface_type = optional(string) + ipv4_address_count = optional(number) + ipv4_addresses = optional(list(string)) + ipv4_prefix_count = optional(number) + ipv4_prefixes = optional(list(string)) + ipv6_address_count = optional(number) + ipv6_addresses = optional(list(string)) + ipv6_prefix_count = optional(number) + ipv6_prefixes = optional(list(string)) + network_card_index = optional(number) + network_interface_id = optional(string) + primary_ipv6 = optional(bool) + private_ip_address = optional(string) + security_groups = optional(list(string), []) + subnet_id = optional(string) + })) + default = [] } variable "placement" { description = "The placement of the instance" - type = map(string) - default = {} + type = object({ + affinity = optional(string) + availability_zone = optional(string) + group_name = optional(string) + host_id = optional(string) + host_resource_group_arn = optional(string) + partition_number = optional(number) + spread_domain = optional(string) + tenancy = optional(string) + }) + default = {} } variable "create_placement_group" { @@ -302,16 +391,14 @@ variable "create_placement_group" { default = false } -variable "placement_group_strategy" { - description = "The placement group strategy" - type = string - default = "cluster" -} - variable "private_dns_name_options" { description = "The options for the instance hostname. The default values are inherited from the subnet" - type = map(string) - default = {} + type = object({ + enable_resource_name_dns_aaaa_record = optional(bool) + enable_resource_name_dns_a_record = optional(bool) + hostname_type = optional(string) + }) + default = null } variable "launch_template_tags" { @@ -381,7 +468,7 @@ variable "ami_release_version" { variable "use_latest_ami_release_version" { description = "Determines whether to use the latest AMI release version for the given `ami_type` (except for `CUSTOM`). Note: `ami_type` and `cluster_version` must be supplied in order to enable this feature" type = bool - default = false + default = true } variable "capacity_type" { @@ -428,19 +515,29 @@ variable "launch_template_version" { variable "remote_access" { description = "Configuration block with remote access settings. Only valid when `use_custom_launch_template` = `false`" - type = any - default = {} + type = object({ + ec2_ssh_key = optional(string) + source_security_group_ids = optional(list(string)) + }) + default = null } variable "taints" { description = "The Kubernetes taints to be applied to the nodes in the node group. Maximum of 50 taints per node group" - type = any - default = {} + type = map(object({ + key = string + value = optional(string) + effect = string + })) + default = null } variable "update_config" { description = "Configuration block of settings for max unavailable resources during node group updates" - type = map(string) + type = object({ + max_unavailable = optional(number) + max_unavailable_percentage = optional(number) + }) default = { max_unavailable_percentage = 33 } @@ -456,8 +553,12 @@ variable "node_repair_config" { variable "timeouts" { description = "Create, update, and delete timeout configurations for the node group" - type = map(string) - default = {} + type = object({ + create = optional(string) + update = optional(string) + delete = optional(string) + }) + default = null } ################################################################################ @@ -542,22 +643,26 @@ variable "create_iam_role_policy" { variable "iam_role_policy_statements" { description = "A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed" - type = any - default = [] -} - -################################################################################ -# Autoscaling Group Schedule -################################################################################ - -variable "create_schedule" { - description = "Determines whether to create autoscaling group schedule or not" - type = bool - default = true -} - -variable "schedules" { - description = "Map of autoscaling group schedule to create" - type = map(any) - default = {} + type = list(object({ + sid = optional(string) + actions = optional(list(string)) + not_actions = optional(list(string)) + effect = optional(string) + resources = optional(list(string)) + not_resources = optional(list(string)) + principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + not_principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + condition = optional(list(object({ + test = string + values = list(string) + variable = string + }))) + })) + default = null } diff --git a/modules/fargate-profile/README.md b/modules/fargate-profile/README.md index cf29596788..430a3753d1 100644 --- a/modules/fargate-profile/README.md +++ b/modules/fargate-profile/README.md @@ -73,15 +73,15 @@ No modules. | [iam\_role\_name](#input\_iam\_role\_name) | Name to use on IAM role created | `string` | `""` | no | | [iam\_role\_path](#input\_iam\_role\_path) | IAM role path | `string` | `null` | no | | [iam\_role\_permissions\_boundary](#input\_iam\_role\_permissions\_boundary) | ARN of the policy that is used to set the permissions boundary for the IAM role | `string` | `null` | no | -| [iam\_role\_policy\_statements](#input\_iam\_role\_policy\_statements) | A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed | `any` | `[]` | no | +| [iam\_role\_policy\_statements](#input\_iam\_role\_policy\_statements) | A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed |
list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
}))
| `null` | no | | [iam\_role\_tags](#input\_iam\_role\_tags) | A map of additional tags to add to the IAM role created | `map(string)` | `{}` | no | | [iam\_role\_use\_name\_prefix](#input\_iam\_role\_use\_name\_prefix) | Determines whether the IAM role name (`iam_role_name`) is used as a prefix | `bool` | `true` | no | | [name](#input\_name) | Name of the EKS Fargate Profile | `string` | `""` | no | | [partition](#input\_partition) | The AWS partition - pass through value to reduce number of GET requests from data sources | `string` | `null` | no | -| [selectors](#input\_selectors) | Configuration block(s) for selecting Kubernetes Pods to execute with this Fargate Profile | `any` | `[]` | no | +| [selectors](#input\_selectors) | Configuration block(s) for selecting Kubernetes Pods to execute with this Fargate Profile |
list(object({
labels = optional(map(string))
namespace = string
}))
| `null` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs for the EKS Fargate Profile | `list(string)` | `[]` | no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | -| [timeouts](#input\_timeouts) | Create and delete timeout configurations for the Fargate Profile | `map(string)` | `{}` | no | +| [timeouts](#input\_timeouts) | Create and delete timeout configurations for the Fargate Profile |
object({
create = optional(string)
delete = optional(string)
})
| `null` | no | ## Outputs diff --git a/modules/fargate-profile/main.tf b/modules/fargate-profile/main.tf index 3e124282dc..aa0f348abd 100644 --- a/modules/fargate-profile/main.tf +++ b/modules/fargate-profile/main.tf @@ -95,25 +95,25 @@ resource "aws_iam_role_policy_attachment" "additional" { ################################################################################ locals { - create_iam_role_policy = local.create_iam_role && var.create_iam_role_policy && length(var.iam_role_policy_statements) > 0 + create_iam_role_policy = local.create_iam_role && var.create_iam_role_policy && var.iam_role_policy_statements != null } data "aws_iam_policy_document" "role" { count = local.create_iam_role_policy ? 1 : 0 dynamic "statement" { - for_each = var.iam_role_policy_statements + for_each = var.iam_role_policy_statements != null ? var.iam_role_policy_statements : [] content { - sid = try(statement.value.sid, null) - actions = try(statement.value.actions, null) - not_actions = try(statement.value.not_actions, null) - effect = try(statement.value.effect, null) - resources = try(statement.value.resources, null) - not_resources = try(statement.value.not_resources, null) + sid = statement.value.sid + actions = statement.value.actions + not_actions = statement.value.not_actions + effect = statement.value.effect + resources = statement.value.resources + not_resources = statement.value.not_resources dynamic "principals" { - for_each = try(statement.value.principals, []) + for_each = statement.value.principals != null ? statement.value.principals : [] content { type = principals.value.type @@ -122,7 +122,7 @@ data "aws_iam_policy_document" "role" { } dynamic "not_principals" { - for_each = try(statement.value.not_principals, []) + for_each = statement.value.not_principals != null ? statement.value.not_principals : [] content { type = not_principals.value.type @@ -131,7 +131,7 @@ data "aws_iam_policy_document" "role" { } dynamic "condition" { - for_each = try(statement.value.conditions, []) + for_each = statement.value.condition != null ? statement.value.condition : [] content { test = condition.value.test @@ -165,19 +165,20 @@ resource "aws_eks_fargate_profile" "this" { subnet_ids = var.subnet_ids dynamic "selector" { - for_each = var.selectors + for_each = var.selectors != null ? var.selectors : [] content { namespace = selector.value.namespace - labels = lookup(selector.value, "labels", {}) + labels = selector.value.labels } } dynamic "timeouts" { - for_each = [var.timeouts] + for_each = var.timeouts != null ? [var.timeouts] : [] + content { - create = lookup(var.timeouts, "create", null) - delete = lookup(var.timeouts, "delete", null) + create = var.timeouts.create + delete = var.timeouts.delete } } diff --git a/modules/fargate-profile/variables.tf b/modules/fargate-profile/variables.tf index cd2db7ac6a..571d250353 100644 --- a/modules/fargate-profile/variables.tf +++ b/modules/fargate-profile/variables.tf @@ -104,8 +104,28 @@ variable "create_iam_role_policy" { variable "iam_role_policy_statements" { description = "A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed" - type = any - default = [] + type = list(object({ + sid = optional(string) + actions = optional(list(string)) + not_actions = optional(list(string)) + effect = optional(string) + resources = optional(list(string)) + not_resources = optional(list(string)) + principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + not_principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + condition = optional(list(object({ + test = string + values = list(string) + variable = string + }))) + })) + default = null } ################################################################################ @@ -132,12 +152,18 @@ variable "subnet_ids" { variable "selectors" { description = "Configuration block(s) for selecting Kubernetes Pods to execute with this Fargate Profile" - type = any - default = [] + type = list(object({ + labels = optional(map(string)) + namespace = string + })) + default = null } variable "timeouts" { description = "Create and delete timeout configurations for the Fargate Profile" - type = map(string) - default = {} + type = object({ + create = optional(string) + delete = optional(string) + }) + default = null } diff --git a/modules/hybrid-node-role/README.md b/modules/hybrid-node-role/README.md index 6f8ffd1b90..176aabcdf4 100644 --- a/modules/hybrid-node-role/README.md +++ b/modules/hybrid-node-role/README.md @@ -115,7 +115,7 @@ No modules. | [enable\_ira](#input\_enable\_ira) | Enables IAM Roles Anywhere based IAM permissions on the node | `bool` | `false` | no | | [enable\_pod\_identity](#input\_enable\_pod\_identity) | Enables EKS Pod Identity based IAM permissions on the node | `bool` | `true` | no | | [intermediate\_policy\_name](#input\_intermediate\_policy\_name) | Name of the IAM policy | `string` | `null` | no | -| [intermediate\_policy\_statements](#input\_intermediate\_policy\_statements) | A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed | `any` | `[]` | no | +| [intermediate\_policy\_statements](#input\_intermediate\_policy\_statements) | A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed |
list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
}))
| `null` | no | | [intermediate\_policy\_use\_name\_prefix](#input\_intermediate\_policy\_use\_name\_prefix) | Determines whether the name of the IAM policy (`intermediate_policy_name`) is used as a prefix | `bool` | `true` | no | | [intermediate\_role\_description](#input\_intermediate\_role\_description) | IAM role description | `string` | `"EKS Hybrid Node IAM Roles Anywhere intermediate IAM role"` | no | | [intermediate\_role\_name](#input\_intermediate\_role\_name) | Name of the IAM role | `string` | `null` | no | @@ -129,7 +129,7 @@ No modules. | [ira\_profile\_session\_policy](#input\_ira\_profile\_session\_policy) | A session policy that applies to the trust boundary of the vended session credentials | `string` | `null` | no | | [ira\_trust\_anchor\_acm\_pca\_arn](#input\_ira\_trust\_anchor\_acm\_pca\_arn) | The ARN of the ACM PCA that issued the trust anchor certificate | `string` | `null` | no | | [ira\_trust\_anchor\_name](#input\_ira\_trust\_anchor\_name) | Name of the Roles Anywhere trust anchor | `string` | `null` | no | -| [ira\_trust\_anchor\_notification\_settings](#input\_ira\_trust\_anchor\_notification\_settings) | Notification settings for the trust anchor | `any` | `[]` | no | +| [ira\_trust\_anchor\_notification\_settings](#input\_ira\_trust\_anchor\_notification\_settings) | Notification settings for the trust anchor |
list(object({
channel = optional(string)
enabled = optional(bool)
event = optional(string)
threshold = optional(number)
}))
| `null` | no | | [ira\_trust\_anchor\_source\_type](#input\_ira\_trust\_anchor\_source\_type) | The source type of the trust anchor | `string` | `null` | no | | [ira\_trust\_anchor\_x509\_certificate\_data](#input\_ira\_trust\_anchor\_x509\_certificate\_data) | The X.509 certificate data of the trust anchor | `string` | `null` | no | | [max\_session\_duration](#input\_max\_session\_duration) | Maximum API session duration in seconds between 3600 and 43200 | `number` | `null` | no | @@ -140,9 +140,9 @@ No modules. | [policy\_description](#input\_policy\_description) | IAM policy description | `string` | `"EKS Hybrid Node IAM role policy"` | no | | [policy\_name](#input\_policy\_name) | Name of the IAM policy | `string` | `"EKSHybridNode"` | no | | [policy\_path](#input\_policy\_path) | Path of the IAM policy | `string` | `"/"` | no | -| [policy\_statements](#input\_policy\_statements) | A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed | `any` | `[]` | no | +| [policy\_statements](#input\_policy\_statements) | A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed |
list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
}))
| `null` | no | | [policy\_use\_name\_prefix](#input\_policy\_use\_name\_prefix) | Determines whether the name of the IAM policy (`policy_name`) is used as a prefix | `bool` | `true` | no | -| [tags](#input\_tags) | A map of additional tags to add the the IAM role | `map(any)` | `{}` | no | +| [tags](#input\_tags) | A map of additional tags to add the the IAM role | `map(string)` | `{}` | no | | [trust\_anchor\_arns](#input\_trust\_anchor\_arns) | List of IAM Roles Anywhere trust anchor ARNs. Required if `enable_ira` is set to `true` | `list(string)` | `[]` | no | | [use\_name\_prefix](#input\_use\_name\_prefix) | Determines whether the name of the IAM role (`name`) is used as a prefix | `bool` | `true` | no | diff --git a/modules/hybrid-node-role/main.tf b/modules/hybrid-node-role/main.tf index 7ef874c6b3..1d14f41b40 100644 --- a/modules/hybrid-node-role/main.tf +++ b/modules/hybrid-node-role/main.tf @@ -1,6 +1,7 @@ data "aws_partition" "current" { count = var.create ? 1 : 0 } + locals { partition = try(data.aws_partition.current[0].partition, "") } @@ -116,18 +117,18 @@ data "aws_iam_policy_document" "this" { } dynamic "statement" { - for_each = var.policy_statements + for_each = var.policy_statements != null ? var.policy_statements : [] content { - sid = try(statement.value.sid, null) - actions = try(statement.value.actions, null) - not_actions = try(statement.value.not_actions, null) - effect = try(statement.value.effect, null) - resources = try(statement.value.resources, null) - not_resources = try(statement.value.not_resources, null) + sid = statement.value.sid + actions = statement.value.actions + not_actions = statement.value.not_actions + effect = statement.value.effect + resources = statement.value.resources + not_resources = statement.value.not_resources dynamic "principals" { - for_each = try(statement.value.principals, []) + for_each = statement.value.principals != null ? statement.value.principals : [] content { type = principals.value.type @@ -136,7 +137,7 @@ data "aws_iam_policy_document" "this" { } dynamic "not_principals" { - for_each = try(statement.value.not_principals, []) + for_each = statement.value.not_principals != null ? statement.value.not_principals : [] content { type = not_principals.value.type @@ -145,7 +146,7 @@ data "aws_iam_policy_document" "this" { } dynamic "condition" { - for_each = try(statement.value.conditions, []) + for_each = statement.value.condition != null ? statement.value.condition : [] content { test = condition.value.test @@ -214,7 +215,7 @@ resource "aws_rolesanywhere_trust_anchor" "this" { name = try(coalesce(var.ira_trust_anchor_name, var.name), null) dynamic "notification_settings" { - for_each = var.ira_trust_anchor_notification_settings + for_each = var.ira_trust_anchor_notification_settings != null ? var.ira_trust_anchor_notification_settings : [] content { channel = try(notification_settings.value.channel, null) @@ -296,18 +297,18 @@ data "aws_iam_policy_document" "intermediate" { } dynamic "statement" { - for_each = var.intermediate_policy_statements + for_each = var.intermediate_policy_statements != null ? var.intermediate_policy_statements : [] content { - sid = try(statement.value.sid, null) - actions = try(statement.value.actions, null) - not_actions = try(statement.value.not_actions, null) - effect = try(statement.value.effect, null) - resources = try(statement.value.resources, null) - not_resources = try(statement.value.not_resources, null) + sid = statement.value.sid + actions = statement.value.actions + not_actions = statement.value.not_actions + effect = statement.value.effect + resources = statement.value.resources + not_resources = statement.value.not_resources dynamic "principals" { - for_each = try(statement.value.principals, []) + for_each = statement.value.principals != null ? statement.value.principals : [] content { type = principals.value.type @@ -316,7 +317,7 @@ data "aws_iam_policy_document" "intermediate" { } dynamic "not_principals" { - for_each = try(statement.value.not_principals, []) + for_each = statement.value.not_principals != null ? statement.value.not_principals : [] content { type = not_principals.value.type @@ -325,7 +326,7 @@ data "aws_iam_policy_document" "intermediate" { } dynamic "condition" { - for_each = try(statement.value.conditions, []) + for_each = statement.value.condition != null ? statement.value.condition : [] content { test = condition.value.test diff --git a/modules/hybrid-node-role/variables.tf b/modules/hybrid-node-role/variables.tf index 6e8d80465e..34e1247667 100644 --- a/modules/hybrid-node-role/variables.tf +++ b/modules/hybrid-node-role/variables.tf @@ -46,7 +46,7 @@ variable "permissions_boundary_arn" { variable "tags" { description = "A map of additional tags to add the the IAM role" - type = map(any) + type = map(string) default = {} } @@ -92,8 +92,28 @@ variable "policy_description" { variable "policy_statements" { description = "A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed" - type = any - default = [] + type = list(object({ + sid = optional(string) + actions = optional(list(string)) + not_actions = optional(list(string)) + effect = optional(string) + resources = optional(list(string)) + not_resources = optional(list(string)) + principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + not_principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + condition = optional(list(object({ + test = string + values = list(string) + variable = string + }))) + })) + default = null } variable "policies" { @@ -160,8 +180,13 @@ variable "ira_trust_anchor_name" { variable "ira_trust_anchor_notification_settings" { description = "Notification settings for the trust anchor" - type = any - default = [] + type = list(object({ + channel = optional(string) + enabled = optional(bool) + event = optional(string) + threshold = optional(number) + })) + default = null } variable "ira_trust_anchor_acm_pca_arn" { @@ -228,8 +253,28 @@ variable "intermediate_policy_use_name_prefix" { variable "intermediate_policy_statements" { description = "A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed" - type = any - default = [] + type = list(object({ + sid = optional(string) + actions = optional(list(string)) + not_actions = optional(list(string)) + effect = optional(string) + resources = optional(list(string)) + not_resources = optional(list(string)) + principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + not_principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + condition = optional(list(object({ + test = string + values = list(string) + variable = string + }))) + })) + default = null } variable "intermediate_role_policies" { diff --git a/modules/karpenter/README.md b/modules/karpenter/README.md index aace65630e..1095260fa0 100644 --- a/modules/karpenter/README.md +++ b/modules/karpenter/README.md @@ -143,7 +143,7 @@ No modules. | [iam\_policy\_description](#input\_iam\_policy\_description) | IAM policy description | `string` | `"Karpenter controller IAM policy"` | no | | [iam\_policy\_name](#input\_iam\_policy\_name) | Name of the IAM policy | `string` | `"KarpenterController"` | no | | [iam\_policy\_path](#input\_iam\_policy\_path) | Path of the IAM policy | `string` | `"/"` | no | -| [iam\_policy\_statements](#input\_iam\_policy\_statements) | A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed | `any` | `[]` | no | +| [iam\_policy\_statements](#input\_iam\_policy\_statements) | A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed |
list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
}))
| `null` | no | | [iam\_policy\_use\_name\_prefix](#input\_iam\_policy\_use\_name\_prefix) | Determines whether the name of the IAM policy (`iam_policy_name`) is used as a prefix | `bool` | `true` | no | | [iam\_role\_description](#input\_iam\_role\_description) | IAM role description | `string` | `"Karpenter controller IAM role"` | no | | [iam\_role\_max\_session\_duration](#input\_iam\_role\_max\_session\_duration) | Maximum API session duration in seconds between 3600 and 43200 | `number` | `null` | no | @@ -151,7 +151,7 @@ No modules. | [iam\_role\_path](#input\_iam\_role\_path) | Path of the IAM role | `string` | `"/"` | no | | [iam\_role\_permissions\_boundary\_arn](#input\_iam\_role\_permissions\_boundary\_arn) | Permissions boundary ARN to use for the IAM role | `string` | `null` | no | | [iam\_role\_policies](#input\_iam\_role\_policies) | Policies to attach to the IAM role in `{'static_name' = 'policy_arn'}` format | `map(string)` | `{}` | no | -| [iam\_role\_tags](#input\_iam\_role\_tags) | A map of additional tags to add the the IAM role | `map(any)` | `{}` | no | +| [iam\_role\_tags](#input\_iam\_role\_tags) | A map of additional tags to add the the IAM role | `map(string)` | `{}` | no | | [iam\_role\_use\_name\_prefix](#input\_iam\_role\_use\_name\_prefix) | Determines whether the name of the IAM role (`iam_role_name`) is used as a prefix | `bool` | `true` | no | | [namespace](#input\_namespace) | Namespace to associate with the Karpenter Pod Identity | `string` | `"kube-system"` | no | | [node\_iam\_role\_additional\_policies](#input\_node\_iam\_role\_additional\_policies) | Additional policies to be added to the IAM role | `map(string)` | `{}` | no | diff --git a/modules/karpenter/policy.tf b/modules/karpenter/policy.tf index 564b1a0907..16f28fa61d 100644 --- a/modules/karpenter/policy.tf +++ b/modules/karpenter/policy.tf @@ -355,18 +355,18 @@ data "aws_iam_policy_document" "controller" { } dynamic "statement" { - for_each = var.iam_policy_statements + for_each = var.iam_policy_statements != null ? var.iam_policy_statements : [] content { - sid = try(statement.value.sid, null) - actions = try(statement.value.actions, null) - not_actions = try(statement.value.not_actions, null) - effect = try(statement.value.effect, null) - resources = try(statement.value.resources, null) - not_resources = try(statement.value.not_resources, null) + sid = statement.value.sid + actions = statement.value.actions + not_actions = statement.value.not_actions + effect = statement.value.effect + resources = statement.value.resources + not_resources = statement.value.not_resources dynamic "principals" { - for_each = try(statement.value.principals, []) + for_each = statement.value.principals != null ? statement.value.principals : [] content { type = principals.value.type @@ -375,7 +375,7 @@ data "aws_iam_policy_document" "controller" { } dynamic "not_principals" { - for_each = try(statement.value.not_principals, []) + for_each = statement.value.not_principals != null ? statement.value.not_principals : [] content { type = not_principals.value.type @@ -384,7 +384,7 @@ data "aws_iam_policy_document" "controller" { } dynamic "condition" { - for_each = try(statement.value.conditions, []) + for_each = statement.value.condition != null ? statement.value.condition : [] content { test = condition.value.test diff --git a/modules/karpenter/variables.tf b/modules/karpenter/variables.tf index a403eba995..4cac5a2ce1 100644 --- a/modules/karpenter/variables.tf +++ b/modules/karpenter/variables.tf @@ -64,7 +64,7 @@ variable "iam_role_permissions_boundary_arn" { variable "iam_role_tags" { description = "A map of additional tags to add the the IAM role" - type = map(any) + type = map(string) default = {} } @@ -94,8 +94,28 @@ variable "iam_policy_description" { variable "iam_policy_statements" { description = "A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed" - type = any - default = [] + type = list(object({ + sid = optional(string) + actions = optional(list(string)) + not_actions = optional(list(string)) + effect = optional(string) + resources = optional(list(string)) + not_resources = optional(list(string)) + principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + not_principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + condition = optional(list(object({ + test = string + values = list(string) + variable = string + }))) + })) + default = null } variable "iam_role_policies" { diff --git a/modules/self-managed-node-group/README.md b/modules/self-managed-node-group/README.md index e4c7bbac50..acbd12fa70 100644 --- a/modules/self-managed-node-group/README.md +++ b/modules/self-managed-node-group/README.md @@ -62,7 +62,6 @@ module "self_managed_node_group" { | Name | Type | |------|------| | [aws_autoscaling_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/autoscaling_group) | resource | -| [aws_autoscaling_schedule.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/autoscaling_schedule) | resource | | [aws_eks_access_entry.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_access_entry) | resource | | [aws_iam_instance_profile.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | | [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | @@ -88,10 +87,10 @@ module "self_managed_node_group" { | [ami\_type](#input\_ami\_type) | Type of Amazon Machine Image (AMI) associated with the node group. See the [AWS documentation](https://docs.aws.amazon.com/eks/latest/APIReference/API_Nodegroup.html#AmazonEKS-Type-Nodegroup-amiType) for valid values | `string` | `"AL2023_x86_64_STANDARD"` | no | | [autoscaling\_group\_tags](#input\_autoscaling\_group\_tags) | A map of additional tags to add to the autoscaling group created. Tags are applied to the autoscaling group only and are NOT propagated to instances | `map(string)` | `{}` | no | | [availability\_zones](#input\_availability\_zones) | A list of one or more availability zones for the group. Used for EC2-Classic and default subnets when not specified with `subnet_ids` argument. Conflicts with `subnet_ids` | `list(string)` | `null` | no | -| [block\_device\_mappings](#input\_block\_device\_mappings) | Specify volumes to attach to the instance besides the volumes specified by the AMI | `any` | `{}` | no | +| [block\_device\_mappings](#input\_block\_device\_mappings) | Specify volumes to attach to the instance besides the volumes specified by the AMI |
map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
}))
| `null` | no | | [bootstrap\_extra\_args](#input\_bootstrap\_extra\_args) | Additional arguments passed to the bootstrap script. When `ami_type` = `BOTTLEROCKET_*`; these are additional [settings](https://github.com/bottlerocket-os/bottlerocket#settings) that are provided to the Bottlerocket user data | `string` | `""` | no | | [capacity\_rebalance](#input\_capacity\_rebalance) | Indicates whether capacity rebalance is enabled | `bool` | `null` | no | -| [capacity\_reservation\_specification](#input\_capacity\_reservation\_specification) | Targeting for EC2 capacity reservations | `any` | `{}` | no | +| [capacity\_reservation\_specification](#input\_capacity\_reservation\_specification) | Targeting for EC2 capacity reservations |
object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
})
| `null` | no | | [cloudinit\_post\_nodeadm](#input\_cloudinit\_post\_nodeadm) | Array of cloud-init document parts that are created after the nodeadm document part |
list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
}))
| `[]` | no | | [cloudinit\_pre\_nodeadm](#input\_cloudinit\_pre\_nodeadm) | Array of cloud-init document parts that are created before the nodeadm document part |
list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
}))
| `[]` | no | | [cluster\_auth\_base64](#input\_cluster\_auth\_base64) | Base64 encoded CA of associated EKS cluster | `string` | `""` | no | @@ -102,7 +101,7 @@ module "self_managed_node_group" { | [cluster\_service\_cidr](#input\_cluster\_service\_cidr) | The CIDR block (IPv4 or IPv6) used by the cluster to assign Kubernetes service IP addresses. This is derived from the cluster itself | `string` | `""` | no | | [cluster\_version](#input\_cluster\_version) | Kubernetes cluster version - used to lookup default AMI ID if one is not provided | `string` | `null` | no | | [context](#input\_context) | Reserved | `string` | `null` | no | -| [cpu\_options](#input\_cpu\_options) | The CPU options for the instance | `map(string)` | `{}` | no | +| [cpu\_options](#input\_cpu\_options) | The CPU options for the instance |
object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
})
| `null` | no | | [create](#input\_create) | Determines whether to create self managed node group or not | `bool` | `true` | no | | [create\_access\_entry](#input\_create\_access\_entry) | Determines whether an access entry is created for the IAM role used by the node group | `bool` | `true` | no | | [create\_autoscaling\_group](#input\_create\_autoscaling\_group) | Determines whether to create autoscaling group or not | `bool` | `true` | no | @@ -110,11 +109,9 @@ module "self_managed_node_group" { | [create\_iam\_role\_policy](#input\_create\_iam\_role\_policy) | Determines whether an IAM role policy is created or not | `bool` | `true` | no | | [create\_launch\_template](#input\_create\_launch\_template) | Determines whether to create launch template or not | `bool` | `true` | no | | [create\_placement\_group](#input\_create\_placement\_group) | Determines whether a placement group is created & used by the node group | `bool` | `false` | no | -| [create\_schedule](#input\_create\_schedule) | Determines whether to create autoscaling group schedule or not | `bool` | `true` | no | -| [credit\_specification](#input\_credit\_specification) | Customize the credit specification of the instance | `map(string)` | `{}` | no | +| [credit\_specification](#input\_credit\_specification) | Customize the credit specification of the instance |
object({
cpu_credits = optional(string)
})
| `null` | no | | [default\_cooldown](#input\_default\_cooldown) | The amount of time, in seconds, after a scaling activity completes before another scaling activity can start | `number` | `null` | no | | [default\_instance\_warmup](#input\_default\_instance\_warmup) | Amount of time, in seconds, until a newly launched instance can contribute to the Amazon CloudWatch metrics. This delay lets an instance finish initializing before Amazon EC2 Auto Scaling aggregates instance metrics, resulting in more reliable usage data | `number` | `null` | no | -| [delete\_timeout](#input\_delete\_timeout) | Delete timeout to wait for destroying autoscaling group | `string` | `null` | no | | [desired\_size](#input\_desired\_size) | The number of Amazon EC2 instances that should be running in the autoscaling group | `number` | `1` | no | | [desired\_size\_type](#input\_desired\_size\_type) | The unit of measurement for the value specified for `desired_size`. Supported for attribute-based instance type selection only. Valid values: `units`, `vcpu`, `memory-mib` | `string` | `null` | no | | [disable\_api\_termination](#input\_disable\_api\_termination) | If true, enables EC2 instance termination protection | `bool` | `null` | no | @@ -124,12 +121,12 @@ module "self_managed_node_group" { | [enable\_efa\_support](#input\_enable\_efa\_support) | Determines whether to enable Elastic Fabric Adapter (EFA) support | `bool` | `false` | no | | [enable\_monitoring](#input\_enable\_monitoring) | Enables/disables detailed monitoring | `bool` | `true` | no | | [enabled\_metrics](#input\_enabled\_metrics) | A list of metrics to collect. The allowed values are `GroupDesiredCapacity`, `GroupInServiceCapacity`, `GroupPendingCapacity`, `GroupMinSize`, `GroupMaxSize`, `GroupInServiceInstances`, `GroupPendingInstances`, `GroupStandbyInstances`, `GroupStandbyCapacity`, `GroupTerminatingCapacity`, `GroupTerminatingInstances`, `GroupTotalCapacity`, `GroupTotalInstances` | `list(string)` | `[]` | no | -| [enclave\_options](#input\_enclave\_options) | Enable Nitro Enclaves on launched instances | `map(string)` | `{}` | no | +| [enclave\_options](#input\_enclave\_options) | Enable Nitro Enclaves on launched instances |
object({
enabled = optional(bool)
})
| `null` | no | | [force\_delete](#input\_force\_delete) | Allows deleting the Auto Scaling Group without waiting for all instances in the pool to terminate. You can force an Auto Scaling Group to delete even if it's in the process of scaling a resource. Normally, Terraform drains all the instances before deleting the group. This bypasses that behavior and potentially leaves resources dangling | `bool` | `null` | no | | [force\_delete\_warm\_pool](#input\_force\_delete\_warm\_pool) | Allows deleting the Auto Scaling Group without waiting for all instances in the warm pool to terminate | `bool` | `null` | no | | [health\_check\_grace\_period](#input\_health\_check\_grace\_period) | Time (in seconds) after instance comes into service before checking health | `number` | `null` | no | | [health\_check\_type](#input\_health\_check\_type) | `EC2` or `ELB`. Controls how health checking is done | `string` | `null` | no | -| [hibernation\_options](#input\_hibernation\_options) | The hibernation options for the instance | `map(string)` | `{}` | no | +| [hibernation\_options](#input\_hibernation\_options) | The hibernation options for the instance |
object({
configured = optional(bool)
})
| `null` | no | | [iam\_instance\_profile\_arn](#input\_iam\_instance\_profile\_arn) | Amazon Resource Name (ARN) of an existing IAM instance profile that provides permissions for the node group. Required if `create_iam_instance_profile` = `false` | `string` | `null` | no | | [iam\_role\_additional\_policies](#input\_iam\_role\_additional\_policies) | Additional policies to be added to the IAM role | `map(string)` | `{}` | no | | [iam\_role\_arn](#input\_iam\_role\_arn) | ARN of the IAM role used by the instance profile. Required when `create_access_entry = true` and `create_iam_instance_profile = false` | `string` | `null` | no | @@ -138,17 +135,17 @@ module "self_managed_node_group" { | [iam\_role\_name](#input\_iam\_role\_name) | Name to use on IAM role created | `string` | `null` | no | | [iam\_role\_path](#input\_iam\_role\_path) | IAM role path | `string` | `null` | no | | [iam\_role\_permissions\_boundary](#input\_iam\_role\_permissions\_boundary) | ARN of the policy that is used to set the permissions boundary for the IAM role | `string` | `null` | no | -| [iam\_role\_policy\_statements](#input\_iam\_role\_policy\_statements) | A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed | `any` | `[]` | no | +| [iam\_role\_policy\_statements](#input\_iam\_role\_policy\_statements) | A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed |
list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
}))
| `null` | no | | [iam\_role\_tags](#input\_iam\_role\_tags) | A map of additional tags to add to the IAM role created | `map(string)` | `{}` | no | | [iam\_role\_use\_name\_prefix](#input\_iam\_role\_use\_name\_prefix) | Determines whether cluster IAM role name (`iam_role_name`) is used as a prefix | `bool` | `true` | no | -| [ignore\_failed\_scaling\_activities](#input\_ignore\_failed\_scaling\_activities) | Whether to ignore failed Auto Scaling scaling activities while waiting for capacity. | `bool` | `null` | no | -| [initial\_lifecycle\_hooks](#input\_initial\_lifecycle\_hooks) | One or more Lifecycle Hooks to attach to the Auto Scaling Group before instances are launched. The syntax is exactly the same as the separate `aws_autoscaling_lifecycle_hook` resource, without the `autoscaling_group_name` attribute. Please note that this will only work when creating a new Auto Scaling Group. For all other use-cases, please use `aws_autoscaling_lifecycle_hook` resource | `list(map(string))` | `[]` | no | +| [ignore\_failed\_scaling\_activities](#input\_ignore\_failed\_scaling\_activities) | Whether to ignore failed Auto Scaling scaling activities while waiting for capacity | `bool` | `null` | no | +| [initial\_lifecycle\_hooks](#input\_initial\_lifecycle\_hooks) | One or more Lifecycle Hooks to attach to the Auto Scaling Group before instances are launched. The syntax is exactly the same as the separate `aws_autoscaling_lifecycle_hook` resource, without the `autoscaling_group_name` attribute. Please note that this will only work when creating a new Auto Scaling Group. For all other use-cases, please use `aws_autoscaling_lifecycle_hook` resource |
list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
}))
| `null` | no | | [instance\_initiated\_shutdown\_behavior](#input\_instance\_initiated\_shutdown\_behavior) | Shutdown behavior for the instance. Can be `stop` or `terminate`. (Default: `stop`) | `string` | `null` | no | -| [instance\_maintenance\_policy](#input\_instance\_maintenance\_policy) | If this block is configured, add a instance maintenance policy to the specified Auto Scaling group | `any` | `{}` | no | -| [instance\_market\_options](#input\_instance\_market\_options) | The market (purchasing) option for the instance | `any` | `{}` | no | -| [instance\_refresh](#input\_instance\_refresh) | If this block is configured, start an Instance Refresh when this Auto Scaling Group is updated | `any` |
{
"preferences": {
"min_healthy_percentage": 66
},
"strategy": "Rolling"
}
| no | -| [instance\_requirements](#input\_instance\_requirements) | The attribute requirements for the type of instance. If present then `instance_type` cannot be present | `any` | `{}` | no | -| [instance\_type](#input\_instance\_type) | The type of the instance to launch | `string` | `""` | no | +| [instance\_maintenance\_policy](#input\_instance\_maintenance\_policy) | If this block is configured, add a instance maintenance policy to the specified Auto Scaling group |
object({
max_healthy_percentage = number
min_healthy_percentage = number
})
| `null` | no | +| [instance\_market\_options](#input\_instance\_market\_options) | The market (purchasing) option for the instance |
object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
})
| `null` | no | +| [instance\_refresh](#input\_instance\_refresh) | If this block is configured, start an Instance Refresh when this Auto Scaling Group is updated |
object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number, 33)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string, "Rolling")
triggers = optional(list(string))
})
|
{
"preferences": {
"min_healthy_percentage": 66
},
"strategy": "Rolling"
}
| no | +| [instance\_requirements](#input\_instance\_requirements) | The attribute requirements for the type of instance. If present then `instance_type` cannot be present |
object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
})
| `null` | no | +| [instance\_type](#input\_instance\_type) | The type of the instance to launch | `string` | `null` | no | | [kernel\_id](#input\_kernel\_id) | The kernel ID | `string` | `null` | no | | [key\_name](#input\_key\_name) | The key name that should be used for the instance | `string` | `null` | no | | [launch\_template\_default\_version](#input\_launch\_template\_default\_version) | Default Version of the launch template | `string` | `null` | no | @@ -158,26 +155,25 @@ module "self_managed_node_group" { | [launch\_template\_tags](#input\_launch\_template\_tags) | A map of additional tags to add to the tag\_specifications of launch template created | `map(string)` | `{}` | no | | [launch\_template\_use\_name\_prefix](#input\_launch\_template\_use\_name\_prefix) | Determines whether to use `launch_template_name` as is or create a unique name beginning with the `launch_template_name` as the prefix | `bool` | `true` | no | | [launch\_template\_version](#input\_launch\_template\_version) | Launch template version. Can be version number, `$Latest`, or `$Default` | `string` | `null` | no | -| [license\_specifications](#input\_license\_specifications) | A map of license specifications to associate with | `any` | `{}` | no | -| [maintenance\_options](#input\_maintenance\_options) | The maintenance options for the instance | `any` | `{}` | no | +| [license\_specifications](#input\_license\_specifications) | A list of license specifications to associate with |
list(object({
license_configuration_arn = string
}))
| `null` | no | +| [maintenance\_options](#input\_maintenance\_options) | The maintenance options for the instance |
object({
auto_recovery = optional(string)
})
| `null` | no | | [max\_instance\_lifetime](#input\_max\_instance\_lifetime) | The maximum amount of time, in seconds, that an instance can be in service, values must be either equal to 0 or between 604800 and 31536000 seconds | `number` | `null` | no | | [max\_size](#input\_max\_size) | The maximum size of the autoscaling group | `number` | `3` | no | -| [metadata\_options](#input\_metadata\_options) | Customize the metadata options for the instance | `map(string)` |
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 1,
"http_tokens": "required"
}
| no | +| [metadata\_options](#input\_metadata\_options) | Customize the metadata options for the instance |
object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
})
|
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 1,
"http_tokens": "required"
}
| no | | [metrics\_granularity](#input\_metrics\_granularity) | The granularity to associate with the metrics to collect. The only valid value is `1Minute` | `string` | `null` | no | | [min\_elb\_capacity](#input\_min\_elb\_capacity) | Setting this causes Terraform to wait for this number of instances to show up healthy in the ELB only on creation. Updates will not wait on ELB instance number changes | `number` | `null` | no | | [min\_size](#input\_min\_size) | The minimum size of the autoscaling group | `number` | `0` | no | -| [mixed\_instances\_policy](#input\_mixed\_instances\_policy) | Configuration block containing settings to define launch targets for Auto Scaling groups | `any` | `null` | no | +| [mixed\_instances\_policy](#input\_mixed\_instances\_policy) | Configuration block containing settings to define launch targets for Auto Scaling groups |
object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
})
| `null` | no | | [name](#input\_name) | Name of the Self managed Node Group | `string` | `""` | no | -| [network\_interfaces](#input\_network\_interfaces) | Customize network interfaces to be attached at instance boot time | `list(any)` | `[]` | no | +| [network\_interfaces](#input\_network\_interfaces) | Customize network interfaces to be attached at instance boot time |
list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
}))
| `[]` | no | | [partition](#input\_partition) | The AWS partition - pass through value to reduce number of GET requests from data sources | `string` | `""` | no | -| [placement](#input\_placement) | The placement of the instance | `map(string)` | `{}` | no | -| [placement\_group](#input\_placement\_group) | The name of the placement group into which you'll launch your instances, if any | `string` | `null` | no | +| [placement](#input\_placement) | The placement of the instance |
object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
})
| `{}` | no | +| [placement\_group](#input\_placement\_group) | The name of the placement group into which you'll launch your instances | `string` | `null` | no | | [post\_bootstrap\_user\_data](#input\_post\_bootstrap\_user\_data) | User data that is appended to the user data script after of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | | [pre\_bootstrap\_user\_data](#input\_pre\_bootstrap\_user\_data) | User data that is injected into the user data script ahead of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | -| [private\_dns\_name\_options](#input\_private\_dns\_name\_options) | The options for the instance hostname. The default values are inherited from the subnet | `map(string)` | `{}` | no | -| [protect\_from\_scale\_in](#input\_protect\_from\_scale\_in) | Allows setting instance protection. The autoscaling group will not select instances with this setting for termination during scale in events. | `bool` | `false` | no | +| [private\_dns\_name\_options](#input\_private\_dns\_name\_options) | The options for the instance hostname. The default values are inherited from the subnet |
object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
})
| `null` | no | +| [protect\_from\_scale\_in](#input\_protect\_from\_scale\_in) | Allows setting instance protection. The autoscaling group will not select instances with this setting for termination during scale in events | `bool` | `false` | no | | [ram\_disk\_id](#input\_ram\_disk\_id) | The ID of the ram disk | `string` | `null` | no | -| [schedules](#input\_schedules) | Map of autoscaling group schedule to create | `map(any)` | `{}` | no | | [service\_linked\_role\_arn](#input\_service\_linked\_role\_arn) | The ARN of the service-linked role that the ASG will use to call other AWS services | `string` | `null` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs to launch resources in. Subnets automatically determine which availability zones the group will reside. Conflicts with `availability_zones` | `list(string)` | `null` | no | | [suspended\_processes](#input\_suspended\_processes) | A list of processes to suspend for the Auto Scaling Group. The allowed values are `Launch`, `Terminate`, `HealthCheck`, `ReplaceUnhealthy`, `AZRebalance`, `AlarmNotification`, `ScheduledActions`, `AddToLoadBalancer`. Note that if you suspend either the `Launch` or `Terminate` process types, it can prevent your Auto Scaling Group from functioning properly | `list(string)` | `[]` | no | @@ -185,14 +181,15 @@ module "self_managed_node_group" { | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | | [target\_group\_arns](#input\_target\_group\_arns) | A set of `aws_alb_target_group` ARNs, for use with Application or Network Load Balancing | `list(string)` | `[]` | no | | [termination\_policies](#input\_termination\_policies) | A list of policies to decide how the instances in the Auto Scaling Group should be terminated. The allowed values are `OldestInstance`, `NewestInstance`, `OldestLaunchConfiguration`, `ClosestToNextInstanceHour`, `OldestLaunchTemplate`, `AllocationStrategy`, `Default` | `list(string)` | `[]` | no | +| [timeouts](#input\_timeouts) | Timeout configurations for the autoscaling group |
object({
delete = optional(string)
})
| `null` | no | | [update\_launch\_template\_default\_version](#input\_update\_launch\_template\_default\_version) | Whether to update Default Version each update. Conflicts with `launch_template_default_version` | `bool` | `true` | no | | [use\_mixed\_instances\_policy](#input\_use\_mixed\_instances\_policy) | Determines whether to use a mixed instances policy in the autoscaling group or not | `bool` | `false` | no | | [use\_name\_prefix](#input\_use\_name\_prefix) | Determines whether to use `name` as is or create a unique name beginning with the `name` as the prefix | `bool` | `true` | no | | [user\_data\_template\_path](#input\_user\_data\_template\_path) | Path to a local, custom user data template file to use when rendering user data | `string` | `""` | no | | [vpc\_security\_group\_ids](#input\_vpc\_security\_group\_ids) | A list of security group IDs to associate | `list(string)` | `[]` | no | -| [wait\_for\_capacity\_timeout](#input\_wait\_for\_capacity\_timeout) | A maximum duration that Terraform should wait for ASG instances to be healthy before timing out. (See also Waiting for Capacity below.) Setting this to '0' causes Terraform to skip all Capacity Waiting behavior. | `string` | `null` | no | -| [wait\_for\_elb\_capacity](#input\_wait\_for\_elb\_capacity) | Setting this will cause Terraform to wait for exactly this number of healthy instances in all attached load balancers on both create and update operations. Takes precedence over `min_elb_capacity` behavior. | `number` | `null` | no | -| [warm\_pool](#input\_warm\_pool) | If this block is configured, add a Warm Pool to the specified Auto Scaling group | `any` | `{}` | no | +| [wait\_for\_capacity\_timeout](#input\_wait\_for\_capacity\_timeout) | A maximum duration that Terraform should wait for ASG instances to be healthy before timing out. (See also Waiting for Capacity below.) Setting this to '0' causes Terraform to skip all Capacity Waiting behavior | `string` | `null` | no | +| [wait\_for\_elb\_capacity](#input\_wait\_for\_elb\_capacity) | Setting this will cause Terraform to wait for exactly this number of healthy instances in all attached load balancers on both create and update operations. Takes precedence over `min_elb_capacity` behavior | `number` | `null` | no | +| [warm\_pool](#input\_warm\_pool) | If this block is configured, add a Warm Pool to the specified Auto Scaling group |
object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
})
| `null` | no | ## Outputs @@ -209,7 +206,6 @@ module "self_managed_node_group" { | [autoscaling\_group\_max\_size](#output\_autoscaling\_group\_max\_size) | The maximum size of the autoscaling group | | [autoscaling\_group\_min\_size](#output\_autoscaling\_group\_min\_size) | The minimum size of the autoscaling group | | [autoscaling\_group\_name](#output\_autoscaling\_group\_name) | The autoscaling group name | -| [autoscaling\_group\_schedule\_arns](#output\_autoscaling\_group\_schedule\_arns) | ARNs of autoscaling group schedules | | [autoscaling\_group\_vpc\_zone\_identifier](#output\_autoscaling\_group\_vpc\_zone\_identifier) | The VPC zone identifier | | [iam\_instance\_profile\_arn](#output\_iam\_instance\_profile\_arn) | ARN assigned by AWS to the instance profile | | [iam\_instance\_profile\_id](#output\_iam\_instance\_profile\_id) | Instance profile's ID | diff --git a/modules/self-managed-node-group/main.tf b/modules/self-managed-node-group/main.tf index d1f693cc06..6718d48dca 100644 --- a/modules/self-managed-node-group/main.tf +++ b/modules/self-managed-node-group/main.tf @@ -112,70 +112,69 @@ locals { locals { launch_template_name = coalesce(var.launch_template_name, "${var.name}-node-group") security_group_ids = compact(concat([var.cluster_primary_security_group_id], var.vpc_security_group_ids)) - - placement = local.enable_efa_support ? { group_name = aws_placement_group.this[0].name } : var.placement } resource "aws_launch_template" "this" { count = var.create && var.create_launch_template ? 1 : 0 dynamic "block_device_mappings" { - for_each = var.block_device_mappings + for_each = var.block_device_mappings != null ? var.block_device_mappings : {} content { - device_name = try(block_device_mappings.value.device_name, null) + device_name = block_device_mappings.value.device_name dynamic "ebs" { - for_each = try([block_device_mappings.value.ebs], []) + for_each = block_device_mappings.value.ebs != null ? [block_device_mappings.value.ebs] : [] content { - delete_on_termination = try(ebs.value.delete_on_termination, null) - encrypted = try(ebs.value.encrypted, null) - iops = try(ebs.value.iops, null) - kms_key_id = try(ebs.value.kms_key_id, null) - snapshot_id = try(ebs.value.snapshot_id, null) - throughput = try(ebs.value.throughput, null) - volume_size = try(ebs.value.volume_size, null) - volume_type = try(ebs.value.volume_type, null) + delete_on_termination = ebs.value.delete_on_termination + encrypted = ebs.value.encrypted + iops = ebs.value.iops + kms_key_id = ebs.value.kms_key_id + snapshot_id = ebs.value.snapshot_id + throughput = ebs.value.throughput + volume_initialization_rate = ebs.value.volume_initialization_rate + volume_size = ebs.value.volume_size + volume_type = ebs.value.volume_type } } - no_device = try(block_device_mappings.value.no_device, null) - virtual_name = try(block_device_mappings.value.virtual_name, null) + no_device = block_device_mappings.value.no_device + virtual_name = block_device_mappings.value.virtual_name } } dynamic "capacity_reservation_specification" { - for_each = length(var.capacity_reservation_specification) > 0 ? [var.capacity_reservation_specification] : [] + for_each = var.capacity_reservation_specification != null ? [var.capacity_reservation_specification] : [] content { - capacity_reservation_preference = try(capacity_reservation_specification.value.capacity_reservation_preference, null) + capacity_reservation_preference = capacity_reservation_specification.value.capacity_reservation_preference dynamic "capacity_reservation_target" { - for_each = try([capacity_reservation_specification.value.capacity_reservation_target], []) - + for_each = capacity_reservation_specification.value.capacity_reservation_target != null ? [capacity_reservation_specification.value.capacity_reservation_target] : [] content { - capacity_reservation_id = try(capacity_reservation_target.value.capacity_reservation_id, null) - capacity_reservation_resource_group_arn = try(capacity_reservation_target.value.capacity_reservation_resource_group_arn, null) + capacity_reservation_id = capacity_reservation_target.value.capacity_reservation_id + capacity_reservation_resource_group_arn = capacity_reservation_target.value.capacity_reservation_resource_group_arn } } } } dynamic "cpu_options" { - for_each = length(var.cpu_options) > 0 ? [var.cpu_options] : [] + for_each = var.cpu_options != null ? [var.cpu_options] : [] content { - core_count = try(cpu_options.value.core_count, null) - threads_per_core = try(cpu_options.value.threads_per_core, null) + amd_sev_snp = cpu_options.value.amd_sev_snp + core_count = cpu_options.value.core_count + threads_per_core = cpu_options.value.threads_per_core } } dynamic "credit_specification" { - for_each = length(var.credit_specification) > 0 ? [var.credit_specification] : [] + for_each = var.credit_specification != null ? [var.credit_specification] : [] content { - cpu_credits = try(credit_specification.value.cpu_credits, null) + cpu_credits = credit_specification.value.cpu_credits } } @@ -185,7 +184,7 @@ resource "aws_launch_template" "this" { ebs_optimized = var.ebs_optimized dynamic "enclave_options" { - for_each = length(var.enclave_options) > 0 ? [var.enclave_options] : [] + for_each = var.enclave_options != null ? [var.enclave_options] : [] content { enabled = enclave_options.value.enabled @@ -193,7 +192,7 @@ resource "aws_launch_template" "this" { } dynamic "hibernation_options" { - for_each = length(var.hibernation_options) > 0 ? [var.hibernation_options] : [] + for_each = var.hibernation_options != null ? [var.hibernation_options] : [] content { configured = hibernation_options.value.configured @@ -208,125 +207,116 @@ resource "aws_launch_template" "this" { instance_initiated_shutdown_behavior = var.instance_initiated_shutdown_behavior dynamic "instance_market_options" { - for_each = length(var.instance_market_options) > 0 ? [var.instance_market_options] : [] + for_each = var.instance_market_options != null ? [var.instance_market_options] : [] content { - market_type = try(instance_market_options.value.market_type, null) + market_type = instance_market_options.value.market_type dynamic "spot_options" { - for_each = try([instance_market_options.value.spot_options], []) + for_each = instance_market_options.value.spot_options != null ? [instance_market_options.value.spot_options] : [] content { - block_duration_minutes = try(spot_options.value.block_duration_minutes, null) - instance_interruption_behavior = try(spot_options.value.instance_interruption_behavior, null) - max_price = try(spot_options.value.max_price, null) - spot_instance_type = try(spot_options.value.spot_instance_type, null) - valid_until = try(spot_options.value.valid_until, null) + block_duration_minutes = spot_options.value.block_duration_minutes + instance_interruption_behavior = spot_options.value.instance_interruption_behavior + max_price = spot_options.value.max_price + spot_instance_type = spot_options.value.spot_instance_type + valid_until = spot_options.value.valid_until } } } } dynamic "instance_requirements" { - for_each = length(var.instance_requirements) > 0 ? [var.instance_requirements] : [] + for_each = var.instance_requirements != null ? [var.instance_requirements] : [] content { - dynamic "accelerator_count" { - for_each = try([instance_requirements.value.accelerator_count], []) + for_each = instance_requirements.value.accelerator_count != null ? [instance_requirements.value.accelerator_count] : [] content { - max = try(accelerator_count.value.max, null) - min = try(accelerator_count.value.min, null) + max = accelerator_count.value.max + min = accelerator_count.value.min } } - accelerator_manufacturers = try(instance_requirements.value.accelerator_manufacturers, []) - accelerator_names = try(instance_requirements.value.accelerator_names, []) + accelerator_manufacturers = instance_requirements.value.accelerator_manufacturers + accelerator_names = instance_requirements.value.accelerator_names dynamic "accelerator_total_memory_mib" { - for_each = try([instance_requirements.value.accelerator_total_memory_mib], []) + for_each = instance_requirements.value.accelerator_total_memory_mib != null ? [instance_requirements.value.accelerator_total_memory_mib] : [] content { - max = try(accelerator_total_memory_mib.value.max, null) - min = try(accelerator_total_memory_mib.value.min, null) + max = accelerator_total_memory_mib.value.max + min = accelerator_total_memory_mib.value.min } } - accelerator_types = try(instance_requirements.value.accelerator_types, []) - allowed_instance_types = try(instance_requirements.value.allowed_instance_types, null) - bare_metal = try(instance_requirements.value.bare_metal, null) + accelerator_types = instance_requirements.value.accelerator_types + allowed_instance_types = instance_requirements.value.allowed_instance_types + bare_metal = instance_requirements.value.bare_metal dynamic "baseline_ebs_bandwidth_mbps" { - for_each = try([instance_requirements.value.baseline_ebs_bandwidth_mbps], []) + for_each = instance_requirements.value.baseline_ebs_bandwidth_mbps != null ? [instance_requirements.value.baseline_ebs_bandwidth_mbps] : [] content { - max = try(baseline_ebs_bandwidth_mbps.value.max, null) - min = try(baseline_ebs_bandwidth_mbps.value.min, null) + max = baseline_ebs_bandwidth_mbps.value.max + min = baseline_ebs_bandwidth_mbps.value.min } } - burstable_performance = try(instance_requirements.value.burstable_performance, null) - cpu_manufacturers = try(instance_requirements.value.cpu_manufacturers, []) - excluded_instance_types = try(instance_requirements.value.excluded_instance_types, null) - instance_generations = try(instance_requirements.value.instance_generations, []) - local_storage = try(instance_requirements.value.local_storage, null) - local_storage_types = try(instance_requirements.value.local_storage_types, []) + burstable_performance = instance_requirements.value.burstable_performance + cpu_manufacturers = instance_requirements.value.cpu_manufacturers + excluded_instance_types = instance_requirements.value.excluded_instance_types + instance_generations = instance_requirements.value.instance_generations + local_storage = instance_requirements.value.local_storage + local_storage_types = instance_requirements.value.local_storage_types + max_spot_price_as_percentage_of_optimal_on_demand_price = instance_requirements.value.max_spot_price_as_percentage_of_optimal_on_demand_price dynamic "memory_gib_per_vcpu" { - for_each = try([instance_requirements.value.memory_gib_per_vcpu], []) + for_each = instance_requirements.value.memory_gib_per_vcpu != null ? [instance_requirements.value.memory_gib_per_vcpu] : [] content { - max = try(memory_gib_per_vcpu.value.max, null) - min = try(memory_gib_per_vcpu.value.min, null) + max = memory_gib_per_vcpu.value.max + min = memory_gib_per_vcpu.value.min } } dynamic "memory_mib" { - for_each = [instance_requirements.value.memory_mib] + for_each = instance_requirements.value.memory_mib != null ? [instance_requirements.value.memory_mib] : [] content { - max = try(memory_mib.value.max, null) + max = memory_mib.value.max min = memory_mib.value.min } } - dynamic "network_bandwidth_gbps" { - for_each = try([instance_requirements.value.network_bandwidth_gbps], []) - - content { - max = try(network_bandwidth_gbps.value.max, null) - min = try(network_bandwidth_gbps.value.min, null) - } - } - dynamic "network_interface_count" { - for_each = try([instance_requirements.value.network_interface_count], []) + for_each = instance_requirements.value.network_interface_count != null ? [instance_requirements.value.network_interface_count] : [] content { - max = try(network_interface_count.value.max, null) - min = try(network_interface_count.value.min, null) + max = network_interface_count.value.max + min = network_interface_count.value.min } } - on_demand_max_price_percentage_over_lowest_price = try(instance_requirements.value.on_demand_max_price_percentage_over_lowest_price, null) - require_hibernate_support = try(instance_requirements.value.require_hibernate_support, null) - spot_max_price_percentage_over_lowest_price = try(instance_requirements.value.spot_max_price_percentage_over_lowest_price, null) + on_demand_max_price_percentage_over_lowest_price = instance_requirements.value.on_demand_max_price_percentage_over_lowest_price + require_hibernate_support = instance_requirements.value.require_hibernate_support + spot_max_price_percentage_over_lowest_price = instance_requirements.value.spot_max_price_percentage_over_lowest_price dynamic "total_local_storage_gb" { - for_each = try([instance_requirements.value.total_local_storage_gb], []) + for_each = instance_requirements.value.total_local_storage_gb != null ? [instance_requirements.value.total_local_storage_gb] : [] content { - max = try(total_local_storage_gb.value.max, null) - min = try(total_local_storage_gb.value.min, null) + max = total_local_storage_gb.value.max + min = total_local_storage_gb.value.min } } dynamic "vcpu_count" { - for_each = [instance_requirements.value.vcpu_count] + for_each = instance_requirements.value.vcpu_count != null ? [instance_requirements.value.vcpu_count] : [] content { - max = try(vcpu_count.value.max, null) + max = vcpu_count.value.max min = vcpu_count.value.min } } @@ -338,7 +328,7 @@ resource "aws_launch_template" "this" { key_name = var.key_name dynamic "license_specification" { - for_each = length(var.license_specifications) > 0 ? var.license_specifications : {} + for_each = var.license_specifications != null ? var.license_specifications : [] content { license_configuration_arn = license_specification.value.license_configuration_arn @@ -346,22 +336,22 @@ resource "aws_launch_template" "this" { } dynamic "maintenance_options" { - for_each = length(var.maintenance_options) > 0 ? [var.maintenance_options] : [] + for_each = var.maintenance_options != null ? [var.maintenance_options] : [] content { - auto_recovery = try(maintenance_options.value.auto_recovery, null) + auto_recovery = maintenance_options.value.auto_recovery } } dynamic "metadata_options" { - for_each = length(var.metadata_options) > 0 ? [var.metadata_options] : [] + for_each = var.metadata_options != null ? [var.metadata_options] : [] content { - http_endpoint = try(metadata_options.value.http_endpoint, null) - http_protocol_ipv6 = try(metadata_options.value.http_protocol_ipv6, null) - http_put_response_hop_limit = try(metadata_options.value.http_put_response_hop_limit, null) - http_tokens = try(metadata_options.value.http_tokens, null) - instance_metadata_tags = try(metadata_options.value.instance_metadata_tags, null) + http_endpoint = metadata_options.value.http_endpoint + http_protocol_ipv6 = metadata_options.value.http_protocol_ipv6 + http_put_response_hop_limit = metadata_options.value.http_put_response_hop_limit + http_tokens = metadata_options.value.http_tokens + instance_metadata_tags = metadata_options.value.instance_metadata_tags } } @@ -377,55 +367,85 @@ resource "aws_launch_template" "this" { name_prefix = var.launch_template_use_name_prefix ? "${local.launch_template_name}-" : null dynamic "network_interfaces" { - for_each = local.network_interfaces + for_each = length(var.network_interfaces) > 0 ? var.network_interfaces : [] content { - associate_carrier_ip_address = try(network_interfaces.value.associate_carrier_ip_address, null) - associate_public_ip_address = try(network_interfaces.value.associate_public_ip_address, null) - delete_on_termination = try(network_interfaces.value.delete_on_termination, null) - description = try(network_interfaces.value.description, null) - device_index = try(network_interfaces.value.device_index, null) - interface_type = try(network_interfaces.value.interface_type, null) - ipv4_address_count = try(network_interfaces.value.ipv4_address_count, null) - ipv4_addresses = try(network_interfaces.value.ipv4_addresses, []) - ipv4_prefix_count = try(network_interfaces.value.ipv4_prefix_count, null) - ipv4_prefixes = try(network_interfaces.value.ipv4_prefixes, null) - ipv6_address_count = try(network_interfaces.value.ipv6_address_count, null) - ipv6_addresses = try(network_interfaces.value.ipv6_addresses, []) - ipv6_prefix_count = try(network_interfaces.value.ipv6_prefix_count, null) - ipv6_prefixes = try(network_interfaces.value.ipv6_prefixes, []) - network_card_index = try(network_interfaces.value.network_card_index, null) - network_interface_id = try(network_interfaces.value.network_interface_id, null) - primary_ipv6 = try(network_interfaces.value.primary_ipv6, null) - private_ip_address = try(network_interfaces.value.private_ip_address, null) + associate_carrier_ip_address = network_interfaces.value.associate_carrier_ip_address + associate_public_ip_address = network_interfaces.value.associate_public_ip_address + + dynamic "connection_tracking_specification" { + for_each = network_interfaces.value.connection_tracking_specification != null ? [network_interfaces.value.connection_tracking_specification] : [] + + content { + tcp_established_timeout = connection_tracking_specification.value.tcp_established_timeout + udp_stream_timeout = connection_tracking_specification.value.udp_stream_timeout + udp_timeout = connection_tracking_specification.value.udp_timeout + } + } + + delete_on_termination = network_interfaces.value.delete_on_termination + description = network_interfaces.value.description + device_index = network_interfaces.value.device_index + + dynamic "ena_srd_specification" { + for_each = network_interfaces.value.ena_srd_specification != null ? [network_interfaces.value.ena_srd_specification] : [] + + content { + ena_srd_enabled = ena_srd_specification.value.ena_srd_enabled + + dynamic "ena_srd_udp_specification" { + for_each = ena_srd_specification.value.ena_srd_udp_specification != null ? [ena_srd_specification.value.ena_srd_udp_specification] : [] + + content { + ena_srd_udp_enabled = ena_srd_udp_specification.value.ena_srd_udp_enabled + } + } + } + } + + interface_type = network_interfaces.value.interface_type + ipv4_address_count = network_interfaces.value.ipv4_address_count + ipv4_addresses = network_interfaces.value.ipv4_addresses + ipv4_prefix_count = network_interfaces.value.ipv4_prefix_count + ipv4_prefixes = network_interfaces.value.ipv4_prefixes + ipv6_address_count = network_interfaces.value.ipv6_address_count + ipv6_addresses = network_interfaces.value.ipv6_addresses + ipv6_prefix_count = network_interfaces.value.ipv6_prefix_count + ipv6_prefixes = network_interfaces.value.ipv6_prefixes + network_card_index = network_interfaces.value.network_card_index + network_interface_id = network_interfaces.value.network_interface_id + primary_ipv6 = network_interfaces.value.primary_ipv6 + private_ip_address = network_interfaces.value.private_ip_address # Ref: https://github.com/hashicorp/terraform-provider-aws/issues/4570 - security_groups = compact(concat(try(network_interfaces.value.security_groups, []), local.security_group_ids)) - subnet_id = try(network_interfaces.value.subnet_id, null) + security_groups = compact(concat(network_interfaces.value.security_groups, var.security_groups)) + # Set on EKS managed node group, will fail if set here + # https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-basics + # subnet_id = try(network_interfaces.value.subnet_id, null) } } dynamic "placement" { - for_each = length(local.placement) > 0 ? [local.placement] : [] + for_each = length(var.placement) > 0 || local.create_placement_group ? [var.placement] : [] content { - affinity = try(placement.value.affinity, null) - availability_zone = lookup(placement.value, "availability_zone", null) - group_name = lookup(placement.value, "group_name", null) - host_id = lookup(placement.value, "host_id", null) - host_resource_group_arn = lookup(placement.value, "host_resource_group_arn", null) - partition_number = try(placement.value.partition_number, null) - spread_domain = try(placement.value.spread_domain, null) - tenancy = try(placement.value.tenancy, null) + affinity = placement.value.affinity + availability_zone = placement.value.availability_zone + group_name = try(coalesce(aws_placement_group.this[0].name, placement.value.group_name), null) + host_id = placement.value.host_id + host_resource_group_arn = placement.value.host_resource_group_arn + partition_number = placement.value.partition_number + spread_domain = placement.value.spread_domain + tenancy = placement.value.tenancy } } dynamic "private_dns_name_options" { - for_each = length(var.private_dns_name_options) > 0 ? [var.private_dns_name_options] : [] + for_each = var.private_dns_name_options != null ? [var.private_dns_name_options] : [] content { - enable_resource_name_dns_aaaa_record = try(private_dns_name_options.value.enable_resource_name_dns_aaaa_record, null) - enable_resource_name_dns_a_record = try(private_dns_name_options.value.enable_resource_name_dns_a_record, null) - hostname_type = try(private_dns_name_options.value.hostname_type, null) + enable_resource_name_dns_aaaa_record = private_dns_name_options.value.enable_resource_name_dns_aaaa_record + enable_resource_name_dns_a_record = private_dns_name_options.value.enable_resource_name_dns_a_record + hostname_type = private_dns_name_options.value.hostname_type } } @@ -485,21 +505,21 @@ resource "aws_autoscaling_group" "this" { health_check_type = var.health_check_type dynamic "initial_lifecycle_hook" { - for_each = var.initial_lifecycle_hooks + for_each = var.initial_lifecycle_hooks != null ? var.initial_lifecycle_hooks : [] content { - default_result = try(initial_lifecycle_hook.value.default_result, null) - heartbeat_timeout = try(initial_lifecycle_hook.value.heartbeat_timeout, null) + default_result = initial_lifecycle_hook.value.default_result + heartbeat_timeout = initial_lifecycle_hook.value.heartbeat_timeout lifecycle_transition = initial_lifecycle_hook.value.lifecycle_transition name = initial_lifecycle_hook.value.name - notification_metadata = try(initial_lifecycle_hook.value.notification_metadata, null) - notification_target_arn = try(initial_lifecycle_hook.value.notification_target_arn, null) - role_arn = try(initial_lifecycle_hook.value.role_arn, null) + notification_metadata = initial_lifecycle_hook.value.notification_metadata + notification_target_arn = initial_lifecycle_hook.value.notification_target_arn + role_arn = initial_lifecycle_hook.value.role_arn } } dynamic "instance_maintenance_policy" { - for_each = length(var.instance_maintenance_policy) > 0 ? [var.instance_maintenance_policy] : [] + for_each = var.instance_maintenance_policy != null ? [var.instance_maintenance_policy] : [] content { min_healthy_percentage = instance_maintenance_policy.value.min_healthy_percentage @@ -508,26 +528,35 @@ resource "aws_autoscaling_group" "this" { } dynamic "instance_refresh" { - for_each = length(var.instance_refresh) > 0 ? [var.instance_refresh] : [] + for_each = var.instance_refresh != null ? [var.instance_refresh] : [] content { dynamic "preferences" { - for_each = try([instance_refresh.value.preferences], []) + for_each = instance_refresh.value.preferences != null ? [instance_refresh.value.preferences] : [] content { - checkpoint_delay = try(preferences.value.checkpoint_delay, null) - checkpoint_percentages = try(preferences.value.checkpoint_percentages, null) - instance_warmup = try(preferences.value.instance_warmup, null) - max_healthy_percentage = try(preferences.value.max_healthy_percentage, null) - min_healthy_percentage = try(preferences.value.min_healthy_percentage, null) - scale_in_protected_instances = try(preferences.value.scale_in_protected_instances, null) - skip_matching = try(preferences.value.skip_matching, null) - standby_instances = try(preferences.value.standby_instances, null) + dynamic "alarm_specification" { + for_each = preferences.value.alarm_specification != null ? [preferences.value.alarm_specification] : [] + + content { + alarms = alarm_specification.value.alarms + } + } + + auto_rollback = preferences.value.auto_rollback + checkpoint_delay = preferences.value.checkpoint_delay + checkpoint_percentages = preferences.value.checkpoint_percentages + instance_warmup = preferences.value.instance_warmup + max_healthy_percentage = preferences.value.max_healthy_percentage + min_healthy_percentage = preferences.value.min_healthy_percentage + scale_in_protected_instances = preferences.value.scale_in_protected_instances + skip_matching = preferences.value.skip_matching + standby_instances = preferences.value.standby_instances } } strategy = instance_refresh.value.strategy - triggers = try(instance_refresh.value.triggers, null) + triggers = instance_refresh.value.triggers } } @@ -553,137 +582,151 @@ resource "aws_autoscaling_group" "this" { content { dynamic "instances_distribution" { - for_each = try([mixed_instances_policy.value.instances_distribution], []) + for_each = mixed_instances_policy.value.instances_distribution != null ? [mixed_instances_policy.value.instances_distribution] : [] content { - on_demand_allocation_strategy = try(instances_distribution.value.on_demand_allocation_strategy, null) - on_demand_base_capacity = try(instances_distribution.value.on_demand_base_capacity, null) - on_demand_percentage_above_base_capacity = try(instances_distribution.value.on_demand_percentage_above_base_capacity, null) - spot_allocation_strategy = try(instances_distribution.value.spot_allocation_strategy, null) - spot_instance_pools = try(instances_distribution.value.spot_instance_pools, null) - spot_max_price = try(instances_distribution.value.spot_max_price, null) + on_demand_allocation_strategy = instances_distribution.value.on_demand_allocation_strategy + on_demand_base_capacity = instances_distribution.value.on_demand_base_capacity + on_demand_percentage_above_base_capacity = instances_distribution.value.on_demand_percentage_above_base_capacity + spot_allocation_strategy = instances_distribution.value.spot_allocation_strategy + spot_instance_pools = instances_distribution.value.spot_instance_pools + spot_max_price = instances_distribution.value.spot_max_price } } - launch_template { - launch_template_specification { - launch_template_id = local.launch_template_id - version = local.launch_template_version - } + dynamic "launch_template" { + for_each = [mixed_instances_policy.value.launch_template] - dynamic "override" { - for_each = try(mixed_instances_policy.value.override, []) + content { + launch_template_specification { + launch_template_id = local.launch_template_id + version = local.launch_template_version + } - content { - dynamic "instance_requirements" { - for_each = try([override.value.instance_requirements], []) + dynamic "override" { + for_each = launch_template.value.override != null ? launch_template.value.override : [] - content { + content { + dynamic "instance_requirements" { + for_each = override.value.instance_requirements != null ? [override.value.instance_requirements] : [] - dynamic "accelerator_count" { - for_each = try([instance_requirements.value.accelerator_count], []) + content { + dynamic "accelerator_count" { + for_each = instance_requirements.value.accelerator_count != null ? [instance_requirements.value.accelerator_count] : [] - content { - max = try(accelerator_count.value.max, null) - min = try(accelerator_count.value.min, null) + content { + max = accelerator_count.value.max + min = accelerator_count.value.min + } } - } - accelerator_manufacturers = try(instance_requirements.value.accelerator_manufacturers, []) - accelerator_names = try(instance_requirements.value.accelerator_names, []) + accelerator_manufacturers = instance_requirements.value.accelerator_manufacturers + accelerator_names = instance_requirements.value.accelerator_names - dynamic "accelerator_total_memory_mib" { - for_each = try([instance_requirements.value.accelerator_total_memory_mib], []) + dynamic "accelerator_total_memory_mib" { + for_each = instance_requirements.value.accelerator_total_memory_mib != null ? [instance_requirements.value.accelerator_total_memory_mib] : [] - content { - max = try(accelerator_total_memory_mib.value.max, null) - min = try(accelerator_total_memory_mib.value.min, null) + content { + max = accelerator_total_memory_mib.value.max + min = accelerator_total_memory_mib.value.min + } } - } - accelerator_types = try(instance_requirements.value.accelerator_types, []) - allowed_instance_types = try(instance_requirements.value.allowed_instance_types, null) - bare_metal = try(instance_requirements.value.bare_metal, null) + accelerator_types = instance_requirements.value.accelerator_types + allowed_instance_types = instance_requirements.value.allowed_instance_types + bare_metal = instance_requirements.value.bare_metal - dynamic "baseline_ebs_bandwidth_mbps" { - for_each = try([instance_requirements.value.baseline_ebs_bandwidth_mbps], []) + dynamic "baseline_ebs_bandwidth_mbps" { + for_each = instance_requirements.value.baseline_ebs_bandwidth_mbps != null ? [instance_requirements.value.baseline_ebs_bandwidth_mbps] : [] - content { - max = try(baseline_ebs_bandwidth_mbps.value.max, null) - min = try(baseline_ebs_bandwidth_mbps.value.min, null) + content { + max = baseline_ebs_bandwidth_mbps.value.max + min = baseline_ebs_bandwidth_mbps.value.min + } } - } - burstable_performance = try(instance_requirements.value.burstable_performance, null) - cpu_manufacturers = try(instance_requirements.value.cpu_manufacturers, []) - excluded_instance_types = try(instance_requirements.value.excluded_instance_types, []) - instance_generations = try(instance_requirements.value.instance_generations, []) - local_storage = try(instance_requirements.value.local_storage, null) - local_storage_types = try(instance_requirements.value.local_storage_types, []) + burstable_performance = instance_requirements.value.burstable_performance + cpu_manufacturers = instance_requirements.value.cpu_manufacturers + excluded_instance_types = instance_requirements.value.excluded_instance_types + instance_generations = instance_requirements.value.instance_generations + local_storage = instance_requirements.value.local_storage + local_storage_types = instance_requirements.value.local_storage_types + max_spot_price_as_percentage_of_optimal_on_demand_price = instance_requirements.value.max_spot_price_as_percentage_of_optimal_on_demand_price + + dynamic "memory_gib_per_vcpu" { + for_each = instance_requirements.value.memory_gib_per_vcpu != null ? [instance_requirements.value.memory_gib_per_vcpu] : [] + + content { + max = memory_gib_per_vcpu.value.max + min = memory_gib_per_vcpu.value.min + } + } - dynamic "memory_gib_per_vcpu" { - for_each = try([instance_requirements.value.memory_gib_per_vcpu], []) + dynamic "memory_mib" { + for_each = instance_requirements.value.memory_mib != null ? [instance_requirements.value.memory_mib] : [] - content { - max = try(memory_gib_per_vcpu.value.max, null) - min = try(memory_gib_per_vcpu.value.min, null) + content { + max = memory_mib.value.max + min = memory_mib.value.min + } } - } - dynamic "memory_mib" { - for_each = [instance_requirements.value.memory_mib] + dynamic "network_bandwidth_gbps" { + for_each = instance_requirements.value.network_bandwidth_gbps != null ? [instance_requirements.value.network_bandwidth_gbps] : [] - content { - max = try(memory_mib.value.max, null) - min = memory_mib.value.min + content { + max = network_bandwidth_gbps.value.max + min = network_bandwidth_gbps.value.min + } } - } - dynamic "network_interface_count" { - for_each = try([instance_requirements.value.network_interface_count], []) + dynamic "network_interface_count" { + for_each = instance_requirements.value.network_interface_count != null ? [instance_requirements.value.network_interface_count] : [] - content { - max = try(network_interface_count.value.max, null) - min = try(network_interface_count.value.min, null) + content { + max = network_interface_count.value.max + min = network_interface_count.value.min + } } - } - on_demand_max_price_percentage_over_lowest_price = try(instance_requirements.value.on_demand_max_price_percentage_over_lowest_price, null) - require_hibernate_support = try(instance_requirements.value.require_hibernate_support, null) - spot_max_price_percentage_over_lowest_price = try(instance_requirements.value.spot_max_price_percentage_over_lowest_price, null) + on_demand_max_price_percentage_over_lowest_price = instance_requirements.value.on_demand_max_price_percentage_over_lowest_price + require_hibernate_support = instance_requirements.value.require_hibernate_support + spot_max_price_percentage_over_lowest_price = instance_requirements.value.spot_max_price_percentage_over_lowest_price - dynamic "total_local_storage_gb" { - for_each = try([instance_requirements.value.total_local_storage_gb], []) + dynamic "total_local_storage_gb" { + for_each = instance_requirements.value.total_local_storage_gb != null ? [instance_requirements.value.total_local_storage_gb] : [] - content { - max = try(total_local_storage_gb.value.max, null) - min = try(total_local_storage_gb.value.min, null) + content { + max = total_local_storage_gb.value.max + min = total_local_storage_gb.value.min + } } - } - dynamic "vcpu_count" { - for_each = [instance_requirements.value.vcpu_count] + dynamic "vcpu_count" { + for_each = instance_requirements.value.vcpu_count != null ? [instance_requirements.value.vcpu_count] : [] - content { - max = try(vcpu_count.value.max, null) - min = vcpu_count.value.min + content { + max = vcpu_count.value.max + min = vcpu_count.value.min + } } } } - } - instance_type = try(override.value.instance_type, null) + instance_type = override.value.instance_type - dynamic "launch_template_specification" { - for_each = try([override.value.launch_template_specification], []) + dynamic "launch_template_specification" { + for_each = override.value.launch_template_specification != null ? [override.value.launch_template_specification] : [] - content { - launch_template_id = try(launch_template_specification.value.launch_template_id, null) - version = try(launch_template_specification.value.version, null) + content { + launch_template_id = launch_template_specification.value.launch_template_id + launch_template_name = launch_template_specification.value.launch_template_name + version = launch_template_specification.value.version + } } - } - weighted_capacity = try(override.value.weighted_capacity, null) + weighted_capacity = override.value.weighted_capacity + } } } } @@ -731,25 +774,29 @@ resource "aws_autoscaling_group" "this" { wait_for_elb_capacity = var.wait_for_elb_capacity dynamic "warm_pool" { - for_each = length(var.warm_pool) > 0 ? [var.warm_pool] : [] + for_each = var.warm_pool != null ? [var.warm_pool] : [] content { dynamic "instance_reuse_policy" { - for_each = try([warm_pool.value.instance_reuse_policy], []) + for_each = warm_pool.value.instance_reuse_policy != null ? [warm_pool.value.instance_reuse_policy] : [] content { - reuse_on_scale_in = try(instance_reuse_policy.value.reuse_on_scale_in, null) + reuse_on_scale_in = instance_reuse_policy.value.reuse_on_scale_in } } - max_group_prepared_capacity = try(warm_pool.value.max_group_prepared_capacity, null) - min_size = try(warm_pool.value.min_size, null) - pool_state = try(warm_pool.value.pool_state, null) + max_group_prepared_capacity = warm_pool.value.max_group_prepared_capacity + min_size = warm_pool.value.min_size + pool_state = warm_pool.value.pool_state } } - timeouts { - delete = var.delete_timeout + dynamic "timeouts" { + for_each = var.timeouts != null ? [var.timeouts] : [] + + content { + delete = var.timeouts.delete + } } lifecycle { @@ -857,18 +904,18 @@ data "aws_iam_policy_document" "role" { count = local.create_iam_role_policy ? 1 : 0 dynamic "statement" { - for_each = var.iam_role_policy_statements + for_each = var.iam_role_policy_statements != null ? var.iam_role_policy_statements : [] content { - sid = try(statement.value.sid, null) - actions = try(statement.value.actions, null) - not_actions = try(statement.value.not_actions, null) - effect = try(statement.value.effect, null) - resources = try(statement.value.resources, null) - not_resources = try(statement.value.not_resources, null) + sid = statement.value.sid + actions = statement.value.actions + not_actions = statement.value.not_actions + effect = statement.value.effect + resources = statement.value.resources + not_resources = statement.value.not_resources dynamic "principals" { - for_each = try(statement.value.principals, []) + for_each = statement.value.principals != null ? statement.value.principals : [] content { type = principals.value.type @@ -877,7 +924,7 @@ data "aws_iam_policy_document" "role" { } dynamic "not_principals" { - for_each = try(statement.value.not_principals, []) + for_each = statement.value.not_principals != null ? statement.value.not_principals : [] content { type = not_principals.value.type @@ -886,7 +933,7 @@ data "aws_iam_policy_document" "role" { } dynamic "condition" { - for_each = try(statement.value.conditions, []) + for_each = statement.value.condition != null ? statement.value.condition : [] content { test = condition.value.test @@ -937,25 +984,3 @@ resource "aws_eks_access_entry" "this" { tags = var.tags } - -################################################################################ -# Autoscaling group schedule -################################################################################ - -resource "aws_autoscaling_schedule" "this" { - for_each = { for k, v in var.schedules : k => v if var.create && var.create_schedule } - - scheduled_action_name = each.key - autoscaling_group_name = aws_autoscaling_group.this[0].name - - min_size = try(each.value.min_size, null) - max_size = try(each.value.max_size, null) - desired_capacity = try(each.value.desired_size, null) - start_time = try(each.value.start_time, null) - end_time = try(each.value.end_time, null) - time_zone = try(each.value.time_zone, null) - - # [Minute] [Hour] [Day_of_Month] [Month_of_Year] [Day_of_Week] - # Cron examples: https://crontab.guru/examples.html - recurrence = try(each.value.recurrence, null) -} diff --git a/modules/self-managed-node-group/outputs.tf b/modules/self-managed-node-group/outputs.tf index bf3564cb25..5520ca3336 100644 --- a/modules/self-managed-node-group/outputs.tf +++ b/modules/self-managed-node-group/outputs.tf @@ -128,15 +128,6 @@ output "access_entry_arn" { value = try(aws_eks_access_entry.this[0].access_entry_arn, null) } -################################################################################ -# Autoscaling Group Schedule -################################################################################ - -output "autoscaling_group_schedule_arns" { - description = "ARNs of autoscaling group schedules" - value = { for k, v in aws_autoscaling_schedule.this : k => v.arn } -} - ################################################################################ # Additional ################################################################################ diff --git a/modules/self-managed-node-group/variables.tf b/modules/self-managed-node-group/variables.tf index 48168a96e6..29fc0bd2d8 100644 --- a/modules/self-managed-node-group/variables.tf +++ b/modules/self-managed-node-group/variables.tf @@ -180,68 +180,153 @@ variable "ram_disk_id" { variable "block_device_mappings" { description = "Specify volumes to attach to the instance besides the volumes specified by the AMI" - type = any - default = {} + type = map(object({ + device_name = optional(string) + ebs = optional(object({ + delete_on_termination = optional(bool) + encrypted = optional(bool) + iops = optional(number) + kms_key_id = optional(string) + snapshot_id = optional(string) + throughput = optional(number) + volume_initialization_rate = optional(number) + volume_size = optional(number) + volume_type = optional(string) + })) + no_device = optional(string) + virtual_name = optional(string) + })) + default = null } variable "capacity_reservation_specification" { description = "Targeting for EC2 capacity reservations" - type = any - default = {} + type = object({ + capacity_reservation_preference = optional(string) + capacity_reservation_target = optional(object({ + capacity_reservation_id = optional(string) + capacity_reservation_resource_group_arn = optional(string) + })) + }) + default = null } variable "cpu_options" { description = "The CPU options for the instance" - type = map(string) - default = {} + type = object({ + amd_sev_snp = optional(string) + core_count = optional(number) + threads_per_core = optional(number) + }) + default = null } variable "credit_specification" { description = "Customize the credit specification of the instance" - type = map(string) - default = {} + type = object({ + cpu_credits = optional(string) + }) + default = null } variable "enclave_options" { description = "Enable Nitro Enclaves on launched instances" - type = map(string) - default = {} + type = object({ + enabled = optional(bool) + }) + default = null } variable "hibernation_options" { description = "The hibernation options for the instance" - type = map(string) - default = {} + type = object({ + configured = optional(bool) + }) + default = null } variable "instance_market_options" { description = "The market (purchasing) option for the instance" - type = any - default = {} + type = object({ + market_type = optional(string) + spot_options = optional(object({ + block_duration_minutes = optional(number) + instance_interruption_behavior = optional(string) + max_price = optional(string) + spot_instance_type = optional(string) + valid_until = optional(string) + })) + }) + default = null } variable "maintenance_options" { description = "The maintenance options for the instance" - type = any - default = {} + type = object({ + auto_recovery = optional(string) + }) + default = null } variable "license_specifications" { - description = "A map of license specifications to associate with" - type = any - default = {} + description = "A list of license specifications to associate with" + type = list(object({ + license_configuration_arn = string + })) + default = null } variable "network_interfaces" { description = "Customize network interfaces to be attached at instance boot time" - type = list(any) - default = [] + type = list(object({ + associate_carrier_ip_address = optional(bool) + associate_public_ip_address = optional(bool) + connection_tracking_specification = optional(object({ + tcp_established_timeout = optional(number) + udp_stream_timeout = optional(number) + udp_timeout = optional(number) + })) + delete_on_termination = optional(bool) + description = optional(string) + device_index = optional(number) + ena_srd_specification = optional(object({ + ena_srd_enabled = optional(bool) + ena_srd_udp_specification = optional(object({ + ena_srd_udp_enabled = optional(bool) + })) + })) + interface_type = optional(string) + ipv4_address_count = optional(number) + ipv4_addresses = optional(list(string)) + ipv4_prefix_count = optional(number) + ipv4_prefixes = optional(list(string)) + ipv6_address_count = optional(number) + ipv6_addresses = optional(list(string)) + ipv6_prefix_count = optional(number) + ipv6_prefixes = optional(list(string)) + network_card_index = optional(number) + network_interface_id = optional(string) + primary_ipv6 = optional(bool) + private_ip_address = optional(string) + security_groups = optional(list(string), []) + subnet_id = optional(string) + })) + default = [] } variable "placement" { description = "The placement of the instance" - type = map(string) - default = {} + type = object({ + affinity = optional(string) + availability_zone = optional(string) + group_name = optional(string) + host_id = optional(string) + host_resource_group_arn = optional(string) + partition_number = optional(number) + spread_domain = optional(string) + tenancy = optional(string) + }) + default = {} } variable "create_placement_group" { @@ -252,8 +337,12 @@ variable "create_placement_group" { variable "private_dns_name_options" { description = "The options for the instance hostname. The default values are inherited from the subnet" - type = map(string) - default = {} + type = object({ + enable_resource_name_dns_aaaa_record = optional(bool) + enable_resource_name_dns_a_record = optional(bool) + hostname_type = optional(string) + }) + default = null } variable "ebs_optimized" { @@ -282,14 +371,66 @@ variable "cluster_version" { variable "instance_requirements" { description = "The attribute requirements for the type of instance. If present then `instance_type` cannot be present" - type = any - default = {} + type = object({ + accelerator_count = optional(object({ + max = optional(number) + min = optional(number) + })) + accelerator_manufacturers = optional(list(string)) + accelerator_names = optional(list(string)) + accelerator_total_memory_mib = optional(object({ + max = optional(number) + min = optional(number) + })) + accelerator_types = optional(list(string)) + allowed_instance_types = optional(list(string)) + bare_metal = optional(string) + baseline_ebs_bandwidth_mbps = optional(object({ + max = optional(number) + min = optional(number) + })) + burstable_performance = optional(string) + cpu_manufacturers = optional(list(string)) + excluded_instance_types = optional(list(string)) + instance_generations = optional(list(string)) + local_storage = optional(string) + local_storage_types = optional(list(string)) + max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number) + memory_gib_per_vcpu = optional(object({ + max = optional(number) + min = optional(number) + })) + memory_mib = optional(object({ + max = optional(number) + min = optional(number) + })) + network_bandwidth_gbps = optional(object({ + max = optional(number) + min = optional(number) + })) + network_interface_count = optional(object({ + max = optional(number) + min = optional(number) + })) + on_demand_max_price_percentage_over_lowest_price = optional(number) + require_hibernate_support = optional(bool) + spot_max_price_percentage_over_lowest_price = optional(number) + total_local_storage_gb = optional(object({ + max = optional(number) + min = optional(number) + })) + vcpu_count = optional(object({ + max = optional(number) + min = string + })) + }) + default = null } variable "instance_type" { description = "The type of the instance to launch" type = string - default = "" + default = null } variable "key_name" { @@ -336,11 +477,17 @@ variable "efa_indices" { variable "metadata_options" { description = "Customize the metadata options for the instance" - type = map(string) + type = object({ + http_endpoint = optional(string, "enabled") + http_protocol_ipv6 = optional(string) + http_put_response_hop_limit = optional(number, 1) + http_tokens = optional(string, "required") + instance_metadata_tags = optional(string) + }) default = { http_endpoint = "enabled" - http_tokens = "required" http_put_response_hop_limit = 1 + http_tokens = "required" } } @@ -421,7 +568,7 @@ variable "desired_size_type" { } variable "ignore_failed_scaling_activities" { - description = "Whether to ignore failed Auto Scaling scaling activities while waiting for capacity." + description = "Whether to ignore failed Auto Scaling scaling activities while waiting for capacity" type = bool default = null } @@ -445,13 +592,13 @@ variable "min_elb_capacity" { } variable "wait_for_elb_capacity" { - description = "Setting this will cause Terraform to wait for exactly this number of healthy instances in all attached load balancers on both create and update operations. Takes precedence over `min_elb_capacity` behavior." + description = "Setting this will cause Terraform to wait for exactly this number of healthy instances in all attached load balancers on both create and update operations. Takes precedence over `min_elb_capacity` behavior" type = number default = null } variable "wait_for_capacity_timeout" { - description = "A maximum duration that Terraform should wait for ASG instances to be healthy before timing out. (See also Waiting for Capacity below.) Setting this to '0' causes Terraform to skip all Capacity Waiting behavior." + description = "A maximum duration that Terraform should wait for ASG instances to be healthy before timing out. (See also Waiting for Capacity below.) Setting this to '0' causes Terraform to skip all Capacity Waiting behavior" type = string default = null } @@ -469,7 +616,7 @@ variable "default_instance_warmup" { } variable "protect_from_scale_in" { - description = "Allows setting instance protection. The autoscaling group will not select instances with this setting for termination during scale in events." + description = "Allows setting instance protection. The autoscaling group will not select instances with this setting for termination during scale in events" type = bool default = false } @@ -481,7 +628,7 @@ variable "target_group_arns" { } variable "placement_group" { - description = "The name of the placement group into which you'll launch your instances, if any" + description = "The name of the placement group into which you'll launch your instances" type = string default = null } @@ -548,19 +695,47 @@ variable "service_linked_role_arn" { variable "initial_lifecycle_hooks" { description = "One or more Lifecycle Hooks to attach to the Auto Scaling Group before instances are launched. The syntax is exactly the same as the separate `aws_autoscaling_lifecycle_hook` resource, without the `autoscaling_group_name` attribute. Please note that this will only work when creating a new Auto Scaling Group. For all other use-cases, please use `aws_autoscaling_lifecycle_hook` resource" - type = list(map(string)) - default = [] + type = list(object({ + default_result = optional(string) + heartbeat_timeout = optional(number) + lifecycle_transition = string + name = string + notification_metadata = optional(string) + notification_target_arn = optional(string) + role_arn = optional(string) + })) + default = null } variable "instance_maintenance_policy" { description = "If this block is configured, add a instance maintenance policy to the specified Auto Scaling group" - type = any - default = {} + type = object({ + max_healthy_percentage = number + min_healthy_percentage = number + }) + default = null } variable "instance_refresh" { description = "If this block is configured, start an Instance Refresh when this Auto Scaling Group is updated" - type = any + type = object({ + preferences = optional(object({ + alarm_specification = optional(object({ + alarms = optional(list(string)) + })) + auto_rollback = optional(bool) + checkpoint_delay = optional(number) + checkpoint_percentages = optional(list(number)) + instance_warmup = optional(number) + max_healthy_percentage = optional(number) + min_healthy_percentage = optional(number, 33) + scale_in_protected_instances = optional(string) + skip_matching = optional(bool) + standby_instances = optional(string) + })) + strategy = optional(string, "Rolling") + triggers = optional(list(string)) + }) default = { strategy = "Rolling" preferences = { @@ -577,20 +752,102 @@ variable "use_mixed_instances_policy" { variable "mixed_instances_policy" { description = "Configuration block containing settings to define launch targets for Auto Scaling groups" - type = any - default = null + type = object({ + instances_distribution = optional(object({ + on_demand_allocation_strategy = optional(string) + on_demand_base_capacity = optional(number) + on_demand_percentage_above_base_capacity = optional(number) + spot_allocation_strategy = optional(string) + spot_instance_pools = optional(number) + spot_max_price = optional(string) + })) + launch_template = object({ + override = optional(list(object({ + instance_requirements = optional(object({ + accelerator_count = optional(object({ + max = optional(number) + min = optional(number) + })) + accelerator_manufacturers = optional(list(string)) + accelerator_names = optional(list(string)) + accelerator_total_memory_mib = optional(object({ + max = optional(number) + min = optional(number) + })) + accelerator_types = optional(list(string)) + allowed_instance_types = optional(list(string)) + bare_metal = optional(string) + baseline_ebs_bandwidth_mbps = optional(object({ + max = optional(number) + min = optional(number) + })) + burstable_performance = optional(string) + cpu_manufacturers = optional(list(string)) + excluded_instance_types = optional(list(string)) + instance_generations = optional(list(string)) + local_storage = optional(string) + local_storage_types = optional(list(string)) + max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number) + memory_gib_per_vcpu = optional(object({ + max = optional(number) + min = optional(number) + })) + memory_mib = optional(object({ + max = optional(number) + min = optional(number) + })) + network_bandwidth_gbps = optional(object({ + max = optional(number) + min = optional(number) + })) + network_interface_count = optional(object({ + max = optional(number) + min = optional(number) + })) + on_demand_max_price_percentage_over_lowest_price = optional(number) + require_hibernate_support = optional(bool) + spot_max_price_percentage_over_lowest_price = optional(number) + total_local_storage_gb = optional(object({ + max = optional(number) + min = optional(number) + })) + vcpu_count = optional(object({ + max = optional(number) + min = optional(number) + })) + })) + instance_type = optional(string) + launch_template_specification = optional(object({ + launch_template_id = optional(string) + launch_template_name = optional(string) + version = optional(string) + })) + weighted_capacity = optional(string) + }))) + }) + }) + default = null } variable "warm_pool" { description = "If this block is configured, add a Warm Pool to the specified Auto Scaling group" - type = any - default = {} + type = object({ + instance_reuse_policy = optional(object({ + reuse_on_scale_in = optional(bool) + })) + max_group_prepared_capacity = optional(number) + min_size = optional(number) + pool_state = optional(string) + }) + default = null } -variable "delete_timeout" { - description = "Delete timeout to wait for destroying autoscaling group" - type = string - default = null +variable "timeouts" { + description = "Timeout configurations for the autoscaling group" + type = object({ + delete = optional(string) + }) + default = null } variable "autoscaling_group_tags" { @@ -675,8 +932,28 @@ variable "create_iam_role_policy" { variable "iam_role_policy_statements" { description = "A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed" - type = any - default = [] + type = list(object({ + sid = optional(string) + actions = optional(list(string)) + not_actions = optional(list(string)) + effect = optional(string) + resources = optional(list(string)) + not_resources = optional(list(string)) + principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + not_principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + condition = optional(list(object({ + test = string + values = list(string) + variable = string + }))) + })) + default = null } ################################################################################ @@ -694,19 +971,3 @@ variable "iam_role_arn" { type = string default = null } - -################################################################################ -# Autoscaling group schedule -################################################################################ - -variable "create_schedule" { - description = "Determines whether to create autoscaling group schedule or not" - type = bool - default = true -} - -variable "schedules" { - description = "Map of autoscaling group schedule to create" - type = map(any) - default = {} -} diff --git a/node_groups.tf b/node_groups.tf index df39d793d7..517cd9080f 100644 --- a/node_groups.tf +++ b/node_groups.tf @@ -1,23 +1,4 @@ locals { - metadata_options = { - http_endpoint = "enabled" - http_tokens = "required" - http_put_response_hop_limit = 1 - } - - # EKS managed node group - default_update_config = { - max_unavailable_percentage = 33 - } - - # Self-managed node group - default_instance_refresh = { - strategy = "Rolling" - preferences = { - min_healthy_percentage = 66 - } - } - kubernetes_network_config = try(aws_eks_cluster.this[0].kubernetes_network_config[0], {}) } @@ -258,9 +239,9 @@ resource "aws_security_group_rule" "node" { module "fargate_profile" { source = "./modules/fargate-profile" - for_each = { for k, v in var.fargate_profiles : k => v if var.create && !local.create_outposts_local_cluster } + for_each = var.create && !local.create_outposts_local_cluster && length(var.fargate_profiles) > 0 ? var.fargate_profiles : {} - create = try(each.value.create, true) + create = each.value.create # Pass through values to reduce GET requests from data sources partition = local.partition @@ -271,26 +252,28 @@ module "fargate_profile" { cluster_ip_family = var.cluster_ip_family name = try(each.value.name, each.key) subnet_ids = try(each.value.subnet_ids, var.fargate_profile_defaults.subnet_ids, var.subnet_ids) - selectors = try(each.value.selectors, var.fargate_profile_defaults.selectors, []) - timeouts = try(each.value.timeouts, var.fargate_profile_defaults.timeouts, {}) + selectors = try(each.value.selectors, var.fargate_profile_defaults.selectors, null) + timeouts = try(each.value.timeouts, var.fargate_profile_defaults.timeouts, null) # IAM role - create_iam_role = try(each.value.create_iam_role, var.fargate_profile_defaults.create_iam_role, true) + create_iam_role = try(each.value.create_iam_role, var.fargate_profile_defaults.create_iam_role, null) iam_role_arn = try(each.value.iam_role_arn, var.fargate_profile_defaults.iam_role_arn, null) iam_role_name = try(each.value.iam_role_name, var.fargate_profile_defaults.iam_role_name, null) - iam_role_use_name_prefix = try(each.value.iam_role_use_name_prefix, var.fargate_profile_defaults.iam_role_use_name_prefix, true) + iam_role_use_name_prefix = try(each.value.iam_role_use_name_prefix, var.fargate_profile_defaults.iam_role_use_name_prefix, null) iam_role_path = try(each.value.iam_role_path, var.fargate_profile_defaults.iam_role_path, null) - iam_role_description = try(each.value.iam_role_description, var.fargate_profile_defaults.iam_role_description, "Fargate profile IAM role") + iam_role_description = try(each.value.iam_role_description, var.fargate_profile_defaults.iam_role_description, null) iam_role_permissions_boundary = try(each.value.iam_role_permissions_boundary, var.fargate_profile_defaults.iam_role_permissions_boundary, null) - iam_role_tags = try(each.value.iam_role_tags, var.fargate_profile_defaults.iam_role_tags, {}) - iam_role_attach_cni_policy = try(each.value.iam_role_attach_cni_policy, var.fargate_profile_defaults.iam_role_attach_cni_policy, true) - # To better understand why this `lookup()` logic is required, see: - # https://github.com/hashicorp/terraform/issues/31646#issuecomment-1217279031 - iam_role_additional_policies = lookup(each.value, "iam_role_additional_policies", lookup(var.fargate_profile_defaults, "iam_role_additional_policies", {})) - create_iam_role_policy = try(each.value.create_iam_role_policy, var.fargate_profile_defaults.create_iam_role_policy, true) - iam_role_policy_statements = try(each.value.iam_role_policy_statements, var.fargate_profile_defaults.iam_role_policy_statements, []) - - tags = merge(var.tags, try(each.value.tags, var.fargate_profile_defaults.tags, {})) + iam_role_tags = try(each.value.iam_role_tags, var.fargate_profile_defaults.iam_role_tags, null) + iam_role_attach_cni_policy = try(each.value.iam_role_attach_cni_policy, var.fargate_profile_defaults.iam_role_attach_cni_policy, null) + iam_role_additional_policies = try(each.value.iam_role_additional_policies, var.fargate_profile_defaults.iam_role_additional_policies, null) + create_iam_role_policy = try(each.value.create_iam_role_policy, var.fargate_profile_defaults.create_iam_role_policy, null) + iam_role_policy_statements = try(each.value.iam_role_policy_statements, var.fargate_profile_defaults.iam_role_policy_statements, null) + + tags = merge( + var.tags, + var.fargate_profile_defaults.tags, + each.value.tags, + ) } ################################################################################ @@ -300,9 +283,9 @@ module "fargate_profile" { module "eks_managed_node_group" { source = "./modules/eks-managed-node-group" - for_each = { for k, v in var.eks_managed_node_groups : k => v if var.create && !local.create_outposts_local_cluster } + for_each = var.create && !local.create_outposts_local_cluster && length(var.eks_managed_node_groups) > 0 ? var.eks_managed_node_groups : {} - create = try(each.value.create, true) + create = each.value.create # Pass through values to reduce GET requests from data sources partition = local.partition @@ -313,18 +296,18 @@ module "eks_managed_node_group" { # EKS Managed Node Group name = try(each.value.name, each.key) - use_name_prefix = try(each.value.use_name_prefix, var.eks_managed_node_group_defaults.use_name_prefix, true) + use_name_prefix = try(each.value.use_name_prefix, var.eks_managed_node_group_defaults.use_name_prefix, null) subnet_ids = try(each.value.subnet_ids, var.eks_managed_node_group_defaults.subnet_ids, var.subnet_ids) - min_size = try(each.value.min_size, var.eks_managed_node_group_defaults.min_size, 1) - max_size = try(each.value.max_size, var.eks_managed_node_group_defaults.max_size, 3) - desired_size = try(each.value.desired_size, var.eks_managed_node_group_defaults.desired_size, 1) + min_size = try(each.value.min_size, var.eks_managed_node_group_defaults.min_size, null) + max_size = try(each.value.max_size, var.eks_managed_node_group_defaults.max_size, null) + desired_size = try(each.value.desired_size, var.eks_managed_node_group_defaults.desired_size, null) - ami_id = try(each.value.ami_id, var.eks_managed_node_group_defaults.ami_id, "") - ami_type = try(each.value.ami_type, var.eks_managed_node_group_defaults.ami_type, "AL2023_x86_64_STANDARD") + ami_id = try(each.value.ami_id, var.eks_managed_node_group_defaults.ami_id, null) + ami_type = try(each.value.ami_type, var.eks_managed_node_group_defaults.ami_type, null) ami_release_version = try(each.value.ami_release_version, var.eks_managed_node_group_defaults.ami_release_version, null) - use_latest_ami_release_version = try(each.value.use_latest_ami_release_version, var.eks_managed_node_group_defaults.use_latest_ami_release_version, false) + use_latest_ami_release_version = try(each.value.use_latest_ami_release_version, var.eks_managed_node_group_defaults.use_latest_ami_release_version, null) capacity_type = try(each.value.capacity_type, var.eks_managed_node_group_defaults.capacity_type, null) disk_size = try(each.value.disk_size, var.eks_managed_node_group_defaults.disk_size, null) @@ -332,36 +315,36 @@ module "eks_managed_node_group" { instance_types = try(each.value.instance_types, var.eks_managed_node_group_defaults.instance_types, null) labels = try(each.value.labels, var.eks_managed_node_group_defaults.labels, null) node_repair_config = try(each.value.node_repair_config, var.eks_managed_node_group_defaults.node_repair_config, null) - remote_access = try(each.value.remote_access, var.eks_managed_node_group_defaults.remote_access, {}) - taints = try(each.value.taints, var.eks_managed_node_group_defaults.taints, {}) - update_config = try(each.value.update_config, var.eks_managed_node_group_defaults.update_config, local.default_update_config) - timeouts = try(each.value.timeouts, var.eks_managed_node_group_defaults.timeouts, {}) + remote_access = try(each.value.remote_access, var.eks_managed_node_group_defaults.remote_access, null) + taints = try(each.value.taints, var.eks_managed_node_group_defaults.taints, null) + update_config = try(each.value.update_config, var.eks_managed_node_group_defaults.update_config, null) + timeouts = try(each.value.timeouts, var.eks_managed_node_group_defaults.timeouts, null) # User data cluster_endpoint = try(time_sleep.this[0].triggers["cluster_endpoint"], "") cluster_auth_base64 = try(time_sleep.this[0].triggers["cluster_certificate_authority_data"], "") cluster_ip_family = var.cluster_ip_family cluster_service_cidr = try(time_sleep.this[0].triggers["cluster_service_cidr"], "") - enable_bootstrap_user_data = try(each.value.enable_bootstrap_user_data, var.eks_managed_node_group_defaults.enable_bootstrap_user_data, false) - pre_bootstrap_user_data = try(each.value.pre_bootstrap_user_data, var.eks_managed_node_group_defaults.pre_bootstrap_user_data, "") - post_bootstrap_user_data = try(each.value.post_bootstrap_user_data, var.eks_managed_node_group_defaults.post_bootstrap_user_data, "") - bootstrap_extra_args = try(each.value.bootstrap_extra_args, var.eks_managed_node_group_defaults.bootstrap_extra_args, "") - user_data_template_path = try(each.value.user_data_template_path, var.eks_managed_node_group_defaults.user_data_template_path, "") - cloudinit_pre_nodeadm = try(each.value.cloudinit_pre_nodeadm, var.eks_managed_node_group_defaults.cloudinit_pre_nodeadm, []) - cloudinit_post_nodeadm = try(each.value.cloudinit_post_nodeadm, var.eks_managed_node_group_defaults.cloudinit_post_nodeadm, []) + enable_bootstrap_user_data = try(each.value.enable_bootstrap_user_data, var.eks_managed_node_group_defaults.enable_bootstrap_user_data, null) + pre_bootstrap_user_data = try(each.value.pre_bootstrap_user_data, var.eks_managed_node_group_defaults.pre_bootstrap_user_data, null) + post_bootstrap_user_data = try(each.value.post_bootstrap_user_data, var.eks_managed_node_group_defaults.post_bootstrap_user_data, null) + bootstrap_extra_args = try(each.value.bootstrap_extra_args, var.eks_managed_node_group_defaults.bootstrap_extra_args, null) + user_data_template_path = try(each.value.user_data_template_path, var.eks_managed_node_group_defaults.user_data_template_path, null) + cloudinit_pre_nodeadm = try(each.value.cloudinit_pre_nodeadm, var.eks_managed_node_group_defaults.cloudinit_pre_nodeadm, null) + cloudinit_post_nodeadm = try(each.value.cloudinit_post_nodeadm, var.eks_managed_node_group_defaults.cloudinit_post_nodeadm, null) # Launch Template - create_launch_template = try(each.value.create_launch_template, var.eks_managed_node_group_defaults.create_launch_template, true) - use_custom_launch_template = try(each.value.use_custom_launch_template, var.eks_managed_node_group_defaults.use_custom_launch_template, true) - launch_template_id = try(each.value.launch_template_id, var.eks_managed_node_group_defaults.launch_template_id, "") + create_launch_template = try(each.value.create_launch_template, var.eks_managed_node_group_defaults.create_launch_template, null) + use_custom_launch_template = try(each.value.use_custom_launch_template, var.eks_managed_node_group_defaults.use_custom_launch_template, null) + launch_template_id = try(each.value.launch_template_id, var.eks_managed_node_group_defaults.launch_template_id, null) launch_template_name = try(each.value.launch_template_name, var.eks_managed_node_group_defaults.launch_template_name, each.key) - launch_template_use_name_prefix = try(each.value.launch_template_use_name_prefix, var.eks_managed_node_group_defaults.launch_template_use_name_prefix, true) + launch_template_use_name_prefix = try(each.value.launch_template_use_name_prefix, var.eks_managed_node_group_defaults.launch_template_use_name_prefix, null) launch_template_version = try(each.value.launch_template_version, var.eks_managed_node_group_defaults.launch_template_version, null) launch_template_default_version = try(each.value.launch_template_default_version, var.eks_managed_node_group_defaults.launch_template_default_version, null) - update_launch_template_default_version = try(each.value.update_launch_template_default_version, var.eks_managed_node_group_defaults.update_launch_template_default_version, true) + update_launch_template_default_version = try(each.value.update_launch_template_default_version, var.eks_managed_node_group_defaults.update_launch_template_default_version, null) launch_template_description = try(each.value.launch_template_description, var.eks_managed_node_group_defaults.launch_template_description, "Custom launch template for ${try(each.value.name, each.key)} EKS managed node group") - launch_template_tags = try(each.value.launch_template_tags, var.eks_managed_node_group_defaults.launch_template_tags, {}) - tag_specifications = try(each.value.tag_specifications, var.eks_managed_node_group_defaults.tag_specifications, ["instance", "volume", "network-interface"]) + launch_template_tags = try(each.value.launch_template_tags, var.eks_managed_node_group_defaults.launch_template_tags, null) + tag_specifications = try(each.value.tag_specifications, var.eks_managed_node_group_defaults.tag_specifications, null) ebs_optimized = try(each.value.ebs_optimized, var.eks_managed_node_group_defaults.ebs_optimized, null) key_name = try(each.value.key_name, var.eks_managed_node_group_defaults.key_name, null) @@ -369,50 +352,47 @@ module "eks_managed_node_group" { kernel_id = try(each.value.kernel_id, var.eks_managed_node_group_defaults.kernel_id, null) ram_disk_id = try(each.value.ram_disk_id, var.eks_managed_node_group_defaults.ram_disk_id, null) - block_device_mappings = try(each.value.block_device_mappings, var.eks_managed_node_group_defaults.block_device_mappings, {}) - capacity_reservation_specification = try(each.value.capacity_reservation_specification, var.eks_managed_node_group_defaults.capacity_reservation_specification, {}) - cpu_options = try(each.value.cpu_options, var.eks_managed_node_group_defaults.cpu_options, {}) - credit_specification = try(each.value.credit_specification, var.eks_managed_node_group_defaults.credit_specification, {}) - enclave_options = try(each.value.enclave_options, var.eks_managed_node_group_defaults.enclave_options, {}) - instance_market_options = try(each.value.instance_market_options, var.eks_managed_node_group_defaults.instance_market_options, {}) - license_specifications = try(each.value.license_specifications, var.eks_managed_node_group_defaults.license_specifications, {}) - metadata_options = try(each.value.metadata_options, var.eks_managed_node_group_defaults.metadata_options, local.metadata_options) - enable_monitoring = try(each.value.enable_monitoring, var.eks_managed_node_group_defaults.enable_monitoring, true) - enable_efa_support = try(each.value.enable_efa_support, var.eks_managed_node_group_defaults.enable_efa_support, false) - enable_efa_only = try(each.value.enable_efa_only, var.eks_managed_node_group_defaults.enable_efa_only, false) - efa_indices = try(each.value.efa_indices, var.eks_managed_node_group_defaults.efa_indices, [0]) - create_placement_group = try(each.value.create_placement_group, var.eks_managed_node_group_defaults.create_placement_group, false) - placement = try(each.value.placement, var.eks_managed_node_group_defaults.placement, {}) - placement_group_strategy = try(each.value.placement_group_strategy, var.eks_managed_node_group_defaults.placement_group_strategy, "cluster") - network_interfaces = try(each.value.network_interfaces, var.eks_managed_node_group_defaults.network_interfaces, []) - maintenance_options = try(each.value.maintenance_options, var.eks_managed_node_group_defaults.maintenance_options, {}) - private_dns_name_options = try(each.value.private_dns_name_options, var.eks_managed_node_group_defaults.private_dns_name_options, {}) + block_device_mappings = try(each.value.block_device_mappings, var.eks_managed_node_group_defaults.block_device_mappings, null) + capacity_reservation_specification = try(each.value.capacity_reservation_specification, var.eks_managed_node_group_defaults.capacity_reservation_specification, null) + cpu_options = try(each.value.cpu_options, var.eks_managed_node_group_defaults.cpu_options, null) + credit_specification = try(each.value.credit_specification, var.eks_managed_node_group_defaults.credit_specification, null) + enclave_options = try(each.value.enclave_options, var.eks_managed_node_group_defaults.enclave_options, null) + instance_market_options = try(each.value.instance_market_options, var.eks_managed_node_group_defaults.instance_market_options, null) + license_specifications = try(each.value.license_specifications, var.eks_managed_node_group_defaults.license_specifications, null) + metadata_options = try(each.value.metadata_options, var.eks_managed_node_group_defaults.metadata_options, null) + enable_monitoring = try(each.value.enable_monitoring, var.eks_managed_node_group_defaults.enable_monitoring, null) + enable_efa_support = try(each.value.enable_efa_support, var.eks_managed_node_group_defaults.enable_efa_support, null) + enable_efa_only = try(each.value.enable_efa_only, var.eks_managed_node_group_defaults.enable_efa_only, null) + efa_indices = try(each.value.efa_indices, var.eks_managed_node_group_defaults.efa_indices, null) + create_placement_group = try(each.value.create_placement_group, var.eks_managed_node_group_defaults.create_placement_group, null) + placement = try(each.value.placement, var.eks_managed_node_group_defaults.placement, null) + network_interfaces = try(each.value.network_interfaces, var.eks_managed_node_group_defaults.network_interfaces, null) + maintenance_options = try(each.value.maintenance_options, var.eks_managed_node_group_defaults.maintenance_options, null) + private_dns_name_options = try(each.value.private_dns_name_options, var.eks_managed_node_group_defaults.private_dns_name_options, null) # IAM role - create_iam_role = try(each.value.create_iam_role, var.eks_managed_node_group_defaults.create_iam_role, true) + create_iam_role = try(each.value.create_iam_role, var.eks_managed_node_group_defaults.create_iam_role, null) iam_role_arn = try(each.value.iam_role_arn, var.eks_managed_node_group_defaults.iam_role_arn, null) iam_role_name = try(each.value.iam_role_name, var.eks_managed_node_group_defaults.iam_role_name, null) - iam_role_use_name_prefix = try(each.value.iam_role_use_name_prefix, var.eks_managed_node_group_defaults.iam_role_use_name_prefix, true) + iam_role_use_name_prefix = try(each.value.iam_role_use_name_prefix, var.eks_managed_node_group_defaults.iam_role_use_name_prefix, null) iam_role_path = try(each.value.iam_role_path, var.eks_managed_node_group_defaults.iam_role_path, null) - iam_role_description = try(each.value.iam_role_description, var.eks_managed_node_group_defaults.iam_role_description, "EKS managed node group IAM role") + iam_role_description = try(each.value.iam_role_description, var.eks_managed_node_group_defaults.iam_role_description, null) iam_role_permissions_boundary = try(each.value.iam_role_permissions_boundary, var.eks_managed_node_group_defaults.iam_role_permissions_boundary, null) - iam_role_tags = try(each.value.iam_role_tags, var.eks_managed_node_group_defaults.iam_role_tags, {}) - iam_role_attach_cni_policy = try(each.value.iam_role_attach_cni_policy, var.eks_managed_node_group_defaults.iam_role_attach_cni_policy, true) - # To better understand why this `lookup()` logic is required, see: - # https://github.com/hashicorp/terraform/issues/31646#issuecomment-1217279031 - iam_role_additional_policies = lookup(each.value, "iam_role_additional_policies", lookup(var.eks_managed_node_group_defaults, "iam_role_additional_policies", {})) - create_iam_role_policy = try(each.value.create_iam_role_policy, var.eks_managed_node_group_defaults.create_iam_role_policy, true) - iam_role_policy_statements = try(each.value.iam_role_policy_statements, var.eks_managed_node_group_defaults.iam_role_policy_statements, []) - - # Autoscaling group schedule - create_schedule = try(each.value.create_schedule, var.eks_managed_node_group_defaults.create_schedule, true) - schedules = try(each.value.schedules, var.eks_managed_node_group_defaults.schedules, {}) + iam_role_tags = try(each.value.iam_role_tags, var.eks_managed_node_group_defaults.iam_role_tags, null) + iam_role_attach_cni_policy = try(each.value.iam_role_attach_cni_policy, var.eks_managed_node_group_defaults.iam_role_attach_cni_policy, null) + iam_role_additional_policies = try(each.value.iam_role_additional_policies, var.eks_managed_node_group_defaults.iam_role_additional_policies, null) + create_iam_role_policy = try(each.value.create_iam_role_policy, var.eks_managed_node_group_defaults.create_iam_role_policy, true) + iam_role_policy_statements = try(each.value.iam_role_policy_statements, var.eks_managed_node_group_defaults.iam_role_policy_statements, null) # Security group vpc_security_group_ids = compact(concat([local.node_security_group_id], try(each.value.vpc_security_group_ids, var.eks_managed_node_group_defaults.vpc_security_group_ids, []))) cluster_primary_security_group_id = try(each.value.attach_cluster_primary_security_group, var.eks_managed_node_group_defaults.attach_cluster_primary_security_group, false) ? aws_eks_cluster.this[0].vpc_config[0].cluster_security_group_id : null - tags = merge(var.tags, try(each.value.tags, var.eks_managed_node_group_defaults.tags, {})) + tags = merge( + var.tags, + var.eks_managed_node_group_defaults.tags, + each.value.tags, + ) } ################################################################################ @@ -422,9 +402,9 @@ module "eks_managed_node_group" { module "self_managed_node_group" { source = "./modules/self-managed-node-group" - for_each = { for k, v in var.self_managed_node_groups : k => v if var.create } + for_each = var.create && length(var.self_managed_node_groups) > 0 ? var.self_managed_node_groups : {} - create = try(each.value.create, true) + create = each.value.create # Pass through values to reduce GET requests from data sources partition = local.partition @@ -433,17 +413,17 @@ module "self_managed_node_group" { cluster_name = time_sleep.this[0].triggers["cluster_name"] # Autoscaling Group - create_autoscaling_group = try(each.value.create_autoscaling_group, var.self_managed_node_group_defaults.create_autoscaling_group, true) + create_autoscaling_group = try(each.value.create_autoscaling_group, var.self_managed_node_group_defaults.create_autoscaling_group, null) name = try(each.value.name, each.key) - use_name_prefix = try(each.value.use_name_prefix, var.self_managed_node_group_defaults.use_name_prefix, true) + use_name_prefix = try(each.value.use_name_prefix, var.self_managed_node_group_defaults.use_name_prefix, null) availability_zones = try(each.value.availability_zones, var.self_managed_node_group_defaults.availability_zones, null) subnet_ids = try(each.value.subnet_ids, var.self_managed_node_group_defaults.subnet_ids, var.subnet_ids) - min_size = try(each.value.min_size, var.self_managed_node_group_defaults.min_size, 0) - max_size = try(each.value.max_size, var.self_managed_node_group_defaults.max_size, 3) - desired_size = try(each.value.desired_size, var.self_managed_node_group_defaults.desired_size, 1) + min_size = try(each.value.min_size, var.self_managed_node_group_defaults.min_size, null) + max_size = try(each.value.max_size, var.self_managed_node_group_defaults.max_size, null) + desired_size = try(each.value.desired_size, var.self_managed_node_group_defaults.desired_size, null) desired_size_type = try(each.value.desired_size_type, var.self_managed_node_group_defaults.desired_size_type, null) capacity_rebalance = try(each.value.capacity_rebalance, var.self_managed_node_group_defaults.capacity_rebalance, null) min_elb_capacity = try(each.value.min_elb_capacity, var.self_managed_node_group_defaults.min_elb_capacity, null) @@ -454,7 +434,7 @@ module "self_managed_node_group" { protect_from_scale_in = try(each.value.protect_from_scale_in, var.self_managed_node_group_defaults.protect_from_scale_in, null) context = try(each.value.context, var.self_managed_node_group_defaults.context, null) - target_group_arns = try(each.value.target_group_arns, var.self_managed_node_group_defaults.target_group_arns, []) + target_group_arns = try(each.value.target_group_arns, var.self_managed_node_group_defaults.target_group_arns, null) create_placement_group = try(each.value.create_placement_group, var.self_managed_node_group_defaults.create_placement_group, false) placement_group = try(each.value.placement_group, var.self_managed_node_group_defaults.placement_group, null) health_check_type = try(each.value.health_check_type, var.self_managed_node_group_defaults.health_check_type, null) @@ -464,54 +444,54 @@ module "self_managed_node_group" { force_delete = try(each.value.force_delete, var.self_managed_node_group_defaults.force_delete, null) force_delete_warm_pool = try(each.value.force_delete_warm_pool, var.self_managed_node_group_defaults.force_delete_warm_pool, null) - termination_policies = try(each.value.termination_policies, var.self_managed_node_group_defaults.termination_policies, []) - suspended_processes = try(each.value.suspended_processes, var.self_managed_node_group_defaults.suspended_processes, []) + termination_policies = try(each.value.termination_policies, var.self_managed_node_group_defaults.termination_policies, null) + suspended_processes = try(each.value.suspended_processes, var.self_managed_node_group_defaults.suspended_processes, null) max_instance_lifetime = try(each.value.max_instance_lifetime, var.self_managed_node_group_defaults.max_instance_lifetime, null) - enabled_metrics = try(each.value.enabled_metrics, var.self_managed_node_group_defaults.enabled_metrics, []) + enabled_metrics = try(each.value.enabled_metrics, var.self_managed_node_group_defaults.enabled_metrics, null) metrics_granularity = try(each.value.metrics_granularity, var.self_managed_node_group_defaults.metrics_granularity, null) service_linked_role_arn = try(each.value.service_linked_role_arn, var.self_managed_node_group_defaults.service_linked_role_arn, null) - initial_lifecycle_hooks = try(each.value.initial_lifecycle_hooks, var.self_managed_node_group_defaults.initial_lifecycle_hooks, []) - instance_maintenance_policy = try(each.value.instance_maintenance_policy, var.self_managed_node_group_defaults.instance_maintenance_policy, {}) - instance_refresh = try(each.value.instance_refresh, var.self_managed_node_group_defaults.instance_refresh, local.default_instance_refresh) - use_mixed_instances_policy = try(each.value.use_mixed_instances_policy, var.self_managed_node_group_defaults.use_mixed_instances_policy, false) + initial_lifecycle_hooks = try(each.value.initial_lifecycle_hooks, var.self_managed_node_group_defaults.initial_lifecycle_hooks, null) + instance_maintenance_policy = try(each.value.instance_maintenance_policy, var.self_managed_node_group_defaults.instance_maintenance_policy, null) + instance_refresh = try(each.value.instance_refresh, var.self_managed_node_group_defaults.instance_refresh, null) + use_mixed_instances_policy = try(each.value.use_mixed_instances_policy, var.self_managed_node_group_defaults.use_mixed_instances_policy, null) mixed_instances_policy = try(each.value.mixed_instances_policy, var.self_managed_node_group_defaults.mixed_instances_policy, null) - warm_pool = try(each.value.warm_pool, var.self_managed_node_group_defaults.warm_pool, {}) + warm_pool = try(each.value.warm_pool, var.self_managed_node_group_defaults.warm_pool, null) - delete_timeout = try(each.value.delete_timeout, var.self_managed_node_group_defaults.delete_timeout, null) - autoscaling_group_tags = try(each.value.autoscaling_group_tags, var.self_managed_node_group_defaults.autoscaling_group_tags, {}) + timeouts = try(each.value.timeouts, var.self_managed_node_group_defaults.timeouts, null) + autoscaling_group_tags = try(each.value.autoscaling_group_tags, var.self_managed_node_group_defaults.autoscaling_group_tags, null) # User data - ami_type = try(each.value.ami_type, var.self_managed_node_group_defaults.ami_type, "AL2023_x86_64_STANDARD") + ami_type = try(each.value.ami_type, var.self_managed_node_group_defaults.ami_type, null) cluster_endpoint = try(time_sleep.this[0].triggers["cluster_endpoint"], "") cluster_auth_base64 = try(time_sleep.this[0].triggers["cluster_certificate_authority_data"], "") cluster_service_cidr = try(time_sleep.this[0].triggers["cluster_service_cidr"], "") - additional_cluster_dns_ips = try(each.value.additional_cluster_dns_ips, var.self_managed_node_group_defaults.additional_cluster_dns_ips, []) + additional_cluster_dns_ips = try(each.value.additional_cluster_dns_ips, var.self_managed_node_group_defaults.additional_cluster_dns_ips, null) cluster_ip_family = var.cluster_ip_family - pre_bootstrap_user_data = try(each.value.pre_bootstrap_user_data, var.self_managed_node_group_defaults.pre_bootstrap_user_data, "") - post_bootstrap_user_data = try(each.value.post_bootstrap_user_data, var.self_managed_node_group_defaults.post_bootstrap_user_data, "") - bootstrap_extra_args = try(each.value.bootstrap_extra_args, var.self_managed_node_group_defaults.bootstrap_extra_args, "") - user_data_template_path = try(each.value.user_data_template_path, var.self_managed_node_group_defaults.user_data_template_path, "") - cloudinit_pre_nodeadm = try(each.value.cloudinit_pre_nodeadm, var.self_managed_node_group_defaults.cloudinit_pre_nodeadm, []) - cloudinit_post_nodeadm = try(each.value.cloudinit_post_nodeadm, var.self_managed_node_group_defaults.cloudinit_post_nodeadm, []) + pre_bootstrap_user_data = try(each.value.pre_bootstrap_user_data, var.self_managed_node_group_defaults.pre_bootstrap_user_data, null) + post_bootstrap_user_data = try(each.value.post_bootstrap_user_data, var.self_managed_node_group_defaults.post_bootstrap_user_data, null) + bootstrap_extra_args = try(each.value.bootstrap_extra_args, var.self_managed_node_group_defaults.bootstrap_extra_args, null) + user_data_template_path = try(each.value.user_data_template_path, var.self_managed_node_group_defaults.user_data_template_path, null) + cloudinit_pre_nodeadm = try(each.value.cloudinit_pre_nodeadm, var.self_managed_node_group_defaults.cloudinit_pre_nodeadm, null) + cloudinit_post_nodeadm = try(each.value.cloudinit_post_nodeadm, var.self_managed_node_group_defaults.cloudinit_post_nodeadm, null) # Launch Template - create_launch_template = try(each.value.create_launch_template, var.self_managed_node_group_defaults.create_launch_template, true) - launch_template_id = try(each.value.launch_template_id, var.self_managed_node_group_defaults.launch_template_id, "") + create_launch_template = try(each.value.create_launch_template, var.self_managed_node_group_defaults.create_launch_template, null) + launch_template_id = try(each.value.launch_template_id, var.self_managed_node_group_defaults.launch_template_id, null) launch_template_name = try(each.value.launch_template_name, var.self_managed_node_group_defaults.launch_template_name, each.key) - launch_template_use_name_prefix = try(each.value.launch_template_use_name_prefix, var.self_managed_node_group_defaults.launch_template_use_name_prefix, true) + launch_template_use_name_prefix = try(each.value.launch_template_use_name_prefix, var.self_managed_node_group_defaults.launch_template_use_name_prefix, null) launch_template_version = try(each.value.launch_template_version, var.self_managed_node_group_defaults.launch_template_version, null) launch_template_default_version = try(each.value.launch_template_default_version, var.self_managed_node_group_defaults.launch_template_default_version, null) - update_launch_template_default_version = try(each.value.update_launch_template_default_version, var.self_managed_node_group_defaults.update_launch_template_default_version, true) + update_launch_template_default_version = try(each.value.update_launch_template_default_version, var.self_managed_node_group_defaults.update_launch_template_default_version, null) launch_template_description = try(each.value.launch_template_description, var.self_managed_node_group_defaults.launch_template_description, "Custom launch template for ${try(each.value.name, each.key)} self managed node group") - launch_template_tags = try(each.value.launch_template_tags, var.self_managed_node_group_defaults.launch_template_tags, {}) - tag_specifications = try(each.value.tag_specifications, var.self_managed_node_group_defaults.tag_specifications, ["instance", "volume", "network-interface"]) + launch_template_tags = try(each.value.launch_template_tags, var.self_managed_node_group_defaults.launch_template_tags, null) + tag_specifications = try(each.value.tag_specifications, var.self_managed_node_group_defaults.tag_specifications, null) ebs_optimized = try(each.value.ebs_optimized, var.self_managed_node_group_defaults.ebs_optimized, null) - ami_id = try(each.value.ami_id, var.self_managed_node_group_defaults.ami_id, "") + ami_id = try(each.value.ami_id, var.self_managed_node_group_defaults.ami_id, null) cluster_version = try(each.value.cluster_version, var.self_managed_node_group_defaults.cluster_version, time_sleep.this[0].triggers["cluster_version"]) - instance_type = try(each.value.instance_type, var.self_managed_node_group_defaults.instance_type, "m6i.large") + instance_type = try(each.value.instance_type, var.self_managed_node_group_defaults.instance_type, null) key_name = try(each.value.key_name, var.self_managed_node_group_defaults.key_name, null) disable_api_termination = try(each.value.disable_api_termination, var.self_managed_node_group_defaults.disable_api_termination, null) @@ -519,52 +499,50 @@ module "self_managed_node_group" { kernel_id = try(each.value.kernel_id, var.self_managed_node_group_defaults.kernel_id, null) ram_disk_id = try(each.value.ram_disk_id, var.self_managed_node_group_defaults.ram_disk_id, null) - block_device_mappings = try(each.value.block_device_mappings, var.self_managed_node_group_defaults.block_device_mappings, {}) - capacity_reservation_specification = try(each.value.capacity_reservation_specification, var.self_managed_node_group_defaults.capacity_reservation_specification, {}) - cpu_options = try(each.value.cpu_options, var.self_managed_node_group_defaults.cpu_options, {}) - credit_specification = try(each.value.credit_specification, var.self_managed_node_group_defaults.credit_specification, {}) - enclave_options = try(each.value.enclave_options, var.self_managed_node_group_defaults.enclave_options, {}) - hibernation_options = try(each.value.hibernation_options, var.self_managed_node_group_defaults.hibernation_options, {}) - instance_requirements = try(each.value.instance_requirements, var.self_managed_node_group_defaults.instance_requirements, {}) - instance_market_options = try(each.value.instance_market_options, var.self_managed_node_group_defaults.instance_market_options, {}) - license_specifications = try(each.value.license_specifications, var.self_managed_node_group_defaults.license_specifications, {}) - metadata_options = try(each.value.metadata_options, var.self_managed_node_group_defaults.metadata_options, local.metadata_options) - enable_monitoring = try(each.value.enable_monitoring, var.self_managed_node_group_defaults.enable_monitoring, true) - enable_efa_support = try(each.value.enable_efa_support, var.self_managed_node_group_defaults.enable_efa_support, false) - enable_efa_only = try(each.value.enable_efa_only, var.self_managed_node_group_defaults.enable_efa_only, false) - efa_indices = try(each.value.efa_indices, var.self_managed_node_group_defaults.efa_indices, [0]) - network_interfaces = try(each.value.network_interfaces, var.self_managed_node_group_defaults.network_interfaces, []) - placement = try(each.value.placement, var.self_managed_node_group_defaults.placement, {}) - maintenance_options = try(each.value.maintenance_options, var.self_managed_node_group_defaults.maintenance_options, {}) - private_dns_name_options = try(each.value.private_dns_name_options, var.self_managed_node_group_defaults.private_dns_name_options, {}) + block_device_mappings = try(each.value.block_device_mappings, var.self_managed_node_group_defaults.block_device_mappings, null) + capacity_reservation_specification = try(each.value.capacity_reservation_specification, var.self_managed_node_group_defaults.capacity_reservation_specification, null) + cpu_options = try(each.value.cpu_options, var.self_managed_node_group_defaults.cpu_options, null) + credit_specification = try(each.value.credit_specification, var.self_managed_node_group_defaults.credit_specification, null) + enclave_options = try(each.value.enclave_options, var.self_managed_node_group_defaults.enclave_options, null) + hibernation_options = try(each.value.hibernation_options, var.self_managed_node_group_defaults.hibernation_options, null) + instance_requirements = try(each.value.instance_requirements, var.self_managed_node_group_defaults.instance_requirements, null) + instance_market_options = try(each.value.instance_market_options, var.self_managed_node_group_defaults.instance_market_options, null) + license_specifications = try(each.value.license_specifications, var.self_managed_node_group_defaults.license_specifications, null) + metadata_options = try(each.value.metadata_options, var.self_managed_node_group_defaults.metadata_options, null) + enable_monitoring = try(each.value.enable_monitoring, var.self_managed_node_group_defaults.enable_monitoring, null) + enable_efa_support = try(each.value.enable_efa_support, var.self_managed_node_group_defaults.enable_efa_support, null) + enable_efa_only = try(each.value.enable_efa_only, var.self_managed_node_group_defaults.enable_efa_only, null) + efa_indices = try(each.value.efa_indices, var.self_managed_node_group_defaults.efa_indices, null) + network_interfaces = try(each.value.network_interfaces, var.self_managed_node_group_defaults.network_interfaces, null) + placement = try(each.value.placement, var.self_managed_node_group_defaults.placement, null) + maintenance_options = try(each.value.maintenance_options, var.self_managed_node_group_defaults.maintenance_options, null) + private_dns_name_options = try(each.value.private_dns_name_options, var.self_managed_node_group_defaults.private_dns_name_options, null) # IAM role - create_iam_instance_profile = try(each.value.create_iam_instance_profile, var.self_managed_node_group_defaults.create_iam_instance_profile, true) + create_iam_instance_profile = try(each.value.create_iam_instance_profile, var.self_managed_node_group_defaults.create_iam_instance_profile, null) iam_instance_profile_arn = try(each.value.iam_instance_profile_arn, var.self_managed_node_group_defaults.iam_instance_profile_arn, null) iam_role_name = try(each.value.iam_role_name, var.self_managed_node_group_defaults.iam_role_name, null) iam_role_use_name_prefix = try(each.value.iam_role_use_name_prefix, var.self_managed_node_group_defaults.iam_role_use_name_prefix, true) iam_role_path = try(each.value.iam_role_path, var.self_managed_node_group_defaults.iam_role_path, null) - iam_role_description = try(each.value.iam_role_description, var.self_managed_node_group_defaults.iam_role_description, "Self managed node group IAM role") + iam_role_description = try(each.value.iam_role_description, var.self_managed_node_group_defaults.iam_role_description, null) iam_role_permissions_boundary = try(each.value.iam_role_permissions_boundary, var.self_managed_node_group_defaults.iam_role_permissions_boundary, null) - iam_role_tags = try(each.value.iam_role_tags, var.self_managed_node_group_defaults.iam_role_tags, {}) - iam_role_attach_cni_policy = try(each.value.iam_role_attach_cni_policy, var.self_managed_node_group_defaults.iam_role_attach_cni_policy, true) - # To better understand why this `lookup()` logic is required, see: - # https://github.com/hashicorp/terraform/issues/31646#issuecomment-1217279031 - iam_role_additional_policies = lookup(each.value, "iam_role_additional_policies", lookup(var.self_managed_node_group_defaults, "iam_role_additional_policies", {})) - create_iam_role_policy = try(each.value.create_iam_role_policy, var.self_managed_node_group_defaults.create_iam_role_policy, true) - iam_role_policy_statements = try(each.value.iam_role_policy_statements, var.self_managed_node_group_defaults.iam_role_policy_statements, []) + iam_role_tags = try(each.value.iam_role_tags, var.self_managed_node_group_defaults.iam_role_tags, null) + iam_role_attach_cni_policy = try(each.value.iam_role_attach_cni_policy, var.self_managed_node_group_defaults.iam_role_attach_cni_policy, null) + iam_role_additional_policies = try(each.value.iam_role_additional_policies, var.self_managed_node_group_defaults.iam_role_additional_policies, null) + create_iam_role_policy = try(each.value.create_iam_role_policy, var.self_managed_node_group_defaults.create_iam_role_policy, null) + iam_role_policy_statements = try(each.value.iam_role_policy_statements, var.self_managed_node_group_defaults.iam_role_policy_statements, null) # Access entry - create_access_entry = try(each.value.create_access_entry, var.self_managed_node_group_defaults.create_access_entry, true) + create_access_entry = try(each.value.create_access_entry, var.self_managed_node_group_defaults.create_access_entry, null) iam_role_arn = try(each.value.iam_role_arn, var.self_managed_node_group_defaults.iam_role_arn, null) - # Autoscaling group schedule - create_schedule = try(each.value.create_schedule, var.self_managed_node_group_defaults.create_schedule, true) - schedules = try(each.value.schedules, var.self_managed_node_group_defaults.schedules, {}) - # Security group vpc_security_group_ids = compact(concat([local.node_security_group_id], try(each.value.vpc_security_group_ids, var.self_managed_node_group_defaults.vpc_security_group_ids, []))) cluster_primary_security_group_id = try(each.value.attach_cluster_primary_security_group, var.self_managed_node_group_defaults.attach_cluster_primary_security_group, false) ? aws_eks_cluster.this[0].vpc_config[0].cluster_security_group_id : null - tags = merge(var.tags, try(each.value.tags, var.self_managed_node_group_defaults.tags, {})) + tags = merge( + var.tags, + var.self_managed_node_group_defaults.tags, + each.value.tags, + ) } diff --git a/scratch/main.tf b/scratch/main.tf new file mode 100644 index 0000000000..f1786814e0 --- /dev/null +++ b/scratch/main.tf @@ -0,0 +1,20 @@ +variable "tags" { + description = "The first variable" + type = map(string) + default = {} +} + +variable "one" { + description = "The first variable" + type = object({ + tags = optional(map(string), {}) + }) + default = {} +} + +output "something" { + value = merge( + var.tags, + var.one.tags, + ) +} \ No newline at end of file diff --git a/tests/self-managed-node-group/main.tf b/tests/self-managed-node-group/main.tf index 2560da9bf2..3dc109554a 100644 --- a/tests/self-managed-node-group/main.tf +++ b/tests/self-managed-node-group/main.tf @@ -153,16 +153,18 @@ module "eks" { spot_allocation_strategy = "capacity-optimized" } - override = [ - { - instance_type = "m5.large" - weighted_capacity = "1" - }, - { - instance_type = "m6i.large" - weighted_capacity = "2" - }, - ] + launch_template = { + override = [ + { + instance_type = "m5.large" + weighted_capacity = "1" + }, + { + instance_type = "m6i.large" + weighted_capacity = "2" + }, + ] + } } } @@ -263,21 +265,23 @@ module "eks" { } # ASG configuration - override = [ - { - instance_requirements = { - cpu_manufacturers = ["intel"] - instance_generations = ["current", "previous"] - spot_max_price_percentage_over_lowest_price = 100 - - vcpu_count = { - min = 1 + launch_template = { + override = [ + { + instance_requirements = { + cpu_manufacturers = ["intel"] + instance_generations = ["current", "previous"] + spot_max_price_percentage_over_lowest_price = 100 + + vcpu_count = { + min = 1 + } + + allowed_instance_types = ["t*", "m*"] } - - allowed_instance_types = ["t*", "m*"] } - } - ] + ] + } } } diff --git a/variables.tf b/variables.tf index ccb27f387c..8fe96283a7 100644 --- a/variables.tf +++ b/variables.tf @@ -624,14 +624,112 @@ variable "node_iam_role_tags" { variable "fargate_profiles" { description = "Map of Fargate Profile definitions to create" - type = any - default = {} + type = map(object({ + create = optional(bool, true) + + # Fargate profile + name = optional(string) # Will fall back to map key + subnet_ids = optional(list(string), []) + selectors = optional(list(object({ + labels = optional(map(string)) + namespace = string + }))) + timeouts = optional(object({ + create = optional(string) + delete = optional(string) + })) + + # IAM role + create_iam_role = optional(bool, true) + iam_role_arn = optional(string) + iam_role_name = optional(string) + iam_role_use_name_prefix = optional(bool, true) + iam_role_path = optional(string) + iam_role_description = optional(string, "Fargate profile IAM role") + iam_role_permissions_boundary = optional(string) + iam_role_tags = optional(map(string), {}) + iam_role_attach_cni_policy = optional(bool, true) + iam_role_additional_policies = optional(map(string), {}) + create_iam_role_policy = optional(bool, true) + iam_role_policy_statements = optional(list(object({ + sid = optional(string) + actions = optional(list(string)) + not_actions = optional(list(string)) + effect = optional(string) + resources = optional(list(string)) + not_resources = optional(list(string)) + principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + not_principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + condition = optional(list(object({ + test = string + values = list(string) + variable = string + }))) + }))) + tags = optional(map(string), {}) + })) + default = {} } variable "fargate_profile_defaults" { description = "Map of Fargate Profile default configurations" - type = any - default = {} + type = object({ + create = optional(bool) + + # Fargate profile + name = optional(string) # Will fall back to map key + subnet_ids = optional(list(string)) + selectors = optional(list(object({ + labels = optional(map(string)) + namespace = string + }))) + timeouts = optional(object({ + create = optional(string) + delete = optional(string) + })) + + # IAM role + create_iam_role = optional(bool) + iam_role_arn = optional(string) + iam_role_name = optional(string) + iam_role_use_name_prefix = optional(bool) + iam_role_path = optional(string) + iam_role_description = optional(string) + iam_role_permissions_boundary = optional(string) + iam_role_tags = optional(map(string), {}) + iam_role_attach_cni_policy = optional(bool) + iam_role_additional_policies = optional(map(string), {}) + create_iam_role_policy = optional(bool) + iam_role_policy_statements = optional(list(object({ + sid = optional(string) + actions = optional(list(string)) + not_actions = optional(list(string)) + effect = optional(string) + resources = optional(list(string)) + not_resources = optional(list(string)) + principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + not_principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + condition = optional(list(object({ + test = string + values = list(string) + variable = string + }))) + }))) + tags = optional(map(string), {}) + }) + default = {} } ################################################################################ @@ -640,14 +738,806 @@ variable "fargate_profile_defaults" { variable "self_managed_node_groups" { description = "Map of self-managed node group definitions to create" - type = any - default = {} + type = map(object({ + create = optional(bool, true) + # Autoscaling Group + create_autoscaling_group = optional(bool, true) + name = optional(string) # Will fall back to map key + use_name_prefix = optional(bool, true) + availability_zones = optional(list(string)) + subnet_ids = optional(list(string)) + min_size = optional(number, 0) + max_size = optional(number, 3) + desired_size = optional(number, 1) + desired_size_type = optional(string) + capacity_rebalance = optional(bool) + min_elb_capacity = optional(number) + wait_for_elb_capacity = optional(number) + default_cooldown = optional(number) + default_instance_warmup = optional(number) + protect_from_scale_in = optional(bool, false) + context = optional(string) + target_group_arns = optional(list(string), []) + create_placement_group = optional(bool, false) + placement_group = optional(string) + health_check_type = optional(string) + health_check_grace_period = optional(number) + ignore_failed_scaling_activities = optional(number) + force_delete = optional(bool) + force_delete_warm_pool = optional(bool) + termination_policies = optional(list(string), []) + suspended_processes = optional(list(string), []) + max_instance_lifetime = optional(number) + enabled_metrics = optional(list(string), []) + metrics_granularity = optional(string) + service_linked_role_arn = optional(string) + initial_lifecycle_hooks = optional(list(object({ + default_result = optional(string) + heartbeat_timeout = optional(number) + lifecycle_transition = string + name = string + notification_metadata = optional(string) + notification_target_arn = optional(string) + role_arn = optional(string) + }))) + instance_maintenance_policy = optional(object({ + max_healthy_percentage = number + min_healthy_percentage = number + })) + instance_refresh = optional(object({ + preferences = optional(object({ + alarm_specification = optional(object({ + alarms = optional(list(string)) + })) + auto_rollback = optional(bool) + checkpoint_delay = optional(number) + checkpoint_percentages = optional(list(number)) + instance_warmup = optional(number) + max_healthy_percentage = optional(number) + min_healthy_percentage = optional(number, 66) + scale_in_protected_instances = optional(string) + skip_matching = optional(bool) + standby_instances = optional(string) + })) + strategy = optional(string, "Rolling") + triggers = optional(list(string)) + }), { + strategy = "Rolling" + preferences = { + min_healthy_percentage = 66 + } + }) + use_mixed_instances_policy = optional(bool, false) + mixed_instances_policy = optional(object({ + instances_distribution = optional(object({ + on_demand_allocation_strategy = optional(string) + on_demand_base_capacity = optional(number) + on_demand_percentage_above_base_capacity = optional(number) + spot_allocation_strategy = optional(string) + spot_instance_pools = optional(number) + spot_max_price = optional(string) + })) + launch_template = object({ + override = optional(list(object({ + instance_requirements = optional(object({ + accelerator_count = optional(object({ + max = optional(number) + min = optional(number) + })) + accelerator_manufacturers = optional(list(string)) + accelerator_names = optional(list(string)) + accelerator_total_memory_mib = optional(object({ + max = optional(number) + min = optional(number) + })) + accelerator_types = optional(list(string)) + allowed_instance_types = optional(list(string)) + bare_metal = optional(string) + baseline_ebs_bandwidth_mbps = optional(object({ + max = optional(number) + min = optional(number) + })) + burstable_performance = optional(string) + cpu_manufacturers = optional(list(string)) + excluded_instance_types = optional(list(string)) + instance_generations = optional(list(string)) + local_storage = optional(string) + local_storage_types = optional(list(string)) + max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number) + memory_gib_per_vcpu = optional(object({ + max = optional(number) + min = optional(number) + })) + memory_mib = optional(object({ + max = optional(number) + min = optional(number) + })) + network_bandwidth_gbps = optional(object({ + max = optional(number) + min = optional(number) + })) + network_interface_count = optional(object({ + max = optional(number) + min = optional(number) + })) + on_demand_max_price_percentage_over_lowest_price = optional(number) + require_hibernate_support = optional(bool) + spot_max_price_percentage_over_lowest_price = optional(number) + total_local_storage_gb = optional(object({ + max = optional(number) + min = optional(number) + })) + vcpu_count = optional(object({ + max = optional(number) + min = optional(number) + })) + })) + instance_type = optional(string) + launch_template_specification = optional(object({ + launch_template_id = optional(string) + launch_template_name = optional(string) + version = optional(string) + })) + weighted_capacity = optional(string) + }))) + }) + })) + warm_pool = optional(object({ + instance_reuse_policy = optional(object({ + reuse_on_scale_in = optional(bool) + })) + max_group_prepared_capacity = optional(number) + min_size = optional(number) + pool_state = optional(string) + })) + timeouts = optional(object({ + delete = optional(string) + })) + autoscaling_group_tags = optional(map(string), {}) + # User data + ami_type = optional(string, "AL2023_x86_64_STANDARD") + additional_cluster_dns_ips = optional(list(string), []) + pre_bootstrap_user_data = optional(string, "") + post_bootstrap_user_data = optional(string, "") + bootstrap_extra_args = optional(string, "") + user_data_template_path = optional(string, "") + cloudinit_pre_nodeadm = optional(list(object({ + content = string + content_type = optional(string) + filename = optional(string) + merge_type = optional(string) + })), []) + cloudinit_post_nodeadm = optional(list(object({ + content = string + content_type = optional(string) + filename = optional(string) + merge_type = optional(string) + })), []) + # Launch Template + create_launch_template = optional(bool, true) + use_custom_launch_template = optional(bool, true) + launch_template_id = optional(string, "") + launch_template_name = optional(string) # Will fall back to map key + launch_template_use_name_prefix = optional(bool, true) + launch_template_version = optional(string) + update_launch_template_default_version = optional(bool, true) + launch_template_description = optional(string) + launch_template_tags = optional(map(string), {}) + tag_specifications = optional(list(string), ["instance", "volume", "network-interface"]) + ebs_optimized = optional(bool) + ami_id = optional(string) + instance_type = optional(string, "m6i.large") + key_name = optional(string) + disable_api_termination = optional(bool) + instance_initiated_shutdown_behavior = optional(string) + kernel_id = optional(string) + ram_disk_id = optional(string) + block_device_mappings = optional(map(object({ + device_name = optional(string) + ebs = optional(object({ + delete_on_termination = optional(bool) + encrypted = optional(bool) + iops = optional(number) + kms_key_id = optional(string) + snapshot_id = optional(string) + throughput = optional(number) + volume_initialization_rate = optional(number) + volume_size = optional(number) + volume_type = optional(string) + })) + no_device = optional(string) + virtual_name = optional(string) + }))) + capacity_reservation_specification = optional(object({ + capacity_reservation_preference = optional(string) + capacity_reservation_target = optional(object({ + capacity_reservation_id = optional(string) + capacity_reservation_resource_group_arn = optional(string) + })) + })) + cpu_options = optional(object({ + amd_sev_snp = optional(string) + core_count = optional(number) + threads_per_core = optional(number) + })) + credit_specification = optional(object({ + cpu_credits = optional(string) + })) + enclave_options = optional(object({ + enabled = optional(bool) + })) + hibernation_options = optional(object({ + configured = optional(bool) + })) + instance_requirements = optional(object({ + accelerator_count = optional(object({ + max = optional(number) + min = optional(number) + })) + accelerator_manufacturers = optional(list(string)) + accelerator_names = optional(list(string)) + accelerator_total_memory_mib = optional(object({ + max = optional(number) + min = optional(number) + })) + accelerator_types = optional(list(string)) + allowed_instance_types = optional(list(string)) + bare_metal = optional(string) + baseline_ebs_bandwidth_mbps = optional(object({ + max = optional(number) + min = optional(number) + })) + burstable_performance = optional(string) + cpu_manufacturers = optional(list(string)) + excluded_instance_types = optional(list(string)) + instance_generations = optional(list(string)) + local_storage = optional(string) + local_storage_types = optional(list(string)) + max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number) + memory_gib_per_vcpu = optional(object({ + max = optional(number) + min = optional(number) + })) + memory_mib = optional(object({ + max = optional(number) + min = optional(number) + })) + network_bandwidth_gbps = optional(object({ + max = optional(number) + min = optional(number) + })) + network_interface_count = optional(object({ + max = optional(number) + min = optional(number) + })) + on_demand_max_price_percentage_over_lowest_price = optional(number) + require_hibernate_support = optional(bool) + spot_max_price_percentage_over_lowest_price = optional(number) + total_local_storage_gb = optional(object({ + max = optional(number) + min = optional(number) + })) + vcpu_count = optional(object({ + max = optional(number) + min = string + })) + })) + instance_market_options = optional(object({ + market_type = optional(string) + spot_options = optional(object({ + block_duration_minutes = optional(number) + instance_interruption_behavior = optional(string) + max_price = optional(string) + spot_instance_type = optional(string) + valid_until = optional(string) + })) + })) + license_specifications = optional(list(object({ + license_configuration_arn = string + }))) + metadata_options = optional(object({ + http_endpoint = optional(string, "enabled") + http_protocol_ipv6 = optional(string) + http_put_response_hop_limit = optional(number, 1) + http_tokens = optional(string, "required") + instance_metadata_tags = optional(string) + }), { + http_endpoint = "enabled" + http_put_response_hop_limit = 1 + http_tokens = "required" + }) + enable_monitoring = optional(bool, false) + enable_efa_support = optional(bool, false) + enable_efa_only = optional(bool, true) + efa_indices = optional(list(string), [0]) + network_interfaces = optional(list(object({ + associate_carrier_ip_address = optional(bool) + associate_public_ip_address = optional(bool) + connection_tracking_specification = optional(object({ + tcp_established_timeout = optional(number) + udp_stream_timeout = optional(number) + udp_timeout = optional(number) + })) + delete_on_termination = optional(bool) + description = optional(string) + device_index = optional(number) + ena_srd_specification = optional(object({ + ena_srd_enabled = optional(bool) + ena_srd_udp_specification = optional(object({ + ena_srd_udp_enabled = optional(bool) + })) + })) + interface_type = optional(string) + ipv4_address_count = optional(number) + ipv4_addresses = optional(list(string)) + ipv4_prefix_count = optional(number) + ipv4_prefixes = optional(list(string)) + ipv6_address_count = optional(number) + ipv6_addresses = optional(list(string)) + ipv6_prefix_count = optional(number) + ipv6_prefixes = optional(list(string)) + network_card_index = optional(number) + network_interface_id = optional(string) + primary_ipv6 = optional(bool) + private_ip_address = optional(string) + security_groups = optional(list(string), []) + subnet_id = optional(string) + })), []) + placement = optional(object({ + affinity = optional(string) + availability_zone = optional(string) + group_name = optional(string) + host_id = optional(string) + host_resource_group_arn = optional(string) + partition_number = optional(number) + spread_domain = optional(string) + tenancy = optional(string) + }), {}) + maintenance_options = optional(object({ + auto_recovery = optional(string) + })) + private_dns_name_options = optional(object({ + enable_resource_name_dns_aaaa_record = optional(bool) + enable_resource_name_dns_a_record = optional(bool) + hostname_type = optional(string) + })) + # IAM role + create_iam_instance_profile = optional(bool, true) + iam_instance_profile_arn = optional(string) + iam_role_name = optional(string) + iam_role_use_name_prefix = optional(bool, true) + iam_role_path = optional(string) + iam_role_description = optional(string, "Self managed node group IAM role") + iam_role_permissions_boundary = optional(string) + iam_role_tags = optional(map(string), {}) + iam_role_attach_cni_policy = optional(bool, true) + iam_role_additional_policies = optional(map(string), {}) + create_iam_role_policy = optional(bool, true) + iam_role_policy_statements = optional(list(object({ + sid = optional(string) + actions = optional(list(string)) + not_actions = optional(list(string)) + effect = optional(string) + resources = optional(list(string)) + not_resources = optional(list(string)) + principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + not_principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + condition = optional(list(object({ + test = string + values = list(string) + variable = string + }))) + }))) + # Access entry + create_access_entry = optional(bool, true) + iam_role_arn = optional(string) + + tags = optional(map(string), {}) + })) + default = {} } variable "self_managed_node_group_defaults" { description = "Map of self-managed node group default configurations" - type = any - default = {} + type = object({ + create = optional(bool) + # Autoscaling Group + create_autoscaling_group = optional(bool) + use_name_prefix = optional(bool) + availability_zones = optional(list(string)) + subnet_ids = optional(list(string)) + min_size = optional(number) + max_size = optional(number) + desired_size = optional(number) + desired_size_type = optional(string) + capacity_rebalance = optional(bool) + min_elb_capacity = optional(number) + wait_for_elb_capacity = optional(number) + default_cooldown = optional(number) + default_instance_warmup = optional(number) + protect_from_scale_in = optional(bool) + context = optional(string) + target_group_arns = optional(list(string)) + create_placement_group = optional(bool) + placement_group = optional(string) + health_check_type = optional(string) + health_check_grace_period = optional(number) + ignore_failed_scaling_activities = optional(number) + force_delete = optional(bool) + force_delete_warm_pool = optional(bool) + termination_policies = optional(list(string)) + suspended_processes = optional(list(string)) + max_instance_lifetime = optional(number) + enabled_metrics = optional(list(string)) + metrics_granularity = optional(string) + service_linked_role_arn = optional(string) + initial_lifecycle_hooks = optional(list(object({ + default_result = optional(string) + heartbeat_timeout = optional(number) + lifecycle_transition = string + name = string + notification_metadata = optional(string) + notification_target_arn = optional(string) + role_arn = optional(string) + }))) + instance_maintenance_policy = optional(object({ + max_healthy_percentage = number + min_healthy_percentage = number + })) + instance_refresh = optional(object({ + preferences = optional(object({ + alarm_specification = optional(object({ + alarms = optional(list(string)) + })) + auto_rollback = optional(bool) + checkpoint_delay = optional(number) + checkpoint_percentages = optional(list(number)) + instance_warmup = optional(number) + max_healthy_percentage = optional(number) + min_healthy_percentage = optional(number) + scale_in_protected_instances = optional(string) + skip_matching = optional(bool) + standby_instances = optional(string) + })) + strategy = optional(string) + triggers = optional(list(string)) + })) + use_mixed_instances_policy = optional(bool) + mixed_instances_policy = optional(object({ + instances_distribution = optional(object({ + on_demand_allocation_strategy = optional(string) + on_demand_base_capacity = optional(number) + on_demand_percentage_above_base_capacity = optional(number) + spot_allocation_strategy = optional(string) + spot_instance_pools = optional(number) + spot_max_price = optional(string) + })) + launch_template = object({ + override = optional(list(object({ + instance_requirements = optional(object({ + accelerator_count = optional(object({ + max = optional(number) + min = optional(number) + })) + accelerator_manufacturers = optional(list(string)) + accelerator_names = optional(list(string)) + accelerator_total_memory_mib = optional(object({ + max = optional(number) + min = optional(number) + })) + accelerator_types = optional(list(string)) + allowed_instance_types = optional(list(string)) + bare_metal = optional(string) + baseline_ebs_bandwidth_mbps = optional(object({ + max = optional(number) + min = optional(number) + })) + burstable_performance = optional(string) + cpu_manufacturers = optional(list(string)) + excluded_instance_types = optional(list(string)) + instance_generations = optional(list(string)) + local_storage = optional(string) + local_storage_types = optional(list(string)) + max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number) + memory_gib_per_vcpu = optional(object({ + max = optional(number) + min = optional(number) + })) + memory_mib = optional(object({ + max = optional(number) + min = optional(number) + })) + network_bandwidth_gbps = optional(object({ + max = optional(number) + min = optional(number) + })) + network_interface_count = optional(object({ + max = optional(number) + min = optional(number) + })) + on_demand_max_price_percentage_over_lowest_price = optional(number) + require_hibernate_support = optional(bool) + spot_max_price_percentage_over_lowest_price = optional(number) + total_local_storage_gb = optional(object({ + max = optional(number) + min = optional(number) + })) + vcpu_count = optional(object({ + max = optional(number) + min = optional(number) + })) + })) + instance_type = optional(string) + launch_template_specification = optional(object({ + launch_template_id = optional(string) + launch_template_name = optional(string) + version = optional(string) + })) + weighted_capacity = optional(string) + }))) + }) + })) + warm_pool = optional(object({ + instance_reuse_policy = optional(object({ + reuse_on_scale_in = optional(bool) + })) + max_group_prepared_capacity = optional(number) + min_size = optional(number) + pool_state = optional(string) + })) + timeouts = optional(object({ + delete = optional(string) + })) + autoscaling_group_tags = optional(map(string)) + # User data + ami_type = optional(string) + additional_cluster_dns_ips = optional(list(string)) + pre_bootstrap_user_data = optional(string) + post_bootstrap_user_data = optional(string) + bootstrap_extra_args = optional(string) + user_data_template_path = optional(string) + cloudinit_pre_nodeadm = optional(list(object({ + content = string + content_type = optional(string) + filename = optional(string) + merge_type = optional(string) + }))) + cloudinit_post_nodeadm = optional(list(object({ + content = string + content_type = optional(string) + filename = optional(string) + merge_type = optional(string) + }))) + # Launch Template + create_launch_template = optional(bool) + use_custom_launch_template = optional(bool) + launch_template_id = optional(string) + launch_template_name = optional(string) + launch_template_use_name_prefix = optional(bool) + launch_template_version = optional(string) + update_launch_template_default_version = optional(bool) + launch_template_description = optional(string) + launch_template_tags = optional(map(string)) + tag_specifications = optional(list(string)) + ebs_optimized = optional(bool) + ami_id = optional(string) + instance_type = optional(string) + key_name = optional(string) + disable_api_termination = optional(bool) + instance_initiated_shutdown_behavior = optional(string) + kernel_id = optional(string) + ram_disk_id = optional(string) + block_device_mappings = optional(map(object({ + device_name = optional(string) + ebs = optional(object({ + delete_on_termination = optional(bool) + encrypted = optional(bool) + iops = optional(number) + kms_key_id = optional(string) + snapshot_id = optional(string) + throughput = optional(number) + volume_initialization_rate = optional(number) + volume_size = optional(number) + volume_type = optional(string) + })) + no_device = optional(string) + virtual_name = optional(string) + }))) + capacity_reservation_specification = optional(object({ + capacity_reservation_preference = optional(string) + capacity_reservation_target = optional(object({ + capacity_reservation_id = optional(string) + capacity_reservation_resource_group_arn = optional(string) + })) + })) + cpu_options = optional(object({ + amd_sev_snp = optional(string) + core_count = optional(number) + threads_per_core = optional(number) + })) + credit_specification = optional(object({ + cpu_credits = optional(string) + })) + enclave_options = optional(object({ + enabled = optional(bool) + })) + hibernation_options = optional(object({ + configured = optional(bool) + })) + instance_requirements = optional(object({ + accelerator_count = optional(object({ + max = optional(number) + min = optional(number) + })) + accelerator_manufacturers = optional(list(string)) + accelerator_names = optional(list(string)) + accelerator_total_memory_mib = optional(object({ + max = optional(number) + min = optional(number) + })) + accelerator_types = optional(list(string)) + allowed_instance_types = optional(list(string)) + bare_metal = optional(string) + baseline_ebs_bandwidth_mbps = optional(object({ + max = optional(number) + min = optional(number) + })) + burstable_performance = optional(string) + cpu_manufacturers = optional(list(string)) + excluded_instance_types = optional(list(string)) + instance_generations = optional(list(string)) + local_storage = optional(string) + local_storage_types = optional(list(string)) + max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number) + memory_gib_per_vcpu = optional(object({ + max = optional(number) + min = optional(number) + })) + memory_mib = optional(object({ + max = optional(number) + min = optional(number) + })) + network_bandwidth_gbps = optional(object({ + max = optional(number) + min = optional(number) + })) + network_interface_count = optional(object({ + max = optional(number) + min = optional(number) + })) + on_demand_max_price_percentage_over_lowest_price = optional(number) + require_hibernate_support = optional(bool) + spot_max_price_percentage_over_lowest_price = optional(number) + total_local_storage_gb = optional(object({ + max = optional(number) + min = optional(number) + })) + vcpu_count = optional(object({ + max = optional(number) + min = string + })) + })) + instance_market_options = optional(object({ + market_type = optional(string) + spot_options = optional(object({ + block_duration_minutes = optional(number) + instance_interruption_behavior = optional(string) + max_price = optional(string) + spot_instance_type = optional(string) + valid_until = optional(string) + })) + })) + license_specifications = optional(list(object({ + license_configuration_arn = string + }))) + metadata_options = optional(object({ + http_endpoint = optional(string) + http_protocol_ipv6 = optional(string) + http_put_response_hop_limit = optional(number) + http_tokens = optional(string) + instance_metadata_tags = optional(string) + })) + enable_monitoring = optional(bool) + enable_efa_support = optional(bool) + enable_efa_only = optional(bool) + efa_indices = optional(list(string)) + network_interfaces = optional(list(object({ + associate_carrier_ip_address = optional(bool) + associate_public_ip_address = optional(bool) + connection_tracking_specification = optional(object({ + tcp_established_timeout = optional(number) + udp_stream_timeout = optional(number) + udp_timeout = optional(number) + })) + delete_on_termination = optional(bool) + description = optional(string) + device_index = optional(number) + ena_srd_specification = optional(object({ + ena_srd_enabled = optional(bool) + ena_srd_udp_specification = optional(object({ + ena_srd_udp_enabled = optional(bool) + })) + })) + interface_type = optional(string) + ipv4_address_count = optional(number) + ipv4_addresses = optional(list(string)) + ipv4_prefix_count = optional(number) + ipv4_prefixes = optional(list(string)) + ipv6_address_count = optional(number) + ipv6_addresses = optional(list(string)) + ipv6_prefix_count = optional(number) + ipv6_prefixes = optional(list(string)) + network_card_index = optional(number) + network_interface_id = optional(string) + primary_ipv6 = optional(bool) + private_ip_address = optional(string) + security_groups = optional(list(string)) + subnet_id = optional(string) + }))) + placement = optional(object({ + affinity = optional(string) + availability_zone = optional(string) + group_name = optional(string) + host_id = optional(string) + host_resource_group_arn = optional(string) + partition_number = optional(number) + spread_domain = optional(string) + tenancy = optional(string) + })) + maintenance_options = optional(object({ + auto_recovery = optional(string) + })) + private_dns_name_options = optional(object({ + enable_resource_name_dns_aaaa_record = optional(bool) + enable_resource_name_dns_a_record = optional(bool) + hostname_type = optional(string) + })) + # IAM role + create_iam_instance_profile = optional(bool) + iam_instance_profile_arn = optional(string) + iam_role_name = optional(string) + iam_role_use_name_prefix = optional(bool) + iam_role_path = optional(string) + iam_role_description = optional(string) + iam_role_permissions_boundary = optional(string) + iam_role_tags = optional(map(string)) + iam_role_attach_cni_policy = optional(bool) + iam_role_additional_policies = optional(map(string)) + create_iam_role_policy = optional(bool) + iam_role_policy_statements = optional(list(object({ + sid = optional(string) + actions = optional(list(string)) + not_actions = optional(list(string)) + effect = optional(string) + resources = optional(list(string)) + not_resources = optional(list(string)) + principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + not_principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + condition = optional(list(object({ + test = string + values = list(string) + variable = string + }))) + }))) + # Access entry + create_access_entry = optional(bool) + iam_role_arn = optional(string) + + tags = optional(map(string)) + }) + default = {} } ################################################################################ @@ -656,14 +1546,465 @@ variable "self_managed_node_group_defaults" { variable "eks_managed_node_groups" { description = "Map of EKS managed node group definitions to create" - type = any - default = {} + type = map(object({ + create = optional(bool, true) + cluster_version = optional(string) + + # EKS Managed Node Group + name = optional(string) # Will fall back to map key + use_name_prefix = optional(bool, true) + subnet_ids = optional(list(string)) + min_size = optional(number, 0) + max_size = optional(number, 3) + desired_size = optional(number, 1) + ami_id = optional(string, "") + ami_type = optional(string, "AL2023_x86_64_STANDARD") + ami_release_version = optional(string) + use_latest_ami_release_version = optional(bool, true) + capacity_type = optional(string, "ON_DEMAND") + disk_size = optional(number) + force_update_version = optional(bool) + instance_types = optional(list(string)) + labels = optional(map(string)) + node_repair_config = optional(object({ + enabled = optional(bool, true) + })) + remote_access = optional(object({ + ec2_ssh_key = optional(string) + source_security_group_ids = optional(list(string)) + })) + taints = optional(map(object({ + key = string + value = optional(string) + effect = string + }))) + update_config = optional(object({ + max_unavailable = optional(number) + max_unavailable_percentage = optional(number) + }), { + max_unavailable_percentage = 33 + }) + timeouts = optional(object({ + create = optional(string) + update = optional(string) + delete = optional(string) + })) + # User data + enable_bootstrap_user_data = optional(bool, false) + pre_bootstrap_user_data = optional(string, "") + post_bootstrap_user_data = optional(string, "") + bootstrap_extra_args = optional(string, "") + user_data_template_path = optional(string, "") + cloudinit_pre_nodeadm = optional(list(object({ + content = string + content_type = optional(string) + filename = optional(string) + merge_type = optional(string) + })), []) + cloudinit_post_nodeadm = optional(list(object({ + content = string + content_type = optional(string) + filename = optional(string) + merge_type = optional(string) + })), []) + # Launch Template + create_launch_template = optional(bool, true) + use_custom_launch_template = optional(bool, true) + launch_template_id = optional(string, "") + launch_template_name = optional(string) # Will fall back to map key + launch_template_use_name_prefix = optional(bool, true) + launch_template_version = optional(string) + update_launch_template_default_version = optional(bool, true) + launch_template_description = optional(string) + launch_template_tags = optional(map(string), {}) + tag_specifications = optional(list(string), ["instance", "volume", "network-interface"]) + ebs_optimized = optional(bool) + key_name = optional(string) + disable_api_termination = optional(bool) + kernel_id = optional(string) + ram_disk_id = optional(string) + block_device_mappings = optional(map(object({ + device_name = optional(string) + ebs = optional(object({ + delete_on_termination = optional(bool) + encrypted = optional(bool) + iops = optional(number) + kms_key_id = optional(string) + snapshot_id = optional(string) + throughput = optional(number) + volume_initialization_rate = optional(number) + volume_size = optional(number) + volume_type = optional(string) + })) + no_device = optional(string) + virtual_name = optional(string) + }))) + capacity_reservation_specification = optional(object({ + capacity_reservation_preference = optional(string) + capacity_reservation_target = optional(object({ + capacity_reservation_id = optional(string) + capacity_reservation_resource_group_arn = optional(string) + })) + })) + cpu_options = optional(object({ + amd_sev_snp = optional(string) + core_count = optional(number) + threads_per_core = optional(number) + })) + credit_specification = optional(object({ + cpu_credits = optional(string) + })) + enclave_options = optional(object({ + enabled = optional(bool) + })) + instance_market_options = optional(object({ + market_type = optional(string) + spot_options = optional(object({ + block_duration_minutes = optional(number) + instance_interruption_behavior = optional(string) + max_price = optional(string) + spot_instance_type = optional(string) + valid_until = optional(string) + })) + })) + license_specifications = optional(list(object({ + license_configuration_arn = string + }))) + metadata_options = optional(object({ + http_endpoint = optional(string, "enabled") + http_protocol_ipv6 = optional(string) + http_put_response_hop_limit = optional(number, 1) + http_tokens = optional(string, "required") + instance_metadata_tags = optional(string) + }), { + http_endpoint = "enabled" + http_put_response_hop_limit = 1 + http_tokens = "required" + }) + enable_monitoring = optional(bool, false) + enable_efa_support = optional(bool, false) + enable_efa_only = optional(bool, true) + efa_indices = optional(list(string), [0]) + create_placement_group = optional(bool, false) + placement = optional(object({ + affinity = optional(string) + availability_zone = optional(string) + group_name = optional(string) + host_id = optional(string) + host_resource_group_arn = optional(string) + partition_number = optional(number) + spread_domain = optional(string) + tenancy = optional(string) + }), {}) + network_interfaces = optional(list(object({ + associate_carrier_ip_address = optional(bool) + associate_public_ip_address = optional(bool) + connection_tracking_specification = optional(object({ + tcp_established_timeout = optional(number) + udp_stream_timeout = optional(number) + udp_timeout = optional(number) + })) + delete_on_termination = optional(bool) + description = optional(string) + device_index = optional(number) + ena_srd_specification = optional(object({ + ena_srd_enabled = optional(bool) + ena_srd_udp_specification = optional(object({ + ena_srd_udp_enabled = optional(bool) + })) + })) + interface_type = optional(string) + ipv4_address_count = optional(number) + ipv4_addresses = optional(list(string)) + ipv4_prefix_count = optional(number) + ipv4_prefixes = optional(list(string)) + ipv6_address_count = optional(number) + ipv6_addresses = optional(list(string)) + ipv6_prefix_count = optional(number) + ipv6_prefixes = optional(list(string)) + network_card_index = optional(number) + network_interface_id = optional(string) + primary_ipv6 = optional(bool) + private_ip_address = optional(string) + security_groups = optional(list(string), []) + subnet_id = optional(string) + })), []) + maintenance_options = optional(object({ + auto_recovery = optional(string) + })) + private_dns_name_options = optional(object({ + enable_resource_name_dns_aaaa_record = optional(bool) + enable_resource_name_dns_a_record = optional(bool) + hostname_type = optional(string) + })) + # IAM role + creat_iam_role = optional(bool, true) + iam_role_arn = optional(string) + iam_role_name = optional(string) + iam_role_use_name_prefix = optional(bool, true) + iam_role_path = optional(string) + iam_role_description = optional(string, "EKS managed node group IAM role") + iam_role_permissions_boundary = optional(string) + iam_role_tags = optional(map(string), {}) + iam_role_attach_cni_policy = optional(bool, true) + iam_role_additional_policies = optional(map(string), {}) + create_iam_role_policy = optional(bool, true) + iam_role_policy_statements = optional(list(object({ + sid = optional(string) + actions = optional(list(string)) + not_actions = optional(list(string)) + effect = optional(string) + resources = optional(list(string)) + not_resources = optional(list(string)) + principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + not_principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + condition = optional(list(object({ + test = string + values = list(string) + variable = string + }))) + }))) + # Security group + vpc_security_group_ids = optional(list(string), []) + cluster_primary_security_group_id = optional(string) + + tags = optional(map(string), {}) + })) + default = {} } variable "eks_managed_node_group_defaults" { description = "Map of EKS managed node group default configurations" - type = any - default = {} + type = object({ + create = optional(bool) + cluster_version = optional(string) + + # EKS Managed Node Group + use_name_prefix = optional(bool) + subnet_ids = optional(list(string)) + min_size = optional(number) + max_size = optional(number) + desired_size = optional(number) + ami_id = optional(string) + ami_type = optional(string) + ami_release_version = optional(string) + use_latest_ami_release_version = optional(bool) + capacity_type = optional(string) + disk_size = optional(number) + force_update_version = optional(bool) + instance_types = optional(list(string)) + labels = optional(map(string)) + node_repair_config = optional(object({ + enabled = optional(bool) + })) + remote_access = optional(object({ + ec2_ssh_key = optional(string) + source_security_group_ids = optional(list(string)) + })) + taints = optional(map(object({ + key = string + value = optional(string) + effect = string + }))) + update_config = optional(object({ + max_unavailable = optional(number) + max_unavailable_percentage = optional(number) + })) + timeouts = optional(object({ + create = optional(string) + update = optional(string) + delete = optional(string) + })) + # User data + enable_bootstrap_user_data = optional(bool) + pre_bootstrap_user_data = optional(string) + post_bootstrap_user_data = optional(string) + bootstrap_extra_args = optional(string) + user_data_template_path = optional(string) + cloudinit_pre_nodeadm = optional(list(object({ + content = string + content_type = optional(string) + filename = optional(string) + merge_type = optional(string) + }))) + cloudinit_post_nodeadm = optional(list(object({ + content = string + content_type = optional(string) + filename = optional(string) + merge_type = optional(string) + }))) + # Launch Template + create_launch_template = optional(bool) + use_custom_launch_template = optional(bool) + launch_template_id = optional(string) + launch_template_name = optional(string) + launch_template_use_name_prefix = optional(bool) + launch_template_version = optional(string) + update_launch_template_default_version = optional(bool) + launch_template_description = optional(string) + launch_template_tags = optional(map(string)) + tag_specifications = optional(list(string)) + ebs_optimized = optional(bool) + key_name = optional(string) + disable_api_termination = optional(bool) + kernel_id = optional(string) + ram_disk_id = optional(string) + block_device_mappings = optional(map(object({ + device_name = optional(string) + ebs = optional(object({ + delete_on_termination = optional(bool) + encrypted = optional(bool) + iops = optional(number) + kms_key_id = optional(string) + snapshot_id = optional(string) + throughput = optional(number) + volume_initialization_rate = optional(number) + volume_size = optional(number) + volume_type = optional(string) + })) + no_device = optional(string) + virtual_name = optional(string) + }))) + capacity_reservation_specification = optional(object({ + capacity_reservation_preference = optional(string) + capacity_reservation_target = optional(object({ + capacity_reservation_id = optional(string) + capacity_reservation_resource_group_arn = optional(string) + })) + })) + cpu_options = optional(object({ + amd_sev_snp = optional(string) + core_count = optional(number) + threads_per_core = optional(number) + })) + credit_specification = optional(object({ + cpu_credits = optional(string) + })) + enclave_options = optional(object({ + enabled = optional(bool) + })) + instance_market_options = optional(object({ + market_type = optional(string) + spot_options = optional(object({ + block_duration_minutes = optional(number) + instance_interruption_behavior = optional(string) + max_price = optional(string) + spot_instance_type = optional(string) + valid_until = optional(string) + })) + })) + license_specifications = optional(list(object({ + license_configuration_arn = string + }))) + metadata_options = optional(object({ + http_endpoint = optional(string) + http_protocol_ipv6 = optional(string) + http_put_response_hop_limit = optional(number) + http_tokens = optional(string) + instance_metadata_tags = optional(string) + })) + enable_monitoring = optional(bool) + enable_efa_support = optional(bool) + enable_efa_only = optional(bool) + efa_indices = optional(list(string)) + create_placement_group = optional(bool) + placement = optional(object({ + affinity = optional(string) + availability_zone = optional(string) + group_name = optional(string) + host_id = optional(string) + host_resource_group_arn = optional(string) + partition_number = optional(number) + spread_domain = optional(string) + tenancy = optional(string) + })) + network_interfaces = optional(list(object({ + associate_carrier_ip_address = optional(bool) + associate_public_ip_address = optional(bool) + connection_tracking_specification = optional(object({ + tcp_established_timeout = optional(number) + udp_stream_timeout = optional(number) + udp_timeout = optional(number) + })) + delete_on_termination = optional(bool) + description = optional(string) + device_index = optional(number) + ena_srd_specification = optional(object({ + ena_srd_enabled = optional(bool) + ena_srd_udp_specification = optional(object({ + ena_srd_udp_enabled = optional(bool) + })) + })) + interface_type = optional(string) + ipv4_address_count = optional(number) + ipv4_addresses = optional(list(string)) + ipv4_prefix_count = optional(number) + ipv4_prefixes = optional(list(string)) + ipv6_address_count = optional(number) + ipv6_addresses = optional(list(string)) + ipv6_prefix_count = optional(number) + ipv6_prefixes = optional(list(string)) + network_card_index = optional(number) + network_interface_id = optional(string) + primary_ipv6 = optional(bool) + private_ip_address = optional(string) + security_groups = optional(list(string)) + subnet_id = optional(string) + }))) + maintenance_options = optional(object({ + auto_recovery = optional(string) + })) + private_dns_name_options = optional(object({ + enable_resource_name_dns_aaaa_record = optional(bool) + enable_resource_name_dns_a_record = optional(bool) + hostname_type = optional(string) + })) + # IAM role + creat_iam_role = optional(bool) + iam_role_arn = optional(string) + iam_role_name = optional(string) + iam_role_use_name_prefix = optional(bool) + iam_role_path = optional(string) + iam_role_description = optional(string) + iam_role_permissions_boundary = optional(string) + iam_role_tags = optional(map(string)) + iam_role_attach_cni_policy = optional(bool) + iam_role_additional_policies = optional(map(string)) + create_iam_role_policy = optional(bool) + iam_role_policy_statements = optional(list(object({ + sid = optional(string) + actions = optional(list(string)) + not_actions = optional(list(string)) + effect = optional(string) + resources = optional(list(string)) + not_resources = optional(list(string)) + principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + not_principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + condition = optional(list(object({ + test = string + values = list(string) + variable = string + }))) + }))) + # Security group + vpc_security_group_ids = optional(list(string)) + cluster_primary_security_group_id = optional(string) + + tags = optional(map(string), {}) + }) + default = {} } variable "putin_khuylo" { From eb26ecb9c4fb07b738ffa99b4e37c66299c134e3 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Wed, 9 Jul 2025 11:05:41 -0500 Subject: [PATCH 10/25] feat: Bump KMS key module version to latest, add remaining variable attribute definitions --- README.md | 28 ++++----- main.tf | 155 +++++++++++++++++++++++++++-------------------- node_groups.tf | 25 ++++---- scratch/main.tf | 20 ------- variables.tf | 156 +++++++++++++++++++++++++++++++++++++++--------- 5 files changed, 241 insertions(+), 143 deletions(-) delete mode 100644 scratch/main.tf diff --git a/README.md b/README.md index f9e8bcac1a..8b51f52e51 100644 --- a/README.md +++ b/README.md @@ -336,7 +336,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple |------|--------|---------| | [eks\_managed\_node\_group](#module\_eks\_managed\_node\_group) | ./modules/eks-managed-node-group | n/a | | [fargate\_profile](#module\_fargate\_profile) | ./modules/fargate-profile | n/a | -| [kms](#module\_kms) | terraform-aws-modules/kms/aws | 2.1.0 | +| [kms](#module\_kms) | terraform-aws-modules/kms/aws | 4.0.0 | | [self\_managed\_node\_group](#module\_self\_managed\_node\_group) | ./modules/self-managed-node-group | n/a | ## Resources @@ -382,7 +382,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [access\_entries](#input\_access\_entries) | Map of access entries to add to the cluster | `any` | `{}` | no | +| [access\_entries](#input\_access\_entries) | Map of access entries to add to the cluster |
map(object({
# Access entry
kubernetes_groups = optional(list(string))
principal_arn = string
type = optional(string, "STANDARD")
user_name = optional(string)
tags = optional(map(string), {})
# Access policy association
policy_associations = optional(map(object({
policy_arn = string
access_scope = object({
type = string
})
namespaces = optional(list(string))
})), {})
}))
| `{}` | no | | [attach\_cluster\_encryption\_policy](#input\_attach\_cluster\_encryption\_policy) | Indicates whether or not to attach an additional policy for the cluster IAM role to utilize the encryption key provided | `bool` | `true` | no | | [authentication\_mode](#input\_authentication\_mode) | The authentication mode for the cluster. Valid values are `CONFIG_MAP`, `API` or `API_AND_CONFIG_MAP` | `string` | `"API_AND_CONFIG_MAP"` | no | | [cloudwatch\_log\_group\_class](#input\_cloudwatch\_log\_group\_class) | Specified the log class of the log group. Possible values are: `STANDARD` or `INFREQUENT_ACCESS` | `string` | `null` | no | @@ -390,11 +390,11 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [cloudwatch\_log\_group\_retention\_in\_days](#input\_cloudwatch\_log\_group\_retention\_in\_days) | Number of days to retain log events. Default retention - 90 days | `number` | `90` | no | | [cloudwatch\_log\_group\_tags](#input\_cloudwatch\_log\_group\_tags) | A map of additional tags to add to the cloudwatch log group created | `map(string)` | `{}` | no | | [cluster\_additional\_security\_group\_ids](#input\_cluster\_additional\_security\_group\_ids) | List of additional, externally created security group IDs to attach to the cluster control plane | `list(string)` | `[]` | no | -| [cluster\_addons](#input\_cluster\_addons) | Map of cluster addon configurations to enable for the cluster. Addon name can be the map keys or set with `name` | `any` | `{}` | no | -| [cluster\_addons\_timeouts](#input\_cluster\_addons\_timeouts) | Create, update, and delete timeout configurations for the cluster addons | `map(string)` | `{}` | no | -| [cluster\_compute\_config](#input\_cluster\_compute\_config) | Configuration block for the cluster compute configuration | `any` | `{}` | no | +| [cluster\_addons](#input\_cluster\_addons) | Map of cluster addon configurations to enable for the cluster. Addon name can be the map keys or set with `name` |
map(object({
name = optional(string) # will fall back to map key
before_compute = optional(bool, false)
most_recent = optional(bool, true)
addon_version = optional(string)
configuration_values = optional(string)
pod_identity_association = optional(list(object({
role_arn = string
service_account = string
})))
preserve = optional(bool, true)
resolve_conflicts_on_create = optional(string, "NONE")
resolve_conflicts_on_update = optional(string, "OVERWRITE")
service_account_role_arn = optional(string)
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
tags = optional(map(string), {})
}))
| `null` | no | +| [cluster\_addons\_timeouts](#input\_cluster\_addons\_timeouts) | Create, update, and delete timeout configurations for the cluster addons |
object({
create = optional(string)
update = optional(string)
delete = optional(string)
})
| `null` | no | +| [cluster\_compute\_config](#input\_cluster\_compute\_config) | Configuration block for the cluster compute configuration |
object({
enabled = optional(bool, false)
node_pools = optional(list(string))
node_role_arn = optional(string)
})
| `null` | no | | [cluster\_enabled\_log\_types](#input\_cluster\_enabled\_log\_types) | A list of the desired control plane logs to enable. For more information, see Amazon EKS Control Plane Logging documentation (https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html) | `list(string)` |
[
"audit",
"api",
"authenticator"
]
| no | -| [cluster\_encryption\_config](#input\_cluster\_encryption\_config) | Configuration block with encryption configuration for the cluster. To disable secret encryption, set this value to `{}` | `any` |
{
"resources": [
"secrets"
]
}
| no | +| [cluster\_encryption\_config](#input\_cluster\_encryption\_config) | Configuration block with encryption configuration for the cluster |
object({
provider_key_arn = optional(string)
resources = optional(list(string), ["secrets"])
})
| `{}` | no | | [cluster\_encryption\_policy\_description](#input\_cluster\_encryption\_policy\_description) | Description of the cluster encryption policy created | `string` | `"Cluster encryption policy to allow cluster role to utilize CMK provided"` | no | | [cluster\_encryption\_policy\_name](#input\_cluster\_encryption\_policy\_name) | Name to use on cluster encryption policy created | `string` | `null` | no | | [cluster\_encryption\_policy\_path](#input\_cluster\_encryption\_policy\_path) | Cluster encryption policy path | `string` | `null` | no | @@ -404,11 +404,11 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [cluster\_endpoint\_public\_access](#input\_cluster\_endpoint\_public\_access) | Indicates whether or not the Amazon EKS public API server endpoint is enabled | `bool` | `false` | no | | [cluster\_endpoint\_public\_access\_cidrs](#input\_cluster\_endpoint\_public\_access\_cidrs) | List of CIDR blocks which can access the Amazon EKS public API server endpoint | `list(string)` |
[
"0.0.0.0/0"
]
| no | | [cluster\_force\_update\_version](#input\_cluster\_force\_update\_version) | Force version update by overriding upgrade-blocking readiness checks when updating a cluster | `bool` | `null` | no | -| [cluster\_identity\_providers](#input\_cluster\_identity\_providers) | Map of cluster identity provider configurations to enable for the cluster. Note - this is different/separate from IRSA | `any` | `{}` | no | +| [cluster\_identity\_providers](#input\_cluster\_identity\_providers) | Map of cluster identity provider configurations to enable for the cluster. Note - this is different/separate from IRSA |
map(object({
client_id = string
groups_claim = optional(string)
groups_prefix = optional(string)
identity_provider_config_name = optional(string) # will fall back to map key
issuer_url = string
required_claims = optional(map(string))
username_claim = optional(string)
username_prefix = optional(string)
}))
| `null` | no | | [cluster\_ip\_family](#input\_cluster\_ip\_family) | The IP family used to assign Kubernetes pod and service addresses. Valid values are `ipv4` (default) and `ipv6`. You can only specify an IP family when you create a cluster, changing this value will force a new cluster to be created | `string` | `"ipv4"` | no | | [cluster\_name](#input\_cluster\_name) | Name of the EKS cluster | `string` | `""` | no | -| [cluster\_remote\_network\_config](#input\_cluster\_remote\_network\_config) | Configuration block for the cluster remote network configuration | `any` | `{}` | no | -| [cluster\_security\_group\_additional\_rules](#input\_cluster\_security\_group\_additional\_rules) | List of additional security group rules to add to the cluster security group created. Set `source_node_security_group = true` inside rules to set the `node_security_group` as source | `any` | `{}` | no | +| [cluster\_remote\_network\_config](#input\_cluster\_remote\_network\_config) | Configuration block for the cluster remote network configuration |
object({
remote_node_networks = object({
cidrs = optional(list(string))
})
remote_pod_networks = optional(object({
cidrs = optional(list(string))
}))
})
| `null` | no | +| [cluster\_security\_group\_additional\_rules](#input\_cluster\_security\_group\_additional\_rules) | List of additional security group rules to add to the cluster security group created. Set `source_node_security_group = true` inside rules to set the `node_security_group` as source |
map(object({
protocol = optional(string, "tcp")
from_port = number
to_port = number
type = optional(string, "ingress")
description = optional(string)
cidr_blocks = optional(list(string))
ipv6_cidr_blocks = optional(list(string))
prefix_list_ids = optional(list(string))
self = optional(bool)
source_node_security_group = optional(bool, false)
source_security_group_id = optional(string)
}))
| `{}` | no | | [cluster\_security\_group\_description](#input\_cluster\_security\_group\_description) | Description of the cluster security group created | `string` | `"EKS cluster security group"` | no | | [cluster\_security\_group\_id](#input\_cluster\_security\_group\_id) | Existing security group ID to be attached to the cluster | `string` | `""` | no | | [cluster\_security\_group\_name](#input\_cluster\_security\_group\_name) | Name to use on cluster security group created | `string` | `null` | no | @@ -417,10 +417,10 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [cluster\_service\_ipv4\_cidr](#input\_cluster\_service\_ipv4\_cidr) | The CIDR block to assign Kubernetes service IP addresses from. If you don't specify a block, Kubernetes assigns addresses from either the 10.100.0.0/16 or 172.20.0.0/16 CIDR blocks | `string` | `null` | no | | [cluster\_service\_ipv6\_cidr](#input\_cluster\_service\_ipv6\_cidr) | The CIDR block to assign Kubernetes pod and service IP addresses from if `ipv6` was specified when the cluster was created. Kubernetes assigns service addresses from the unique local address range (fc00::/7) because you can't specify a custom IPv6 CIDR block when you create the cluster | `string` | `null` | no | | [cluster\_tags](#input\_cluster\_tags) | A map of additional tags to add to the cluster | `map(string)` | `{}` | no | -| [cluster\_timeouts](#input\_cluster\_timeouts) | Create, update, and delete timeout configurations for the cluster | `map(string)` | `{}` | no | -| [cluster\_upgrade\_policy](#input\_cluster\_upgrade\_policy) | Configuration block for the cluster upgrade policy | `any` | `{}` | no | +| [cluster\_timeouts](#input\_cluster\_timeouts) | Create, update, and delete timeout configurations for the cluster |
object({
create = optional(string)
update = optional(string)
delete = optional(string)
})
| `null` | no | +| [cluster\_upgrade\_policy](#input\_cluster\_upgrade\_policy) | Configuration block for the cluster upgrade policy |
object({
support_type = optional(string)
})
| `null` | no | | [cluster\_version](#input\_cluster\_version) | Kubernetes `.` version to use for the EKS cluster (i.e.: `1.27`) | `string` | `null` | no | -| [cluster\_zonal\_shift\_config](#input\_cluster\_zonal\_shift\_config) | Configuration block for the cluster zonal shift | `any` | `{}` | no | +| [cluster\_zonal\_shift\_config](#input\_cluster\_zonal\_shift\_config) | Configuration block for the cluster zonal shift |
object({
enabled = optional(bool)
})
| `null` | no | | [control\_plane\_subnet\_ids](#input\_control\_plane\_subnet\_ids) | A list of subnet IDs where the EKS cluster control plane (ENIs) will be provisioned. Used for expanding the pool of subnets used by nodes/node groups without replacing the EKS control plane | `list(string)` | `[]` | no | | [create](#input\_create) | Controls if resources should be created (affects nearly all resources) | `bool` | `true` | no | | [create\_cloudwatch\_log\_group](#input\_create\_cloudwatch\_log\_group) | Determines whether a log group is created by this module for the cluster logs. If not, AWS will automatically create one if logging is enabled | `bool` | `true` | no | @@ -468,7 +468,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [node\_iam\_role\_permissions\_boundary](#input\_node\_iam\_role\_permissions\_boundary) | ARN of the policy that is used to set the permissions boundary for the EKS Auto node IAM role | `string` | `null` | no | | [node\_iam\_role\_tags](#input\_node\_iam\_role\_tags) | A map of additional tags to add to the EKS Auto node IAM role created | `map(string)` | `{}` | no | | [node\_iam\_role\_use\_name\_prefix](#input\_node\_iam\_role\_use\_name\_prefix) | Determines whether the EKS Auto node IAM role name (`node_iam_role_name`) is used as a prefix | `bool` | `true` | no | -| [node\_security\_group\_additional\_rules](#input\_node\_security\_group\_additional\_rules) | List of additional security group rules to add to the node security group created. Set `source_cluster_security_group = true` inside rules to set the `cluster_security_group` as source | `any` | `{}` | no | +| [node\_security\_group\_additional\_rules](#input\_node\_security\_group\_additional\_rules) | List of additional security group rules to add to the node security group created. Set `source_cluster_security_group = true` inside rules to set the `cluster_security_group` as source |
map(object({
protocol = optional(string, "tcp")
from_port = number
to_port = number
type = optional(string, "ingress")
description = optional(string)
cidr_blocks = optional(list(string))
ipv6_cidr_blocks = optional(list(string))
prefix_list_ids = optional(list(string))
self = optional(bool)
source_cluster_security_group = optional(bool, false)
source_security_group_id = optional(string)
}))
| `{}` | no | | [node\_security\_group\_description](#input\_node\_security\_group\_description) | Description of the node security group created | `string` | `"EKS node shared security group"` | no | | [node\_security\_group\_enable\_recommended\_rules](#input\_node\_security\_group\_enable\_recommended\_rules) | Determines whether to enable recommended security group rules for the node security group created. This includes node-to-node TCP ingress on ephemeral ports and allows all egress traffic | `bool` | `true` | no | | [node\_security\_group\_id](#input\_node\_security\_group\_id) | ID of an existing security group to attach to the node groups created | `string` | `""` | no | @@ -476,7 +476,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [node\_security\_group\_tags](#input\_node\_security\_group\_tags) | A map of additional tags to add to the node security group created | `map(string)` | `{}` | no | | [node\_security\_group\_use\_name\_prefix](#input\_node\_security\_group\_use\_name\_prefix) | Determines whether node security group name (`node_security_group_name`) is used as a prefix | `bool` | `true` | no | | [openid\_connect\_audiences](#input\_openid\_connect\_audiences) | List of OpenID Connect audience client IDs to add to the IRSA provider | `list(string)` | `[]` | no | -| [outpost\_config](#input\_outpost\_config) | Configuration for the AWS Outpost to provision the cluster on | `any` | `{}` | no | +| [outpost\_config](#input\_outpost\_config) | Configuration for the AWS Outpost to provision the cluster on |
object({
control_plane_instance_type = optional(string)
control_plane_placement = optional(object({
group_name = string
}))
outpost_arns = list(string)
})
| `null` | no | | [prefix\_separator](#input\_prefix\_separator) | The separator to use between the prefix and the generated timestamp for resource names | `string` | `"-"` | no | | [putin\_khuylo](#input\_putin\_khuylo) | Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo! | `bool` | `true` | no | | [self\_managed\_node\_group\_defaults](#input\_self\_managed\_node\_group\_defaults) | Map of self-managed node group default configurations |
object({
create = optional(bool)
# Autoscaling Group
create_autoscaling_group = optional(bool)
use_name_prefix = optional(bool)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool)
context = optional(string)
target_group_arns = optional(list(string))
create_placement_group = optional(bool)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(number)
force_delete = optional(bool)
force_delete_warm_pool = optional(bool)
termination_policies = optional(list(string))
suspended_processes = optional(list(string))
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string))
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string)
triggers = optional(list(string))
}))
use_mixed_instances_policy = optional(bool)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
warm_pool = optional(object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string))
# User data
ami_type = optional(string)
additional_cluster_dns_ips = optional(list(string))
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string)
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
hibernation_options = optional(object({
configured = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool)
iam_role_arn = optional(string)

tags = optional(map(string))
})
| `{}` | no | diff --git a/main.tf b/main.tf index 63891561d2..a6383c6171 100644 --- a/main.tf +++ b/main.tf @@ -23,7 +23,7 @@ locals { cluster_role = try(aws_iam_role.this[0].arn, var.iam_role_arn) - create_outposts_local_cluster = length(var.outpost_config) > 0 + create_outposts_local_cluster = var.outpost_config != null enable_cluster_encryption_config = length(var.cluster_encryption_config) > 0 && !local.create_outposts_local_cluster auto_mode_enabled = try(var.cluster_compute_config.enabled, false) @@ -55,12 +55,12 @@ resource "aws_eks_cluster" "this" { } dynamic "compute_config" { - for_each = length(var.cluster_compute_config) > 0 ? [var.cluster_compute_config] : [] + for_each = var.cluster_compute_config != null ? [var.cluster_compute_config] : [] content { - enabled = local.auto_mode_enabled - node_pools = local.auto_mode_enabled ? try(compute_config.value.node_pools, []) : null - node_role_arn = local.auto_mode_enabled && length(try(compute_config.value.node_pools, [])) > 0 ? try(compute_config.value.node_role_arn, aws_iam_role.eks_auto[0].arn, null) : null + enabled = compute_config.value.enabled + node_pools = compute_config.value.node_pools + node_role_arn = try(compute_config.value.node_pools, []) > 0 ? try(compute_config.value.node_role_arn, aws_iam_role.eks_auto[0].arn, null) : null } } @@ -96,7 +96,16 @@ resource "aws_eks_cluster" "this" { content { control_plane_instance_type = outpost_config.value.control_plane_instance_type - outpost_arns = outpost_config.value.outpost_arns + + dynamic "control_plane_placement" { + for_each = outpost_config.value.control_plane_placement != null ? [outpost_config.value.control_plane_placement] : [] + + content { + group_name = control_plane_placement.value.group_name + } + } + + outpost_arns = outpost_config.value.outpost_arns } } @@ -114,7 +123,7 @@ resource "aws_eks_cluster" "this" { dynamic "remote_network_config" { # Not valid on Outposts - for_each = length(var.cluster_remote_network_config) > 0 && !local.create_outposts_local_cluster ? [var.cluster_remote_network_config] : [] + for_each = var.cluster_remote_network_config != null && !local.create_outposts_local_cluster ? [var.cluster_remote_network_config] : [] content { dynamic "remote_node_networks" { @@ -126,7 +135,7 @@ resource "aws_eks_cluster" "this" { } dynamic "remote_pod_networks" { - for_each = try([remote_network_config.value.remote_pod_networks], []) + for_each = remote_network_config.value.remote_pod_networks != null ? [remote_network_config.value.remote_pod_networks] : [] content { cidrs = remote_pod_networks.value.cidrs @@ -146,18 +155,18 @@ resource "aws_eks_cluster" "this" { } dynamic "upgrade_policy" { - for_each = length(var.cluster_upgrade_policy) > 0 ? [var.cluster_upgrade_policy] : [] + for_each = var.cluster_upgrade_policy != null ? [var.cluster_upgrade_policy] : [] content { - support_type = try(upgrade_policy.value.support_type, null) + support_type = upgrade_policy.value.support_type } } dynamic "zonal_shift_config" { - for_each = length(var.cluster_zonal_shift_config) > 0 ? [var.cluster_zonal_shift_config] : [] + for_each = var.cluster_zonal_shift_config != null ? [var.cluster_zonal_shift_config] : [] content { - enabled = try(zonal_shift_config.value.enabled, null) + enabled = zonal_shift_config.value.enabled } } @@ -167,10 +176,14 @@ resource "aws_eks_cluster" "this" { var.cluster_tags, ) - timeouts { - create = try(var.cluster_timeouts.create, null) - update = try(var.cluster_timeouts.update, null) - delete = try(var.cluster_timeouts.delete, null) + dynamic "timeouts" { + for_each = var.cluster_timeouts != null ? [var.cluster_timeouts] : [] + + content { + create = var.cluster_timeouts.create + update = var.cluster_timeouts.update + delete = var.cluster_timeouts.delete + } } depends_on = [ @@ -249,7 +262,7 @@ locals { # associations within a single entry flattened_access_entries = flatten([ for entry_key, entry_val in local.merged_access_entries : [ - for pol_key, pol_val in lookup(entry_val, "policy_associations", {}) : + for pol_key, pol_val in try(entry_val.policy_associations, {}) : merge( { principal_arn = entry_val.principal_arn @@ -259,7 +272,7 @@ locals { { for k, v in { association_policy_arn = pol_val.policy_arn association_access_scope_type = pol_val.access_scope.type - association_access_scope_namespaces = lookup(pol_val.access_scope, "namespaces", []) + association_access_scope_namespaces = try(pol_val.access_scope.namespaces, null) } : k => v if !contains(["EC2_LINUX", "EC2_WINDOWS", "FARGATE_LINUX", "HYBRID_LINUX"], lookup(entry_val, "type", "STANDARD")) }, ) ] @@ -270,19 +283,22 @@ resource "aws_eks_access_entry" "this" { for_each = { for k, v in local.merged_access_entries : k => v if local.create } cluster_name = aws_eks_cluster.this[0].id - kubernetes_groups = try(each.value.kubernetes_groups, null) + kubernetes_groups = each.value.kubernetes_groups principal_arn = each.value.principal_arn - type = try(each.value.type, "STANDARD") - user_name = try(each.value.user_name, null) + type = each.value.type + user_name = each.value.user_name - tags = merge(var.tags, try(each.value.tags, {})) + tags = merge( + var.tags, + each.value.tags, + ) } resource "aws_eks_access_policy_association" "this" { for_each = { for k, v in local.flattened_access_entries : "${v.entry_key}_${v.pol_key}" => v if local.create } access_scope { - namespaces = try(each.value.association_access_scope_namespaces, []) + namespaces = each.value.association_access_scope_namespaces type = each.value.association_access_scope_type } @@ -302,7 +318,7 @@ resource "aws_eks_access_policy_association" "this" { module "kms" { source = "terraform-aws-modules/kms/aws" - version = "2.1.0" # Note - be mindful of Terraform/provider version compatibility between modules + version = "4.0.0" # Note - be mindful of Terraform/provider version compatibility between modules create = local.create && var.create_kms_key && local.enable_cluster_encryption_config # not valid on Outposts @@ -382,20 +398,17 @@ resource "aws_security_group_rule" "cluster" { var.cluster_security_group_additional_rules ) : k => v if local.create_cluster_sg } - # Required - security_group_id = aws_security_group.cluster[0].id - protocol = each.value.protocol - from_port = each.value.from_port - to_port = each.value.to_port - type = each.value.type - - # Optional - description = lookup(each.value, "description", null) - cidr_blocks = lookup(each.value, "cidr_blocks", null) - ipv6_cidr_blocks = lookup(each.value, "ipv6_cidr_blocks", null) - prefix_list_ids = lookup(each.value, "prefix_list_ids", null) - self = lookup(each.value, "self", null) - source_security_group_id = try(each.value.source_node_security_group, false) ? local.node_security_group_id : lookup(each.value, "source_security_group_id", null) + security_group_id = aws_security_group.cluster[0].id + protocol = each.value.protocol + from_port = each.value.from_port + to_port = each.value.to_port + type = each.value.type + description = each.value.description + cidr_blocks = each.value.cidr_blocks + ipv6_cidr_blocks = each.value.ipv6_cidr_blocks + prefix_list_ids = each.value.prefix_list_ids + self = each.value.self + source_security_group_id = each.value.source_node_security_group ? local.node_security_group_id : each.value.source_security_group_id } ################################################################################ @@ -718,25 +731,25 @@ resource "aws_iam_role_policy_attachment" "custom" { ################################################################################ data "aws_eks_addon_version" "this" { - for_each = { for k, v in var.cluster_addons : k => v if local.create && !local.create_outposts_local_cluster } + for_each = var.cluster_addons != null && local.create && !local.create_outposts_local_cluster ? var.cluster_addons : {} addon_name = try(each.value.name, each.key) kubernetes_version = coalesce(var.cluster_version, aws_eks_cluster.this[0].version) - most_recent = try(each.value.most_recent, true) + most_recent = each.value.most_recent } resource "aws_eks_addon" "this" { # Not supported on outposts - for_each = { for k, v in var.cluster_addons : k => v if !try(v.before_compute, false) && local.create && !local.create_outposts_local_cluster } + for_each = var.cluster_addons != null && local.create && !local.create_outposts_local_cluster ? { for k, v in var.cluster_addons : k => v if !v.before_compute } : {} cluster_name = aws_eks_cluster.this[0].id addon_name = try(each.value.name, each.key) - addon_version = coalesce(try(each.value.addon_version, null), data.aws_eks_addon_version.this[each.key].version) - configuration_values = try(each.value.configuration_values, null) + addon_version = try(each.value.addon_version, data.aws_eks_addon_version.this[each.key].version) + configuration_values = each.value.configuration_values dynamic "pod_identity_association" { - for_each = try(each.value.pod_identity_association, []) + for_each = each.value.pod_identity_association != null ? each.value.pod_identity_association : [] content { role_arn = pod_identity_association.value.role_arn @@ -744,10 +757,10 @@ resource "aws_eks_addon" "this" { } } - preserve = try(each.value.preserve, true) - resolve_conflicts_on_create = try(each.value.resolve_conflicts_on_create, "NONE") - resolve_conflicts_on_update = try(each.value.resolve_conflicts_on_update, "OVERWRITE") - service_account_role_arn = try(each.value.service_account_role_arn, null) + preserve = each.value.preserve + resolve_conflicts_on_create = each.value.resolve_conflicts_on_create + resolve_conflicts_on_update = each.value.resolve_conflicts_on_update + service_account_role_arn = each.value.service_account_role_arn timeouts { create = try(each.value.timeouts.create, var.cluster_addons_timeouts.create, null) @@ -755,27 +768,31 @@ resource "aws_eks_addon" "this" { delete = try(each.value.timeouts.delete, var.cluster_addons_timeouts.delete, null) } + tags = merge( + var.tags, + each.value.tags, + ) + + # before_compute = false depends_on = [ module.fargate_profile, module.eks_managed_node_group, module.self_managed_node_group, ] - - tags = merge(var.tags, try(each.value.tags, {})) } resource "aws_eks_addon" "before_compute" { # Not supported on outposts - for_each = { for k, v in var.cluster_addons : k => v if try(v.before_compute, false) && local.create && !local.create_outposts_local_cluster } + for_each = var.cluster_addons != null && local.create && !local.create_outposts_local_cluster ? { for k, v in var.cluster_addons : k => v if v.before_compute } : {} cluster_name = aws_eks_cluster.this[0].id addon_name = try(each.value.name, each.key) - addon_version = coalesce(try(each.value.addon_version, null), data.aws_eks_addon_version.this[each.key].version) - configuration_values = try(each.value.configuration_values, null) + addon_version = try(each.value.addon_version, data.aws_eks_addon_version.this[each.key].version) + configuration_values = each.value.configuration_values dynamic "pod_identity_association" { - for_each = try(each.value.pod_identity_association, []) + for_each = each.value.pod_identity_association != null ? each.value.pod_identity_association : [] content { role_arn = pod_identity_association.value.role_arn @@ -783,10 +800,10 @@ resource "aws_eks_addon" "before_compute" { } } - preserve = try(each.value.preserve, true) - resolve_conflicts_on_create = try(each.value.resolve_conflicts_on_create, "NONE") - resolve_conflicts_on_update = try(each.value.resolve_conflicts_on_update, "OVERWRITE") - service_account_role_arn = try(each.value.service_account_role_arn, null) + preserve = each.value.preserve + resolve_conflicts_on_create = each.value.resolve_conflicts_on_create + resolve_conflicts_on_update = each.value.resolve_conflicts_on_update + service_account_role_arn = each.value.service_account_role_arn timeouts { create = try(each.value.timeouts.create, var.cluster_addons_timeouts.create, null) @@ -794,7 +811,10 @@ resource "aws_eks_addon" "before_compute" { delete = try(each.value.timeouts.delete, var.cluster_addons_timeouts.delete, null) } - tags = merge(var.tags, try(each.value.tags, {})) + tags = merge( + var.tags, + each.value.tags, + ) } ################################################################################ @@ -803,22 +823,25 @@ resource "aws_eks_addon" "before_compute" { ################################################################################ resource "aws_eks_identity_provider_config" "this" { - for_each = { for k, v in var.cluster_identity_providers : k => v if local.create && !local.create_outposts_local_cluster } + for_each = var.cluster_identity_providers != null && local.create && !local.create_outposts_local_cluster ? var.cluster_identity_providers : {} cluster_name = aws_eks_cluster.this[0].id oidc { client_id = each.value.client_id - groups_claim = lookup(each.value, "groups_claim", null) - groups_prefix = lookup(each.value, "groups_prefix", null) + groups_claim = each.value.groups_claim + groups_prefix = each.value.groups_prefix identity_provider_config_name = try(each.value.identity_provider_config_name, each.key) issuer_url = each.value.issuer_url - required_claims = lookup(each.value, "required_claims", null) - username_claim = lookup(each.value, "username_claim", null) - username_prefix = lookup(each.value, "username_prefix", null) + required_claims = each.value.required_claims + username_claim = each.value.username_claim + username_prefix = each.value.username_prefix } - tags = merge(var.tags, try(each.value.tags, {})) + tags = merge( + var.tags, + each.value.tags, + ) } ################################################################################ diff --git a/node_groups.tf b/node_groups.tf index 517cd9080f..f9874dc448 100644 --- a/node_groups.tf +++ b/node_groups.tf @@ -216,20 +216,17 @@ resource "aws_security_group_rule" "node" { var.node_security_group_additional_rules, ) : k => v if local.create_node_sg } - # Required - security_group_id = aws_security_group.node[0].id - protocol = each.value.protocol - from_port = each.value.from_port - to_port = each.value.to_port - type = each.value.type - - # Optional - description = lookup(each.value, "description", null) - cidr_blocks = lookup(each.value, "cidr_blocks", null) - ipv6_cidr_blocks = lookup(each.value, "ipv6_cidr_blocks", null) - prefix_list_ids = lookup(each.value, "prefix_list_ids", []) - self = lookup(each.value, "self", null) - source_security_group_id = try(each.value.source_cluster_security_group, false) ? local.cluster_security_group_id : lookup(each.value, "source_security_group_id", null) + security_group_id = aws_security_group.node[0].id + protocol = each.value.protocol + from_port = each.value.from_port + to_port = each.value.to_port + type = each.value.type + description = each.value.description + cidr_blocks = each.value.cidr_blocks + ipv6_cidr_blocks = each.value.ipv6_cidr_blocks + prefix_list_ids = each.value.prefix_list_ids + self = each.value.self + source_security_group_id = each.value.source_cluster_security_group ? local.cluster_security_group_id : each.value.source_security_group_id } ################################################################################ diff --git a/scratch/main.tf b/scratch/main.tf deleted file mode 100644 index f1786814e0..0000000000 --- a/scratch/main.tf +++ /dev/null @@ -1,20 +0,0 @@ -variable "tags" { - description = "The first variable" - type = map(string) - default = {} -} - -variable "one" { - description = "The first variable" - type = object({ - tags = optional(map(string), {}) - }) - default = {} -} - -output "something" { - value = merge( - var.tags, - var.one.tags, - ) -} \ No newline at end of file diff --git a/variables.tf b/variables.tf index 8fe96283a7..9ff278ed02 100644 --- a/variables.tf +++ b/variables.tf @@ -52,26 +52,41 @@ variable "authentication_mode" { variable "cluster_compute_config" { description = "Configuration block for the cluster compute configuration" - type = any - default = {} + type = object({ + enabled = optional(bool, false) + node_pools = optional(list(string)) + node_role_arn = optional(string) + }) + default = null } variable "cluster_upgrade_policy" { description = "Configuration block for the cluster upgrade policy" - type = any - default = {} + type = object({ + support_type = optional(string) + }) + default = null } variable "cluster_remote_network_config" { description = "Configuration block for the cluster remote network configuration" - type = any - default = {} + type = object({ + remote_node_networks = object({ + cidrs = optional(list(string)) + }) + remote_pod_networks = optional(object({ + cidrs = optional(list(string)) + })) + }) + default = null } variable "cluster_zonal_shift_config" { description = "Configuration block for the cluster zonal shift" - type = any - default = {} + type = object({ + enabled = optional(bool) + }) + default = null } variable "cluster_additional_security_group_ids" { @@ -130,16 +145,23 @@ variable "cluster_service_ipv6_cidr" { variable "outpost_config" { description = "Configuration for the AWS Outpost to provision the cluster on" - type = any - default = {} + type = object({ + control_plane_instance_type = optional(string) + control_plane_placement = optional(object({ + group_name = string + })) + outpost_arns = list(string) + }) + default = null } variable "cluster_encryption_config" { - description = "Configuration block with encryption configuration for the cluster. To disable secret encryption, set this value to `{}`" - type = any - default = { - resources = ["secrets"] - } + description = "Configuration block with encryption configuration for the cluster" + type = object({ + provider_key_arn = optional(string) + resources = optional(list(string), ["secrets"]) + }) + default = {} } variable "attach_cluster_encryption_policy" { @@ -162,8 +184,12 @@ variable "create_cluster_primary_security_group_tags" { variable "cluster_timeouts" { description = "Create, update, and delete timeout configurations for the cluster" - type = map(string) - default = {} + type = object({ + create = optional(string) + update = optional(string) + delete = optional(string) + }) + default = null } ################################################################################ @@ -172,8 +198,23 @@ variable "cluster_timeouts" { variable "access_entries" { description = "Map of access entries to add to the cluster" - type = any - default = {} + type = map(object({ + # Access entry + kubernetes_groups = optional(list(string)) + principal_arn = string + type = optional(string, "STANDARD") + user_name = optional(string) + tags = optional(map(string), {}) + # Access policy association + policy_associations = optional(map(object({ + policy_arn = string + access_scope = object({ + type = string + }) + namespaces = optional(list(string)) + })), {}) + })) + default = {} } variable "enable_cluster_creator_admin_permissions" { @@ -334,8 +375,20 @@ variable "cluster_security_group_description" { variable "cluster_security_group_additional_rules" { description = "List of additional security group rules to add to the cluster security group created. Set `source_node_security_group = true` inside rules to set the `node_security_group` as source" - type = any - default = {} + type = map(object({ + protocol = optional(string, "tcp") + from_port = number + to_port = number + type = optional(string, "ingress") + description = optional(string) + cidr_blocks = optional(list(string)) + ipv6_cidr_blocks = optional(list(string)) + prefix_list_ids = optional(list(string)) + self = optional(bool) + source_node_security_group = optional(bool, false) + source_security_group_id = optional(string) + })) + default = {} } variable "cluster_security_group_tags" { @@ -390,8 +443,20 @@ variable "node_security_group_description" { variable "node_security_group_additional_rules" { description = "List of additional security group rules to add to the node security group created. Set `source_cluster_security_group = true` inside rules to set the `cluster_security_group` as source" - type = any - default = {} + type = map(object({ + protocol = optional(string, "tcp") + from_port = number + to_port = number + type = optional(string, "ingress") + description = optional(string) + cidr_blocks = optional(list(string)) + ipv6_cidr_blocks = optional(list(string)) + prefix_list_ids = optional(list(string)) + self = optional(bool) + source_cluster_security_group = optional(bool, false) + source_security_group_id = optional(string) + })) + default = {} } variable "node_security_group_enable_recommended_rules" { @@ -546,14 +611,38 @@ variable "enable_auto_mode_custom_tags" { variable "cluster_addons" { description = "Map of cluster addon configurations to enable for the cluster. Addon name can be the map keys or set with `name`" - type = any - default = {} + type = map(object({ + name = optional(string) # will fall back to map key + before_compute = optional(bool, false) + most_recent = optional(bool, true) + addon_version = optional(string) + configuration_values = optional(string) + pod_identity_association = optional(list(object({ + role_arn = string + service_account = string + }))) + preserve = optional(bool, true) + resolve_conflicts_on_create = optional(string, "NONE") + resolve_conflicts_on_update = optional(string, "OVERWRITE") + service_account_role_arn = optional(string) + timeouts = optional(object({ + create = optional(string) + update = optional(string) + delete = optional(string) + })) + tags = optional(map(string), {}) + })) + default = null } variable "cluster_addons_timeouts" { description = "Create, update, and delete timeout configurations for the cluster addons" - type = map(string) - default = {} + type = object({ + create = optional(string) + update = optional(string) + delete = optional(string) + }) + default = null } ################################################################################ @@ -562,8 +651,17 @@ variable "cluster_addons_timeouts" { variable "cluster_identity_providers" { description = "Map of cluster identity provider configurations to enable for the cluster. Note - this is different/separate from IRSA" - type = any - default = {} + type = map(object({ + client_id = string + groups_claim = optional(string) + groups_prefix = optional(string) + identity_provider_config_name = optional(string) # will fall back to map key + issuer_url = string + required_claims = optional(map(string)) + username_claim = optional(string) + username_prefix = optional(string) + })) + default = null } ################################################################################ From 20d9722e3e349bb59dfe7088f12cfc5793b3f827 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Wed, 9 Jul 2025 11:59:46 -0500 Subject: [PATCH 11/25] fix: Remove `cluster_` prefix from variable names to better match the underlying API --- README.md | 115 ++++++++------- docs/compute_resources.md | 4 +- examples/eks-auto-mode/main.tf | 14 +- examples/eks-hybrid-nodes/main.tf | 16 +-- examples/eks-hybrid-nodes/remote.tf | 2 +- examples/eks-managed-node-group/eks-al2023.tf | 6 +- .../eks-bottlerocket.tf | 6 +- examples/karpenter/main.tf | 8 +- .../self-managed-node-group/eks-al2023.tf | 6 +- .../eks-bottlerocket.tf | 6 +- main.tf | 132 +++++++++--------- modules/eks-managed-node-group/README.md | 4 +- modules/eks-managed-node-group/main.tf | 44 +++--- modules/eks-managed-node-group/variables.tf | 4 +- modules/self-managed-node-group/README.md | 4 +- modules/self-managed-node-group/main.tf | 40 +++--- modules/self-managed-node-group/variables.tf | 2 +- node_groups.tf | 34 ++--- outputs.tf | 2 +- tests/eks-fargate-profile/main.tf | 18 +-- tests/eks-managed-node-group/README.md | 2 +- tests/eks-managed-node-group/main.tf | 28 ++-- tests/self-managed-node-group/README.md | 4 +- tests/self-managed-node-group/main.tf | 24 ++-- variables.tf | 76 +++++----- 25 files changed, 300 insertions(+), 301 deletions(-) diff --git a/README.md b/README.md index 8b51f52e51..670d1381eb 100644 --- a/README.md +++ b/README.md @@ -30,18 +30,18 @@ Please note that we strive to provide a comprehensive suite of documentation for ```hcl module "eks" { source = "terraform-aws-modules/eks/aws" - version = "~> 20.31" + version = "~> 21.0" - cluster_name = "example" - cluster_version = "1.33" + name = "example" + kubernetes_version = "1.33" # Optional - cluster_endpoint_public_access = true + endpoint_public_access = true # Optional: Adds the current caller identity as an administrator via cluster access entry enable_cluster_creator_admin_permissions = true - cluster_compute_config = { + compute_config = { enabled = true node_pools = ["general-purpose"] } @@ -69,7 +69,7 @@ locals { # SSM and IAM Roles Anywhere supported - SSM is default module "eks_hybrid_node_role" { source = "terraform-aws-modules/eks/aws//modules/hybrid-node-role" - version = "~> 20.31" + version = "~> 21.0" tags = { Environment = "dev" @@ -79,25 +79,25 @@ module "eks_hybrid_node_role" { module "eks" { source = "terraform-aws-modules/eks/aws" - version = "~> 20.31" + version = "~> 21.0" - cluster_name = "example" - cluster_version = "1.33" + name = "example" + kubernetes_version = "1.33" - cluster_addons = { + addons = { coredns = {} eks-pod-identity-agent = {} kube-proxy = {} } # Optional - cluster_endpoint_public_access = true + endpoint_public_access = true # Optional: Adds the current caller identity as an administrator via cluster access entry enable_cluster_creator_admin_permissions = true create_node_security_group = false - cluster_security_group_additional_rules = { + security_group_additional_rules = { hybrid-all = { cidr_blocks = [local.remote_network_cidr] description = "Allow all traffic from remote node/pod network" @@ -109,7 +109,7 @@ module "eks" { } # Optional - cluster_compute_config = { + compute_config = { enabled = true node_pools = ["system"] } @@ -124,7 +124,7 @@ module "eks" { vpc_id = "vpc-1234556abcdef" subnet_ids = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"] - cluster_remote_network_config = { + remote_network_config = { remote_node_networks = { cidrs = [local.remote_node_cidr] } @@ -146,13 +146,12 @@ module "eks" { ```hcl module "eks" { source = "terraform-aws-modules/eks/aws" - version = "~> 20.0" + version = "~> 21.0" - cluster_name = "my-cluster" - cluster_version = "1.33" + name = "my-cluster" + kubernetes_version = "1.33" - bootstrap_self_managed_addons = false - cluster_addons = { + addons = { coredns = {} eks-pod-identity-agent = {} kube-proxy = {} @@ -160,7 +159,7 @@ module "eks" { } # Optional - cluster_endpoint_public_access = true + endpoint_public_access = true # Optional: Adds the current caller identity as an administrator via cluster access entry enable_cluster_creator_admin_permissions = true @@ -202,7 +201,7 @@ On clusters that were created prior to cluster access management (CAM) support, ```hcl module "eks" { source = "terraform-aws-modules/eks/aws" - version = "~> 20.0" + version = "~> 21.0" # Truncated for brevity ... @@ -251,7 +250,7 @@ In order to enable EFA support, you will have to specify `enable_efa_support = t ```hcl module "eks" { source = "terraform-aws-modules/eks/aws" - version = "~> 20.0" + version = "~> 21.0" # Truncated for brevity ... @@ -383,65 +382,49 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [access\_entries](#input\_access\_entries) | Map of access entries to add to the cluster |
map(object({
# Access entry
kubernetes_groups = optional(list(string))
principal_arn = string
type = optional(string, "STANDARD")
user_name = optional(string)
tags = optional(map(string), {})
# Access policy association
policy_associations = optional(map(object({
policy_arn = string
access_scope = object({
type = string
})
namespaces = optional(list(string))
})), {})
}))
| `{}` | no | -| [attach\_cluster\_encryption\_policy](#input\_attach\_cluster\_encryption\_policy) | Indicates whether or not to attach an additional policy for the cluster IAM role to utilize the encryption key provided | `bool` | `true` | no | +| [additional\_security\_group\_ids](#input\_additional\_security\_group\_ids) | List of additional, externally created security group IDs to attach to the cluster control plane | `list(string)` | `[]` | no | +| [addons](#input\_addons) | Map of cluster addon configurations to enable for the cluster. Addon name can be the map keys or set with `name` |
map(object({
name = optional(string) # will fall back to map key
before_compute = optional(bool, false)
most_recent = optional(bool, true)
addon_version = optional(string)
configuration_values = optional(string)
pod_identity_association = optional(list(object({
role_arn = string
service_account = string
})))
preserve = optional(bool, true)
resolve_conflicts_on_create = optional(string, "NONE")
resolve_conflicts_on_update = optional(string, "OVERWRITE")
service_account_role_arn = optional(string)
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
tags = optional(map(string), {})
}))
| `null` | no | +| [addons\_timeouts](#input\_addons\_timeouts) | Create, update, and delete timeout configurations for the cluster addons |
object({
create = optional(string)
update = optional(string)
delete = optional(string)
})
| `null` | no | +| [attach\_encryption\_policy](#input\_attach\_encryption\_policy) | Indicates whether or not to attach an additional policy for the cluster IAM role to utilize the encryption key provided | `bool` | `true` | no | | [authentication\_mode](#input\_authentication\_mode) | The authentication mode for the cluster. Valid values are `CONFIG_MAP`, `API` or `API_AND_CONFIG_MAP` | `string` | `"API_AND_CONFIG_MAP"` | no | | [cloudwatch\_log\_group\_class](#input\_cloudwatch\_log\_group\_class) | Specified the log class of the log group. Possible values are: `STANDARD` or `INFREQUENT_ACCESS` | `string` | `null` | no | | [cloudwatch\_log\_group\_kms\_key\_id](#input\_cloudwatch\_log\_group\_kms\_key\_id) | If a KMS Key ARN is set, this key will be used to encrypt the corresponding log group. Please be sure that the KMS Key has an appropriate key policy (https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/encrypt-log-data-kms.html) | `string` | `null` | no | | [cloudwatch\_log\_group\_retention\_in\_days](#input\_cloudwatch\_log\_group\_retention\_in\_days) | Number of days to retain log events. Default retention - 90 days | `number` | `90` | no | | [cloudwatch\_log\_group\_tags](#input\_cloudwatch\_log\_group\_tags) | A map of additional tags to add to the cloudwatch log group created | `map(string)` | `{}` | no | -| [cluster\_additional\_security\_group\_ids](#input\_cluster\_additional\_security\_group\_ids) | List of additional, externally created security group IDs to attach to the cluster control plane | `list(string)` | `[]` | no | -| [cluster\_addons](#input\_cluster\_addons) | Map of cluster addon configurations to enable for the cluster. Addon name can be the map keys or set with `name` |
map(object({
name = optional(string) # will fall back to map key
before_compute = optional(bool, false)
most_recent = optional(bool, true)
addon_version = optional(string)
configuration_values = optional(string)
pod_identity_association = optional(list(object({
role_arn = string
service_account = string
})))
preserve = optional(bool, true)
resolve_conflicts_on_create = optional(string, "NONE")
resolve_conflicts_on_update = optional(string, "OVERWRITE")
service_account_role_arn = optional(string)
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
tags = optional(map(string), {})
}))
| `null` | no | -| [cluster\_addons\_timeouts](#input\_cluster\_addons\_timeouts) | Create, update, and delete timeout configurations for the cluster addons |
object({
create = optional(string)
update = optional(string)
delete = optional(string)
})
| `null` | no | -| [cluster\_compute\_config](#input\_cluster\_compute\_config) | Configuration block for the cluster compute configuration |
object({
enabled = optional(bool, false)
node_pools = optional(list(string))
node_role_arn = optional(string)
})
| `null` | no | -| [cluster\_enabled\_log\_types](#input\_cluster\_enabled\_log\_types) | A list of the desired control plane logs to enable. For more information, see Amazon EKS Control Plane Logging documentation (https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html) | `list(string)` |
[
"audit",
"api",
"authenticator"
]
| no | -| [cluster\_encryption\_config](#input\_cluster\_encryption\_config) | Configuration block with encryption configuration for the cluster |
object({
provider_key_arn = optional(string)
resources = optional(list(string), ["secrets"])
})
| `{}` | no | -| [cluster\_encryption\_policy\_description](#input\_cluster\_encryption\_policy\_description) | Description of the cluster encryption policy created | `string` | `"Cluster encryption policy to allow cluster role to utilize CMK provided"` | no | -| [cluster\_encryption\_policy\_name](#input\_cluster\_encryption\_policy\_name) | Name to use on cluster encryption policy created | `string` | `null` | no | -| [cluster\_encryption\_policy\_path](#input\_cluster\_encryption\_policy\_path) | Cluster encryption policy path | `string` | `null` | no | -| [cluster\_encryption\_policy\_tags](#input\_cluster\_encryption\_policy\_tags) | A map of additional tags to add to the cluster encryption policy created | `map(string)` | `{}` | no | -| [cluster\_encryption\_policy\_use\_name\_prefix](#input\_cluster\_encryption\_policy\_use\_name\_prefix) | Determines whether cluster encryption policy name (`cluster_encryption_policy_name`) is used as a prefix | `bool` | `true` | no | -| [cluster\_endpoint\_private\_access](#input\_cluster\_endpoint\_private\_access) | Indicates whether or not the Amazon EKS private API server endpoint is enabled | `bool` | `true` | no | -| [cluster\_endpoint\_public\_access](#input\_cluster\_endpoint\_public\_access) | Indicates whether or not the Amazon EKS public API server endpoint is enabled | `bool` | `false` | no | -| [cluster\_endpoint\_public\_access\_cidrs](#input\_cluster\_endpoint\_public\_access\_cidrs) | List of CIDR blocks which can access the Amazon EKS public API server endpoint | `list(string)` |
[
"0.0.0.0/0"
]
| no | -| [cluster\_force\_update\_version](#input\_cluster\_force\_update\_version) | Force version update by overriding upgrade-blocking readiness checks when updating a cluster | `bool` | `null` | no | -| [cluster\_identity\_providers](#input\_cluster\_identity\_providers) | Map of cluster identity provider configurations to enable for the cluster. Note - this is different/separate from IRSA |
map(object({
client_id = string
groups_claim = optional(string)
groups_prefix = optional(string)
identity_provider_config_name = optional(string) # will fall back to map key
issuer_url = string
required_claims = optional(map(string))
username_claim = optional(string)
username_prefix = optional(string)
}))
| `null` | no | -| [cluster\_ip\_family](#input\_cluster\_ip\_family) | The IP family used to assign Kubernetes pod and service addresses. Valid values are `ipv4` (default) and `ipv6`. You can only specify an IP family when you create a cluster, changing this value will force a new cluster to be created | `string` | `"ipv4"` | no | -| [cluster\_name](#input\_cluster\_name) | Name of the EKS cluster | `string` | `""` | no | -| [cluster\_remote\_network\_config](#input\_cluster\_remote\_network\_config) | Configuration block for the cluster remote network configuration |
object({
remote_node_networks = object({
cidrs = optional(list(string))
})
remote_pod_networks = optional(object({
cidrs = optional(list(string))
}))
})
| `null` | no | -| [cluster\_security\_group\_additional\_rules](#input\_cluster\_security\_group\_additional\_rules) | List of additional security group rules to add to the cluster security group created. Set `source_node_security_group = true` inside rules to set the `node_security_group` as source |
map(object({
protocol = optional(string, "tcp")
from_port = number
to_port = number
type = optional(string, "ingress")
description = optional(string)
cidr_blocks = optional(list(string))
ipv6_cidr_blocks = optional(list(string))
prefix_list_ids = optional(list(string))
self = optional(bool)
source_node_security_group = optional(bool, false)
source_security_group_id = optional(string)
}))
| `{}` | no | -| [cluster\_security\_group\_description](#input\_cluster\_security\_group\_description) | Description of the cluster security group created | `string` | `"EKS cluster security group"` | no | -| [cluster\_security\_group\_id](#input\_cluster\_security\_group\_id) | Existing security group ID to be attached to the cluster | `string` | `""` | no | -| [cluster\_security\_group\_name](#input\_cluster\_security\_group\_name) | Name to use on cluster security group created | `string` | `null` | no | -| [cluster\_security\_group\_tags](#input\_cluster\_security\_group\_tags) | A map of additional tags to add to the cluster security group created | `map(string)` | `{}` | no | -| [cluster\_security\_group\_use\_name\_prefix](#input\_cluster\_security\_group\_use\_name\_prefix) | Determines whether cluster security group name (`cluster_security_group_name`) is used as a prefix | `bool` | `true` | no | -| [cluster\_service\_ipv4\_cidr](#input\_cluster\_service\_ipv4\_cidr) | The CIDR block to assign Kubernetes service IP addresses from. If you don't specify a block, Kubernetes assigns addresses from either the 10.100.0.0/16 or 172.20.0.0/16 CIDR blocks | `string` | `null` | no | -| [cluster\_service\_ipv6\_cidr](#input\_cluster\_service\_ipv6\_cidr) | The CIDR block to assign Kubernetes pod and service IP addresses from if `ipv6` was specified when the cluster was created. Kubernetes assigns service addresses from the unique local address range (fc00::/7) because you can't specify a custom IPv6 CIDR block when you create the cluster | `string` | `null` | no | | [cluster\_tags](#input\_cluster\_tags) | A map of additional tags to add to the cluster | `map(string)` | `{}` | no | -| [cluster\_timeouts](#input\_cluster\_timeouts) | Create, update, and delete timeout configurations for the cluster |
object({
create = optional(string)
update = optional(string)
delete = optional(string)
})
| `null` | no | -| [cluster\_upgrade\_policy](#input\_cluster\_upgrade\_policy) | Configuration block for the cluster upgrade policy |
object({
support_type = optional(string)
})
| `null` | no | -| [cluster\_version](#input\_cluster\_version) | Kubernetes `.` version to use for the EKS cluster (i.e.: `1.27`) | `string` | `null` | no | -| [cluster\_zonal\_shift\_config](#input\_cluster\_zonal\_shift\_config) | Configuration block for the cluster zonal shift |
object({
enabled = optional(bool)
})
| `null` | no | +| [compute\_config](#input\_compute\_config) | Configuration block for the cluster compute configuration |
object({
enabled = optional(bool, false)
node_pools = optional(list(string))
node_role_arn = optional(string)
})
| `null` | no | | [control\_plane\_subnet\_ids](#input\_control\_plane\_subnet\_ids) | A list of subnet IDs where the EKS cluster control plane (ENIs) will be provisioned. Used for expanding the pool of subnets used by nodes/node groups without replacing the EKS control plane | `list(string)` | `[]` | no | | [create](#input\_create) | Controls if resources should be created (affects nearly all resources) | `bool` | `true` | no | | [create\_cloudwatch\_log\_group](#input\_create\_cloudwatch\_log\_group) | Determines whether a log group is created by this module for the cluster logs. If not, AWS will automatically create one if logging is enabled | `bool` | `true` | no | -| [create\_cluster\_primary\_security\_group\_tags](#input\_create\_cluster\_primary\_security\_group\_tags) | Indicates whether or not to tag the cluster's primary security group. This security group is created by the EKS service, not the module, and therefore tagging is handled after cluster creation | `bool` | `true` | no | -| [create\_cluster\_security\_group](#input\_create\_cluster\_security\_group) | Determines if a security group is created for the cluster. Note: the EKS service creates a primary security group for the cluster by default | `bool` | `true` | no | | [create\_cni\_ipv6\_iam\_policy](#input\_create\_cni\_ipv6\_iam\_policy) | Determines whether to create an [`AmazonEKS_CNI_IPv6_Policy`](https://docs.aws.amazon.com/eks/latest/userguide/cni-iam-role.html#cni-iam-role-create-ipv6-policy) | `bool` | `false` | no | | [create\_iam\_role](#input\_create\_iam\_role) | Determines whether an IAM role is created for the cluster | `bool` | `true` | no | | [create\_kms\_key](#input\_create\_kms\_key) | Controls if a KMS key for cluster encryption should be created | `bool` | `true` | no | | [create\_node\_iam\_role](#input\_create\_node\_iam\_role) | Determines whether an EKS Auto node IAM role is created | `bool` | `true` | no | | [create\_node\_security\_group](#input\_create\_node\_security\_group) | Determines whether to create a security group for the node groups or use the existing `node_security_group_id` | `bool` | `true` | no | +| [create\_primary\_security\_group\_tags](#input\_create\_primary\_security\_group\_tags) | Indicates whether or not to tag the cluster's primary security group. This security group is created by the EKS service, not the module, and therefore tagging is handled after cluster creation | `bool` | `true` | no | +| [create\_security\_group](#input\_create\_security\_group) | Determines if a security group is created for the cluster. Note: the EKS service creates a primary security group for the cluster by default | `bool` | `true` | no | | [custom\_oidc\_thumbprints](#input\_custom\_oidc\_thumbprints) | Additional list of server certificate thumbprints for the OpenID Connect (OIDC) identity provider's server certificate(s) | `list(string)` | `[]` | no | | [dataplane\_wait\_duration](#input\_dataplane\_wait\_duration) | Duration to wait after the EKS cluster has become active before creating the dataplane components (EKS managed node group(s), self-managed node group(s), Fargate profile(s)) | `string` | `"30s"` | no | -| [eks\_managed\_node\_group\_defaults](#input\_eks\_managed\_node\_group\_defaults) | Map of EKS managed node group default configurations |
object({
create = optional(bool)
cluster_version = optional(string)

# EKS Managed Node Group
use_name_prefix = optional(bool)
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
ami_id = optional(string)
ami_type = optional(string)
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool)
capacity_type = optional(string)
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}))
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool)
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
create_placement_group = optional(bool)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string))
cluster_primary_security_group_id = optional(string)

tags = optional(map(string), {})
})
| `{}` | no | -| [eks\_managed\_node\_groups](#input\_eks\_managed\_node\_groups) | Map of EKS managed node group definitions to create |
map(object({
create = optional(bool, true)
cluster_version = optional(string)

# EKS Managed Node Group
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
ami_id = optional(string, "")
ami_type = optional(string, "AL2023_x86_64_STANDARD")
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool, true)
capacity_type = optional(string, "ON_DEMAND")
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool, true)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}), {
max_unavailable_percentage = 33
})
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool, false)
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
create_placement_group = optional(bool, false)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool, true)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "EKS managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string), [])
cluster_primary_security_group_id = optional(string)

tags = optional(map(string), {})
}))
| `{}` | no | +| [eks\_managed\_node\_group\_defaults](#input\_eks\_managed\_node\_group\_defaults) | Map of EKS managed node group default configurations |
object({
create = optional(bool)
kubernetes_version = optional(string)

# EKS Managed Node Group
use_name_prefix = optional(bool)
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
ami_id = optional(string)
ami_type = optional(string)
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool)
capacity_type = optional(string)
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}))
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool)
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
create_placement_group = optional(bool)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string))
cluster_primary_security_group_id = optional(string)

tags = optional(map(string), {})
})
| `{}` | no | +| [eks\_managed\_node\_groups](#input\_eks\_managed\_node\_groups) | Map of EKS managed node group definitions to create |
map(object({
create = optional(bool, true)
kubernetes_version = optional(string)

# EKS Managed Node Group
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
ami_id = optional(string, "")
ami_type = optional(string, "AL2023_x86_64_STANDARD")
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool, true)
capacity_type = optional(string, "ON_DEMAND")
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool, true)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}), {
max_unavailable_percentage = 33
})
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool, false)
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
create_placement_group = optional(bool, false)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool, true)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "EKS managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string), [])
cluster_primary_security_group_id = optional(string)

tags = optional(map(string), {})
}))
| `{}` | no | | [enable\_auto\_mode\_custom\_tags](#input\_enable\_auto\_mode\_custom\_tags) | Determines whether to enable permissions for custom tags resources created by EKS Auto Mode | `bool` | `true` | no | | [enable\_cluster\_creator\_admin\_permissions](#input\_enable\_cluster\_creator\_admin\_permissions) | Indicates whether or not to add the cluster creator (the identity used by Terraform) as an administrator via access entry | `bool` | `false` | no | | [enable\_efa\_support](#input\_enable\_efa\_support) | Determines whether to enable Elastic Fabric Adapter (EFA) support | `bool` | `false` | no | | [enable\_irsa](#input\_enable\_irsa) | Determines whether to create an OpenID Connect Provider for EKS to enable IRSA | `bool` | `true` | no | | [enable\_kms\_key\_rotation](#input\_enable\_kms\_key\_rotation) | Specifies whether key rotation is enabled | `bool` | `true` | no | +| [enabled\_log\_types](#input\_enabled\_log\_types) | A list of the desired control plane logs to enable. For more information, see Amazon EKS Control Plane Logging documentation (https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html) | `list(string)` |
[
"audit",
"api",
"authenticator"
]
| no | +| [encryption\_config](#input\_encryption\_config) | Configuration block with encryption configuration for the cluster |
object({
provider_key_arn = optional(string)
resources = optional(list(string), ["secrets"])
})
| `{}` | no | +| [encryption\_policy\_description](#input\_encryption\_policy\_description) | Description of the cluster encryption policy created | `string` | `"Cluster encryption policy to allow cluster role to utilize CMK provided"` | no | +| [encryption\_policy\_name](#input\_encryption\_policy\_name) | Name to use on cluster encryption policy created | `string` | `null` | no | +| [encryption\_policy\_path](#input\_encryption\_policy\_path) | Cluster encryption policy path | `string` | `null` | no | +| [encryption\_policy\_tags](#input\_encryption\_policy\_tags) | A map of additional tags to add to the cluster encryption policy created | `map(string)` | `{}` | no | +| [encryption\_policy\_use\_name\_prefix](#input\_encryption\_policy\_use\_name\_prefix) | Determines whether cluster encryption policy name (`cluster_encryption_policy_name`) is used as a prefix | `bool` | `true` | no | +| [endpoint\_private\_access](#input\_endpoint\_private\_access) | Indicates whether or not the Amazon EKS private API server endpoint is enabled | `bool` | `true` | no | +| [endpoint\_public\_access](#input\_endpoint\_public\_access) | Indicates whether or not the Amazon EKS public API server endpoint is enabled | `bool` | `false` | no | +| [endpoint\_public\_access\_cidrs](#input\_endpoint\_public\_access\_cidrs) | List of CIDR blocks which can access the Amazon EKS public API server endpoint | `list(string)` |
[
"0.0.0.0/0"
]
| no | | [fargate\_profile\_defaults](#input\_fargate\_profile\_defaults) | Map of Fargate Profile default configurations |
object({
create = optional(bool)

# Fargate profile
name = optional(string) # Will fall back to map key
subnet_ids = optional(list(string))
selectors = optional(list(object({
labels = optional(map(string))
namespace = string
})))
timeouts = optional(object({
create = optional(string)
delete = optional(string)
}))

# IAM role
create_iam_role = optional(bool)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
tags = optional(map(string), {})
})
| `{}` | no | | [fargate\_profiles](#input\_fargate\_profiles) | Map of Fargate Profile definitions to create |
map(object({
create = optional(bool, true)

# Fargate profile
name = optional(string) # Will fall back to map key
subnet_ids = optional(list(string), [])
selectors = optional(list(object({
labels = optional(map(string))
namespace = string
})))
timeouts = optional(object({
create = optional(string)
delete = optional(string)
}))

# IAM role
create_iam_role = optional(bool, true)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Fargate profile IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
tags = optional(map(string), {})
}))
| `{}` | no | +| [force\_update\_version](#input\_force\_update\_version) | Force version update by overriding upgrade-blocking readiness checks when updating a cluster | `bool` | `null` | no | | [iam\_role\_additional\_policies](#input\_iam\_role\_additional\_policies) | Additional policies to be added to the IAM role | `map(string)` | `{}` | no | | [iam\_role\_arn](#input\_iam\_role\_arn) | Existing IAM role ARN for the cluster. Required if `create_iam_role` is set to `false` | `string` | `null` | no | | [iam\_role\_description](#input\_iam\_role\_description) | Description of the role | `string` | `null` | no | @@ -450,7 +433,9 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [iam\_role\_permissions\_boundary](#input\_iam\_role\_permissions\_boundary) | ARN of the policy that is used to set the permissions boundary for the IAM role | `string` | `null` | no | | [iam\_role\_tags](#input\_iam\_role\_tags) | A map of additional tags to add to the IAM role created | `map(string)` | `{}` | no | | [iam\_role\_use\_name\_prefix](#input\_iam\_role\_use\_name\_prefix) | Determines whether the IAM role name (`iam_role_name`) is used as a prefix | `bool` | `true` | no | +| [identity\_providers](#input\_identity\_providers) | Map of cluster identity provider configurations to enable for the cluster. Note - this is different/separate from IRSA |
map(object({
client_id = string
groups_claim = optional(string)
groups_prefix = optional(string)
identity_provider_config_name = optional(string) # will fall back to map key
issuer_url = string
required_claims = optional(map(string))
username_claim = optional(string)
username_prefix = optional(string)
}))
| `null` | no | | [include\_oidc\_root\_ca\_thumbprint](#input\_include\_oidc\_root\_ca\_thumbprint) | Determines whether to include the root CA thumbprint in the OpenID Connect (OIDC) identity provider's server certificate(s) | `bool` | `true` | no | +| [ip\_family](#input\_ip\_family) | The IP family used to assign Kubernetes pod and service addresses. Valid values are `ipv4` (default) and `ipv6`. You can only specify an IP family when you create a cluster, changing this value will force a new cluster to be created | `string` | `"ipv4"` | no | | [kms\_key\_administrators](#input\_kms\_key\_administrators) | A list of IAM ARNs for [key administrators](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-administrators). If no value is provided, the current caller identity is used to ensure at least one key admin is available | `list(string)` | `[]` | no | | [kms\_key\_aliases](#input\_kms\_key\_aliases) | A list of aliases to create. Note - due to the use of `toset()`, values must be static strings and not computed values | `list(string)` | `[]` | no | | [kms\_key\_deletion\_window\_in\_days](#input\_kms\_key\_deletion\_window\_in\_days) | The waiting period, specified in number of days. After the waiting period ends, AWS KMS deletes the KMS key. If you specify a value, it must be between `7` and `30`, inclusive. If you do not specify a value, it defaults to `30` | `number` | `null` | no | @@ -461,6 +446,8 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [kms\_key\_service\_users](#input\_kms\_key\_service\_users) | A list of IAM ARNs for [key service users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-service-integration) | `list(string)` | `[]` | no | | [kms\_key\_source\_policy\_documents](#input\_kms\_key\_source\_policy\_documents) | List of IAM policy documents that are merged together into the exported document. Statements must have unique `sid`s | `list(string)` | `[]` | no | | [kms\_key\_users](#input\_kms\_key\_users) | A list of IAM ARNs for [key users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-users) | `list(string)` | `[]` | no | +| [kubernetes\_version](#input\_kubernetes\_version) | Kubernetes `.` version to use for the EKS cluster (i.e.: `1.27`) | `string` | `null` | no | +| [name](#input\_name) | Name of the EKS cluster | `string` | `""` | no | | [node\_iam\_role\_additional\_policies](#input\_node\_iam\_role\_additional\_policies) | Additional policies to be added to the EKS Auto node IAM role | `map(string)` | `{}` | no | | [node\_iam\_role\_description](#input\_node\_iam\_role\_description) | Description of the EKS Auto node IAM role | `string` | `null` | no | | [node\_iam\_role\_name](#input\_node\_iam\_role\_name) | Name to use on the EKS Auto node IAM role created | `string` | `null` | no | @@ -479,11 +466,23 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [outpost\_config](#input\_outpost\_config) | Configuration for the AWS Outpost to provision the cluster on |
object({
control_plane_instance_type = optional(string)
control_plane_placement = optional(object({
group_name = string
}))
outpost_arns = list(string)
})
| `null` | no | | [prefix\_separator](#input\_prefix\_separator) | The separator to use between the prefix and the generated timestamp for resource names | `string` | `"-"` | no | | [putin\_khuylo](#input\_putin\_khuylo) | Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo! | `bool` | `true` | no | +| [remote\_network\_config](#input\_remote\_network\_config) | Configuration block for the cluster remote network configuration |
object({
remote_node_networks = object({
cidrs = optional(list(string))
})
remote_pod_networks = optional(object({
cidrs = optional(list(string))
}))
})
| `null` | no | +| [security\_group\_additional\_rules](#input\_security\_group\_additional\_rules) | List of additional security group rules to add to the cluster security group created. Set `source_node_security_group = true` inside rules to set the `node_security_group` as source |
map(object({
protocol = optional(string, "tcp")
from_port = number
to_port = number
type = optional(string, "ingress")
description = optional(string)
cidr_blocks = optional(list(string))
ipv6_cidr_blocks = optional(list(string))
prefix_list_ids = optional(list(string))
self = optional(bool)
source_node_security_group = optional(bool, false)
source_security_group_id = optional(string)
}))
| `{}` | no | +| [security\_group\_description](#input\_security\_group\_description) | Description of the cluster security group created | `string` | `"EKS cluster security group"` | no | +| [security\_group\_id](#input\_security\_group\_id) | Existing security group ID to be attached to the cluster | `string` | `""` | no | +| [security\_group\_name](#input\_security\_group\_name) | Name to use on cluster security group created | `string` | `null` | no | +| [security\_group\_tags](#input\_security\_group\_tags) | A map of additional tags to add to the cluster security group created | `map(string)` | `{}` | no | +| [security\_group\_use\_name\_prefix](#input\_security\_group\_use\_name\_prefix) | Determines whether cluster security group name (`cluster_security_group_name`) is used as a prefix | `bool` | `true` | no | | [self\_managed\_node\_group\_defaults](#input\_self\_managed\_node\_group\_defaults) | Map of self-managed node group default configurations |
object({
create = optional(bool)
# Autoscaling Group
create_autoscaling_group = optional(bool)
use_name_prefix = optional(bool)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool)
context = optional(string)
target_group_arns = optional(list(string))
create_placement_group = optional(bool)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(number)
force_delete = optional(bool)
force_delete_warm_pool = optional(bool)
termination_policies = optional(list(string))
suspended_processes = optional(list(string))
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string))
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string)
triggers = optional(list(string))
}))
use_mixed_instances_policy = optional(bool)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
warm_pool = optional(object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string))
# User data
ami_type = optional(string)
additional_cluster_dns_ips = optional(list(string))
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string)
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
hibernation_options = optional(object({
configured = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool)
iam_role_arn = optional(string)

tags = optional(map(string))
})
| `{}` | no | | [self\_managed\_node\_groups](#input\_self\_managed\_node\_groups) | Map of self-managed node group definitions to create |
map(object({
create = optional(bool, true)
# Autoscaling Group
create_autoscaling_group = optional(bool, true)
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool, false)
context = optional(string)
target_group_arns = optional(list(string), [])
create_placement_group = optional(bool, false)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(number)
force_delete = optional(bool)
force_delete_warm_pool = optional(bool)
termination_policies = optional(list(string), [])
suspended_processes = optional(list(string), [])
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string), [])
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number, 66)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string, "Rolling")
triggers = optional(list(string))
}), {
strategy = "Rolling"
preferences = {
min_healthy_percentage = 66
}
})
use_mixed_instances_policy = optional(bool, false)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
warm_pool = optional(object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string), {})
# User data
ami_type = optional(string, "AL2023_x86_64_STANDARD")
additional_cluster_dns_ips = optional(list(string), [])
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string, "m6i.large")
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
hibernation_options = optional(object({
configured = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool, true)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Self managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool, true)
iam_role_arn = optional(string)

tags = optional(map(string), {})
}))
| `{}` | no | +| [service\_ipv4\_cidr](#input\_service\_ipv4\_cidr) | The CIDR block to assign Kubernetes service IP addresses from. If you don't specify a block, Kubernetes assigns addresses from either the 10.100.0.0/16 or 172.20.0.0/16 CIDR blocks | `string` | `null` | no | +| [service\_ipv6\_cidr](#input\_service\_ipv6\_cidr) | The CIDR block to assign Kubernetes pod and service IP addresses from if `ipv6` was specified when the cluster was created. Kubernetes assigns service addresses from the unique local address range (fc00::/7) because you can't specify a custom IPv6 CIDR block when you create the cluster | `string` | `null` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs where the nodes/node groups will be provisioned. If `control_plane_subnet_ids` is not provided, the EKS cluster control plane (ENIs) will be provisioned in these subnets | `list(string)` | `[]` | no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | +| [timeouts](#input\_timeouts) | Create, update, and delete timeout configurations for the cluster |
object({
create = optional(string)
update = optional(string)
delete = optional(string)
})
| `null` | no | +| [upgrade\_policy](#input\_upgrade\_policy) | Configuration block for the cluster upgrade policy |
object({
support_type = optional(string)
})
| `null` | no | | [vpc\_id](#input\_vpc\_id) | ID of the VPC where the cluster security group will be provisioned | `string` | `null` | no | +| [zonal\_shift\_config](#input\_zonal\_shift\_config) | Configuration block for the cluster zonal shift |
object({
enabled = optional(bool)
})
| `null` | no | ## Outputs diff --git a/docs/compute_resources.md b/docs/compute_resources.md index a7bd5b5e93..4b40c2e68e 100644 --- a/docs/compute_resources.md +++ b/docs/compute_resources.md @@ -113,7 +113,7 @@ Refer to the [Self Managed Node Group documentation](https://docs.aws.amazon.com 1. The `self-managed-node-group` uses the latest AWS EKS Optimized AMI (Linux) for the given Kubernetes version by default: ```hcl - cluster_version = "1.33" + kubernetes_version = "1.33" # This self managed node group will use the latest AWS EKS Optimized AMI for Kubernetes 1.27 self_managed_node_groups = { @@ -124,7 +124,7 @@ Refer to the [Self Managed Node Group documentation](https://docs.aws.amazon.com 2. To use Bottlerocket, specify the `ami_type` as one of the respective `"BOTTLEROCKET_*" types` and supply a Bottlerocket OS AMI: ```hcl - cluster_version = "1.33" + kubernetes_version = "1.33" self_managed_node_groups = { bottlerocket = { diff --git a/examples/eks-auto-mode/main.tf b/examples/eks-auto-mode/main.tf index aa7bad1cd2..c99c60c970 100644 --- a/examples/eks-auto-mode/main.tf +++ b/examples/eks-auto-mode/main.tf @@ -11,9 +11,9 @@ data "aws_availability_zones" "available" { } locals { - name = "ex-${basename(path.cwd)}" - cluster_version = "1.33" - region = "us-west-2" + name = "ex-${basename(path.cwd)}" + kubernetes_version = "1.33" + region = "us-west-2" vpc_cidr = "10.0.0.0/16" azs = slice(data.aws_availability_zones.available.names, 0, 3) @@ -32,13 +32,13 @@ locals { module "eks" { source = "../.." - cluster_name = local.name - cluster_version = local.cluster_version - cluster_endpoint_public_access = true + name = local.name + kubernetes_version = local.kubernetes_version + endpoint_public_access = true enable_cluster_creator_admin_permissions = true - cluster_compute_config = { + compute_config = { enabled = true node_pools = ["general-purpose"] } diff --git a/examples/eks-hybrid-nodes/main.tf b/examples/eks-hybrid-nodes/main.tf index 95d26f8909..d23f05e370 100644 --- a/examples/eks-hybrid-nodes/main.tf +++ b/examples/eks-hybrid-nodes/main.tf @@ -20,7 +20,7 @@ locals { name = "ex-${basename(path.cwd)}" region = "us-west-2" - cluster_version = "1.33" + kubernetes_version = "1.33" tags = { Test = local.name @@ -36,20 +36,20 @@ locals { module "eks" { source = "../.." - cluster_name = local.name - cluster_version = local.cluster_version + name = local.name + kubernetes_version = local.kubernetes_version - cluster_endpoint_public_access = true + endpoint_public_access = true enable_cluster_creator_admin_permissions = true - cluster_addons = { + addons = { coredns = {} eks-pod-identity-agent = {} kube-proxy = {} } create_node_security_group = false - cluster_security_group_additional_rules = { + security_group_additional_rules = { hybrid-all = { cidr_blocks = [local.remote_network_cidr] description = "Allow all traffic from remote node/pod network" @@ -60,7 +60,7 @@ module "eks" { } } - cluster_compute_config = { + compute_config = { enabled = true node_pools = ["system"] } @@ -75,7 +75,7 @@ module "eks" { vpc_id = module.vpc.vpc_id subnet_ids = module.vpc.private_subnets - cluster_remote_network_config = { + remote_network_config = { remote_node_networks = { cidrs = [local.remote_node_cidr] } diff --git a/examples/eks-hybrid-nodes/remote.tf b/examples/eks-hybrid-nodes/remote.tf index 66baff9eed..5aaf85ec96 100644 --- a/examples/eks-hybrid-nodes/remote.tf +++ b/examples/eks-hybrid-nodes/remote.tf @@ -89,7 +89,7 @@ data "aws_ami" "hybrid_node" { provider = aws.remote most_recent = true - name_regex = "eks-hybrid-ubuntu-${local.cluster_version}-amd64-*" + name_regex = "eks-hybrid-ubuntu-${local.kubernetes_version}-amd64-*" owners = ["self"] } diff --git a/examples/eks-managed-node-group/eks-al2023.tf b/examples/eks-managed-node-group/eks-al2023.tf index b96a94a875..e1dd71d38c 100644 --- a/examples/eks-managed-node-group/eks-al2023.tf +++ b/examples/eks-managed-node-group/eks-al2023.tf @@ -3,11 +3,11 @@ module "eks_al2023" { # version = "~> 20.0" source = "../.." - cluster_name = "${local.name}-al2023" - cluster_version = "1.33" + name = "${local.name}-al2023" + kubernetes_version = "1.33" # EKS Addons - cluster_addons = { + addons = { coredns = {} eks-pod-identity-agent = {} kube-proxy = {} diff --git a/examples/eks-managed-node-group/eks-bottlerocket.tf b/examples/eks-managed-node-group/eks-bottlerocket.tf index f970639967..037028ce68 100644 --- a/examples/eks-managed-node-group/eks-bottlerocket.tf +++ b/examples/eks-managed-node-group/eks-bottlerocket.tf @@ -3,11 +3,11 @@ module "eks_bottlerocket" { # version = "~> 20.0" source = "../.." - cluster_name = "${local.name}-bottlerocket" - cluster_version = "1.33" + name = "${local.name}-bottlerocket" + kubernetes_version = "1.33" # EKS Addons - cluster_addons = { + addons = { coredns = {} eks-pod-identity-agent = {} kube-proxy = {} diff --git a/examples/karpenter/main.tf b/examples/karpenter/main.tf index de205e3854..3884bb5a36 100644 --- a/examples/karpenter/main.tf +++ b/examples/karpenter/main.tf @@ -54,15 +54,15 @@ locals { module "eks" { source = "../.." - cluster_name = local.name - cluster_version = "1.33" + name = local.name + kubernetes_version = "1.33" # Gives Terraform identity admin access to cluster which will # allow deploying resources (Karpenter) into the cluster enable_cluster_creator_admin_permissions = true - cluster_endpoint_public_access = true + endpoint_public_access = true - cluster_addons = { + addons = { coredns = {} eks-pod-identity-agent = {} kube-proxy = {} diff --git a/examples/self-managed-node-group/eks-al2023.tf b/examples/self-managed-node-group/eks-al2023.tf index 6154a1f68a..29dd80ee86 100644 --- a/examples/self-managed-node-group/eks-al2023.tf +++ b/examples/self-managed-node-group/eks-al2023.tf @@ -3,11 +3,11 @@ module "eks_al2023" { # version = "~> 20.0" source = "../.." - cluster_name = "${local.name}-al2023" - cluster_version = "1.33" + name = "${local.name}-al2023" + kubernetes_version = "1.33" # EKS Addons - cluster_addons = { + addons = { coredns = {} eks-pod-identity-agent = {} kube-proxy = {} diff --git a/examples/self-managed-node-group/eks-bottlerocket.tf b/examples/self-managed-node-group/eks-bottlerocket.tf index c1634fdd1d..bb46e90631 100644 --- a/examples/self-managed-node-group/eks-bottlerocket.tf +++ b/examples/self-managed-node-group/eks-bottlerocket.tf @@ -3,11 +3,11 @@ module "eks_bottlerocket" { # version = "~> 20.0" source = "../.." - cluster_name = "${local.name}-bottlerocket" - cluster_version = "1.33" + name = "${local.name}-bottlerocket" + kubernetes_version = "1.33" # EKS Addons - cluster_addons = { + addons = { coredns = {} eks-pod-identity-agent = {} kube-proxy = {} diff --git a/main.tf b/main.tf index a6383c6171..cde2b90508 100644 --- a/main.tf +++ b/main.tf @@ -21,12 +21,12 @@ locals { account_id = try(data.aws_caller_identity.current[0].account_id, "") partition = try(data.aws_partition.current[0].partition, "") - cluster_role = try(aws_iam_role.this[0].arn, var.iam_role_arn) + role_arn = try(aws_iam_role.this[0].arn, var.iam_role_arn) - create_outposts_local_cluster = var.outpost_config != null - enable_cluster_encryption_config = length(var.cluster_encryption_config) > 0 && !local.create_outposts_local_cluster + create_outposts_local_cluster = var.outpost_config != null + enable_encryption_config = length(var.encryption_config) > 0 && !local.create_outposts_local_cluster - auto_mode_enabled = try(var.cluster_compute_config.enabled, false) + auto_mode_enabled = try(var.compute_config.enabled, false) } ################################################################################ @@ -36,12 +36,12 @@ locals { resource "aws_eks_cluster" "this" { count = local.create ? 1 : 0 - name = var.cluster_name - role_arn = local.cluster_role - version = var.cluster_version - enabled_cluster_log_types = var.cluster_enabled_log_types + name = var.name + role_arn = local.role_arn + version = var.kubernetes_version + enabled_cluster_log_types = var.enabled_log_types bootstrap_self_managed_addons = false - force_update_version = var.cluster_force_update_version + force_update_version = var.force_update_version access_config { authentication_mode = var.authentication_mode @@ -55,7 +55,7 @@ resource "aws_eks_cluster" "this" { } dynamic "compute_config" { - for_each = var.cluster_compute_config != null ? [var.cluster_compute_config] : [] + for_each = var.compute_config != null ? [var.compute_config] : [] content { enabled = compute_config.value.enabled @@ -65,11 +65,11 @@ resource "aws_eks_cluster" "this" { } vpc_config { - security_group_ids = compact(distinct(concat(var.cluster_additional_security_group_ids, [local.cluster_security_group_id]))) + security_group_ids = compact(distinct(concat(var.additional_security_group_ids, [local.security_group_id]))) subnet_ids = coalescelist(var.control_plane_subnet_ids, var.subnet_ids) - endpoint_private_access = var.cluster_endpoint_private_access - endpoint_public_access = var.cluster_endpoint_public_access - public_access_cidrs = var.cluster_endpoint_public_access_cidrs + endpoint_private_access = var.endpoint_private_access + endpoint_public_access = var.endpoint_public_access + public_access_cidrs = var.endpoint_public_access_cidrs } dynamic "kubernetes_network_config" { @@ -85,9 +85,9 @@ resource "aws_eks_cluster" "this" { } } - ip_family = var.cluster_ip_family - service_ipv4_cidr = var.cluster_service_ipv4_cidr - service_ipv6_cidr = var.cluster_service_ipv6_cidr + ip_family = var.ip_family + service_ipv4_cidr = var.service_ipv4_cidr + service_ipv6_cidr = var.service_ipv6_cidr } } @@ -111,7 +111,7 @@ resource "aws_eks_cluster" "this" { dynamic "encryption_config" { # Not available on Outposts - for_each = local.enable_cluster_encryption_config ? [var.cluster_encryption_config] : [] + for_each = local.enable_encryption_config ? [var.encryption_config] : [] content { provider { @@ -123,7 +123,7 @@ resource "aws_eks_cluster" "this" { dynamic "remote_network_config" { # Not valid on Outposts - for_each = var.cluster_remote_network_config != null && !local.create_outposts_local_cluster ? [var.cluster_remote_network_config] : [] + for_each = var.remote_network_config != null && !local.create_outposts_local_cluster ? [var.remote_network_config] : [] content { dynamic "remote_node_networks" { @@ -155,7 +155,7 @@ resource "aws_eks_cluster" "this" { } dynamic "upgrade_policy" { - for_each = var.cluster_upgrade_policy != null ? [var.cluster_upgrade_policy] : [] + for_each = var.upgrade_policy != null ? [var.upgrade_policy] : [] content { support_type = upgrade_policy.value.support_type @@ -163,7 +163,7 @@ resource "aws_eks_cluster" "this" { } dynamic "zonal_shift_config" { - for_each = var.cluster_zonal_shift_config != null ? [var.cluster_zonal_shift_config] : [] + for_each = var.zonal_shift_config != null ? [var.zonal_shift_config] : [] content { enabled = zonal_shift_config.value.enabled @@ -177,12 +177,12 @@ resource "aws_eks_cluster" "this" { ) dynamic "timeouts" { - for_each = var.cluster_timeouts != null ? [var.cluster_timeouts] : [] + for_each = var.timeouts != null ? [var.timeouts] : [] content { - create = var.cluster_timeouts.create - update = var.cluster_timeouts.update - delete = var.cluster_timeouts.delete + create = var.timeouts.create + update = var.timeouts.update + delete = var.timeouts.delete } } @@ -206,7 +206,7 @@ resource "aws_ec2_tag" "cluster_primary_security_group" { # Ref: https://github.com/terraform-aws-modules/terraform-aws-eks/pull/2006 # Ref: https://github.com/terraform-aws-modules/terraform-aws-eks/pull/2008 for_each = { for k, v in merge(var.tags, var.cluster_tags) : - k => v if local.create && k != "Name" && var.create_cluster_primary_security_group_tags + k => v if local.create && k != "Name" && var.create_primary_security_group_tags } resource_id = aws_eks_cluster.this[0].vpc_config[0].cluster_security_group_id @@ -217,7 +217,7 @@ resource "aws_ec2_tag" "cluster_primary_security_group" { resource "aws_cloudwatch_log_group" "this" { count = local.create && var.create_cloudwatch_log_group ? 1 : 0 - name = "/aws/eks/${var.cluster_name}/cluster" + name = "/aws/eks/${var.name}/cluster" retention_in_days = var.cloudwatch_log_group_retention_in_days kms_key_id = var.cloudwatch_log_group_kms_key_id log_group_class = var.cloudwatch_log_group_class @@ -225,7 +225,7 @@ resource "aws_cloudwatch_log_group" "this" { tags = merge( var.tags, var.cloudwatch_log_group_tags, - { Name = "/aws/eks/${var.cluster_name}/cluster" } + { Name = "/aws/eks/${var.name}/cluster" } ) } @@ -320,9 +320,9 @@ module "kms" { source = "terraform-aws-modules/kms/aws" version = "4.0.0" # Note - be mindful of Terraform/provider version compatibility between modules - create = local.create && var.create_kms_key && local.enable_cluster_encryption_config # not valid on Outposts + create = local.create && var.create_kms_key && local.enable_encryption_config # not valid on Outposts - description = coalesce(var.kms_key_description, "${var.cluster_name} cluster encryption key") + description = coalesce(var.kms_key_description, "${var.name} cluster encryption key") key_usage = "ENCRYPT_DECRYPT" deletion_window_in_days = var.kms_key_deletion_window_in_days enable_key_rotation = var.enable_kms_key_rotation @@ -331,7 +331,7 @@ module "kms" { enable_default_policy = var.kms_key_enable_default_policy key_owners = var.kms_key_owners key_administrators = coalescelist(var.kms_key_administrators, [try(data.aws_iam_session_context.current[0].issuer_arn, "")]) - key_users = concat([local.cluster_role], var.kms_key_users) + key_users = concat([local.role_arn], var.kms_key_users) key_service_users = var.kms_key_service_users source_policy_documents = var.kms_key_source_policy_documents override_policy_documents = var.kms_key_override_policy_documents @@ -340,7 +340,7 @@ module "kms" { aliases = var.kms_key_aliases computed_aliases = { # Computed since users can pass in computed values for cluster name such as random provider resources - cluster = { name = "eks/${var.cluster_name}" } + cluster = { name = "eks/${var.name}" } } tags = merge( @@ -355,10 +355,10 @@ module "kms" { ################################################################################ locals { - cluster_sg_name = coalesce(var.cluster_security_group_name, "${var.cluster_name}-cluster") - create_cluster_sg = local.create && var.create_cluster_security_group + security_group_name = coalesce(var.security_group_name, "${var.name}-cluster") + create_security_group = local.create && var.create_security_group - cluster_security_group_id = local.create_cluster_sg ? aws_security_group.cluster[0].id : var.cluster_security_group_id + security_group_id = local.create_security_group ? aws_security_group.cluster[0].id : var.security_group_id # Do not add rules to node security group if the module is not creating it cluster_security_group_rules = { for k, v in { @@ -374,17 +374,17 @@ locals { } resource "aws_security_group" "cluster" { - count = local.create_cluster_sg ? 1 : 0 + count = local.create_security_group ? 1 : 0 - name = var.cluster_security_group_use_name_prefix ? null : local.cluster_sg_name - name_prefix = var.cluster_security_group_use_name_prefix ? "${local.cluster_sg_name}${var.prefix_separator}" : null - description = var.cluster_security_group_description + name = var.security_group_use_name_prefix ? null : local.security_group_name + name_prefix = var.security_group_use_name_prefix ? "${local.security_group_name}${var.prefix_separator}" : null + description = var.security_group_description vpc_id = var.vpc_id tags = merge( var.tags, - { "Name" = local.cluster_sg_name }, - var.cluster_security_group_tags + { "Name" = local.security_group_name }, + var.security_group_tags ) lifecycle { @@ -395,8 +395,8 @@ resource "aws_security_group" "cluster" { resource "aws_security_group_rule" "cluster" { for_each = { for k, v in merge( local.cluster_security_group_rules, - var.cluster_security_group_additional_rules - ) : k => v if local.create_cluster_sg } + var.security_group_additional_rules + ) : k => v if local.create_security_group } security_group_id = aws_security_group.cluster[0].id protocol = each.value.protocol @@ -439,7 +439,7 @@ resource "aws_iam_openid_connect_provider" "oidc_provider" { url = aws_eks_cluster.this[0].identity[0].oidc[0].issuer tags = merge( - { Name = "${var.cluster_name}-eks-irsa" }, + { Name = "${var.name}-eks-irsa" }, var.tags ) } @@ -450,10 +450,10 @@ resource "aws_iam_openid_connect_provider" "oidc_provider" { locals { create_iam_role = local.create && var.create_iam_role - iam_role_name = coalesce(var.iam_role_name, "${var.cluster_name}-cluster") + iam_role_name = coalesce(var.iam_role_name, "${var.name}-cluster") iam_role_policy_prefix = "arn:${local.partition}:iam::aws:policy" - cluster_encryption_policy_name = coalesce(var.cluster_encryption_policy_name, "${local.iam_role_name}-ClusterEncryption") + cluster_encryption_policy_name = coalesce(var.encryption_policy_name, "${local.iam_role_name}-ClusterEncryption") # Standard EKS cluster eks_standard_iam_role_policies = { for k, v in { @@ -538,7 +538,7 @@ resource "aws_iam_role_policy_attachment" "additional" { # Using separate attachment due to `The "for_each" value depends on resource attributes that cannot be determined until apply` resource "aws_iam_role_policy_attachment" "cluster_encryption" { # Encryption config not available on Outposts - count = local.create_iam_role && var.attach_cluster_encryption_policy && local.enable_cluster_encryption_config ? 1 : 0 + count = local.create_iam_role && var.attach_encryption_policy && local.enable_encryption_config ? 1 : 0 policy_arn = aws_iam_policy.cluster_encryption[0].arn role = aws_iam_role.this[0].name @@ -546,12 +546,12 @@ resource "aws_iam_role_policy_attachment" "cluster_encryption" { resource "aws_iam_policy" "cluster_encryption" { # Encryption config not available on Outposts - count = local.create_iam_role && var.attach_cluster_encryption_policy && local.enable_cluster_encryption_config ? 1 : 0 + count = local.create_iam_role && var.attach_encryption_policy && local.enable_encryption_config ? 1 : 0 - name = var.cluster_encryption_policy_use_name_prefix ? null : local.cluster_encryption_policy_name - name_prefix = var.cluster_encryption_policy_use_name_prefix ? local.cluster_encryption_policy_name : null - description = var.cluster_encryption_policy_description - path = var.cluster_encryption_policy_path + name = var.encryption_policy_use_name_prefix ? null : local.cluster_encryption_policy_name + name_prefix = var.encryption_policy_use_name_prefix ? local.cluster_encryption_policy_name : null + description = var.encryption_policy_description + path = var.encryption_policy_path policy = jsonencode({ Version = "2012-10-17" @@ -564,12 +564,12 @@ resource "aws_iam_policy" "cluster_encryption" { "kms:DescribeKey", ] Effect = "Allow" - Resource = var.create_kms_key ? module.kms.key_arn : var.cluster_encryption_config.provider_key_arn + Resource = var.create_kms_key ? module.kms.key_arn : var.encryption_config.provider_key_arn }, ] }) - tags = merge(var.tags, var.cluster_encryption_policy_tags) + tags = merge(var.tags, var.encryption_policy_tags) } data "aws_iam_policy_document" "custom" { @@ -731,16 +731,16 @@ resource "aws_iam_role_policy_attachment" "custom" { ################################################################################ data "aws_eks_addon_version" "this" { - for_each = var.cluster_addons != null && local.create && !local.create_outposts_local_cluster ? var.cluster_addons : {} + for_each = var.addons != null && local.create && !local.create_outposts_local_cluster ? var.addons : {} addon_name = try(each.value.name, each.key) - kubernetes_version = coalesce(var.cluster_version, aws_eks_cluster.this[0].version) + kubernetes_version = coalesce(var.kubernetes_version, aws_eks_cluster.this[0].version) most_recent = each.value.most_recent } resource "aws_eks_addon" "this" { # Not supported on outposts - for_each = var.cluster_addons != null && local.create && !local.create_outposts_local_cluster ? { for k, v in var.cluster_addons : k => v if !v.before_compute } : {} + for_each = var.addons != null && local.create && !local.create_outposts_local_cluster ? { for k, v in var.addons : k => v if !v.before_compute } : {} cluster_name = aws_eks_cluster.this[0].id addon_name = try(each.value.name, each.key) @@ -763,9 +763,9 @@ resource "aws_eks_addon" "this" { service_account_role_arn = each.value.service_account_role_arn timeouts { - create = try(each.value.timeouts.create, var.cluster_addons_timeouts.create, null) - update = try(each.value.timeouts.update, var.cluster_addons_timeouts.update, null) - delete = try(each.value.timeouts.delete, var.cluster_addons_timeouts.delete, null) + create = try(each.value.timeouts.create, var.addons_timeouts.create, null) + update = try(each.value.timeouts.update, var.addons_timeouts.update, null) + delete = try(each.value.timeouts.delete, var.addons_timeouts.delete, null) } tags = merge( @@ -783,7 +783,7 @@ resource "aws_eks_addon" "this" { resource "aws_eks_addon" "before_compute" { # Not supported on outposts - for_each = var.cluster_addons != null && local.create && !local.create_outposts_local_cluster ? { for k, v in var.cluster_addons : k => v if v.before_compute } : {} + for_each = var.addons != null && local.create && !local.create_outposts_local_cluster ? { for k, v in var.addons : k => v if v.before_compute } : {} cluster_name = aws_eks_cluster.this[0].id addon_name = try(each.value.name, each.key) @@ -806,9 +806,9 @@ resource "aws_eks_addon" "before_compute" { service_account_role_arn = each.value.service_account_role_arn timeouts { - create = try(each.value.timeouts.create, var.cluster_addons_timeouts.create, null) - update = try(each.value.timeouts.update, var.cluster_addons_timeouts.update, null) - delete = try(each.value.timeouts.delete, var.cluster_addons_timeouts.delete, null) + create = try(each.value.timeouts.create, var.addons_timeouts.create, null) + update = try(each.value.timeouts.update, var.addons_timeouts.update, null) + delete = try(each.value.timeouts.delete, var.addons_timeouts.delete, null) } tags = merge( @@ -823,7 +823,7 @@ resource "aws_eks_addon" "before_compute" { ################################################################################ resource "aws_eks_identity_provider_config" "this" { - for_each = var.cluster_identity_providers != null && local.create && !local.create_outposts_local_cluster ? var.cluster_identity_providers : {} + for_each = var.identity_providers != null && local.create && !local.create_outposts_local_cluster ? var.identity_providers : {} cluster_name = aws_eks_cluster.this[0].id @@ -850,7 +850,7 @@ resource "aws_eks_identity_provider_config" "this" { locals { create_node_iam_role = local.create && var.create_node_iam_role && local.auto_mode_enabled - node_iam_role_name = coalesce(var.node_iam_role_name, "${var.cluster_name}-eks-auto") + node_iam_role_name = coalesce(var.node_iam_role_name, "${var.name}-eks-auto") } data "aws_iam_policy_document" "node_assume_role_policy" { diff --git a/modules/eks-managed-node-group/README.md b/modules/eks-managed-node-group/README.md index 4f310e5df3..f03067e2ad 100644 --- a/modules/eks-managed-node-group/README.md +++ b/modules/eks-managed-node-group/README.md @@ -116,7 +116,6 @@ module "eks_managed_node_group" { | [cluster\_name](#input\_cluster\_name) | Name of associated EKS cluster | `string` | `null` | no | | [cluster\_primary\_security\_group\_id](#input\_cluster\_primary\_security\_group\_id) | The ID of the EKS cluster primary security group to associate with the instance(s). This is the security group that is automatically created by the EKS service | `string` | `null` | no | | [cluster\_service\_cidr](#input\_cluster\_service\_cidr) | The CIDR block (IPv4 or IPv6) used by the cluster to assign Kubernetes service IP addresses. This is derived from the cluster itself | `string` | `""` | no | -| [cluster\_version](#input\_cluster\_version) | Kubernetes version. Defaults to EKS Cluster Kubernetes version | `string` | `null` | no | | [cpu\_options](#input\_cpu\_options) | The CPU options for the instance |
object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
})
| `null` | no | | [create](#input\_create) | Determines whether to create EKS managed node group or not | `bool` | `true` | no | | [create\_iam\_role](#input\_create\_iam\_role) | Determines whether an IAM role is created or to use an existing IAM role | `bool` | `true` | no | @@ -149,6 +148,7 @@ module "eks_managed_node_group" { | [instance\_types](#input\_instance\_types) | Set of instance types associated with the EKS Node Group. Defaults to `["t3.medium"]` | `list(string)` | `null` | no | | [kernel\_id](#input\_kernel\_id) | The kernel ID | `string` | `null` | no | | [key\_name](#input\_key\_name) | The key name that should be used for the instance(s) | `string` | `null` | no | +| [kubernetes\_version](#input\_kubernetes\_version) | Kubernetes version. Defaults to EKS Cluster Kubernetes version | `string` | `null` | no | | [labels](#input\_labels) | Key-value map of Kubernetes labels. Only labels that are applied with the EKS API are managed by this argument. Other Kubernetes labels applied to the EKS Node Group will not be managed | `map(string)` | `null` | no | | [launch\_template\_default\_version](#input\_launch\_template\_default\_version) | Default version of the launch template | `string` | `null` | no | | [launch\_template\_description](#input\_launch\_template\_description) | Description of the launch template | `string` | `null` | no | @@ -180,7 +180,7 @@ module "eks_managed_node_group" { | [update\_config](#input\_update\_config) | Configuration block of settings for max unavailable resources during node group updates |
object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
})
|
{
"max_unavailable_percentage": 33
}
| no | | [update\_launch\_template\_default\_version](#input\_update\_launch\_template\_default\_version) | Whether to update the launch templates default version on each update. Conflicts with `launch_template_default_version` | `bool` | `true` | no | | [use\_custom\_launch\_template](#input\_use\_custom\_launch\_template) | Determines whether to use a custom launch template or not. If set to `false`, EKS will use its own default launch template | `bool` | `true` | no | -| [use\_latest\_ami\_release\_version](#input\_use\_latest\_ami\_release\_version) | Determines whether to use the latest AMI release version for the given `ami_type` (except for `CUSTOM`). Note: `ami_type` and `cluster_version` must be supplied in order to enable this feature | `bool` | `true` | no | +| [use\_latest\_ami\_release\_version](#input\_use\_latest\_ami\_release\_version) | Determines whether to use the latest AMI release version for the given `ami_type` (except for `CUSTOM`). Note: `ami_type` and `kubernetes_version` must be supplied in order to enable this feature | `bool` | `true` | no | | [use\_name\_prefix](#input\_use\_name\_prefix) | Determines whether to use `name` as is or create a unique name beginning with the `name` as the prefix | `bool` | `true` | no | | [user\_data\_template\_path](#input\_user\_data\_template\_path) | Path to a local, custom user data template file to use when rendering user data | `string` | `""` | no | | [vpc\_security\_group\_ids](#input\_vpc\_security\_group\_ids) | A list of security group IDs to associate | `list(string)` | `[]` | no | diff --git a/modules/eks-managed-node-group/main.tf b/modules/eks-managed-node-group/main.tf index 90850f0edb..8b0df59819 100644 --- a/modules/eks-managed-node-group/main.tf +++ b/modules/eks-managed-node-group/main.tf @@ -293,7 +293,7 @@ resource "aws_launch_template" "this" { primary_ipv6 = network_interfaces.value.primary_ipv6 private_ip_address = network_interfaces.value.private_ip_address # Ref: https://github.com/hashicorp/terraform-provider-aws/issues/4570 - security_groups = compact(concat(network_interfaces.value.security_groups, var.security_groups)) + security_groups = compact(concat(network_interfaces.value.security_groups, var.vpc_security_group_ids)) # Set on EKS managed node group, will fail if set here # https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-basics # subnet_id = try(network_interfaces.value.subnet_id, null) @@ -363,30 +363,30 @@ resource "aws_launch_template" "this" { locals { # Just to ensure templating doesn't fail when values are not provided - ssm_cluster_version = var.cluster_version != null ? var.cluster_version : "" - ssm_ami_type = var.ami_type != null ? var.ami_type : "" + ssm_kubernetes_version = var.kubernetes_version != null ? var.kubernetes_version : "" + ssm_ami_type = var.ami_type != null ? var.ami_type : "" # Map the AMI type to the respective SSM param path ssm_ami_type_to_ssm_param = { - AL2_x86_64 = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2/recommended/release_version" - AL2_x86_64_GPU = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2-gpu/recommended/release_version" - AL2_ARM_64 = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2-arm64/recommended/release_version" + AL2_x86_64 = "/aws/service/eks/optimized-ami/${local.ssm_kubernetes_version}/amazon-linux-2/recommended/release_version" + AL2_x86_64_GPU = "/aws/service/eks/optimized-ami/${local.ssm_kubernetes_version}/amazon-linux-2-gpu/recommended/release_version" + AL2_ARM_64 = "/aws/service/eks/optimized-ami/${local.ssm_kubernetes_version}/amazon-linux-2-arm64/recommended/release_version" CUSTOM = "NONE" - BOTTLEROCKET_ARM_64 = "/aws/service/bottlerocket/aws-k8s-${local.ssm_cluster_version}/arm64/latest/image_version" - BOTTLEROCKET_x86_64 = "/aws/service/bottlerocket/aws-k8s-${local.ssm_cluster_version}/x86_64/latest/image_version" - BOTTLEROCKET_ARM_64_FIPS = "/aws/service/bottlerocket/aws-k8s-${local.ssm_cluster_version}-fips/arm64/latest/image_version" - BOTTLEROCKET_x86_64_FIPS = "/aws/service/bottlerocket/aws-k8s-${local.ssm_cluster_version}-fips/x86_64/latest/image_version" - BOTTLEROCKET_ARM_64_NVIDIA = "/aws/service/bottlerocket/aws-k8s-${local.ssm_cluster_version}-nvidia/arm64/latest/image_version" - BOTTLEROCKET_x86_64_NVIDIA = "/aws/service/bottlerocket/aws-k8s-${local.ssm_cluster_version}-nvidia/x86_64/latest/image_version" - WINDOWS_CORE_2019_x86_64 = "/aws/service/ami-windows-latest/Windows_Server-2019-English-Full-EKS_Optimized-${local.ssm_cluster_version}" - WINDOWS_FULL_2019_x86_64 = "/aws/service/ami-windows-latest/Windows_Server-2019-English-Core-EKS_Optimized-${local.ssm_cluster_version}" - WINDOWS_CORE_2022_x86_64 = "/aws/service/ami-windows-latest/Windows_Server-2022-English-Full-EKS_Optimized-${local.ssm_cluster_version}" - WINDOWS_FULL_2022_x86_64 = "/aws/service/ami-windows-latest/Windows_Server-2022-English-Core-EKS_Optimized-${local.ssm_cluster_version}" - AL2023_x86_64_STANDARD = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2023/x86_64/standard/recommended/release_version" - AL2023_ARM_64_STANDARD = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2023/arm64/standard/recommended/release_version" - AL2023_x86_64_NEURON = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2023/x86_64/neuron/recommended/release_version" - AL2023_x86_64_NVIDIA = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2023/x86_64/nvidia/recommended/release_version" - AL2023_ARM_64_NVIDIA = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2023/arm64/nvidia/recommended/release_version" + BOTTLEROCKET_ARM_64 = "/aws/service/bottlerocket/aws-k8s-${local.ssm_kubernetes_version}/arm64/latest/image_version" + BOTTLEROCKET_x86_64 = "/aws/service/bottlerocket/aws-k8s-${local.ssm_kubernetes_version}/x86_64/latest/image_version" + BOTTLEROCKET_ARM_64_FIPS = "/aws/service/bottlerocket/aws-k8s-${local.ssm_kubernetes_version}-fips/arm64/latest/image_version" + BOTTLEROCKET_x86_64_FIPS = "/aws/service/bottlerocket/aws-k8s-${local.ssm_kubernetes_version}-fips/x86_64/latest/image_version" + BOTTLEROCKET_ARM_64_NVIDIA = "/aws/service/bottlerocket/aws-k8s-${local.ssm_kubernetes_version}-nvidia/arm64/latest/image_version" + BOTTLEROCKET_x86_64_NVIDIA = "/aws/service/bottlerocket/aws-k8s-${local.ssm_kubernetes_version}-nvidia/x86_64/latest/image_version" + WINDOWS_CORE_2019_x86_64 = "/aws/service/ami-windows-latest/Windows_Server-2019-English-Full-EKS_Optimized-${local.ssm_kubernetes_version}" + WINDOWS_FULL_2019_x86_64 = "/aws/service/ami-windows-latest/Windows_Server-2019-English-Core-EKS_Optimized-${local.ssm_kubernetes_version}" + WINDOWS_CORE_2022_x86_64 = "/aws/service/ami-windows-latest/Windows_Server-2022-English-Full-EKS_Optimized-${local.ssm_kubernetes_version}" + WINDOWS_FULL_2022_x86_64 = "/aws/service/ami-windows-latest/Windows_Server-2022-English-Core-EKS_Optimized-${local.ssm_kubernetes_version}" + AL2023_x86_64_STANDARD = "/aws/service/eks/optimized-ami/${local.ssm_kubernetes_version}/amazon-linux-2023/x86_64/standard/recommended/release_version" + AL2023_ARM_64_STANDARD = "/aws/service/eks/optimized-ami/${local.ssm_kubernetes_version}/amazon-linux-2023/arm64/standard/recommended/release_version" + AL2023_x86_64_NEURON = "/aws/service/eks/optimized-ami/${local.ssm_kubernetes_version}/amazon-linux-2023/x86_64/neuron/recommended/release_version" + AL2023_x86_64_NVIDIA = "/aws/service/eks/optimized-ami/${local.ssm_kubernetes_version}/amazon-linux-2023/x86_64/nvidia/recommended/release_version" + AL2023_ARM_64_NVIDIA = "/aws/service/eks/optimized-ami/${local.ssm_kubernetes_version}/amazon-linux-2023/arm64/nvidia/recommended/release_version" } # The Windows SSM params currently do not have a release version, so we have to get the full output JSON blob and parse out the release version @@ -432,7 +432,7 @@ resource "aws_eks_node_group" "this" { # https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-custom-ami ami_type = var.ami_id != "" ? null : var.ami_type release_version = var.ami_id != "" ? null : var.use_latest_ami_release_version ? local.latest_ami_release_version : var.ami_release_version - version = var.ami_id != "" ? null : var.cluster_version + version = var.ami_id != "" ? null : var.kubernetes_version capacity_type = var.capacity_type disk_size = var.use_custom_launch_template ? null : var.disk_size # if using a custom LT, set disk size on custom LT or else it will error here diff --git a/modules/eks-managed-node-group/variables.tf b/modules/eks-managed-node-group/variables.tf index 294563dc7b..3131913eb9 100644 --- a/modules/eks-managed-node-group/variables.tf +++ b/modules/eks-managed-node-group/variables.tf @@ -466,7 +466,7 @@ variable "ami_release_version" { } variable "use_latest_ami_release_version" { - description = "Determines whether to use the latest AMI release version for the given `ami_type` (except for `CUSTOM`). Note: `ami_type` and `cluster_version` must be supplied in order to enable this feature" + description = "Determines whether to use the latest AMI release version for the given `ami_type` (except for `CUSTOM`). Note: `ami_type` and `kubernetes_version` must be supplied in order to enable this feature" type = bool default = true } @@ -501,7 +501,7 @@ variable "labels" { default = null } -variable "cluster_version" { +variable "kubernetes_version" { description = "Kubernetes version. Defaults to EKS Cluster Kubernetes version" type = string default = null diff --git a/modules/self-managed-node-group/README.md b/modules/self-managed-node-group/README.md index acbd12fa70..4a2f6d806f 100644 --- a/modules/self-managed-node-group/README.md +++ b/modules/self-managed-node-group/README.md @@ -10,7 +10,7 @@ module "self_managed_node_group" { name = "separate-self-mng" cluster_name = "my-cluster" - cluster_version = "1.31" + kubernetes_version = "1.31" cluster_endpoint = "https://012345678903AB2BAE5D1E0BFE0E2B50.gr7.us-east-1.eks.amazonaws.com" cluster_auth_base64 = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKbXFqQ1VqNGdGR2w3ZW5PeWthWnZ2RjROOTVOUEZCM2o0cGhVZUsrWGFtN2ZSQnZya0d6OGxKZmZEZWF2b2plTwpQK2xOZFlqdHZncmxCUEpYdHZIZmFzTzYxVzdIZmdWQ2EvamdRM2w3RmkvL1dpQmxFOG9oWUZkdWpjc0s1SXM2CnNkbk5KTTNYUWN2TysrSitkV09NT2ZlNzlsSWdncmdQLzgvRU9CYkw3eUY1aU1hS3lsb1RHL1V3TlhPUWt3ZUcKblBNcjdiUmdkQ1NCZTlXYXowOGdGRmlxV2FOditsTDhsODBTdFZLcWVNVlUxbjQyejVwOVpQRTd4T2l6L0xTNQpYV2lXWkVkT3pMN0xBWGVCS2gzdkhnczFxMkI2d1BKZnZnS1NzWllQRGFpZTloT1NNOUJkNFNPY3JrZTRYSVBOCkVvcXVhMlYrUDRlTWJEQzhMUkVWRDdCdVZDdWdMTldWOTBoL3VJUy9WU2VOcEdUOGVScE5DakszSjc2aFlsWm8KWjNGRG5QWUY0MWpWTHhiOXF0U1ROdEp6amYwWXBEYnFWci9xZzNmQWlxbVorMzd3YWM1eHlqMDZ4cmlaRUgzZgpUM002d2lCUEVHYVlGeWN5TmNYTk5aYW9DWDJVL0N1d2JsUHAKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==" @@ -99,7 +99,6 @@ module "self_managed_node_group" { | [cluster\_name](#input\_cluster\_name) | Name of associated EKS cluster | `string` | `""` | no | | [cluster\_primary\_security\_group\_id](#input\_cluster\_primary\_security\_group\_id) | The ID of the EKS cluster primary security group to associate with the instance(s). This is the security group that is automatically created by the EKS service | `string` | `null` | no | | [cluster\_service\_cidr](#input\_cluster\_service\_cidr) | The CIDR block (IPv4 or IPv6) used by the cluster to assign Kubernetes service IP addresses. This is derived from the cluster itself | `string` | `""` | no | -| [cluster\_version](#input\_cluster\_version) | Kubernetes cluster version - used to lookup default AMI ID if one is not provided | `string` | `null` | no | | [context](#input\_context) | Reserved | `string` | `null` | no | | [cpu\_options](#input\_cpu\_options) | The CPU options for the instance |
object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
})
| `null` | no | | [create](#input\_create) | Determines whether to create self managed node group or not | `bool` | `true` | no | @@ -148,6 +147,7 @@ module "self_managed_node_group" { | [instance\_type](#input\_instance\_type) | The type of the instance to launch | `string` | `null` | no | | [kernel\_id](#input\_kernel\_id) | The kernel ID | `string` | `null` | no | | [key\_name](#input\_key\_name) | The key name that should be used for the instance | `string` | `null` | no | +| [kubernetes\_version](#input\_kubernetes\_version) | Kubernetes cluster version - used to lookup default AMI ID if one is not provided | `string` | `null` | no | | [launch\_template\_default\_version](#input\_launch\_template\_default\_version) | Default Version of the launch template | `string` | `null` | no | | [launch\_template\_description](#input\_launch\_template\_description) | Description of the launch template | `string` | `null` | no | | [launch\_template\_id](#input\_launch\_template\_id) | The ID of an existing launch template to use. Required when `create_launch_template` = `false` | `string` | `""` | no | diff --git a/modules/self-managed-node-group/main.tf b/modules/self-managed-node-group/main.tf index 6718d48dca..13cd6febf6 100644 --- a/modules/self-managed-node-group/main.tf +++ b/modules/self-managed-node-group/main.tf @@ -16,28 +16,28 @@ locals { locals { # Just to ensure templating doesn't fail when values are not provided - ssm_cluster_version = var.cluster_version != null ? var.cluster_version : "" + ssm_kubernetes_version = var.kubernetes_version != null ? var.kubernetes_version : "" # Map the AMI type to the respective SSM param path ami_type_to_ssm_param = { - AL2_x86_64 = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2/recommended/image_id" - AL2_x86_64_GPU = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2-gpu/recommended/image_id" - AL2_ARM_64 = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2-arm64/recommended/image_id" - BOTTLEROCKET_ARM_64 = "/aws/service/bottlerocket/aws-k8s-${local.ssm_cluster_version}/arm64/latest/image_id" - BOTTLEROCKET_x86_64 = "/aws/service/bottlerocket/aws-k8s-${local.ssm_cluster_version}/x86_64/latest/image_id" - BOTTLEROCKET_ARM_64_FIPS = "/aws/service/bottlerocket/aws-k8s-${local.ssm_cluster_version}-fips/arm64/latest/image_id" - BOTTLEROCKET_x86_64_FIPS = "/aws/service/bottlerocket/aws-k8s-${local.ssm_cluster_version}-fips/x86_64/latest/image_id" - BOTTLEROCKET_ARM_64_NVIDIA = "/aws/service/bottlerocket/aws-k8s-${local.ssm_cluster_version}-nvidia/arm64/latest/image_id" - BOTTLEROCKET_x86_64_NVIDIA = "/aws/service/bottlerocket/aws-k8s-${local.ssm_cluster_version}-nvidia/x86_64/latest/image_id" - WINDOWS_CORE_2019_x86_64 = "/aws/service/ami-windows-latest/Windows_Server-2019-English-Full-EKS_Optimized-${local.ssm_cluster_version}/image_id" - WINDOWS_FULL_2019_x86_64 = "/aws/service/ami-windows-latest/Windows_Server-2019-English-Core-EKS_Optimized-${local.ssm_cluster_version}/image_id" - WINDOWS_CORE_2022_x86_64 = "/aws/service/ami-windows-latest/Windows_Server-2022-English-Full-EKS_Optimized-${local.ssm_cluster_version}/image_id" - WINDOWS_FULL_2022_x86_64 = "/aws/service/ami-windows-latest/Windows_Server-2022-English-Core-EKS_Optimized-${local.ssm_cluster_version}/image_id" - AL2023_x86_64_STANDARD = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2023/x86_64/standard/recommended/image_id" - AL2023_ARM_64_STANDARD = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2023/arm64/standard/recommended/image_id" - AL2023_x86_64_NEURON = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2023/x86_64/neuron/recommended/image_id" - AL2023_x86_64_NVIDIA = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2023/x86_64/nvidia/recommended/image_id" - AL2023_ARM_64_NVIDIA = "/aws/service/eks/optimized-ami/${local.ssm_cluster_version}/amazon-linux-2023/arm64/nvidia/recommended/image_id" + AL2_x86_64 = "/aws/service/eks/optimized-ami/${local.ssm_kubernetes_version}/amazon-linux-2/recommended/image_id" + AL2_x86_64_GPU = "/aws/service/eks/optimized-ami/${local.ssm_kubernetes_version}/amazon-linux-2-gpu/recommended/image_id" + AL2_ARM_64 = "/aws/service/eks/optimized-ami/${local.ssm_kubernetes_version}/amazon-linux-2-arm64/recommended/image_id" + BOTTLEROCKET_ARM_64 = "/aws/service/bottlerocket/aws-k8s-${local.ssm_kubernetes_version}/arm64/latest/image_id" + BOTTLEROCKET_x86_64 = "/aws/service/bottlerocket/aws-k8s-${local.ssm_kubernetes_version}/x86_64/latest/image_id" + BOTTLEROCKET_ARM_64_FIPS = "/aws/service/bottlerocket/aws-k8s-${local.ssm_kubernetes_version}-fips/arm64/latest/image_id" + BOTTLEROCKET_x86_64_FIPS = "/aws/service/bottlerocket/aws-k8s-${local.ssm_kubernetes_version}-fips/x86_64/latest/image_id" + BOTTLEROCKET_ARM_64_NVIDIA = "/aws/service/bottlerocket/aws-k8s-${local.ssm_kubernetes_version}-nvidia/arm64/latest/image_id" + BOTTLEROCKET_x86_64_NVIDIA = "/aws/service/bottlerocket/aws-k8s-${local.ssm_kubernetes_version}-nvidia/x86_64/latest/image_id" + WINDOWS_CORE_2019_x86_64 = "/aws/service/ami-windows-latest/Windows_Server-2019-English-Full-EKS_Optimized-${local.ssm_kubernetes_version}/image_id" + WINDOWS_FULL_2019_x86_64 = "/aws/service/ami-windows-latest/Windows_Server-2019-English-Core-EKS_Optimized-${local.ssm_kubernetes_version}/image_id" + WINDOWS_CORE_2022_x86_64 = "/aws/service/ami-windows-latest/Windows_Server-2022-English-Full-EKS_Optimized-${local.ssm_kubernetes_version}/image_id" + WINDOWS_FULL_2022_x86_64 = "/aws/service/ami-windows-latest/Windows_Server-2022-English-Core-EKS_Optimized-${local.ssm_kubernetes_version}/image_id" + AL2023_x86_64_STANDARD = "/aws/service/eks/optimized-ami/${local.ssm_kubernetes_version}/amazon-linux-2023/x86_64/standard/recommended/image_id" + AL2023_ARM_64_STANDARD = "/aws/service/eks/optimized-ami/${local.ssm_kubernetes_version}/amazon-linux-2023/arm64/standard/recommended/image_id" + AL2023_x86_64_NEURON = "/aws/service/eks/optimized-ami/${local.ssm_kubernetes_version}/amazon-linux-2023/x86_64/neuron/recommended/image_id" + AL2023_x86_64_NVIDIA = "/aws/service/eks/optimized-ami/${local.ssm_kubernetes_version}/amazon-linux-2023/x86_64/nvidia/recommended/image_id" + AL2023_ARM_64_NVIDIA = "/aws/service/eks/optimized-ami/${local.ssm_kubernetes_version}/amazon-linux-2023/arm64/nvidia/recommended/image_id" } } @@ -417,7 +417,7 @@ resource "aws_launch_template" "this" { primary_ipv6 = network_interfaces.value.primary_ipv6 private_ip_address = network_interfaces.value.private_ip_address # Ref: https://github.com/hashicorp/terraform-provider-aws/issues/4570 - security_groups = compact(concat(network_interfaces.value.security_groups, var.security_groups)) + security_groups = compact(concat(network_interfaces.value.security_groups, var.vpc_security_group_ids)) # Set on EKS managed node group, will fail if set here # https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-basics # subnet_id = try(network_interfaces.value.subnet_id, null) diff --git a/modules/self-managed-node-group/variables.tf b/modules/self-managed-node-group/variables.tf index 29fc0bd2d8..a36b99d431 100644 --- a/modules/self-managed-node-group/variables.tf +++ b/modules/self-managed-node-group/variables.tf @@ -363,7 +363,7 @@ variable "ami_type" { default = "AL2023_x86_64_STANDARD" } -variable "cluster_version" { +variable "kubernetes_version" { description = "Kubernetes cluster version - used to lookup default AMI ID if one is not provided" type = string default = null diff --git a/node_groups.tf b/node_groups.tf index f9874dc448..e7d5a676b9 100644 --- a/node_groups.tf +++ b/node_groups.tf @@ -15,8 +15,8 @@ resource "time_sleep" "this" { triggers = { cluster_name = aws_eks_cluster.this[0].id cluster_endpoint = aws_eks_cluster.this[0].endpoint - cluster_version = aws_eks_cluster.this[0].version - cluster_service_cidr = var.cluster_ip_family == "ipv6" ? try(local.kubernetes_network_config.service_ipv6_cidr, "") : try(local.kubernetes_network_config.service_ipv4_cidr, "") + kubernetes_version = aws_eks_cluster.this[0].version + cluster_service_cidr = var.ip_family == "ipv6" ? try(local.kubernetes_network_config.service_ipv6_cidr, "") : try(local.kubernetes_network_config.service_ipv4_cidr, "") cluster_certificate_authority_data = aws_eks_cluster.this[0].certificate_authority[0].data } @@ -68,7 +68,7 @@ resource "aws_iam_policy" "cni_ipv6_policy" { ################################################################################ locals { - node_sg_name = coalesce(var.node_security_group_name, "${var.cluster_name}-node") + node_sg_name = coalesce(var.node_security_group_name, "${var.name}-node") create_node_sg = var.create && var.create_node_security_group node_security_group_id = local.create_node_sg ? aws_security_group.node[0].id : var.node_security_group_id @@ -160,7 +160,7 @@ locals { to_port = 0 type = "egress" cidr_blocks = ["0.0.0.0/0"] - ipv6_cidr_blocks = var.cluster_ip_family == "ipv6" ? ["::/0"] : null + ipv6_cidr_blocks = var.ip_family == "ipv6" ? ["::/0"] : null } } : k => v if var.node_security_group_enable_recommended_rules } @@ -197,8 +197,8 @@ resource "aws_security_group" "node" { tags = merge( var.tags, { - "Name" = local.node_sg_name - "kubernetes.io/cluster/${var.cluster_name}" = "owned" + "Name" = local.node_sg_name + "kubernetes.io/cluster/${var.name}" = "owned" }, var.node_security_group_tags ) @@ -226,7 +226,7 @@ resource "aws_security_group_rule" "node" { ipv6_cidr_blocks = each.value.ipv6_cidr_blocks prefix_list_ids = each.value.prefix_list_ids self = each.value.self - source_security_group_id = each.value.source_cluster_security_group ? local.cluster_security_group_id : each.value.source_security_group_id + source_security_group_id = each.value.source_cluster_security_group ? local.security_group_id : each.value.source_security_group_id } ################################################################################ @@ -246,7 +246,7 @@ module "fargate_profile" { # Fargate Profile cluster_name = time_sleep.this[0].triggers["cluster_name"] - cluster_ip_family = var.cluster_ip_family + cluster_ip_family = var.ip_family name = try(each.value.name, each.key) subnet_ids = try(each.value.subnet_ids, var.fargate_profile_defaults.subnet_ids, var.subnet_ids) selectors = try(each.value.selectors, var.fargate_profile_defaults.selectors, null) @@ -288,8 +288,8 @@ module "eks_managed_node_group" { partition = local.partition account_id = local.account_id - cluster_name = time_sleep.this[0].triggers["cluster_name"] - cluster_version = try(each.value.cluster_version, var.eks_managed_node_group_defaults.cluster_version, time_sleep.this[0].triggers["cluster_version"]) + cluster_name = time_sleep.this[0].triggers["cluster_name"] + kubernetes_version = try(each.value.kubernetes_version, var.eks_managed_node_group_defaults.kubernetes_version, time_sleep.this[0].triggers["kubernetes_version"]) # EKS Managed Node Group name = try(each.value.name, each.key) @@ -320,7 +320,7 @@ module "eks_managed_node_group" { # User data cluster_endpoint = try(time_sleep.this[0].triggers["cluster_endpoint"], "") cluster_auth_base64 = try(time_sleep.this[0].triggers["cluster_certificate_authority_data"], "") - cluster_ip_family = var.cluster_ip_family + cluster_ip_family = var.ip_family cluster_service_cidr = try(time_sleep.this[0].triggers["cluster_service_cidr"], "") enable_bootstrap_user_data = try(each.value.enable_bootstrap_user_data, var.eks_managed_node_group_defaults.enable_bootstrap_user_data, null) pre_bootstrap_user_data = try(each.value.pre_bootstrap_user_data, var.eks_managed_node_group_defaults.pre_bootstrap_user_data, null) @@ -465,7 +465,7 @@ module "self_managed_node_group" { cluster_auth_base64 = try(time_sleep.this[0].triggers["cluster_certificate_authority_data"], "") cluster_service_cidr = try(time_sleep.this[0].triggers["cluster_service_cidr"], "") additional_cluster_dns_ips = try(each.value.additional_cluster_dns_ips, var.self_managed_node_group_defaults.additional_cluster_dns_ips, null) - cluster_ip_family = var.cluster_ip_family + cluster_ip_family = var.ip_family pre_bootstrap_user_data = try(each.value.pre_bootstrap_user_data, var.self_managed_node_group_defaults.pre_bootstrap_user_data, null) post_bootstrap_user_data = try(each.value.post_bootstrap_user_data, var.self_managed_node_group_defaults.post_bootstrap_user_data, null) bootstrap_extra_args = try(each.value.bootstrap_extra_args, var.self_managed_node_group_defaults.bootstrap_extra_args, null) @@ -485,11 +485,11 @@ module "self_managed_node_group" { launch_template_tags = try(each.value.launch_template_tags, var.self_managed_node_group_defaults.launch_template_tags, null) tag_specifications = try(each.value.tag_specifications, var.self_managed_node_group_defaults.tag_specifications, null) - ebs_optimized = try(each.value.ebs_optimized, var.self_managed_node_group_defaults.ebs_optimized, null) - ami_id = try(each.value.ami_id, var.self_managed_node_group_defaults.ami_id, null) - cluster_version = try(each.value.cluster_version, var.self_managed_node_group_defaults.cluster_version, time_sleep.this[0].triggers["cluster_version"]) - instance_type = try(each.value.instance_type, var.self_managed_node_group_defaults.instance_type, null) - key_name = try(each.value.key_name, var.self_managed_node_group_defaults.key_name, null) + ebs_optimized = try(each.value.ebs_optimized, var.self_managed_node_group_defaults.ebs_optimized, null) + ami_id = try(each.value.ami_id, var.self_managed_node_group_defaults.ami_id, null) + kubernetes_version = try(each.value.kubernetes_version, var.self_managed_node_group_defaults.kubernetes_version, time_sleep.this[0].triggers["kubernetes_version"]) + instance_type = try(each.value.instance_type, var.self_managed_node_group_defaults.instance_type, null) + key_name = try(each.value.key_name, var.self_managed_node_group_defaults.key_name, null) disable_api_termination = try(each.value.disable_api_termination, var.self_managed_node_group_defaults.disable_api_termination, null) instance_initiated_shutdown_behavior = try(each.value.instance_initiated_shutdown_behavior, var.self_managed_node_group_defaults.instance_initiated_shutdown_behavior, null) diff --git a/outputs.tf b/outputs.tf index 688076f604..f082de8c17 100644 --- a/outputs.tf +++ b/outputs.tf @@ -83,7 +83,7 @@ output "cluster_primary_security_group_id" { output "cluster_service_cidr" { description = "The CIDR block where Kubernetes pod and service IP addresses are assigned from" - value = var.cluster_ip_family == "ipv6" ? try(aws_eks_cluster.this[0].kubernetes_network_config[0].service_ipv6_cidr, null) : try(aws_eks_cluster.this[0].kubernetes_network_config[0].service_ipv4_cidr, null) + value = var.ip_family == "ipv6" ? try(aws_eks_cluster.this[0].kubernetes_network_config[0].service_ipv6_cidr, null) : try(aws_eks_cluster.this[0].kubernetes_network_config[0].service_ipv4_cidr, null) } output "cluster_ip_family" { diff --git a/tests/eks-fargate-profile/main.tf b/tests/eks-fargate-profile/main.tf index 7ec4e9f414..40b458bd94 100644 --- a/tests/eks-fargate-profile/main.tf +++ b/tests/eks-fargate-profile/main.tf @@ -11,9 +11,9 @@ data "aws_availability_zones" "available" { } locals { - name = "ex-${basename(path.cwd)}" - cluster_version = "1.33" - region = "eu-west-1" + name = "ex-${basename(path.cwd)}" + kubernetes_version = "1.33" + region = "eu-west-1" vpc_cidr = "10.0.0.0/16" azs = slice(data.aws_availability_zones.available.names, 0, 3) @@ -32,11 +32,11 @@ locals { module "eks" { source = "../.." - cluster_name = local.name - cluster_version = local.cluster_version - cluster_endpoint_public_access = true + name = local.name + kubernetes_version = local.kubernetes_version + endpoint_public_access = true - cluster_addons = { + addons = { kube-proxy = {} vpc-cni = {} coredns = { @@ -51,8 +51,8 @@ module "eks" { control_plane_subnet_ids = module.vpc.intra_subnets # Fargate profiles use the cluster primary security group so these are not utilized - create_cluster_security_group = false - create_node_security_group = false + create_security_group = false + create_node_security_group = false fargate_profile_defaults = { iam_role_additional_policies = { diff --git a/tests/eks-managed-node-group/README.md b/tests/eks-managed-node-group/README.md index be01e4bf7e..15a05fa9e6 100644 --- a/tests/eks-managed-node-group/README.md +++ b/tests/eks-managed-node-group/README.md @@ -33,7 +33,7 @@ Note that this example may create resources which cost money. Run `terraform des | [aws\_vpc\_cni\_ipv6\_pod\_identity](#module\_aws\_vpc\_cni\_ipv6\_pod\_identity) | terraform-aws-modules/eks-pod-identity/aws | ~> 1.6 | | [disabled\_eks](#module\_disabled\_eks) | ../.. | n/a | | [disabled\_eks\_managed\_node\_group](#module\_disabled\_eks\_managed\_node\_group) | ../../modules/eks-managed-node-group | n/a | -| [ebs\_kms\_key](#module\_ebs\_kms\_key) | terraform-aws-modules/kms/aws | ~> 3.0 | +| [ebs\_kms\_key](#module\_ebs\_kms\_key) | terraform-aws-modules/kms/aws | ~> 4.0 | | [eks](#module\_eks) | ../.. | n/a | | [eks\_managed\_node\_group](#module\_eks\_managed\_node\_group) | ../../modules/eks-managed-node-group | n/a | | [key\_pair](#module\_key\_pair) | terraform-aws-modules/key-pair/aws | ~> 2.0 | diff --git a/tests/eks-managed-node-group/main.tf b/tests/eks-managed-node-group/main.tf index e1f263b4a9..ca4b3225d3 100644 --- a/tests/eks-managed-node-group/main.tf +++ b/tests/eks-managed-node-group/main.tf @@ -13,9 +13,9 @@ data "aws_availability_zones" "available" { } locals { - name = "ex-${replace(basename(path.cwd), "_", "-")}" - cluster_version = "1.33" - region = "eu-west-1" + name = "ex-${replace(basename(path.cwd), "_", "-")}" + kubernetes_version = "1.33" + region = "eu-west-1" vpc_cidr = "10.0.0.0/16" azs = slice(data.aws_availability_zones.available.names, 0, 3) @@ -34,12 +34,12 @@ locals { module "eks" { source = "../.." - cluster_name = local.name - cluster_version = local.cluster_version - cluster_endpoint_public_access = true + name = local.name + kubernetes_version = local.kubernetes_version + endpoint_public_access = true # IPV6 - cluster_ip_family = "ipv6" + ip_family = "ipv6" create_cni_ipv6_iam_policy = true enable_cluster_creator_admin_permissions = true @@ -48,7 +48,7 @@ module "eks" { # to the shared node security group enable_efa_support = true - cluster_addons = { + addons = { coredns = { most_recent = true } @@ -79,11 +79,11 @@ module "eks" { } } - cluster_upgrade_policy = { + upgrade_policy = { support_type = "STANDARD" } - cluster_zonal_shift_config = { + zonal_shift_config = { enabled = true } @@ -523,7 +523,7 @@ module "aws_vpc_cni_ipv6_pod_identity" { module "ebs_kms_key" { source = "terraform-aws-modules/kms/aws" - version = "~> 3.0" + version = "~> 4.0" description = "Customer managed key to encrypt EKS managed node group volumes" @@ -605,7 +605,7 @@ data "aws_ami" "eks_default" { filter { name = "name" - values = ["amazon-eks-node-al2023-x86_64-standard-${local.cluster_version}-v*"] + values = ["amazon-eks-node-al2023-x86_64-standard-${local.kubernetes_version}-v*"] } } @@ -615,7 +615,7 @@ data "aws_ami" "eks_default_arm" { filter { name = "name" - values = ["amazon-eks-node-al2023-arm64-standard-${local.cluster_version}-v*"] + values = ["amazon-eks-node-al2023-arm64-standard-${local.kubernetes_version}-v*"] } } @@ -625,7 +625,7 @@ data "aws_ami" "eks_default_bottlerocket" { filter { name = "name" - values = ["bottlerocket-aws-k8s-${local.cluster_version}-x86_64-*"] + values = ["bottlerocket-aws-k8s-${local.kubernetes_version}-x86_64-*"] } } diff --git a/tests/self-managed-node-group/README.md b/tests/self-managed-node-group/README.md index d540b58b8d..feee069124 100644 --- a/tests/self-managed-node-group/README.md +++ b/tests/self-managed-node-group/README.md @@ -32,10 +32,10 @@ Note that this example may create resources which cost money. Run `terraform des |------|--------|---------| | [aws\_vpc\_cni\_ipv4\_pod\_identity](#module\_aws\_vpc\_cni\_ipv4\_pod\_identity) | terraform-aws-modules/eks-pod-identity/aws | ~> 1.6 | | [disabled\_self\_managed\_node\_group](#module\_disabled\_self\_managed\_node\_group) | ../../modules/self-managed-node-group | n/a | -| [ebs\_kms\_key](#module\_ebs\_kms\_key) | terraform-aws-modules/kms/aws | ~> 3.0 | +| [ebs\_kms\_key](#module\_ebs\_kms\_key) | terraform-aws-modules/kms/aws | ~> 4.0 | | [eks](#module\_eks) | ../.. | n/a | | [key\_pair](#module\_key\_pair) | terraform-aws-modules/key-pair/aws | ~> 2.0 | -| [kms](#module\_kms) | terraform-aws-modules/kms/aws | ~> 3.0 | +| [kms](#module\_kms) | terraform-aws-modules/kms/aws | ~> 4.0 | | [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 | ## Resources diff --git a/tests/self-managed-node-group/main.tf b/tests/self-managed-node-group/main.tf index 3dc109554a..3e68f0ce8e 100644 --- a/tests/self-managed-node-group/main.tf +++ b/tests/self-managed-node-group/main.tf @@ -13,9 +13,9 @@ data "aws_availability_zones" "available" { } locals { - name = "ex-${replace(basename(path.cwd), "_", "-")}" - cluster_version = "1.33" - region = "eu-west-1" + name = "ex-${replace(basename(path.cwd), "_", "-")}" + kubernetes_version = "1.33" + region = "eu-west-1" vpc_cidr = "10.0.0.0/16" azs = slice(data.aws_availability_zones.available.names, 0, 3) @@ -34,9 +34,9 @@ locals { module "eks" { source = "../.." - cluster_name = local.name - cluster_version = local.cluster_version - cluster_endpoint_public_access = true + name = local.name + kubernetes_version = local.kubernetes_version + endpoint_public_access = true enable_cluster_creator_admin_permissions = true @@ -44,7 +44,7 @@ module "eks" { # to the shared node security group enable_efa_support = true - cluster_addons = { + addons = { coredns = { most_recent = true } @@ -69,7 +69,7 @@ module "eks" { # External encryption key create_kms_key = false - cluster_encryption_config = { + encryption_config = { resources = ["secrets"] provider_key_arn = module.kms.key_arn } @@ -424,7 +424,7 @@ data "aws_ami" "eks_default" { filter { name = "name" - values = ["amazon-eks-node-al2023-x86_64-standard-${local.cluster_version}-v*"] + values = ["amazon-eks-node-al2023-x86_64-standard-${local.kubernetes_version}-v*"] } } @@ -434,7 +434,7 @@ data "aws_ami" "eks_default_bottlerocket" { filter { name = "name" - values = ["bottlerocket-aws-k8s-${local.cluster_version}-x86_64-*"] + values = ["bottlerocket-aws-k8s-${local.kubernetes_version}-x86_64-*"] } } @@ -450,7 +450,7 @@ module "key_pair" { module "ebs_kms_key" { source = "terraform-aws-modules/kms/aws" - version = "~> 3.0" + version = "~> 4.0" description = "Customer managed key to encrypt EKS managed node group volumes" @@ -474,7 +474,7 @@ module "ebs_kms_key" { module "kms" { source = "terraform-aws-modules/kms/aws" - version = "~> 3.0" + version = "~> 4.0" aliases = ["eks/${local.name}"] description = "${local.name} cluster encryption key" diff --git a/variables.tf b/variables.tf index 9ff278ed02..b7ddd87dd2 100644 --- a/variables.tf +++ b/variables.tf @@ -20,25 +20,25 @@ variable "prefix_separator" { # Cluster ################################################################################ -variable "cluster_name" { +variable "name" { description = "Name of the EKS cluster" type = string default = "" } -variable "cluster_version" { +variable "kubernetes_version" { description = "Kubernetes `.` version to use for the EKS cluster (i.e.: `1.27`)" type = string default = null } -variable "cluster_enabled_log_types" { +variable "enabled_log_types" { description = "A list of the desired control plane logs to enable. For more information, see Amazon EKS Control Plane Logging documentation (https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html)" type = list(string) default = ["audit", "api", "authenticator"] } -variable "cluster_force_update_version" { +variable "force_update_version" { description = "Force version update by overriding upgrade-blocking readiness checks when updating a cluster" type = bool default = null @@ -50,7 +50,7 @@ variable "authentication_mode" { default = "API_AND_CONFIG_MAP" } -variable "cluster_compute_config" { +variable "compute_config" { description = "Configuration block for the cluster compute configuration" type = object({ enabled = optional(bool, false) @@ -60,7 +60,7 @@ variable "cluster_compute_config" { default = null } -variable "cluster_upgrade_policy" { +variable "upgrade_policy" { description = "Configuration block for the cluster upgrade policy" type = object({ support_type = optional(string) @@ -68,7 +68,7 @@ variable "cluster_upgrade_policy" { default = null } -variable "cluster_remote_network_config" { +variable "remote_network_config" { description = "Configuration block for the cluster remote network configuration" type = object({ remote_node_networks = object({ @@ -81,7 +81,7 @@ variable "cluster_remote_network_config" { default = null } -variable "cluster_zonal_shift_config" { +variable "zonal_shift_config" { description = "Configuration block for the cluster zonal shift" type = object({ enabled = optional(bool) @@ -89,7 +89,7 @@ variable "cluster_zonal_shift_config" { default = null } -variable "cluster_additional_security_group_ids" { +variable "additional_security_group_ids" { description = "List of additional, externally created security group IDs to attach to the cluster control plane" type = list(string) default = [] @@ -107,37 +107,37 @@ variable "subnet_ids" { default = [] } -variable "cluster_endpoint_private_access" { +variable "endpoint_private_access" { description = "Indicates whether or not the Amazon EKS private API server endpoint is enabled" type = bool default = true } -variable "cluster_endpoint_public_access" { +variable "endpoint_public_access" { description = "Indicates whether or not the Amazon EKS public API server endpoint is enabled" type = bool default = false } -variable "cluster_endpoint_public_access_cidrs" { +variable "endpoint_public_access_cidrs" { description = "List of CIDR blocks which can access the Amazon EKS public API server endpoint" type = list(string) default = ["0.0.0.0/0"] } -variable "cluster_ip_family" { +variable "ip_family" { description = "The IP family used to assign Kubernetes pod and service addresses. Valid values are `ipv4` (default) and `ipv6`. You can only specify an IP family when you create a cluster, changing this value will force a new cluster to be created" type = string default = "ipv4" } -variable "cluster_service_ipv4_cidr" { +variable "service_ipv4_cidr" { description = "The CIDR block to assign Kubernetes service IP addresses from. If you don't specify a block, Kubernetes assigns addresses from either the 10.100.0.0/16 or 172.20.0.0/16 CIDR blocks" type = string default = null } -variable "cluster_service_ipv6_cidr" { +variable "service_ipv6_cidr" { description = "The CIDR block to assign Kubernetes pod and service IP addresses from if `ipv6` was specified when the cluster was created. Kubernetes assigns service addresses from the unique local address range (fc00::/7) because you can't specify a custom IPv6 CIDR block when you create the cluster" type = string default = null @@ -155,7 +155,7 @@ variable "outpost_config" { default = null } -variable "cluster_encryption_config" { +variable "encryption_config" { description = "Configuration block with encryption configuration for the cluster" type = object({ provider_key_arn = optional(string) @@ -164,7 +164,7 @@ variable "cluster_encryption_config" { default = {} } -variable "attach_cluster_encryption_policy" { +variable "attach_encryption_policy" { description = "Indicates whether or not to attach an additional policy for the cluster IAM role to utilize the encryption key provided" type = bool default = true @@ -176,13 +176,13 @@ variable "cluster_tags" { default = {} } -variable "create_cluster_primary_security_group_tags" { +variable "create_primary_security_group_tags" { description = "Indicates whether or not to tag the cluster's primary security group. This security group is created by the EKS service, not the module, and therefore tagging is handled after cluster creation" type = bool default = true } -variable "cluster_timeouts" { +variable "timeouts" { description = "Create, update, and delete timeout configurations for the cluster" type = object({ create = optional(string) @@ -337,13 +337,13 @@ variable "cloudwatch_log_group_tags" { # Cluster Security Group ################################################################################ -variable "create_cluster_security_group" { +variable "create_security_group" { description = "Determines if a security group is created for the cluster. Note: the EKS service creates a primary security group for the cluster by default" type = bool default = true } -variable "cluster_security_group_id" { +variable "security_group_id" { description = "Existing security group ID to be attached to the cluster" type = string default = "" @@ -355,25 +355,25 @@ variable "vpc_id" { default = null } -variable "cluster_security_group_name" { +variable "security_group_name" { description = "Name to use on cluster security group created" type = string default = null } -variable "cluster_security_group_use_name_prefix" { +variable "security_group_use_name_prefix" { description = "Determines whether cluster security group name (`cluster_security_group_name`) is used as a prefix" type = bool default = true } -variable "cluster_security_group_description" { +variable "security_group_description" { description = "Description of the cluster security group created" type = string default = "EKS cluster security group" } -variable "cluster_security_group_additional_rules" { +variable "security_group_additional_rules" { description = "List of additional security group rules to add to the cluster security group created. Set `source_node_security_group = true` inside rules to set the `node_security_group` as source" type = map(object({ protocol = optional(string, "tcp") @@ -391,7 +391,7 @@ variable "cluster_security_group_additional_rules" { default = {} } -variable "cluster_security_group_tags" { +variable "security_group_tags" { description = "A map of additional tags to add to the cluster security group created" type = map(string) default = {} @@ -563,31 +563,31 @@ variable "iam_role_tags" { default = {} } -variable "cluster_encryption_policy_use_name_prefix" { +variable "encryption_policy_use_name_prefix" { description = "Determines whether cluster encryption policy name (`cluster_encryption_policy_name`) is used as a prefix" type = bool default = true } -variable "cluster_encryption_policy_name" { +variable "encryption_policy_name" { description = "Name to use on cluster encryption policy created" type = string default = null } -variable "cluster_encryption_policy_description" { +variable "encryption_policy_description" { description = "Description of the cluster encryption policy created" type = string default = "Cluster encryption policy to allow cluster role to utilize CMK provided" } -variable "cluster_encryption_policy_path" { +variable "encryption_policy_path" { description = "Cluster encryption policy path" type = string default = null } -variable "cluster_encryption_policy_tags" { +variable "encryption_policy_tags" { description = "A map of additional tags to add to the cluster encryption policy created" type = map(string) default = {} @@ -609,7 +609,7 @@ variable "enable_auto_mode_custom_tags" { # EKS Addons ################################################################################ -variable "cluster_addons" { +variable "addons" { description = "Map of cluster addon configurations to enable for the cluster. Addon name can be the map keys or set with `name`" type = map(object({ name = optional(string) # will fall back to map key @@ -635,7 +635,7 @@ variable "cluster_addons" { default = null } -variable "cluster_addons_timeouts" { +variable "addons_timeouts" { description = "Create, update, and delete timeout configurations for the cluster addons" type = object({ create = optional(string) @@ -649,7 +649,7 @@ variable "cluster_addons_timeouts" { # EKS Identity Provider ################################################################################ -variable "cluster_identity_providers" { +variable "identity_providers" { description = "Map of cluster identity provider configurations to enable for the cluster. Note - this is different/separate from IRSA" type = map(object({ client_id = string @@ -1645,8 +1645,8 @@ variable "self_managed_node_group_defaults" { variable "eks_managed_node_groups" { description = "Map of EKS managed node group definitions to create" type = map(object({ - create = optional(bool, true) - cluster_version = optional(string) + create = optional(bool, true) + kubernetes_version = optional(string) # EKS Managed Node Group name = optional(string) # Will fall back to map key @@ -1880,8 +1880,8 @@ variable "eks_managed_node_groups" { variable "eks_managed_node_group_defaults" { description = "Map of EKS managed node group default configurations" type = object({ - create = optional(bool) - cluster_version = optional(string) + create = optional(bool) + kubernetes_version = optional(string) # EKS Managed Node Group use_name_prefix = optional(bool) From 96d79e5c5b6ca2c514f27cf11346a685fae28441 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Wed, 9 Jul 2025 13:20:25 -0500 Subject: [PATCH 12/25] fix: Move all EFA logic to the nodegroup itself --- README.md | 9 +- modules/eks-managed-node-group/README.md | 13 ++ modules/eks-managed-node-group/main.tf | 101 +++++++++++++- modules/eks-managed-node-group/outputs.tf | 14 ++ modules/eks-managed-node-group/variables.tf | 72 ++++++++++ modules/self-managed-node-group/README.md | 13 ++ modules/self-managed-node-group/main.tf | 99 ++++++++++++++ modules/self-managed-node-group/outputs.tf | 14 ++ modules/self-managed-node-group/variables.tf | 72 ++++++++++ node_groups.tf | 36 ++--- tests/eks-managed-node-group/main.tf | 6 +- tests/self-managed-node-group/main.tf | 6 +- variables.tf | 132 ++++++++++++++++++- 13 files changed, 543 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 670d1381eb..8123dcb7fb 100644 --- a/README.md +++ b/README.md @@ -405,11 +405,10 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [create\_security\_group](#input\_create\_security\_group) | Determines if a security group is created for the cluster. Note: the EKS service creates a primary security group for the cluster by default | `bool` | `true` | no | | [custom\_oidc\_thumbprints](#input\_custom\_oidc\_thumbprints) | Additional list of server certificate thumbprints for the OpenID Connect (OIDC) identity provider's server certificate(s) | `list(string)` | `[]` | no | | [dataplane\_wait\_duration](#input\_dataplane\_wait\_duration) | Duration to wait after the EKS cluster has become active before creating the dataplane components (EKS managed node group(s), self-managed node group(s), Fargate profile(s)) | `string` | `"30s"` | no | -| [eks\_managed\_node\_group\_defaults](#input\_eks\_managed\_node\_group\_defaults) | Map of EKS managed node group default configurations |
object({
create = optional(bool)
kubernetes_version = optional(string)

# EKS Managed Node Group
use_name_prefix = optional(bool)
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
ami_id = optional(string)
ami_type = optional(string)
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool)
capacity_type = optional(string)
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}))
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool)
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
create_placement_group = optional(bool)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string))
cluster_primary_security_group_id = optional(string)

tags = optional(map(string), {})
})
| `{}` | no | -| [eks\_managed\_node\_groups](#input\_eks\_managed\_node\_groups) | Map of EKS managed node group definitions to create |
map(object({
create = optional(bool, true)
kubernetes_version = optional(string)

# EKS Managed Node Group
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
ami_id = optional(string, "")
ami_type = optional(string, "AL2023_x86_64_STANDARD")
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool, true)
capacity_type = optional(string, "ON_DEMAND")
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool, true)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}), {
max_unavailable_percentage = 33
})
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool, false)
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
create_placement_group = optional(bool, false)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool, true)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "EKS managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string), [])
cluster_primary_security_group_id = optional(string)

tags = optional(map(string), {})
}))
| `{}` | no | +| [eks\_managed\_node\_group\_defaults](#input\_eks\_managed\_node\_group\_defaults) | Map of EKS managed node group default configurations |
object({
create = optional(bool)
kubernetes_version = optional(string)

# EKS Managed Node Group
use_name_prefix = optional(bool)
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
ami_id = optional(string)
ami_type = optional(string)
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool)
capacity_type = optional(string)
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}))
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool)
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
create_placement_group = optional(bool)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string))
cluster_primary_security_group_id = optional(string)
create_security_group = optional(bool)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_tags = optional(map(string))

tags = optional(map(string), {})
})
| `{}` | no | +| [eks\_managed\_node\_groups](#input\_eks\_managed\_node\_groups) | Map of EKS managed node group definitions to create |
map(object({
create = optional(bool, true)
kubernetes_version = optional(string)

# EKS Managed Node Group
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
ami_id = optional(string, "")
ami_type = optional(string, "AL2023_x86_64_STANDARD")
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool, true)
capacity_type = optional(string, "ON_DEMAND")
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool, true)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}), {
max_unavailable_percentage = 33
})
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool, false)
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
create_placement_group = optional(bool, false)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool, true)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "EKS managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string), [])
cluster_primary_security_group_id = optional(string)
create_security_group = optional(bool, true)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool, true)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_tags = optional(map(string), {})

tags = optional(map(string), {})
}))
| `{}` | no | | [enable\_auto\_mode\_custom\_tags](#input\_enable\_auto\_mode\_custom\_tags) | Determines whether to enable permissions for custom tags resources created by EKS Auto Mode | `bool` | `true` | no | | [enable\_cluster\_creator\_admin\_permissions](#input\_enable\_cluster\_creator\_admin\_permissions) | Indicates whether or not to add the cluster creator (the identity used by Terraform) as an administrator via access entry | `bool` | `false` | no | -| [enable\_efa\_support](#input\_enable\_efa\_support) | Determines whether to enable Elastic Fabric Adapter (EFA) support | `bool` | `false` | no | | [enable\_irsa](#input\_enable\_irsa) | Determines whether to create an OpenID Connect Provider for EKS to enable IRSA | `bool` | `true` | no | | [enable\_kms\_key\_rotation](#input\_enable\_kms\_key\_rotation) | Specifies whether key rotation is enabled | `bool` | `true` | no | | [enabled\_log\_types](#input\_enabled\_log\_types) | A list of the desired control plane logs to enable. For more information, see Amazon EKS Control Plane Logging documentation (https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html) | `list(string)` |
[
"audit",
"api",
"authenticator"
]
| no | @@ -473,8 +472,8 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [security\_group\_name](#input\_security\_group\_name) | Name to use on cluster security group created | `string` | `null` | no | | [security\_group\_tags](#input\_security\_group\_tags) | A map of additional tags to add to the cluster security group created | `map(string)` | `{}` | no | | [security\_group\_use\_name\_prefix](#input\_security\_group\_use\_name\_prefix) | Determines whether cluster security group name (`cluster_security_group_name`) is used as a prefix | `bool` | `true` | no | -| [self\_managed\_node\_group\_defaults](#input\_self\_managed\_node\_group\_defaults) | Map of self-managed node group default configurations |
object({
create = optional(bool)
# Autoscaling Group
create_autoscaling_group = optional(bool)
use_name_prefix = optional(bool)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool)
context = optional(string)
target_group_arns = optional(list(string))
create_placement_group = optional(bool)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(number)
force_delete = optional(bool)
force_delete_warm_pool = optional(bool)
termination_policies = optional(list(string))
suspended_processes = optional(list(string))
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string))
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string)
triggers = optional(list(string))
}))
use_mixed_instances_policy = optional(bool)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
warm_pool = optional(object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string))
# User data
ami_type = optional(string)
additional_cluster_dns_ips = optional(list(string))
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string)
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
hibernation_options = optional(object({
configured = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool)
iam_role_arn = optional(string)

tags = optional(map(string))
})
| `{}` | no | -| [self\_managed\_node\_groups](#input\_self\_managed\_node\_groups) | Map of self-managed node group definitions to create |
map(object({
create = optional(bool, true)
# Autoscaling Group
create_autoscaling_group = optional(bool, true)
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool, false)
context = optional(string)
target_group_arns = optional(list(string), [])
create_placement_group = optional(bool, false)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(number)
force_delete = optional(bool)
force_delete_warm_pool = optional(bool)
termination_policies = optional(list(string), [])
suspended_processes = optional(list(string), [])
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string), [])
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number, 66)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string, "Rolling")
triggers = optional(list(string))
}), {
strategy = "Rolling"
preferences = {
min_healthy_percentage = 66
}
})
use_mixed_instances_policy = optional(bool, false)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
warm_pool = optional(object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string), {})
# User data
ami_type = optional(string, "AL2023_x86_64_STANDARD")
additional_cluster_dns_ips = optional(list(string), [])
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string, "m6i.large")
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
hibernation_options = optional(object({
configured = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool, true)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Self managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool, true)
iam_role_arn = optional(string)

tags = optional(map(string), {})
}))
| `{}` | no | +| [self\_managed\_node\_group\_defaults](#input\_self\_managed\_node\_group\_defaults) | Map of self-managed node group default configurations |
object({
create = optional(bool)
# Autoscaling Group
create_autoscaling_group = optional(bool)
use_name_prefix = optional(bool)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool)
context = optional(string)
target_group_arns = optional(list(string))
create_placement_group = optional(bool)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(number)
force_delete = optional(bool)
force_delete_warm_pool = optional(bool)
termination_policies = optional(list(string))
suspended_processes = optional(list(string))
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string))
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string)
triggers = optional(list(string))
}))
use_mixed_instances_policy = optional(bool)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
warm_pool = optional(object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string))
# User data
ami_type = optional(string)
additional_cluster_dns_ips = optional(list(string))
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string)
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
hibernation_options = optional(object({
configured = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool)
iam_role_arn = optional(string)
# Security group
create_security_group = optional(bool)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_tags = optional(map(string))

tags = optional(map(string))
})
| `{}` | no | +| [self\_managed\_node\_groups](#input\_self\_managed\_node\_groups) | Map of self-managed node group definitions to create |
map(object({
create = optional(bool, true)
# Autoscaling Group
create_autoscaling_group = optional(bool, true)
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool, false)
context = optional(string)
target_group_arns = optional(list(string), [])
create_placement_group = optional(bool, false)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(number)
force_delete = optional(bool)
force_delete_warm_pool = optional(bool)
termination_policies = optional(list(string), [])
suspended_processes = optional(list(string), [])
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string), [])
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number, 66)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string, "Rolling")
triggers = optional(list(string))
}), {
strategy = "Rolling"
preferences = {
min_healthy_percentage = 66
}
})
use_mixed_instances_policy = optional(bool, false)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
warm_pool = optional(object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string), {})
# User data
ami_type = optional(string, "AL2023_x86_64_STANDARD")
additional_cluster_dns_ips = optional(list(string), [])
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string, "m6i.large")
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
hibernation_options = optional(object({
configured = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool, true)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Self managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool, true)
iam_role_arn = optional(string)
# Security group
create_security_group = optional(bool, true)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool, true)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_tags = optional(map(string), {})

tags = optional(map(string), {})
}))
| `{}` | no | | [service\_ipv4\_cidr](#input\_service\_ipv4\_cidr) | The CIDR block to assign Kubernetes service IP addresses from. If you don't specify a block, Kubernetes assigns addresses from either the 10.100.0.0/16 or 172.20.0.0/16 CIDR blocks | `string` | `null` | no | | [service\_ipv6\_cidr](#input\_service\_ipv6\_cidr) | The CIDR block to assign Kubernetes pod and service IP addresses from if `ipv6` was specified when the cluster was created. Kubernetes assigns service addresses from the unique local address range (fc00::/7) because you can't specify a custom IPv6 CIDR block when you create the cluster | `string` | `null` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs where the nodes/node groups will be provisioned. If `control_plane_subnet_ids` is not provided, the EKS cluster control plane (ENIs) will be provisioned in these subnets | `list(string)` | `[]` | no | diff --git a/modules/eks-managed-node-group/README.md b/modules/eks-managed-node-group/README.md index f03067e2ad..ca829e00e1 100644 --- a/modules/eks-managed-node-group/README.md +++ b/modules/eks-managed-node-group/README.md @@ -89,12 +89,16 @@ module "eks_managed_node_group" { | [aws_iam_role_policy_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_launch_template.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | | [aws_placement_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/placement_group) | resource | +| [aws_security_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_vpc_security_group_egress_rule.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | resource | +| [aws_vpc_security_group_ingress_rule.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule) | resource | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_ec2_instance_type.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_instance_type) | data source | | [aws_iam_policy_document.assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | | [aws_ssm_parameter.ami](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | +| [aws_subnet.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnet) | data source | ## Inputs @@ -122,6 +126,7 @@ module "eks_managed_node_group" { | [create\_iam\_role\_policy](#input\_create\_iam\_role\_policy) | Determines whether an IAM role policy is created or not | `bool` | `true` | no | | [create\_launch\_template](#input\_create\_launch\_template) | Determines whether to create a launch template or not. If set to `false`, EKS will use its own default launch template | `bool` | `true` | no | | [create\_placement\_group](#input\_create\_placement\_group) | Determines whether a placement group is created & used by the node group | `bool` | `false` | no | +| [create\_security\_group](#input\_create\_security\_group) | Determines if a security group is created | `bool` | `true` | no | | [credit\_specification](#input\_credit\_specification) | Customize the credit specification of the instance |
object({
cpu_credits = optional(string)
})
| `null` | no | | [desired\_size](#input\_desired\_size) | Desired number of instances/nodes | `number` | `1` | no | | [disable\_api\_termination](#input\_disable\_api\_termination) | If true, enables EC2 instance termination protection | `bool` | `null` | no | @@ -172,6 +177,12 @@ module "eks_managed_node_group" { | [private\_dns\_name\_options](#input\_private\_dns\_name\_options) | The options for the instance hostname. The default values are inherited from the subnet |
object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
})
| `null` | no | | [ram\_disk\_id](#input\_ram\_disk\_id) | The ID of the ram disk | `string` | `null` | no | | [remote\_access](#input\_remote\_access) | Configuration block with remote access settings. Only valid when `use_custom_launch_template` = `false` |
object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
})
| `null` | no | +| [security\_group\_description](#input\_security\_group\_description) | Description of the security group created | `string` | `null` | no | +| [security\_group\_egress\_rules](#input\_security\_group\_egress\_rules) | Security group egress rules to add to the security group created |
map(object({
name = optional(string)

cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
}))
| `{}` | no | +| [security\_group\_ingress\_rules](#input\_security\_group\_ingress\_rules) | Security group ingress rules to add to the security group created |
map(object({
name = optional(string)

cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
}))
| `{}` | no | +| [security\_group\_name](#input\_security\_group\_name) | Name to use on security group created | `string` | `null` | no | +| [security\_group\_tags](#input\_security\_group\_tags) | A map of additional tags to add to the security group created | `map(string)` | `{}` | no | +| [security\_group\_use\_name\_prefix](#input\_security\_group\_use\_name\_prefix) | Determines whether the security group name (`security_group_name`) is used as a prefix | `bool` | `true` | no | | [subnet\_ids](#input\_subnet\_ids) | Identifiers of EC2 Subnets to associate with the EKS Node Group. These subnets must have the following resource tag: `kubernetes.io/cluster/CLUSTER_NAME` | `list(string)` | `null` | no | | [tag\_specifications](#input\_tag\_specifications) | The tags to apply to the resources during launch | `list(string)` |
[
"instance",
"volume",
"network-interface"
]
| no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | @@ -203,4 +214,6 @@ module "eks_managed_node_group" { | [node\_group\_resources](#output\_node\_group\_resources) | List of objects containing information about underlying resources | | [node\_group\_status](#output\_node\_group\_status) | Status of the EKS Node Group | | [node\_group\_taints](#output\_node\_group\_taints) | List of objects containing information about taints applied to the node group | +| [security\_group\_arn](#output\_security\_group\_arn) | Amazon Resource Name (ARN) of the security group | +| [security\_group\_id](#output\_security\_group\_id) | ID of the security group | diff --git a/modules/eks-managed-node-group/main.tf b/modules/eks-managed-node-group/main.tf index 8b0df59819..a33f2cca81 100644 --- a/modules/eks-managed-node-group/main.tf +++ b/modules/eks-managed-node-group/main.tf @@ -72,7 +72,7 @@ locals { locals { launch_template_name = coalesce(var.launch_template_name, "${var.name}-eks-node-group") - security_group_ids = compact(concat([var.cluster_primary_security_group_id], var.vpc_security_group_ids)) + security_group_ids = compact(concat([var.cluster_primary_security_group_id], var.vpc_security_group_ids, aws_security_group.this[*].id)) } resource "aws_launch_template" "this" { @@ -656,3 +656,102 @@ resource "aws_placement_group" "this" { tags = var.tags } + +################################################################################ +# Security Group +################################################################################ + +locals { + create_security_group = var.create && var.create_security_group && length(merge(local.security_group_ingress_rules, local.security_group_egress_rules)) > 0 + security_group_name = coalesce(var.security_group_name, "${var.cluster_name}-${var.name}") + + security_group_ingress_rules = merge({ for k, v in + { + all_self_efa = { + description = "Node to node EFA" + protocol = "-1" + from_port = 0 + self = true + } + } : k => v if var.enable_efa_support + }, + var.security_group_ingress_rules + ) + security_group_egress_rules = merge({ for k, v in + { + all_self_efa = { + description = "Node to node EFA" + protocol = "-1" + to_port = 0 + self = true + } + } : k => v if var.enable_efa_support + }, + var.security_group_egress_rules + ) +} + +data "aws_subnet" "this" { + count = local.create_security_group ? 1 : 0 + + id = element(var.subnet_ids, 0) +} + +resource "aws_security_group" "this" { + count = local.create_security_group ? 1 : 0 + + name = var.security_group_use_name_prefix ? null : local.security_group_name + name_prefix = var.security_group_use_name_prefix ? "${local.security_group_name}-" : null + description = var.security_group_description + vpc_id = data.aws_subnet.this[0].vpc_id + + tags = merge( + var.tags, + { "Name" = local.security_group_name }, + var.security_group_tags + ) + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_vpc_security_group_ingress_rule" "this" { + for_each = { for k, v in local.security_group_ingress_rules : k => v if length(local.security_group_ingress_rules) > 0 && local.create_security_group } + + cidr_ipv4 = each.value.cidr_ipv4 + cidr_ipv6 = each.value.cidr_ipv6 + description = each.value.description + from_port = each.value.from_port + ip_protocol = each.value.ip_protocol + prefix_list_id = each.value.prefix_list_id + referenced_security_group_id = each.value.self ? aws_security_group.this[0].id : each.value.referenced_security_group_id + security_group_id = aws_security_group.this[0].id + tags = merge( + var.tags, + var.security_group_tags, + { "Name" = coalesce(each.value.name, "${local.security_group_name}-${each.key}") }, + each.value.tags + ) + to_port = try(coalesce(each.value.to_port, each.value.from_port), null) +} + +resource "aws_vpc_security_group_egress_rule" "this" { + for_each = { for k, v in local.security_group_egress_rules : k => v if length(local.security_group_egress_rules) && local.create_security_group } + + cidr_ipv4 = each.value.cidr_ipv4 + cidr_ipv6 = each.value.cidr_ipv6 + description = each.value.description + from_port = try(coalesce(each.value.from_port, each.value.to_port), null) + ip_protocol = each.value.ip_protocol + prefix_list_id = each.value.prefix_list_id + referenced_security_group_id = each.value.self ? aws_security_group.this[0].id : each.value.referenced_security_group_id + security_group_id = aws_security_group.this[0].id + tags = merge( + var.tags, + var.security_group_tags, + { "Name" = coalesce(each.value.name, "${local.security_group_name}-${each.key}") }, + each.value.tags + ) + to_port = each.value.to_port +} diff --git a/modules/eks-managed-node-group/outputs.tf b/modules/eks-managed-node-group/outputs.tf index 0475953452..a7d6fcf62b 100644 --- a/modules/eks-managed-node-group/outputs.tf +++ b/modules/eks-managed-node-group/outputs.tf @@ -79,3 +79,17 @@ output "iam_role_unique_id" { description = "Stable and unique string identifying the IAM role" value = try(aws_iam_role.this[0].unique_id, null) } + +################################################################################ +# Security Group +################################################################################ + +output "security_group_arn" { + description = "Amazon Resource Name (ARN) of the security group" + value = try(aws_security_group.this[0].arn, null) +} + +output "security_group_id" { + description = "ID of the security group" + value = try(aws_security_group.this[0].id, null) +} diff --git a/modules/eks-managed-node-group/variables.tf b/modules/eks-managed-node-group/variables.tf index 3131913eb9..7810da0058 100644 --- a/modules/eks-managed-node-group/variables.tf +++ b/modules/eks-managed-node-group/variables.tf @@ -666,3 +666,75 @@ variable "iam_role_policy_statements" { })) default = null } + +################################################################################ +# Security Group +################################################################################ + +variable "create_security_group" { + description = "Determines if a security group is created" + type = bool + default = true +} + +variable "security_group_name" { + description = "Name to use on security group created" + type = string + default = null +} + +variable "security_group_use_name_prefix" { + description = "Determines whether the security group name (`security_group_name`) is used as a prefix" + type = bool + default = true +} + +variable "security_group_description" { + description = "Description of the security group created" + type = string + default = null +} + +variable "security_group_ingress_rules" { + description = "Security group ingress rules to add to the security group created" + type = map(object({ + name = optional(string) + + cidr_ipv4 = optional(string) + cidr_ipv6 = optional(string) + description = optional(string) + from_port = optional(string) + ip_protocol = optional(string, "tcp") + prefix_list_id = optional(string) + referenced_security_group_id = optional(string) + self = optional(bool, false) + tags = optional(map(string), {}) + to_port = optional(string) + })) + default = {} +} + +variable "security_group_egress_rules" { + description = "Security group egress rules to add to the security group created" + type = map(object({ + name = optional(string) + + cidr_ipv4 = optional(string) + cidr_ipv6 = optional(string) + description = optional(string) + from_port = optional(string) + ip_protocol = optional(string, "tcp") + prefix_list_id = optional(string) + referenced_security_group_id = optional(string) + self = optional(bool, false) + tags = optional(map(string), {}) + to_port = optional(string) + })) + default = {} +} + +variable "security_group_tags" { + description = "A map of additional tags to add to the security group created" + type = map(string) + default = {} +} diff --git a/modules/self-managed-node-group/README.md b/modules/self-managed-node-group/README.md index 4a2f6d806f..663c7f10b0 100644 --- a/modules/self-managed-node-group/README.md +++ b/modules/self-managed-node-group/README.md @@ -70,12 +70,16 @@ module "self_managed_node_group" { | [aws_iam_role_policy_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_launch_template.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | | [aws_placement_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/placement_group) | resource | +| [aws_security_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_vpc_security_group_egress_rule.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | resource | +| [aws_vpc_security_group_ingress_rule.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule) | resource | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_ec2_instance_type.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_instance_type) | data source | | [aws_iam_policy_document.assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | | [aws_ssm_parameter.ami](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | +| [aws_subnet.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnet) | data source | ## Inputs @@ -108,6 +112,7 @@ module "self_managed_node_group" { | [create\_iam\_role\_policy](#input\_create\_iam\_role\_policy) | Determines whether an IAM role policy is created or not | `bool` | `true` | no | | [create\_launch\_template](#input\_create\_launch\_template) | Determines whether to create launch template or not | `bool` | `true` | no | | [create\_placement\_group](#input\_create\_placement\_group) | Determines whether a placement group is created & used by the node group | `bool` | `false` | no | +| [create\_security\_group](#input\_create\_security\_group) | Determines if a security group is created | `bool` | `true` | no | | [credit\_specification](#input\_credit\_specification) | Customize the credit specification of the instance |
object({
cpu_credits = optional(string)
})
| `null` | no | | [default\_cooldown](#input\_default\_cooldown) | The amount of time, in seconds, after a scaling activity completes before another scaling activity can start | `number` | `null` | no | | [default\_instance\_warmup](#input\_default\_instance\_warmup) | Amount of time, in seconds, until a newly launched instance can contribute to the Amazon CloudWatch metrics. This delay lets an instance finish initializing before Amazon EC2 Auto Scaling aggregates instance metrics, resulting in more reliable usage data | `number` | `null` | no | @@ -174,6 +179,12 @@ module "self_managed_node_group" { | [private\_dns\_name\_options](#input\_private\_dns\_name\_options) | The options for the instance hostname. The default values are inherited from the subnet |
object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
})
| `null` | no | | [protect\_from\_scale\_in](#input\_protect\_from\_scale\_in) | Allows setting instance protection. The autoscaling group will not select instances with this setting for termination during scale in events | `bool` | `false` | no | | [ram\_disk\_id](#input\_ram\_disk\_id) | The ID of the ram disk | `string` | `null` | no | +| [security\_group\_description](#input\_security\_group\_description) | Description of the security group created | `string` | `null` | no | +| [security\_group\_egress\_rules](#input\_security\_group\_egress\_rules) | Security group egress rules to add to the security group created |
map(object({
name = optional(string)

cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
}))
| `{}` | no | +| [security\_group\_ingress\_rules](#input\_security\_group\_ingress\_rules) | Security group ingress rules to add to the security group created |
map(object({
name = optional(string)

cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
}))
| `{}` | no | +| [security\_group\_name](#input\_security\_group\_name) | Name to use on security group created | `string` | `null` | no | +| [security\_group\_tags](#input\_security\_group\_tags) | A map of additional tags to add to the security group created | `map(string)` | `{}` | no | +| [security\_group\_use\_name\_prefix](#input\_security\_group\_use\_name\_prefix) | Determines whether the security group name (`security_group_name`) is used as a prefix | `bool` | `true` | no | | [service\_linked\_role\_arn](#input\_service\_linked\_role\_arn) | The ARN of the service-linked role that the ASG will use to call other AWS services | `string` | `null` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs to launch resources in. Subnets automatically determine which availability zones the group will reside. Conflicts with `availability_zones` | `list(string)` | `null` | no | | [suspended\_processes](#input\_suspended\_processes) | A list of processes to suspend for the Auto Scaling Group. The allowed values are `Launch`, `Terminate`, `HealthCheck`, `ReplaceUnhealthy`, `AZRebalance`, `AlarmNotification`, `ScheduledActions`, `AddToLoadBalancer`. Note that if you suspend either the `Launch` or `Terminate` process types, it can prevent your Auto Scaling Group from functioning properly | `list(string)` | `[]` | no | @@ -218,5 +229,7 @@ module "self_managed_node_group" { | [launch\_template\_id](#output\_launch\_template\_id) | The ID of the launch template | | [launch\_template\_latest\_version](#output\_launch\_template\_latest\_version) | The latest version of the launch template | | [launch\_template\_name](#output\_launch\_template\_name) | The name of the launch template | +| [security\_group\_arn](#output\_security\_group\_arn) | Amazon Resource Name (ARN) of the security group | +| [security\_group\_id](#output\_security\_group\_id) | ID of the security group | | [user\_data](#output\_user\_data) | Base64 encoded user data | diff --git a/modules/self-managed-node-group/main.tf b/modules/self-managed-node-group/main.tf index 13cd6febf6..54b03c7a46 100644 --- a/modules/self-managed-node-group/main.tf +++ b/modules/self-managed-node-group/main.tf @@ -984,3 +984,102 @@ resource "aws_eks_access_entry" "this" { tags = var.tags } + +################################################################################ +# Security Group +################################################################################ + +locals { + create_security_group = var.create && var.create_security_group && length(merge(local.security_group_ingress_rules, local.security_group_egress_rules)) > 0 + security_group_name = coalesce(var.security_group_name, "${var.cluster_name}-${var.name}") + + security_group_ingress_rules = merge({ for k, v in + { + all_self_efa = { + description = "Node to node EFA" + protocol = "-1" + from_port = 0 + self = true + } + } : k => v if var.enable_efa_support + }, + var.security_group_ingress_rules + ) + security_group_egress_rules = merge({ for k, v in + { + all_self_efa = { + description = "Node to node EFA" + protocol = "-1" + to_port = 0 + self = true + } + } : k => v if var.enable_efa_support + }, + var.security_group_egress_rules + ) +} + +data "aws_subnet" "this" { + count = local.create_security_group ? 1 : 0 + + id = element(var.subnet_ids, 0) +} + +resource "aws_security_group" "this" { + count = local.create_security_group ? 1 : 0 + + name = var.security_group_use_name_prefix ? null : local.security_group_name + name_prefix = var.security_group_use_name_prefix ? "${local.security_group_name}-" : null + description = var.security_group_description + vpc_id = data.aws_subnet.this[0].vpc_id + + tags = merge( + var.tags, + { "Name" = local.security_group_name }, + var.security_group_tags + ) + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_vpc_security_group_ingress_rule" "this" { + for_each = { for k, v in local.security_group_ingress_rules : k => v if length(local.security_group_ingress_rules) > 0 && local.create_security_group } + + cidr_ipv4 = each.value.cidr_ipv4 + cidr_ipv6 = each.value.cidr_ipv6 + description = each.value.description + from_port = each.value.from_port + ip_protocol = each.value.ip_protocol + prefix_list_id = each.value.prefix_list_id + referenced_security_group_id = each.value.self ? aws_security_group.this[0].id : each.value.referenced_security_group_id + security_group_id = aws_security_group.this[0].id + tags = merge( + var.tags, + var.security_group_tags, + { "Name" = coalesce(each.value.name, "${local.security_group_name}-${each.key}") }, + each.value.tags + ) + to_port = try(coalesce(each.value.to_port, each.value.from_port), null) +} + +resource "aws_vpc_security_group_egress_rule" "this" { + for_each = { for k, v in local.security_group_egress_rules : k => v if length(local.security_group_egress_rules) && local.create_security_group } + + cidr_ipv4 = each.value.cidr_ipv4 + cidr_ipv6 = each.value.cidr_ipv6 + description = each.value.description + from_port = try(coalesce(each.value.from_port, each.value.to_port), null) + ip_protocol = each.value.ip_protocol + prefix_list_id = each.value.prefix_list_id + referenced_security_group_id = each.value.self ? aws_security_group.this[0].id : each.value.referenced_security_group_id + security_group_id = aws_security_group.this[0].id + tags = merge( + var.tags, + var.security_group_tags, + { "Name" = coalesce(each.value.name, "${local.security_group_name}-${each.key}") }, + each.value.tags + ) + to_port = each.value.to_port +} diff --git a/modules/self-managed-node-group/outputs.tf b/modules/self-managed-node-group/outputs.tf index 5520ca3336..ad8710b890 100644 --- a/modules/self-managed-node-group/outputs.tf +++ b/modules/self-managed-node-group/outputs.tf @@ -141,3 +141,17 @@ output "user_data" { description = "Base64 encoded user data" value = try(module.user_data.user_data, null) } + +################################################################################ +# Security Group +################################################################################ + +output "security_group_arn" { + description = "Amazon Resource Name (ARN) of the security group" + value = try(aws_security_group.this[0].arn, null) +} + +output "security_group_id" { + description = "ID of the security group" + value = try(aws_security_group.this[0].id, null) +} diff --git a/modules/self-managed-node-group/variables.tf b/modules/self-managed-node-group/variables.tf index a36b99d431..34fde3831c 100644 --- a/modules/self-managed-node-group/variables.tf +++ b/modules/self-managed-node-group/variables.tf @@ -971,3 +971,75 @@ variable "iam_role_arn" { type = string default = null } + +################################################################################ +# Security Group +################################################################################ + +variable "create_security_group" { + description = "Determines if a security group is created" + type = bool + default = true +} + +variable "security_group_name" { + description = "Name to use on security group created" + type = string + default = null +} + +variable "security_group_use_name_prefix" { + description = "Determines whether the security group name (`security_group_name`) is used as a prefix" + type = bool + default = true +} + +variable "security_group_description" { + description = "Description of the security group created" + type = string + default = null +} + +variable "security_group_ingress_rules" { + description = "Security group ingress rules to add to the security group created" + type = map(object({ + name = optional(string) + + cidr_ipv4 = optional(string) + cidr_ipv6 = optional(string) + description = optional(string) + from_port = optional(string) + ip_protocol = optional(string, "tcp") + prefix_list_id = optional(string) + referenced_security_group_id = optional(string) + self = optional(bool, false) + tags = optional(map(string), {}) + to_port = optional(string) + })) + default = {} +} + +variable "security_group_egress_rules" { + description = "Security group egress rules to add to the security group created" + type = map(object({ + name = optional(string) + + cidr_ipv4 = optional(string) + cidr_ipv6 = optional(string) + description = optional(string) + from_port = optional(string) + ip_protocol = optional(string, "tcp") + prefix_list_id = optional(string) + referenced_security_group_id = optional(string) + self = optional(bool, false) + tags = optional(map(string), {}) + to_port = optional(string) + })) + default = {} +} + +variable "security_group_tags" { + description = "A map of additional tags to add to the security group created" + type = map(string) + default = {} +} diff --git a/node_groups.tf b/node_groups.tf index e7d5a676b9..e240eaa3e0 100644 --- a/node_groups.tf +++ b/node_groups.tf @@ -163,27 +163,6 @@ locals { ipv6_cidr_blocks = var.ip_family == "ipv6" ? ["::/0"] : null } } : k => v if var.node_security_group_enable_recommended_rules } - - efa_security_group_rules = { for k, v in - { - ingress_all_self_efa = { - description = "Node to node EFA" - protocol = "-1" - from_port = 0 - to_port = 0 - type = "ingress" - self = true - } - egress_all_self_efa = { - description = "Node to node EFA" - protocol = "-1" - from_port = 0 - to_port = 0 - type = "egress" - self = true - } - } : k => v if var.enable_efa_support - } } resource "aws_security_group" "node" { @@ -210,7 +189,6 @@ resource "aws_security_group" "node" { resource "aws_security_group_rule" "node" { for_each = { for k, v in merge( - local.efa_security_group_rules, local.node_security_group_rules, local.node_security_group_recommended_rules, var.node_security_group_additional_rules, @@ -384,6 +362,13 @@ module "eks_managed_node_group" { # Security group vpc_security_group_ids = compact(concat([local.node_security_group_id], try(each.value.vpc_security_group_ids, var.eks_managed_node_group_defaults.vpc_security_group_ids, []))) cluster_primary_security_group_id = try(each.value.attach_cluster_primary_security_group, var.eks_managed_node_group_defaults.attach_cluster_primary_security_group, false) ? aws_eks_cluster.this[0].vpc_config[0].cluster_security_group_id : null + create_security_group = try(each.value.create_security_group, var.eks_managed_node_group_defaults.create_security_group, null) + security_group_name = try(each.value.security_group_name, var.eks_managed_node_group_defaults.security_group_name, null) + security_group_use_name_prefix = try(each.value.security_group_use_name_prefix, var.eks_managed_node_group_defaults.security_group_use_name_prefix, null) + security_group_description = try(each.value.security_group_description, var.eks_managed_node_group_defaults.security_group_description, null) + security_group_ingress_rules = try(each.value.security_group_ingress_rules, var.eks_managed_node_group_defaults.security_group_ingress_rules, null) + security_group_egress_rules = try(each.value.security_group_egress_rules, var.eks_managed_node_group_defaults.security_group_egress_rules, null) + security_group_tags = try(each.value.security_group_tags, var.eks_managed_node_group_defaults.security_group_tags, null) tags = merge( var.tags, @@ -536,6 +521,13 @@ module "self_managed_node_group" { # Security group vpc_security_group_ids = compact(concat([local.node_security_group_id], try(each.value.vpc_security_group_ids, var.self_managed_node_group_defaults.vpc_security_group_ids, []))) cluster_primary_security_group_id = try(each.value.attach_cluster_primary_security_group, var.self_managed_node_group_defaults.attach_cluster_primary_security_group, false) ? aws_eks_cluster.this[0].vpc_config[0].cluster_security_group_id : null + create_security_group = try(each.value.create_security_group, var.self_managed_node_group_defaults.create_security_group, null) + security_group_name = try(each.value.security_group_name, var.self_managed_node_group_defaults.security_group_name, null) + security_group_use_name_prefix = try(each.value.security_group_use_name_prefix, var.self_managed_node_group_defaults.security_group_use_name_prefix, null) + security_group_description = try(each.value.security_group_description, var.self_managed_node_group_defaults.security_group_description, null) + security_group_ingress_rules = try(each.value.security_group_ingress_rules, var.self_managed_node_group_defaults.security_group_ingress_rules, null) + security_group_egress_rules = try(each.value.security_group_egress_rules, var.self_managed_node_group_defaults.security_group_egress_rules, null) + security_group_tags = try(each.value.security_group_tags, var.self_managed_node_group_defaults.security_group_tags, null) tags = merge( var.tags, diff --git a/tests/eks-managed-node-group/main.tf b/tests/eks-managed-node-group/main.tf index ca4b3225d3..22d4c5a602 100644 --- a/tests/eks-managed-node-group/main.tf +++ b/tests/eks-managed-node-group/main.tf @@ -44,10 +44,6 @@ module "eks" { enable_cluster_creator_admin_permissions = true - # Enable EFA support by adding necessary security group rules - # to the shared node security group - enable_efa_support = true - addons = { coredns = { most_recent = true @@ -359,7 +355,7 @@ module "eks" { # This will: # 1. Create a placement group to place the instances close to one another - # 2. Ignore subnets that reside in AZs that do not support the instance type + # 2. Create and attach the necessary security group rules (and security group) # 3. Expose all of the available EFA interfaces on the launch template enable_efa_support = true enable_efa_only = true diff --git a/tests/self-managed-node-group/main.tf b/tests/self-managed-node-group/main.tf index 3e68f0ce8e..9a19e98635 100644 --- a/tests/self-managed-node-group/main.tf +++ b/tests/self-managed-node-group/main.tf @@ -40,10 +40,6 @@ module "eks" { enable_cluster_creator_admin_permissions = true - # Enable EFA support by adding necessary security group rules - # to the shared node security group - enable_efa_support = true - addons = { coredns = { most_recent = true @@ -338,7 +334,7 @@ module "eks" { # This will: # 1. Create a placement group to place the instances close to one another - # 2. Ignore subnets that reside in AZs that do not support the instance type + # 2. Create and attach the necessary security group rules (and security group) # 3. Expose all of the available EFA interfaces on the launch template enable_efa_support = true enable_efa_only = true diff --git a/variables.tf b/variables.tf index b7ddd87dd2..f27bf7bde7 100644 --- a/variables.tf +++ b/variables.tf @@ -471,12 +471,6 @@ variable "node_security_group_tags" { default = {} } -variable "enable_efa_support" { - description = "Determines whether to enable Elastic Fabric Adapter (EFA) support" - type = bool - default = false -} - ################################################################################ # IRSA ################################################################################ @@ -1235,6 +1229,38 @@ variable "self_managed_node_groups" { # Access entry create_access_entry = optional(bool, true) iam_role_arn = optional(string) + # Security group + create_security_group = optional(bool, true) + security_group_name = optional(string) + security_group_use_name_prefix = optional(bool, true) + security_group_description = optional(string) + security_group_ingress_rules = optional(map(object({ + name = optional(string) + cidr_ipv4 = optional(string) + cidr_ipv6 = optional(string) + description = optional(string) + from_port = optional(string) + ip_protocol = optional(string, "tcp") + prefix_list_id = optional(string) + referenced_security_group_id = optional(string) + self = optional(bool, false) + tags = optional(map(string), {}) + to_port = optional(string) + })), {}) + security_group_egress_rules = optional(map(object({ + name = optional(string) + cidr_ipv4 = optional(string) + cidr_ipv6 = optional(string) + description = optional(string) + from_port = optional(string) + ip_protocol = optional(string, "tcp") + prefix_list_id = optional(string) + referenced_security_group_id = optional(string) + self = optional(bool, false) + tags = optional(map(string), {}) + to_port = optional(string) + })), {}) + security_group_tags = optional(map(string), {}) tags = optional(map(string), {}) })) @@ -1632,6 +1658,38 @@ variable "self_managed_node_group_defaults" { # Access entry create_access_entry = optional(bool) iam_role_arn = optional(string) + # Security group + create_security_group = optional(bool) + security_group_name = optional(string) + security_group_use_name_prefix = optional(bool) + security_group_description = optional(string) + security_group_ingress_rules = optional(map(object({ + name = optional(string) + cidr_ipv4 = optional(string) + cidr_ipv6 = optional(string) + description = optional(string) + from_port = optional(string) + ip_protocol = optional(string) + prefix_list_id = optional(string) + referenced_security_group_id = optional(string) + self = optional(bool) + tags = optional(map(string)) + to_port = optional(string) + }))) + security_group_egress_rules = optional(map(object({ + name = optional(string) + cidr_ipv4 = optional(string) + cidr_ipv6 = optional(string) + description = optional(string) + from_port = optional(string) + ip_protocol = optional(string) + prefix_list_id = optional(string) + referenced_security_group_id = optional(string) + self = optional(bool) + tags = optional(map(string)) + to_port = optional(string) + }))) + security_group_tags = optional(map(string)) tags = optional(map(string)) }) @@ -1871,6 +1929,37 @@ variable "eks_managed_node_groups" { # Security group vpc_security_group_ids = optional(list(string), []) cluster_primary_security_group_id = optional(string) + create_security_group = optional(bool, true) + security_group_name = optional(string) + security_group_use_name_prefix = optional(bool, true) + security_group_description = optional(string) + security_group_ingress_rules = optional(map(object({ + name = optional(string) + cidr_ipv4 = optional(string) + cidr_ipv6 = optional(string) + description = optional(string) + from_port = optional(string) + ip_protocol = optional(string, "tcp") + prefix_list_id = optional(string) + referenced_security_group_id = optional(string) + self = optional(bool, false) + tags = optional(map(string), {}) + to_port = optional(string) + })), {}) + security_group_egress_rules = optional(map(object({ + name = optional(string) + cidr_ipv4 = optional(string) + cidr_ipv6 = optional(string) + description = optional(string) + from_port = optional(string) + ip_protocol = optional(string, "tcp") + prefix_list_id = optional(string) + referenced_security_group_id = optional(string) + self = optional(bool, false) + tags = optional(map(string), {}) + to_port = optional(string) + })), {}) + security_group_tags = optional(map(string), {}) tags = optional(map(string), {}) })) @@ -2099,6 +2188,37 @@ variable "eks_managed_node_group_defaults" { # Security group vpc_security_group_ids = optional(list(string)) cluster_primary_security_group_id = optional(string) + create_security_group = optional(bool) + security_group_name = optional(string) + security_group_use_name_prefix = optional(bool) + security_group_description = optional(string) + security_group_ingress_rules = optional(map(object({ + name = optional(string) + cidr_ipv4 = optional(string) + cidr_ipv6 = optional(string) + description = optional(string) + from_port = optional(string) + ip_protocol = optional(string) + prefix_list_id = optional(string) + referenced_security_group_id = optional(string) + self = optional(bool) + tags = optional(map(string)) + to_port = optional(string) + }))) + security_group_egress_rules = optional(map(object({ + name = optional(string) + cidr_ipv4 = optional(string) + cidr_ipv6 = optional(string) + description = optional(string) + from_port = optional(string) + ip_protocol = optional(string) + prefix_list_id = optional(string) + referenced_security_group_id = optional(string) + self = optional(bool) + tags = optional(map(string)) + to_port = optional(string) + }))) + security_group_tags = optional(map(string)) tags = optional(map(string), {}) }) From 8bf26fa7eb18bdf0d7b1511958139e99da1dffc3 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Wed, 9 Jul 2025 13:27:10 -0500 Subject: [PATCH 13/25] fix: Remove arguments that do not make sense in EKS --- README.md | 4 +-- modules/self-managed-node-group/README.md | 3 --- modules/self-managed-node-group/main.tf | 27 -------------------- modules/self-managed-node-group/variables.tf | 27 -------------------- node_groups.tf | 11 +++----- variables.tf | 15 ----------- 6 files changed, 6 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index 8123dcb7fb..7719aae515 100644 --- a/README.md +++ b/README.md @@ -472,8 +472,8 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [security\_group\_name](#input\_security\_group\_name) | Name to use on cluster security group created | `string` | `null` | no | | [security\_group\_tags](#input\_security\_group\_tags) | A map of additional tags to add to the cluster security group created | `map(string)` | `{}` | no | | [security\_group\_use\_name\_prefix](#input\_security\_group\_use\_name\_prefix) | Determines whether cluster security group name (`cluster_security_group_name`) is used as a prefix | `bool` | `true` | no | -| [self\_managed\_node\_group\_defaults](#input\_self\_managed\_node\_group\_defaults) | Map of self-managed node group default configurations |
object({
create = optional(bool)
# Autoscaling Group
create_autoscaling_group = optional(bool)
use_name_prefix = optional(bool)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool)
context = optional(string)
target_group_arns = optional(list(string))
create_placement_group = optional(bool)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(number)
force_delete = optional(bool)
force_delete_warm_pool = optional(bool)
termination_policies = optional(list(string))
suspended_processes = optional(list(string))
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string))
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string)
triggers = optional(list(string))
}))
use_mixed_instances_policy = optional(bool)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
warm_pool = optional(object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string))
# User data
ami_type = optional(string)
additional_cluster_dns_ips = optional(list(string))
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string)
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
hibernation_options = optional(object({
configured = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool)
iam_role_arn = optional(string)
# Security group
create_security_group = optional(bool)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_tags = optional(map(string))

tags = optional(map(string))
})
| `{}` | no | -| [self\_managed\_node\_groups](#input\_self\_managed\_node\_groups) | Map of self-managed node group definitions to create |
map(object({
create = optional(bool, true)
# Autoscaling Group
create_autoscaling_group = optional(bool, true)
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool, false)
context = optional(string)
target_group_arns = optional(list(string), [])
create_placement_group = optional(bool, false)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(number)
force_delete = optional(bool)
force_delete_warm_pool = optional(bool)
termination_policies = optional(list(string), [])
suspended_processes = optional(list(string), [])
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string), [])
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number, 66)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string, "Rolling")
triggers = optional(list(string))
}), {
strategy = "Rolling"
preferences = {
min_healthy_percentage = 66
}
})
use_mixed_instances_policy = optional(bool, false)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
warm_pool = optional(object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string), {})
# User data
ami_type = optional(string, "AL2023_x86_64_STANDARD")
additional_cluster_dns_ips = optional(list(string), [])
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string, "m6i.large")
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
hibernation_options = optional(object({
configured = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool, true)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Self managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool, true)
iam_role_arn = optional(string)
# Security group
create_security_group = optional(bool, true)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool, true)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_tags = optional(map(string), {})

tags = optional(map(string), {})
}))
| `{}` | no | +| [self\_managed\_node\_group\_defaults](#input\_self\_managed\_node\_group\_defaults) | Map of self-managed node group default configurations |
object({
create = optional(bool)
# Autoscaling Group
create_autoscaling_group = optional(bool)
use_name_prefix = optional(bool)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool)
context = optional(string)
target_group_arns = optional(list(string))
create_placement_group = optional(bool)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(number)
force_delete = optional(bool)
termination_policies = optional(list(string))
suspended_processes = optional(list(string))
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string))
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string)
triggers = optional(list(string))
}))
use_mixed_instances_policy = optional(bool)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string))
# User data
ami_type = optional(string)
additional_cluster_dns_ips = optional(list(string))
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string)
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool)
iam_role_arn = optional(string)
# Security group
create_security_group = optional(bool)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_tags = optional(map(string))

tags = optional(map(string))
})
| `{}` | no | +| [self\_managed\_node\_groups](#input\_self\_managed\_node\_groups) | Map of self-managed node group definitions to create |
map(object({
create = optional(bool, true)
# Autoscaling Group
create_autoscaling_group = optional(bool, true)
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool, false)
context = optional(string)
target_group_arns = optional(list(string), [])
create_placement_group = optional(bool, false)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(number)
force_delete = optional(bool)
force_delete_warm_pool = optional(bool)
termination_policies = optional(list(string), [])
suspended_processes = optional(list(string), [])
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string), [])
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number, 66)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string, "Rolling")
triggers = optional(list(string))
}), {
strategy = "Rolling"
preferences = {
min_healthy_percentage = 66
}
})
use_mixed_instances_policy = optional(bool, false)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
warm_pool = optional(object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string), {})
# User data
ami_type = optional(string, "AL2023_x86_64_STANDARD")
additional_cluster_dns_ips = optional(list(string), [])
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string, "m6i.large")
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool, true)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Self managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool, true)
iam_role_arn = optional(string)
# Security group
create_security_group = optional(bool, true)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool, true)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_tags = optional(map(string), {})

tags = optional(map(string), {})
}))
| `{}` | no | | [service\_ipv4\_cidr](#input\_service\_ipv4\_cidr) | The CIDR block to assign Kubernetes service IP addresses from. If you don't specify a block, Kubernetes assigns addresses from either the 10.100.0.0/16 or 172.20.0.0/16 CIDR blocks | `string` | `null` | no | | [service\_ipv6\_cidr](#input\_service\_ipv6\_cidr) | The CIDR block to assign Kubernetes pod and service IP addresses from if `ipv6` was specified when the cluster was created. Kubernetes assigns service addresses from the unique local address range (fc00::/7) because you can't specify a custom IPv6 CIDR block when you create the cluster | `string` | `null` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs where the nodes/node groups will be provisioned. If `control_plane_subnet_ids` is not provided, the EKS cluster control plane (ENIs) will be provisioned in these subnets | `list(string)` | `[]` | no | diff --git a/modules/self-managed-node-group/README.md b/modules/self-managed-node-group/README.md index 663c7f10b0..2ef6fdb426 100644 --- a/modules/self-managed-node-group/README.md +++ b/modules/self-managed-node-group/README.md @@ -127,10 +127,8 @@ module "self_managed_node_group" { | [enabled\_metrics](#input\_enabled\_metrics) | A list of metrics to collect. The allowed values are `GroupDesiredCapacity`, `GroupInServiceCapacity`, `GroupPendingCapacity`, `GroupMinSize`, `GroupMaxSize`, `GroupInServiceInstances`, `GroupPendingInstances`, `GroupStandbyInstances`, `GroupStandbyCapacity`, `GroupTerminatingCapacity`, `GroupTerminatingInstances`, `GroupTotalCapacity`, `GroupTotalInstances` | `list(string)` | `[]` | no | | [enclave\_options](#input\_enclave\_options) | Enable Nitro Enclaves on launched instances |
object({
enabled = optional(bool)
})
| `null` | no | | [force\_delete](#input\_force\_delete) | Allows deleting the Auto Scaling Group without waiting for all instances in the pool to terminate. You can force an Auto Scaling Group to delete even if it's in the process of scaling a resource. Normally, Terraform drains all the instances before deleting the group. This bypasses that behavior and potentially leaves resources dangling | `bool` | `null` | no | -| [force\_delete\_warm\_pool](#input\_force\_delete\_warm\_pool) | Allows deleting the Auto Scaling Group without waiting for all instances in the warm pool to terminate | `bool` | `null` | no | | [health\_check\_grace\_period](#input\_health\_check\_grace\_period) | Time (in seconds) after instance comes into service before checking health | `number` | `null` | no | | [health\_check\_type](#input\_health\_check\_type) | `EC2` or `ELB`. Controls how health checking is done | `string` | `null` | no | -| [hibernation\_options](#input\_hibernation\_options) | The hibernation options for the instance |
object({
configured = optional(bool)
})
| `null` | no | | [iam\_instance\_profile\_arn](#input\_iam\_instance\_profile\_arn) | Amazon Resource Name (ARN) of an existing IAM instance profile that provides permissions for the node group. Required if `create_iam_instance_profile` = `false` | `string` | `null` | no | | [iam\_role\_additional\_policies](#input\_iam\_role\_additional\_policies) | Additional policies to be added to the IAM role | `map(string)` | `{}` | no | | [iam\_role\_arn](#input\_iam\_role\_arn) | ARN of the IAM role used by the instance profile. Required when `create_access_entry = true` and `create_iam_instance_profile = false` | `string` | `null` | no | @@ -200,7 +198,6 @@ module "self_managed_node_group" { | [vpc\_security\_group\_ids](#input\_vpc\_security\_group\_ids) | A list of security group IDs to associate | `list(string)` | `[]` | no | | [wait\_for\_capacity\_timeout](#input\_wait\_for\_capacity\_timeout) | A maximum duration that Terraform should wait for ASG instances to be healthy before timing out. (See also Waiting for Capacity below.) Setting this to '0' causes Terraform to skip all Capacity Waiting behavior | `string` | `null` | no | | [wait\_for\_elb\_capacity](#input\_wait\_for\_elb\_capacity) | Setting this will cause Terraform to wait for exactly this number of healthy instances in all attached load balancers on both create and update operations. Takes precedence over `min_elb_capacity` behavior | `number` | `null` | no | -| [warm\_pool](#input\_warm\_pool) | If this block is configured, add a Warm Pool to the specified Auto Scaling group |
object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
})
| `null` | no | ## Outputs diff --git a/modules/self-managed-node-group/main.tf b/modules/self-managed-node-group/main.tf index 54b03c7a46..d9c3cdc5db 100644 --- a/modules/self-managed-node-group/main.tf +++ b/modules/self-managed-node-group/main.tf @@ -191,14 +191,6 @@ resource "aws_launch_template" "this" { } } - dynamic "hibernation_options" { - for_each = var.hibernation_options != null ? [var.hibernation_options] : [] - - content { - configured = hibernation_options.value.configured - } - } - iam_instance_profile { arn = var.create_iam_instance_profile ? aws_iam_instance_profile.this[0].arn : var.iam_instance_profile_arn } @@ -500,7 +492,6 @@ resource "aws_autoscaling_group" "this" { desired_capacity_type = var.desired_size_type enabled_metrics = var.enabled_metrics force_delete = var.force_delete - force_delete_warm_pool = var.force_delete_warm_pool health_check_grace_period = var.health_check_grace_period health_check_type = var.health_check_type @@ -773,24 +764,6 @@ resource "aws_autoscaling_group" "this" { wait_for_capacity_timeout = var.wait_for_capacity_timeout wait_for_elb_capacity = var.wait_for_elb_capacity - dynamic "warm_pool" { - for_each = var.warm_pool != null ? [var.warm_pool] : [] - - content { - dynamic "instance_reuse_policy" { - for_each = warm_pool.value.instance_reuse_policy != null ? [warm_pool.value.instance_reuse_policy] : [] - - content { - reuse_on_scale_in = instance_reuse_policy.value.reuse_on_scale_in - } - } - - max_group_prepared_capacity = warm_pool.value.max_group_prepared_capacity - min_size = warm_pool.value.min_size - pool_state = warm_pool.value.pool_state - } - } - dynamic "timeouts" { for_each = var.timeouts != null ? [var.timeouts] : [] diff --git a/modules/self-managed-node-group/variables.tf b/modules/self-managed-node-group/variables.tf index 34fde3831c..21bdb82fff 100644 --- a/modules/self-managed-node-group/variables.tf +++ b/modules/self-managed-node-group/variables.tf @@ -237,14 +237,6 @@ variable "enclave_options" { default = null } -variable "hibernation_options" { - description = "The hibernation options for the instance" - type = object({ - configured = optional(bool) - }) - default = null -} - variable "instance_market_options" { description = "The market (purchasing) option for the instance" type = object({ @@ -651,12 +643,6 @@ variable "force_delete" { default = null } -variable "force_delete_warm_pool" { - description = "Allows deleting the Auto Scaling Group without waiting for all instances in the warm pool to terminate" - type = bool - default = null -} - variable "termination_policies" { description = "A list of policies to decide how the instances in the Auto Scaling Group should be terminated. The allowed values are `OldestInstance`, `NewestInstance`, `OldestLaunchConfiguration`, `ClosestToNextInstanceHour`, `OldestLaunchTemplate`, `AllocationStrategy`, `Default`" type = list(string) @@ -829,19 +815,6 @@ variable "mixed_instances_policy" { default = null } -variable "warm_pool" { - description = "If this block is configured, add a Warm Pool to the specified Auto Scaling group" - type = object({ - instance_reuse_policy = optional(object({ - reuse_on_scale_in = optional(bool) - })) - max_group_prepared_capacity = optional(number) - min_size = optional(number) - pool_state = optional(string) - }) - default = null -} - variable "timeouts" { description = "Timeout configurations for the autoscaling group" type = object({ diff --git a/node_groups.tf b/node_groups.tf index e240eaa3e0..44ce11a473 100644 --- a/node_groups.tf +++ b/node_groups.tf @@ -424,11 +424,10 @@ module "self_managed_node_group" { ignore_failed_scaling_activities = try(each.value.ignore_failed_scaling_activities, var.self_managed_node_group_defaults.ignore_failed_scaling_activities, null) - force_delete = try(each.value.force_delete, var.self_managed_node_group_defaults.force_delete, null) - force_delete_warm_pool = try(each.value.force_delete_warm_pool, var.self_managed_node_group_defaults.force_delete_warm_pool, null) - termination_policies = try(each.value.termination_policies, var.self_managed_node_group_defaults.termination_policies, null) - suspended_processes = try(each.value.suspended_processes, var.self_managed_node_group_defaults.suspended_processes, null) - max_instance_lifetime = try(each.value.max_instance_lifetime, var.self_managed_node_group_defaults.max_instance_lifetime, null) + force_delete = try(each.value.force_delete, var.self_managed_node_group_defaults.force_delete, null) + termination_policies = try(each.value.termination_policies, var.self_managed_node_group_defaults.termination_policies, null) + suspended_processes = try(each.value.suspended_processes, var.self_managed_node_group_defaults.suspended_processes, null) + max_instance_lifetime = try(each.value.max_instance_lifetime, var.self_managed_node_group_defaults.max_instance_lifetime, null) enabled_metrics = try(each.value.enabled_metrics, var.self_managed_node_group_defaults.enabled_metrics, null) metrics_granularity = try(each.value.metrics_granularity, var.self_managed_node_group_defaults.metrics_granularity, null) @@ -439,7 +438,6 @@ module "self_managed_node_group" { instance_refresh = try(each.value.instance_refresh, var.self_managed_node_group_defaults.instance_refresh, null) use_mixed_instances_policy = try(each.value.use_mixed_instances_policy, var.self_managed_node_group_defaults.use_mixed_instances_policy, null) mixed_instances_policy = try(each.value.mixed_instances_policy, var.self_managed_node_group_defaults.mixed_instances_policy, null) - warm_pool = try(each.value.warm_pool, var.self_managed_node_group_defaults.warm_pool, null) timeouts = try(each.value.timeouts, var.self_managed_node_group_defaults.timeouts, null) autoscaling_group_tags = try(each.value.autoscaling_group_tags, var.self_managed_node_group_defaults.autoscaling_group_tags, null) @@ -486,7 +484,6 @@ module "self_managed_node_group" { cpu_options = try(each.value.cpu_options, var.self_managed_node_group_defaults.cpu_options, null) credit_specification = try(each.value.credit_specification, var.self_managed_node_group_defaults.credit_specification, null) enclave_options = try(each.value.enclave_options, var.self_managed_node_group_defaults.enclave_options, null) - hibernation_options = try(each.value.hibernation_options, var.self_managed_node_group_defaults.hibernation_options, null) instance_requirements = try(each.value.instance_requirements, var.self_managed_node_group_defaults.instance_requirements, null) instance_market_options = try(each.value.instance_market_options, var.self_managed_node_group_defaults.instance_market_options, null) license_specifications = try(each.value.license_specifications, var.self_managed_node_group_defaults.license_specifications, null) diff --git a/variables.tf b/variables.tf index f27bf7bde7..57096db34f 100644 --- a/variables.tf +++ b/variables.tf @@ -1058,9 +1058,6 @@ variable "self_managed_node_groups" { enclave_options = optional(object({ enabled = optional(bool) })) - hibernation_options = optional(object({ - configured = optional(bool) - })) instance_requirements = optional(object({ accelerator_count = optional(object({ max = optional(number) @@ -1294,7 +1291,6 @@ variable "self_managed_node_group_defaults" { health_check_grace_period = optional(number) ignore_failed_scaling_activities = optional(number) force_delete = optional(bool) - force_delete_warm_pool = optional(bool) termination_policies = optional(list(string)) suspended_processes = optional(list(string)) max_instance_lifetime = optional(number) @@ -1407,14 +1403,6 @@ variable "self_managed_node_group_defaults" { }))) }) })) - warm_pool = optional(object({ - instance_reuse_policy = optional(object({ - reuse_on_scale_in = optional(bool) - })) - max_group_prepared_capacity = optional(number) - min_size = optional(number) - pool_state = optional(string) - })) timeouts = optional(object({ delete = optional(string) })) @@ -1491,9 +1479,6 @@ variable "self_managed_node_group_defaults" { enclave_options = optional(object({ enabled = optional(bool) })) - hibernation_options = optional(object({ - configured = optional(bool) - })) instance_requirements = optional(object({ accelerator_count = optional(object({ max = optional(number) From a28e9aefd3ad1b063af29ee631c460a95bb35cc5 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Wed, 9 Jul 2025 15:02:57 -0500 Subject: [PATCH 14/25] fix: Updates from plan validation --- README.md | 176 +++++++++---------- docs/compute_resources.md | 41 +++-- docs/faq.md | 35 ++-- docs/network_connectivity.md | 2 +- docs/user_data.md | 24 ++- main.tf | 28 +-- modules/eks-managed-node-group/README.md | 3 +- modules/eks-managed-node-group/main.tf | 11 +- modules/eks-managed-node-group/variables.tf | 10 +- modules/fargate-profile/README.md | 6 +- modules/fargate-profile/variables.tf | 10 +- modules/self-managed-node-group/main.tf | 4 +- modules/self-managed-node-group/variables.tf | 8 + node_groups.tf | 58 +++--- variables.tf | 50 +++--- 15 files changed, 271 insertions(+), 195 deletions(-) diff --git a/README.md b/README.md index 7719aae515..06f230472a 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,89 @@ module "eks" { } ``` +### EKS Managed Node Group + +```hcl +module "eks" { + source = "terraform-aws-modules/eks/aws" + version = "~> 21.0" + + name = "my-cluster" + kubernetes_version = "1.33" + + addons = { + coredns = {} + eks-pod-identity-agent = {} + kube-proxy = {} + vpc-cni = {} + } + + # Optional + endpoint_public_access = true + + # Optional: Adds the current caller identity as an administrator via cluster access entry + enable_cluster_creator_admin_permissions = true + + vpc_id = "vpc-1234556abcdef" + subnet_ids = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"] + control_plane_subnet_ids = ["subnet-xyzde987", "subnet-slkjf456", "subnet-qeiru789"] + + # EKS Managed Node Group(s) + eks_managed_node_group_defaults = { + instance_types = ["m6i.large", "m5.large", "m5n.large", "m5zn.large"] + } + + eks_managed_node_groups = { + example = { + # Starting on 1.30, AL2023 is the default AMI type for EKS managed node groups + ami_type = "AL2023_x86_64_STANDARD" + instance_types = ["m5.xlarge"] + + min_size = 2 + max_size = 10 + desired_size = 2 + } + } + + tags = { + Environment = "dev" + Terraform = "true" + } +} +``` + +### Cluster Access Entry + +When enabling `authentication_mode = "API_AND_CONFIG_MAP"`, EKS will automatically create an access entry for the IAM role(s) used by managed node group(s) and Fargate profile(s). There are no additional actions required by users. For self-managed node groups and the Karpenter sub-module, this project automatically adds the access entry on behalf of users so there are no additional actions required by users. + +On clusters that were created prior to cluster access management (CAM) support, there will be an existing access entry for the cluster creator. This was previously not visible when using `aws-auth` ConfigMap, but will become visible when access entry is enabled. + +```hcl +module "eks" { + source = "terraform-aws-modules/eks/aws" + version = "~> 21.0" + + # Truncated for brevity ... + + access_entries = { + # One access entry with a policy associated + example = { + principal_arn = "arn:aws:iam::123456789012:role/something" + + policy_associations = { + example = { + policy_arn = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSViewPolicy" + access_scope = { + namespaces = ["default"] + type = "namespace" + } + } + } + } + } +} +``` + ### EKS Hybrid Nodes ```hcl @@ -141,89 +224,6 @@ module "eks" { } ``` -### EKS Managed Node Group - -```hcl -module "eks" { - source = "terraform-aws-modules/eks/aws" - version = "~> 21.0" - - name = "my-cluster" - kubernetes_version = "1.33" - - addons = { - coredns = {} - eks-pod-identity-agent = {} - kube-proxy = {} - vpc-cni = {} - } - - # Optional - endpoint_public_access = true - - # Optional: Adds the current caller identity as an administrator via cluster access entry - enable_cluster_creator_admin_permissions = true - - vpc_id = "vpc-1234556abcdef" - subnet_ids = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"] - control_plane_subnet_ids = ["subnet-xyzde987", "subnet-slkjf456", "subnet-qeiru789"] - - # EKS Managed Node Group(s) - eks_managed_node_group_defaults = { - instance_types = ["m6i.large", "m5.large", "m5n.large", "m5zn.large"] - } - - eks_managed_node_groups = { - example = { - # Starting on 1.30, AL2023 is the default AMI type for EKS managed node groups - ami_type = "AL2023_x86_64_STANDARD" - instance_types = ["m5.xlarge"] - - min_size = 2 - max_size = 10 - desired_size = 2 - } - } - - tags = { - Environment = "dev" - Terraform = "true" - } -} -``` - -### Cluster Access Entry - -When enabling `authentication_mode = "API_AND_CONFIG_MAP"`, EKS will automatically create an access entry for the IAM role(s) used by managed node group(s) and Fargate profile(s). There are no additional actions required by users. For self-managed node groups and the Karpenter sub-module, this project automatically adds the access entry on behalf of users so there are no additional actions required by users. - -On clusters that were created prior to cluster access management (CAM) support, there will be an existing access entry for the cluster creator. This was previously not visible when using `aws-auth` ConfigMap, but will become visible when access entry is enabled. - -```hcl -module "eks" { - source = "terraform-aws-modules/eks/aws" - version = "~> 21.0" - - # Truncated for brevity ... - - access_entries = { - # One access entry with a policy associated - example = { - principal_arn = "arn:aws:iam::123456789012:role/something" - - policy_associations = { - example = { - policy_arn = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSViewPolicy" - access_scope = { - namespaces = ["default"] - type = "namespace" - } - } - } - } - } -} -``` - ### Bootstrap Cluster Creator Admin Permissions Setting the `bootstrap_cluster_creator_admin_permissions` is a one time operation when the cluster is created; it cannot be modified later through the EKS API. In this project we are hardcoding this to `false`. If users wish to achieve the same functionality, we will do that through an access entry which can be enabled or disabled at any time of their choosing using the variable `enable_cluster_creator_admin_permissions` @@ -405,8 +405,8 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [create\_security\_group](#input\_create\_security\_group) | Determines if a security group is created for the cluster. Note: the EKS service creates a primary security group for the cluster by default | `bool` | `true` | no | | [custom\_oidc\_thumbprints](#input\_custom\_oidc\_thumbprints) | Additional list of server certificate thumbprints for the OpenID Connect (OIDC) identity provider's server certificate(s) | `list(string)` | `[]` | no | | [dataplane\_wait\_duration](#input\_dataplane\_wait\_duration) | Duration to wait after the EKS cluster has become active before creating the dataplane components (EKS managed node group(s), self-managed node group(s), Fargate profile(s)) | `string` | `"30s"` | no | -| [eks\_managed\_node\_group\_defaults](#input\_eks\_managed\_node\_group\_defaults) | Map of EKS managed node group default configurations |
object({
create = optional(bool)
kubernetes_version = optional(string)

# EKS Managed Node Group
use_name_prefix = optional(bool)
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
ami_id = optional(string)
ami_type = optional(string)
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool)
capacity_type = optional(string)
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}))
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool)
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
create_placement_group = optional(bool)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string))
cluster_primary_security_group_id = optional(string)
create_security_group = optional(bool)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_tags = optional(map(string))

tags = optional(map(string), {})
})
| `{}` | no | -| [eks\_managed\_node\_groups](#input\_eks\_managed\_node\_groups) | Map of EKS managed node group definitions to create |
map(object({
create = optional(bool, true)
kubernetes_version = optional(string)

# EKS Managed Node Group
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
ami_id = optional(string, "")
ami_type = optional(string, "AL2023_x86_64_STANDARD")
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool, true)
capacity_type = optional(string, "ON_DEMAND")
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool, true)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}), {
max_unavailable_percentage = 33
})
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool, false)
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
create_placement_group = optional(bool, false)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool, true)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "EKS managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string), [])
cluster_primary_security_group_id = optional(string)
create_security_group = optional(bool, true)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool, true)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_tags = optional(map(string), {})

tags = optional(map(string), {})
}))
| `{}` | no | +| [eks\_managed\_node\_group\_defaults](#input\_eks\_managed\_node\_group\_defaults) | Map of EKS managed node group default configurations |
object({
create = optional(bool)
kubernetes_version = optional(string)

# EKS Managed Node Group
use_name_prefix = optional(bool)
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
ami_id = optional(string)
ami_type = optional(string)
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool)
capacity_type = optional(string)
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}))
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool)
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
create_placement_group = optional(bool)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string))
attach_cluster_primary_security_group = optional(bool, false)
cluster_primary_security_group_id = optional(string)
create_security_group = optional(bool)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_tags = optional(map(string))

tags = optional(map(string), {})
})
| `{}` | no | +| [eks\_managed\_node\_groups](#input\_eks\_managed\_node\_groups) | Map of EKS managed node group definitions to create |
map(object({
create = optional(bool, true)
kubernetes_version = optional(string)

# EKS Managed Node Group
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
ami_id = optional(string, "")
ami_type = optional(string, "AL2023_x86_64_STANDARD")
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool, true)
capacity_type = optional(string, "ON_DEMAND")
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool, true)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}), {
max_unavailable_percentage = 33
})
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool, false)
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
create_placement_group = optional(bool, false)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool, true)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "EKS managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string), [])
attach_cluster_primary_security_group = optional(bool, false)
cluster_primary_security_group_id = optional(string)
create_security_group = optional(bool, true)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool, true)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_tags = optional(map(string), {})

tags = optional(map(string), {})
}))
| `{}` | no | | [enable\_auto\_mode\_custom\_tags](#input\_enable\_auto\_mode\_custom\_tags) | Determines whether to enable permissions for custom tags resources created by EKS Auto Mode | `bool` | `true` | no | | [enable\_cluster\_creator\_admin\_permissions](#input\_enable\_cluster\_creator\_admin\_permissions) | Indicates whether or not to add the cluster creator (the identity used by Terraform) as an administrator via access entry | `bool` | `false` | no | | [enable\_irsa](#input\_enable\_irsa) | Determines whether to create an OpenID Connect Provider for EKS to enable IRSA | `bool` | `true` | no | @@ -422,7 +422,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [endpoint\_public\_access](#input\_endpoint\_public\_access) | Indicates whether or not the Amazon EKS public API server endpoint is enabled | `bool` | `false` | no | | [endpoint\_public\_access\_cidrs](#input\_endpoint\_public\_access\_cidrs) | List of CIDR blocks which can access the Amazon EKS public API server endpoint | `list(string)` |
[
"0.0.0.0/0"
]
| no | | [fargate\_profile\_defaults](#input\_fargate\_profile\_defaults) | Map of Fargate Profile default configurations |
object({
create = optional(bool)

# Fargate profile
name = optional(string) # Will fall back to map key
subnet_ids = optional(list(string))
selectors = optional(list(object({
labels = optional(map(string))
namespace = string
})))
timeouts = optional(object({
create = optional(string)
delete = optional(string)
}))

# IAM role
create_iam_role = optional(bool)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
tags = optional(map(string), {})
})
| `{}` | no | -| [fargate\_profiles](#input\_fargate\_profiles) | Map of Fargate Profile definitions to create |
map(object({
create = optional(bool, true)

# Fargate profile
name = optional(string) # Will fall back to map key
subnet_ids = optional(list(string), [])
selectors = optional(list(object({
labels = optional(map(string))
namespace = string
})))
timeouts = optional(object({
create = optional(string)
delete = optional(string)
}))

# IAM role
create_iam_role = optional(bool, true)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Fargate profile IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
tags = optional(map(string), {})
}))
| `{}` | no | +| [fargate\_profiles](#input\_fargate\_profiles) | Map of Fargate Profile definitions to create |
map(object({
create = optional(bool, true)

# Fargate profile
name = optional(string) # Will fall back to map key
subnet_ids = optional(list(string))
selectors = optional(list(object({
labels = optional(map(string))
namespace = string
})))
timeouts = optional(object({
create = optional(string)
delete = optional(string)
}))

# IAM role
create_iam_role = optional(bool, true)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Fargate profile IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
tags = optional(map(string), {})
}))
| `{}` | no | | [force\_update\_version](#input\_force\_update\_version) | Force version update by overriding upgrade-blocking readiness checks when updating a cluster | `bool` | `null` | no | | [iam\_role\_additional\_policies](#input\_iam\_role\_additional\_policies) | Additional policies to be added to the IAM role | `map(string)` | `{}` | no | | [iam\_role\_arn](#input\_iam\_role\_arn) | Existing IAM role ARN for the cluster. Required if `create_iam_role` is set to `false` | `string` | `null` | no | @@ -472,8 +472,8 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [security\_group\_name](#input\_security\_group\_name) | Name to use on cluster security group created | `string` | `null` | no | | [security\_group\_tags](#input\_security\_group\_tags) | A map of additional tags to add to the cluster security group created | `map(string)` | `{}` | no | | [security\_group\_use\_name\_prefix](#input\_security\_group\_use\_name\_prefix) | Determines whether cluster security group name (`cluster_security_group_name`) is used as a prefix | `bool` | `true` | no | -| [self\_managed\_node\_group\_defaults](#input\_self\_managed\_node\_group\_defaults) | Map of self-managed node group default configurations |
object({
create = optional(bool)
# Autoscaling Group
create_autoscaling_group = optional(bool)
use_name_prefix = optional(bool)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool)
context = optional(string)
target_group_arns = optional(list(string))
create_placement_group = optional(bool)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(number)
force_delete = optional(bool)
termination_policies = optional(list(string))
suspended_processes = optional(list(string))
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string))
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string)
triggers = optional(list(string))
}))
use_mixed_instances_policy = optional(bool)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string))
# User data
ami_type = optional(string)
additional_cluster_dns_ips = optional(list(string))
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string)
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool)
iam_role_arn = optional(string)
# Security group
create_security_group = optional(bool)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_tags = optional(map(string))

tags = optional(map(string))
})
| `{}` | no | -| [self\_managed\_node\_groups](#input\_self\_managed\_node\_groups) | Map of self-managed node group definitions to create |
map(object({
create = optional(bool, true)
# Autoscaling Group
create_autoscaling_group = optional(bool, true)
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool, false)
context = optional(string)
target_group_arns = optional(list(string), [])
create_placement_group = optional(bool, false)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(number)
force_delete = optional(bool)
force_delete_warm_pool = optional(bool)
termination_policies = optional(list(string), [])
suspended_processes = optional(list(string), [])
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string), [])
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number, 66)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string, "Rolling")
triggers = optional(list(string))
}), {
strategy = "Rolling"
preferences = {
min_healthy_percentage = 66
}
})
use_mixed_instances_policy = optional(bool, false)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
warm_pool = optional(object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string), {})
# User data
ami_type = optional(string, "AL2023_x86_64_STANDARD")
additional_cluster_dns_ips = optional(list(string), [])
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string, "m6i.large")
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool, true)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Self managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool, true)
iam_role_arn = optional(string)
# Security group
create_security_group = optional(bool, true)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool, true)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_tags = optional(map(string), {})

tags = optional(map(string), {})
}))
| `{}` | no | +| [self\_managed\_node\_group\_defaults](#input\_self\_managed\_node\_group\_defaults) | Map of self-managed node group default configurations |
object({
create = optional(bool)
# Autoscaling Group
create_autoscaling_group = optional(bool)
use_name_prefix = optional(bool)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool)
context = optional(string)
target_group_arns = optional(list(string))
create_placement_group = optional(bool)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(bool)
force_delete = optional(bool)
termination_policies = optional(list(string))
suspended_processes = optional(list(string))
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string))
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string)
triggers = optional(list(string))
}))
use_mixed_instances_policy = optional(bool)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string))
# User data
ami_type = optional(string)
additional_cluster_dns_ips = optional(list(string))
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string)
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool)
iam_role_arn = optional(string)
# Security group
attach_cluster_primary_security_group = optional(bool, false)
create_security_group = optional(bool)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_tags = optional(map(string))

tags = optional(map(string))
})
| `{}` | no | +| [self\_managed\_node\_groups](#input\_self\_managed\_node\_groups) | Map of self-managed node group definitions to create |
map(object({
create = optional(bool, true)
# Autoscaling Group
create_autoscaling_group = optional(bool, true)
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool, false)
context = optional(string)
target_group_arns = optional(list(string), [])
create_placement_group = optional(bool, false)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(bool)
force_delete = optional(bool)
force_delete_warm_pool = optional(bool)
termination_policies = optional(list(string), [])
suspended_processes = optional(list(string), [])
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string), [])
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number, 66)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string, "Rolling")
triggers = optional(list(string))
}), {
strategy = "Rolling"
preferences = {
min_healthy_percentage = 66
}
})
use_mixed_instances_policy = optional(bool, false)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
warm_pool = optional(object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string), {})
# User data
ami_type = optional(string, "AL2023_x86_64_STANDARD")
additional_cluster_dns_ips = optional(list(string), [])
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string, "m6i.large")
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool, true)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Self managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool, true)
iam_role_arn = optional(string)
# Security group
attach_cluster_primary_security_group = optional(bool, false)
create_security_group = optional(bool, true)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool, true)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_tags = optional(map(string), {})

tags = optional(map(string), {})
}))
| `{}` | no | | [service\_ipv4\_cidr](#input\_service\_ipv4\_cidr) | The CIDR block to assign Kubernetes service IP addresses from. If you don't specify a block, Kubernetes assigns addresses from either the 10.100.0.0/16 or 172.20.0.0/16 CIDR blocks | `string` | `null` | no | | [service\_ipv6\_cidr](#input\_service\_ipv6\_cidr) | The CIDR block to assign Kubernetes pod and service IP addresses from if `ipv6` was specified when the cluster was created. Kubernetes assigns service addresses from the unique local address range (fc00::/7) because you can't specify a custom IPv6 CIDR block when you create the cluster | `string` | `null` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs where the nodes/node groups will be provisioned. If `control_plane_subnet_ids` is not provided, the EKS cluster control plane (ENIs) will be provisioned in these subnets | `list(string)` | `[]` | no | diff --git a/docs/compute_resources.md b/docs/compute_resources.md index 4b40c2e68e..7838ce616b 100644 --- a/docs/compute_resources.md +++ b/docs/compute_resources.md @@ -56,22 +56,36 @@ Refer to the [EKS Managed Node Group documentation](https://docs.aws.amazon.com/ ```hcl eks_managed_node_groups = { custom_ami = { - ami_id = "ami-0caf35bc73450c396" + ami_id = "ami-0caf35bc73450c396" + ami_type = "AL2023_x86_64_STANDARD" # By default, EKS managed node groups will not append bootstrap script; # this adds it back in using the default template provided by the module # Note: this assumes the AMI provided is an EKS optimized AMI derivative enable_bootstrap_user_data = true - pre_bootstrap_user_data = <<-EOT - export FOO=bar - EOT - - # Because we have full control over the user data supplied, we can also run additional - # scripts/configuration changes after the bootstrap script has been run - post_bootstrap_user_data = <<-EOT - echo "you are free little kubelet!" - EOT + cloudinit_pre_nodeadm = [{ + content = <<-EOT + --- + apiVersion: node.eks.aws/v1alpha1 + kind: NodeConfig + spec: + kubelet: + config: + shutdownGracePeriod: 30s + featureGates: + DisableKubeletCloudCredentialProviders: true + EOT + content_type = "application/node.eks.aws" + }] + + # This is only possible when `ami_id` is specified, indicating a custom AMI + cloudinit_post_nodeadm = [{ + content = <<-EOT + echo "All done" + EOT + content_type = "text/x-shellscript; charset=\"us-ascii\"" + }] } } ``` @@ -115,7 +129,7 @@ Refer to the [Self Managed Node Group documentation](https://docs.aws.amazon.com ```hcl kubernetes_version = "1.33" - # This self managed node group will use the latest AWS EKS Optimized AMI for Kubernetes 1.27 + # This self managed node group will use the latest AWS EKS Optimized AMI for Kubernetes 1.33 self_managed_node_groups = { default = {} } @@ -152,7 +166,7 @@ For example, the following creates 4 AWS EKS Managed Node Groups: ```hcl eks_managed_node_group_defaults = { - ami_type = "AL2_x86_64" + ami_type = "AL2023_x86_64_STANDARD" disk_size = 50 instance_types = ["m6i.large", "m5.large", "m5n.large", "m5zn.large"] } @@ -166,9 +180,8 @@ For example, the following creates 4 AWS EKS Managed Node Groups: instance_types = ["c5.large", "c6i.large", "c6d.large"] } - # This further overrides the instance types and disk size used + # This further overrides the instance types persistent = { - disk_size = 1024 instance_types = ["r5.xlarge", "r6i.xlarge", "r5b.xlarge"] } diff --git a/docs/faq.md b/docs/faq.md index 2abd6695c2..27b873e72a 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -12,23 +12,36 @@ `disk_size`, and `remote_access` can only be set when using the EKS managed node group default launch template. This module defaults to providing a custom launch template to allow for custom security groups, tag propagation, etc. If you wish to forgo the custom launch template route, you can set `use_custom_launch_template = false` and then you can set `disk_size` and `remote_access`. -### I received an error: `expect exactly one securityGroup tagged with kubernetes.io/cluster/ ...` +### I received an error: `expect exactly one securityGroup tagged with kubernetes.io/cluster/ ...` -By default, EKS creates a cluster primary security group that is created outside of the module and the EKS service adds the tag `{ "kubernetes.io/cluster/" = "owned" }`. This on its own does not cause any conflicts for addons such as the AWS Load Balancer Controller until users decide to attach both the cluster primary security group and the shared node security group created by the module (by setting `attach_cluster_primary_security_group = true`). The issue is not with having multiple security groups in your account with this tag key:value combination, but having multiple security groups with this tag key:value combination attached to nodes in the same cluster. There are a few ways to resolve this depending on your use case/intentions: +⚠️ `` would be the name of your cluster -⚠️ `` below needs to be replaced with the name of your cluster +By default, EKS creates a cluster primary security group that is created outside of the module and the EKS service adds the tag `{ "kubernetes.io/cluster/" = "owned" }`. This on its own does not cause any conflicts for addons such as the AWS Load Balancer Controller until users decide to attach both the cluster primary security group and the shared node security group created by the module (by setting `attach_cluster_primary_security_group = true`). The issue is not with having multiple security groups in your account with this tag key:value combination, but having multiple security groups with this tag key:value combination attached to nodes in the same cluster. There are a few ways to resolve this depending on your use case/intentions: 1. If you want to use the cluster primary security group, you can disable the creation of the shared node security group with: ```hcl - create_node_security_group = false # default is true - attach_cluster_primary_security_group = true # default is false + create_node_security_group = false # default is true + + eks_managed_node_group_defaults = { + attach_cluster_primary_security_group = true # default is false + } + # Or for self-managed + self_managed_node_group_defaults = { + attach_cluster_primary_security_group = true # default is false + } ``` 2. By not attaching the cluster primary security group. The cluster primary security group has quite broad access and the module has instead provided a security group with the minimum amount of access to launch an empty EKS cluster successfully and users are encouraged to open up access when necessary to support their workload. ```hcl - attach_cluster_primary_security_group = false # this is the default for the module + eks_managed_node_group_defaults = { + attach_cluster_primary_security_group = true # default is false + } + # Or for self-managed + self_managed_node_group_defaults = { + attach_cluster_primary_security_group = true # default is false + } ``` In theory, if you are attaching the cluster primary security group, you shouldn't need to use the shared node security group created by the module. However, this is left up to users to decide for their requirements and use case. @@ -58,6 +71,8 @@ If you require a public endpoint, setting up both (public and private) and restr The module is configured to ignore this value. Unfortunately, Terraform does not support variables within the `lifecycle` block. The setting is ignored to allow autoscaling via controllers such as cluster autoscaler or Karpenter to work properly and without interference by Terraform. Changing the desired count must be handled outside of Terraform once the node group is created. +:info: See [this](https://github.com/bryantbiggs/eks-desired-size-hack) for a workaround to this limitation. + ### How do I access compute resource attributes? Examples of accessing the attributes of the compute resource(s) created by the root module are shown below. Note - the assumption is that your cluster module definition is named `eks` as in `module "eks" { ... }`: @@ -90,6 +105,10 @@ aws eks describe-addon-versions --query 'addons[*].addonName' ### What configuration values are available for an add-on? +> [!NOTE] +> The available configuration values will vary between add-on versions, +> typically more configuration values will be added in later versions as functionality is enabled by EKS. + You can retrieve the configuration value schema for a given addon using the following command: ```sh @@ -286,7 +305,3 @@ Returns (at the time of writing): } } ``` - -> [!NOTE] -> The available configuration values will vary between add-on versions, -> typically more configuration values will be added in later versions as functionality is enabled by EKS. diff --git a/docs/network_connectivity.md b/docs/network_connectivity.md index 9d38fc130d..2cb38d5e3e 100644 --- a/docs/network_connectivity.md +++ b/docs/network_connectivity.md @@ -27,7 +27,7 @@ See the example snippet below which adds additional security group rules to the ```hcl ... # Extend cluster security group rules - cluster_security_group_additional_rules = { + security_group_additional_rules = { egress_nodes_ephemeral_ports_tcp = { description = "To node 1025-65535" protocol = "tcp" diff --git a/docs/user_data.md b/docs/user_data.md index 3ca2263deb..2bd17f69a9 100644 --- a/docs/user_data.md +++ b/docs/user_data.md @@ -10,7 +10,8 @@ Users can see the various methods of using and providing user data through the [ - AMI types of `BOTTLEROCKET_*`, user data must be in TOML format - AMI types of `WINDOWS_*`, user data must be in powershell/PS1 script format - Self Managed Node Groups - - `AL2_x86_64` AMI type (default) -> the user data template (bash/shell script) provided by the module is used as the default; users are able to provide their own user data template + - `AL2_*` AMI types -> the user data template (bash/shell script) provided by the module is used as the default; users are able to provide their own user data template + - `AL2023_*` AMI types -> the user data template (MIME multipart format) provided by the module is used as the default; users are able to provide their own user data template - `BOTTLEROCKET_*` AMI types -> the user data template (TOML file) provided by the module is used as the default; users are able to provide their own user data template - `WINDOWS_*` AMI types -> the user data template (powershell/PS1 script) provided by the module is used as the default; users are able to provide their own user data template @@ -24,9 +25,24 @@ When using an EKS managed node group, users have 2 primary routes for interactin - Users can use the following variables to facilitate this process: - ```hcl - pre_bootstrap_user_data = "..." - ``` + For `AL2_*`, `BOTTLEROCKET_*`, and `WINDOWS_*`: + ```hcl + pre_bootstrap_user_data = "..." + ``` + + For `AL2023_*` + ```hcl + cloudinit_pre_nodeadm = [{ + content = <<-EOT + --- + apiVersion: node.eks.aws/v1alpha1 + kind: NodeConfig + spec: + ... + EOT + content_type = "application/node.eks.aws" + }] + ``` 2. If a custom AMI is used, then per the [AWS documentation](https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-custom-ami), users will need to supply the necessary user data to bootstrap and register nodes with the cluster when launched. There are two routes to facilitate this bootstrapping process: - If the AMI used is a derivative of the [AWS EKS Optimized AMI ](https://github.com/awslabs/amazon-eks-ami), users can opt in to using a template provided by the module that provides the minimum necessary configuration to bootstrap the node when launched: diff --git a/main.tf b/main.tf index cde2b90508..4f016b3752 100644 --- a/main.tf +++ b/main.tf @@ -60,7 +60,7 @@ resource "aws_eks_cluster" "this" { content { enabled = compute_config.value.enabled node_pools = compute_config.value.node_pools - node_role_arn = try(compute_config.value.node_pools, []) > 0 ? try(compute_config.value.node_role_arn, aws_iam_role.eks_auto[0].arn, null) : null + node_role_arn = compute_config.value.node_pools != null ? try(compute_config.value.node_role_arn, aws_iam_role.eks_auto[0].arn, null) : null } } @@ -283,14 +283,14 @@ resource "aws_eks_access_entry" "this" { for_each = { for k, v in local.merged_access_entries : k => v if local.create } cluster_name = aws_eks_cluster.this[0].id - kubernetes_groups = each.value.kubernetes_groups + kubernetes_groups = try(each.value.kubernetes_groups, null) principal_arn = each.value.principal_arn - type = each.value.type - user_name = each.value.user_name + type = try(each.value.type, null) + user_name = try(each.value.user_name, null) tags = merge( var.tags, - each.value.tags, + try(each.value.tags, {}), ) } @@ -403,12 +403,12 @@ resource "aws_security_group_rule" "cluster" { from_port = each.value.from_port to_port = each.value.to_port type = each.value.type - description = each.value.description - cidr_blocks = each.value.cidr_blocks - ipv6_cidr_blocks = each.value.ipv6_cidr_blocks - prefix_list_ids = each.value.prefix_list_ids - self = each.value.self - source_security_group_id = each.value.source_node_security_group ? local.node_security_group_id : each.value.source_security_group_id + description = try(each.value.description, null) + cidr_blocks = try(each.value.cidr_blocks, null) + ipv6_cidr_blocks = try(each.value.ipv6_cidr_blocks, null) + prefix_list_ids = try(each.value.prefix_list_ids, null) + self = try(each.value.self, null) + source_security_group_id = try(each.value.source_node_security_group, false) ? local.node_security_group_id : try(each.value.source_security_group_id, null) } ################################################################################ @@ -733,7 +733,7 @@ resource "aws_iam_role_policy_attachment" "custom" { data "aws_eks_addon_version" "this" { for_each = var.addons != null && local.create && !local.create_outposts_local_cluster ? var.addons : {} - addon_name = try(each.value.name, each.key) + addon_name = coalesce(each.value.name, each.key) kubernetes_version = coalesce(var.kubernetes_version, aws_eks_cluster.this[0].version) most_recent = each.value.most_recent } @@ -743,7 +743,7 @@ resource "aws_eks_addon" "this" { for_each = var.addons != null && local.create && !local.create_outposts_local_cluster ? { for k, v in var.addons : k => v if !v.before_compute } : {} cluster_name = aws_eks_cluster.this[0].id - addon_name = try(each.value.name, each.key) + addon_name = coalesce(each.value.name, each.key) addon_version = try(each.value.addon_version, data.aws_eks_addon_version.this[each.key].version) configuration_values = each.value.configuration_values @@ -786,7 +786,7 @@ resource "aws_eks_addon" "before_compute" { for_each = var.addons != null && local.create && !local.create_outposts_local_cluster ? { for k, v in var.addons : k => v if v.before_compute } : {} cluster_name = aws_eks_cluster.this[0].id - addon_name = try(each.value.name, each.key) + addon_name = coalesce(each.value.name, each.key) addon_version = try(each.value.addon_version, data.aws_eks_addon_version.this[each.key].version) configuration_values = each.value.configuration_values diff --git a/modules/eks-managed-node-group/README.md b/modules/eks-managed-node-group/README.md index ca829e00e1..be15277ee4 100644 --- a/modules/eks-managed-node-group/README.md +++ b/modules/eks-managed-node-group/README.md @@ -94,6 +94,7 @@ module "eks_managed_node_group" { | [aws_vpc_security_group_ingress_rule.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule) | resource | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_ec2_instance_type.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_instance_type) | data source | +| [aws_eks_cluster_versions.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/eks_cluster_versions) | data source | | [aws_iam_policy_document.assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | @@ -117,7 +118,7 @@ module "eks_managed_node_group" { | [cluster\_auth\_base64](#input\_cluster\_auth\_base64) | Base64 encoded CA of associated EKS cluster | `string` | `""` | no | | [cluster\_endpoint](#input\_cluster\_endpoint) | Endpoint of associated EKS cluster | `string` | `""` | no | | [cluster\_ip\_family](#input\_cluster\_ip\_family) | The IP family used to assign Kubernetes pod and service addresses. Valid values are `ipv4` (default) and `ipv6` | `string` | `"ipv4"` | no | -| [cluster\_name](#input\_cluster\_name) | Name of associated EKS cluster | `string` | `null` | no | +| [cluster\_name](#input\_cluster\_name) | Name of associated EKS cluster | `string` | `""` | no | | [cluster\_primary\_security\_group\_id](#input\_cluster\_primary\_security\_group\_id) | The ID of the EKS cluster primary security group to associate with the instance(s). This is the security group that is automatically created by the EKS service | `string` | `null` | no | | [cluster\_service\_cidr](#input\_cluster\_service\_cidr) | The CIDR block (IPv4 or IPv6) used by the cluster to assign Kubernetes service IP addresses. This is derived from the cluster itself | `string` | `""` | no | | [cpu\_options](#input\_cpu\_options) | The CPU options for the instance |
object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
})
| `null` | no | diff --git a/modules/eks-managed-node-group/main.tf b/modules/eks-managed-node-group/main.tf index a33f2cca81..df8bde2fd0 100644 --- a/modules/eks-managed-node-group/main.tf +++ b/modules/eks-managed-node-group/main.tf @@ -361,9 +361,16 @@ resource "aws_launch_template" "this" { # AMI SSM Parameter ################################################################################ +data "aws_eks_cluster_versions" "this" { + count = var.create && var.kubernetes_version == null ? 1 : 0 + + cluster_type = "eks" + version_status = "STANDARD_SUPPORT" +} + locals { # Just to ensure templating doesn't fail when values are not provided - ssm_kubernetes_version = var.kubernetes_version != null ? var.kubernetes_version : "" + ssm_kubernetes_version = var.kubernetes_version != null ? var.kubernetes_version : try(data.aws_eks_cluster_versions.this[0].cluster_versions[0].cluster_version, "UNSPECIFIED") ssm_ami_type = var.ami_type != null ? var.ami_type : "" # Map the AMI type to the respective SSM param path @@ -737,7 +744,7 @@ resource "aws_vpc_security_group_ingress_rule" "this" { } resource "aws_vpc_security_group_egress_rule" "this" { - for_each = { for k, v in local.security_group_egress_rules : k => v if length(local.security_group_egress_rules) && local.create_security_group } + for_each = { for k, v in local.security_group_egress_rules : k => v if length(local.security_group_egress_rules) > 0 && local.create_security_group } cidr_ipv4 = each.value.cidr_ipv4 cidr_ipv6 = each.value.cidr_ipv6 diff --git a/modules/eks-managed-node-group/variables.tf b/modules/eks-managed-node-group/variables.tf index 7810da0058..e16c98af27 100644 --- a/modules/eks-managed-node-group/variables.tf +++ b/modules/eks-managed-node-group/variables.tf @@ -2,6 +2,7 @@ variable "create" { description = "Determines whether to create EKS managed node group or not" type = bool default = true + nullable = false } variable "tags" { @@ -35,7 +36,8 @@ variable "enable_bootstrap_user_data" { variable "cluster_name" { description = "Name of associated EKS cluster" type = string - default = null + default = "" + nullable = false } variable "cluster_endpoint" { @@ -110,6 +112,7 @@ variable "create_launch_template" { description = "Determines whether to create a launch template or not. If set to `false`, EKS will use its own default launch template" type = bool default = true + nullable = false } variable "use_custom_launch_template" { @@ -389,6 +392,7 @@ variable "create_placement_group" { description = "Determines whether a placement group is created & used by the node group" type = bool default = false + nullable = false } variable "private_dns_name_options" { @@ -445,6 +449,7 @@ variable "name" { description = "Name of the EKS managed node group" type = string default = "" + nullable = false } variable "use_name_prefix" { @@ -569,6 +574,7 @@ variable "create_iam_role" { description = "Determines whether an IAM role is created or to use an existing IAM role" type = bool default = true + nullable = false } variable "cluster_ip_family" { @@ -639,6 +645,7 @@ variable "create_iam_role_policy" { description = "Determines whether an IAM role policy is created or not" type = bool default = true + nullable = false } variable "iam_role_policy_statements" { @@ -675,6 +682,7 @@ variable "create_security_group" { description = "Determines if a security group is created" type = bool default = true + nullable = false } variable "security_group_name" { diff --git a/modules/fargate-profile/README.md b/modules/fargate-profile/README.md index 430a3753d1..c93a3d2da9 100644 --- a/modules/fargate-profile/README.md +++ b/modules/fargate-profile/README.md @@ -60,9 +60,9 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [account\_id](#input\_account\_id) | The AWS account ID - pass through value to reduce number of GET requests from data sources | `string` | `null` | no | +| [account\_id](#input\_account\_id) | The AWS account ID - pass through value to reduce number of GET requests from data sources | `string` | `""` | no | | [cluster\_ip\_family](#input\_cluster\_ip\_family) | The IP family used to assign Kubernetes pod and service addresses. Valid values are `ipv4` (default) and `ipv6` | `string` | `"ipv4"` | no | -| [cluster\_name](#input\_cluster\_name) | Name of the EKS cluster | `string` | `null` | no | +| [cluster\_name](#input\_cluster\_name) | Name of the EKS cluster | `string` | `""` | no | | [create](#input\_create) | Determines whether to create Fargate profile or not | `bool` | `true` | no | | [create\_iam\_role](#input\_create\_iam\_role) | Determines whether an IAM role is created or to use an existing IAM role | `bool` | `true` | no | | [create\_iam\_role\_policy](#input\_create\_iam\_role\_policy) | Determines whether an IAM role policy is created or not | `bool` | `true` | no | @@ -77,7 +77,7 @@ No modules. | [iam\_role\_tags](#input\_iam\_role\_tags) | A map of additional tags to add to the IAM role created | `map(string)` | `{}` | no | | [iam\_role\_use\_name\_prefix](#input\_iam\_role\_use\_name\_prefix) | Determines whether the IAM role name (`iam_role_name`) is used as a prefix | `bool` | `true` | no | | [name](#input\_name) | Name of the EKS Fargate Profile | `string` | `""` | no | -| [partition](#input\_partition) | The AWS partition - pass through value to reduce number of GET requests from data sources | `string` | `null` | no | +| [partition](#input\_partition) | The AWS partition - pass through value to reduce number of GET requests from data sources | `string` | `""` | no | | [selectors](#input\_selectors) | Configuration block(s) for selecting Kubernetes Pods to execute with this Fargate Profile |
list(object({
labels = optional(map(string))
namespace = string
}))
| `null` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs for the EKS Fargate Profile | `list(string)` | `[]` | no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | diff --git a/modules/fargate-profile/variables.tf b/modules/fargate-profile/variables.tf index 571d250353..5afa5f1c65 100644 --- a/modules/fargate-profile/variables.tf +++ b/modules/fargate-profile/variables.tf @@ -2,6 +2,7 @@ variable "create" { description = "Determines whether to create Fargate profile or not" type = bool default = true + nullable = false } variable "tags" { @@ -13,13 +14,13 @@ variable "tags" { variable "partition" { description = "The AWS partition - pass through value to reduce number of GET requests from data sources" type = string - default = null + default = "" } variable "account_id" { description = "The AWS account ID - pass through value to reduce number of GET requests from data sources" type = string - default = null + default = "" } ################################################################################ @@ -30,6 +31,7 @@ variable "create_iam_role" { description = "Determines whether an IAM role is created or to use an existing IAM role" type = bool default = true + nullable = false } variable "cluster_ip_family" { @@ -100,6 +102,7 @@ variable "create_iam_role_policy" { description = "Determines whether an IAM role policy is created or not" type = bool default = true + nullable = false } variable "iam_role_policy_statements" { @@ -135,13 +138,14 @@ variable "iam_role_policy_statements" { variable "cluster_name" { description = "Name of the EKS cluster" type = string - default = null + default = "" } variable "name" { description = "Name of the EKS Fargate Profile" type = string default = "" + nullable = false } variable "subnet_ids" { diff --git a/modules/self-managed-node-group/main.tf b/modules/self-managed-node-group/main.tf index d9c3cdc5db..0241f1dba7 100644 --- a/modules/self-managed-node-group/main.tf +++ b/modules/self-managed-node-group/main.tf @@ -870,7 +870,7 @@ resource "aws_iam_instance_profile" "this" { ################################################################################ locals { - create_iam_role_policy = local.create_iam_instance_profile && var.create_iam_role_policy && length(var.iam_role_policy_statements) > 0 + create_iam_role_policy = local.create_iam_instance_profile && var.create_iam_role_policy && var.iam_role_policy_statements != null } data "aws_iam_policy_document" "role" { @@ -1038,7 +1038,7 @@ resource "aws_vpc_security_group_ingress_rule" "this" { } resource "aws_vpc_security_group_egress_rule" "this" { - for_each = { for k, v in local.security_group_egress_rules : k => v if length(local.security_group_egress_rules) && local.create_security_group } + for_each = { for k, v in local.security_group_egress_rules : k => v if length(local.security_group_egress_rules) > 0 && local.create_security_group } cidr_ipv4 = each.value.cidr_ipv4 cidr_ipv6 = each.value.cidr_ipv6 diff --git a/modules/self-managed-node-group/variables.tf b/modules/self-managed-node-group/variables.tf index 21bdb82fff..d53c52571a 100644 --- a/modules/self-managed-node-group/variables.tf +++ b/modules/self-managed-node-group/variables.tf @@ -2,6 +2,7 @@ variable "create" { description = "Determines whether to create self managed node group or not" type = bool default = true + nullable = false } variable "tags" { @@ -116,6 +117,7 @@ variable "create_launch_template" { description = "Determines whether to create launch template or not" type = bool default = true + nullable = false } variable "launch_template_id" { @@ -325,6 +327,7 @@ variable "create_placement_group" { description = "Determines whether a placement group is created & used by the node group" type = bool default = false + nullable = false } variable "private_dns_name_options" { @@ -503,6 +506,7 @@ variable "create_autoscaling_group" { description = "Determines whether to create autoscaling group or not" type = bool default = true + nullable = false } variable "name" { @@ -837,6 +841,7 @@ variable "create_iam_instance_profile" { description = "Determines whether an IAM instance profile is created or to use an existing IAM instance profile" type = bool default = true + nullable = false } variable "iam_instance_profile_arn" { @@ -901,6 +906,7 @@ variable "create_iam_role_policy" { description = "Determines whether an IAM role policy is created or not" type = bool default = true + nullable = false } variable "iam_role_policy_statements" { @@ -937,6 +943,7 @@ variable "create_access_entry" { description = "Determines whether an access entry is created for the IAM role used by the node group" type = bool default = true + nullable = false } variable "iam_role_arn" { @@ -953,6 +960,7 @@ variable "create_security_group" { description = "Determines if a security group is created" type = bool default = true + nullable = false } variable "security_group_name" { diff --git a/node_groups.tf b/node_groups.tf index 44ce11a473..a434cf1f64 100644 --- a/node_groups.tf +++ b/node_groups.tf @@ -13,12 +13,12 @@ resource "time_sleep" "this" { create_duration = var.dataplane_wait_duration triggers = { - cluster_name = aws_eks_cluster.this[0].id - cluster_endpoint = aws_eks_cluster.this[0].endpoint - kubernetes_version = aws_eks_cluster.this[0].version - cluster_service_cidr = var.ip_family == "ipv6" ? try(local.kubernetes_network_config.service_ipv6_cidr, "") : try(local.kubernetes_network_config.service_ipv4_cidr, "") + name = aws_eks_cluster.this[0].id + endpoint = aws_eks_cluster.this[0].endpoint + kubernetes_version = aws_eks_cluster.this[0].version + service_cidr = var.ip_family == "ipv6" ? try(local.kubernetes_network_config.service_ipv6_cidr, "") : try(local.kubernetes_network_config.service_ipv4_cidr, "") - cluster_certificate_authority_data = aws_eks_cluster.this[0].certificate_authority[0].data + certificate_authority_data = aws_eks_cluster.this[0].certificate_authority[0].data } } @@ -199,12 +199,12 @@ resource "aws_security_group_rule" "node" { from_port = each.value.from_port to_port = each.value.to_port type = each.value.type - description = each.value.description - cidr_blocks = each.value.cidr_blocks - ipv6_cidr_blocks = each.value.ipv6_cidr_blocks - prefix_list_ids = each.value.prefix_list_ids - self = each.value.self - source_security_group_id = each.value.source_cluster_security_group ? local.security_group_id : each.value.source_security_group_id + description = try(each.value.description, null) + cidr_blocks = try(each.value.cidr_blocks, null) + ipv6_cidr_blocks = try(each.value.ipv6_cidr_blocks, null) + prefix_list_ids = try(each.value.prefix_list_ids, null) + self = try(each.value.self, null) + source_security_group_id = try(each.value.source_cluster_security_group, false) ? local.security_group_id : try(each.value.source_security_group_id, null) } ################################################################################ @@ -223,10 +223,10 @@ module "fargate_profile" { account_id = local.account_id # Fargate Profile - cluster_name = time_sleep.this[0].triggers["cluster_name"] + cluster_name = time_sleep.this[0].triggers["name"] cluster_ip_family = var.ip_family - name = try(each.value.name, each.key) - subnet_ids = try(each.value.subnet_ids, var.fargate_profile_defaults.subnet_ids, var.subnet_ids) + name = coalesce(each.value.name, each.key) + subnet_ids = coalesce(each.value.subnet_ids, var.fargate_profile_defaults.subnet_ids, var.subnet_ids) selectors = try(each.value.selectors, var.fargate_profile_defaults.selectors, null) timeouts = try(each.value.timeouts, var.fargate_profile_defaults.timeouts, null) @@ -240,7 +240,7 @@ module "fargate_profile" { iam_role_permissions_boundary = try(each.value.iam_role_permissions_boundary, var.fargate_profile_defaults.iam_role_permissions_boundary, null) iam_role_tags = try(each.value.iam_role_tags, var.fargate_profile_defaults.iam_role_tags, null) iam_role_attach_cni_policy = try(each.value.iam_role_attach_cni_policy, var.fargate_profile_defaults.iam_role_attach_cni_policy, null) - iam_role_additional_policies = try(each.value.iam_role_additional_policies, var.fargate_profile_defaults.iam_role_additional_policies, null) + iam_role_additional_policies = lookup(each.value, "iam_role_additional_policies", lookup(var.fargate_profile_defaults, "iam_role_additional_policies", null)) create_iam_role_policy = try(each.value.create_iam_role_policy, var.fargate_profile_defaults.create_iam_role_policy, null) iam_role_policy_statements = try(each.value.iam_role_policy_statements, var.fargate_profile_defaults.iam_role_policy_statements, null) @@ -266,14 +266,14 @@ module "eks_managed_node_group" { partition = local.partition account_id = local.account_id - cluster_name = time_sleep.this[0].triggers["cluster_name"] + cluster_name = time_sleep.this[0].triggers["name"] kubernetes_version = try(each.value.kubernetes_version, var.eks_managed_node_group_defaults.kubernetes_version, time_sleep.this[0].triggers["kubernetes_version"]) # EKS Managed Node Group - name = try(each.value.name, each.key) + name = coalesce(each.value.name, each.key) use_name_prefix = try(each.value.use_name_prefix, var.eks_managed_node_group_defaults.use_name_prefix, null) - subnet_ids = try(each.value.subnet_ids, var.eks_managed_node_group_defaults.subnet_ids, var.subnet_ids) + subnet_ids = coalesce(each.value.subnet_ids, var.eks_managed_node_group_defaults.subnet_ids, var.subnet_ids) min_size = try(each.value.min_size, var.eks_managed_node_group_defaults.min_size, null) max_size = try(each.value.max_size, var.eks_managed_node_group_defaults.max_size, null) @@ -296,10 +296,10 @@ module "eks_managed_node_group" { timeouts = try(each.value.timeouts, var.eks_managed_node_group_defaults.timeouts, null) # User data - cluster_endpoint = try(time_sleep.this[0].triggers["cluster_endpoint"], "") - cluster_auth_base64 = try(time_sleep.this[0].triggers["cluster_certificate_authority_data"], "") + cluster_endpoint = try(time_sleep.this[0].triggers["endpoint"], "") + cluster_auth_base64 = try(time_sleep.this[0].triggers["certificate_authority_data"], "") cluster_ip_family = var.ip_family - cluster_service_cidr = try(time_sleep.this[0].triggers["cluster_service_cidr"], "") + cluster_service_cidr = try(time_sleep.this[0].triggers["service_cidr"], "") enable_bootstrap_user_data = try(each.value.enable_bootstrap_user_data, var.eks_managed_node_group_defaults.enable_bootstrap_user_data, null) pre_bootstrap_user_data = try(each.value.pre_bootstrap_user_data, var.eks_managed_node_group_defaults.pre_bootstrap_user_data, null) post_bootstrap_user_data = try(each.value.post_bootstrap_user_data, var.eks_managed_node_group_defaults.post_bootstrap_user_data, null) @@ -355,7 +355,7 @@ module "eks_managed_node_group" { iam_role_permissions_boundary = try(each.value.iam_role_permissions_boundary, var.eks_managed_node_group_defaults.iam_role_permissions_boundary, null) iam_role_tags = try(each.value.iam_role_tags, var.eks_managed_node_group_defaults.iam_role_tags, null) iam_role_attach_cni_policy = try(each.value.iam_role_attach_cni_policy, var.eks_managed_node_group_defaults.iam_role_attach_cni_policy, null) - iam_role_additional_policies = try(each.value.iam_role_additional_policies, var.eks_managed_node_group_defaults.iam_role_additional_policies, null) + iam_role_additional_policies = lookup(each.value, "iam_role_additional_policies", lookup(var.eks_managed_node_group_defaults, "iam_role_additional_policies", null)) create_iam_role_policy = try(each.value.create_iam_role_policy, var.eks_managed_node_group_defaults.create_iam_role_policy, true) iam_role_policy_statements = try(each.value.iam_role_policy_statements, var.eks_managed_node_group_defaults.iam_role_policy_statements, null) @@ -392,16 +392,16 @@ module "self_managed_node_group" { partition = local.partition account_id = local.account_id - cluster_name = time_sleep.this[0].triggers["cluster_name"] + cluster_name = time_sleep.this[0].triggers["name"] # Autoscaling Group create_autoscaling_group = try(each.value.create_autoscaling_group, var.self_managed_node_group_defaults.create_autoscaling_group, null) - name = try(each.value.name, each.key) + name = coalesce(each.value.name, each.key) use_name_prefix = try(each.value.use_name_prefix, var.self_managed_node_group_defaults.use_name_prefix, null) availability_zones = try(each.value.availability_zones, var.self_managed_node_group_defaults.availability_zones, null) - subnet_ids = try(each.value.subnet_ids, var.self_managed_node_group_defaults.subnet_ids, var.subnet_ids) + subnet_ids = coalesce(each.value.subnet_ids, var.self_managed_node_group_defaults.subnet_ids, var.subnet_ids) min_size = try(each.value.min_size, var.self_managed_node_group_defaults.min_size, null) max_size = try(each.value.max_size, var.self_managed_node_group_defaults.max_size, null) @@ -444,9 +444,9 @@ module "self_managed_node_group" { # User data ami_type = try(each.value.ami_type, var.self_managed_node_group_defaults.ami_type, null) - cluster_endpoint = try(time_sleep.this[0].triggers["cluster_endpoint"], "") - cluster_auth_base64 = try(time_sleep.this[0].triggers["cluster_certificate_authority_data"], "") - cluster_service_cidr = try(time_sleep.this[0].triggers["cluster_service_cidr"], "") + cluster_endpoint = try(time_sleep.this[0].triggers["endpoint"], "") + cluster_auth_base64 = try(time_sleep.this[0].triggers["certificate_authority_data"], "") + cluster_service_cidr = try(time_sleep.this[0].triggers["service_cidr"], "") additional_cluster_dns_ips = try(each.value.additional_cluster_dns_ips, var.self_managed_node_group_defaults.additional_cluster_dns_ips, null) cluster_ip_family = var.ip_family pre_bootstrap_user_data = try(each.value.pre_bootstrap_user_data, var.self_managed_node_group_defaults.pre_bootstrap_user_data, null) @@ -507,7 +507,7 @@ module "self_managed_node_group" { iam_role_permissions_boundary = try(each.value.iam_role_permissions_boundary, var.self_managed_node_group_defaults.iam_role_permissions_boundary, null) iam_role_tags = try(each.value.iam_role_tags, var.self_managed_node_group_defaults.iam_role_tags, null) iam_role_attach_cni_policy = try(each.value.iam_role_attach_cni_policy, var.self_managed_node_group_defaults.iam_role_attach_cni_policy, null) - iam_role_additional_policies = try(each.value.iam_role_additional_policies, var.self_managed_node_group_defaults.iam_role_additional_policies, null) + iam_role_additional_policies = lookup(each.value, "iam_role_additional_policies", lookup(var.self_managed_node_group_defaults, "iam_role_additional_policies", null)) create_iam_role_policy = try(each.value.create_iam_role_policy, var.self_managed_node_group_defaults.create_iam_role_policy, null) iam_role_policy_statements = try(each.value.iam_role_policy_statements, var.self_managed_node_group_defaults.iam_role_policy_statements, null) diff --git a/variables.tf b/variables.tf index 57096db34f..5092cf3c85 100644 --- a/variables.tf +++ b/variables.tf @@ -721,7 +721,7 @@ variable "fargate_profiles" { # Fargate profile name = optional(string) # Will fall back to map key - subnet_ids = optional(list(string), []) + subnet_ids = optional(list(string)) selectors = optional(list(object({ labels = optional(map(string)) namespace = string @@ -854,7 +854,7 @@ variable "self_managed_node_groups" { placement_group = optional(string) health_check_type = optional(string) health_check_grace_period = optional(number) - ignore_failed_scaling_activities = optional(number) + ignore_failed_scaling_activities = optional(bool) force_delete = optional(bool) force_delete_warm_pool = optional(bool) termination_policies = optional(list(string), []) @@ -1227,10 +1227,11 @@ variable "self_managed_node_groups" { create_access_entry = optional(bool, true) iam_role_arn = optional(string) # Security group - create_security_group = optional(bool, true) - security_group_name = optional(string) - security_group_use_name_prefix = optional(bool, true) - security_group_description = optional(string) + attach_cluster_primary_security_group = optional(bool, false) + create_security_group = optional(bool, true) + security_group_name = optional(string) + security_group_use_name_prefix = optional(bool, true) + security_group_description = optional(string) security_group_ingress_rules = optional(map(object({ name = optional(string) cidr_ipv4 = optional(string) @@ -1289,7 +1290,7 @@ variable "self_managed_node_group_defaults" { placement_group = optional(string) health_check_type = optional(string) health_check_grace_period = optional(number) - ignore_failed_scaling_activities = optional(number) + ignore_failed_scaling_activities = optional(bool) force_delete = optional(bool) termination_policies = optional(list(string)) suspended_processes = optional(list(string)) @@ -1644,10 +1645,11 @@ variable "self_managed_node_group_defaults" { create_access_entry = optional(bool) iam_role_arn = optional(string) # Security group - create_security_group = optional(bool) - security_group_name = optional(string) - security_group_use_name_prefix = optional(bool) - security_group_description = optional(string) + attach_cluster_primary_security_group = optional(bool, false) + create_security_group = optional(bool) + security_group_name = optional(string) + security_group_use_name_prefix = optional(bool) + security_group_description = optional(string) security_group_ingress_rules = optional(map(object({ name = optional(string) cidr_ipv4 = optional(string) @@ -1912,12 +1914,13 @@ variable "eks_managed_node_groups" { }))) }))) # Security group - vpc_security_group_ids = optional(list(string), []) - cluster_primary_security_group_id = optional(string) - create_security_group = optional(bool, true) - security_group_name = optional(string) - security_group_use_name_prefix = optional(bool, true) - security_group_description = optional(string) + vpc_security_group_ids = optional(list(string), []) + attach_cluster_primary_security_group = optional(bool, false) + cluster_primary_security_group_id = optional(string) + create_security_group = optional(bool, true) + security_group_name = optional(string) + security_group_use_name_prefix = optional(bool, true) + security_group_description = optional(string) security_group_ingress_rules = optional(map(object({ name = optional(string) cidr_ipv4 = optional(string) @@ -2171,12 +2174,13 @@ variable "eks_managed_node_group_defaults" { }))) }))) # Security group - vpc_security_group_ids = optional(list(string)) - cluster_primary_security_group_id = optional(string) - create_security_group = optional(bool) - security_group_name = optional(string) - security_group_use_name_prefix = optional(bool) - security_group_description = optional(string) + vpc_security_group_ids = optional(list(string)) + attach_cluster_primary_security_group = optional(bool, false) + cluster_primary_security_group_id = optional(string) + create_security_group = optional(bool) + security_group_name = optional(string) + security_group_use_name_prefix = optional(bool) + security_group_description = optional(string) security_group_ingress_rules = optional(map(object({ name = optional(string) cidr_ipv4 = optional(string) From f3df353d78fbde23b1f1ec710d3074f655b0f9c8 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Wed, 9 Jul 2025 19:38:17 -0500 Subject: [PATCH 15/25] fix: Remove more self-managed node group attributes that are commonly not used in EKS clusters --- .pre-commit-config.yaml | 2 +- README.md | 4 +-- modules/self-managed-node-group/README.md | 6 ---- modules/self-managed-node-group/main.tf | 20 ++++------- modules/self-managed-node-group/variables.tf | 36 -------------------- node_groups.tf | 28 ++++++--------- variables.tf | 19 ----------- 7 files changed, 21 insertions(+), 94 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bfddd4b673..b489ccee0d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.99.4 + rev: v1.99.5 hooks: - id: terraform_fmt - id: terraform_docs diff --git a/README.md b/README.md index 06f230472a..251c46ac6c 100644 --- a/README.md +++ b/README.md @@ -472,8 +472,8 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [security\_group\_name](#input\_security\_group\_name) | Name to use on cluster security group created | `string` | `null` | no | | [security\_group\_tags](#input\_security\_group\_tags) | A map of additional tags to add to the cluster security group created | `map(string)` | `{}` | no | | [security\_group\_use\_name\_prefix](#input\_security\_group\_use\_name\_prefix) | Determines whether cluster security group name (`cluster_security_group_name`) is used as a prefix | `bool` | `true` | no | -| [self\_managed\_node\_group\_defaults](#input\_self\_managed\_node\_group\_defaults) | Map of self-managed node group default configurations |
object({
create = optional(bool)
# Autoscaling Group
create_autoscaling_group = optional(bool)
use_name_prefix = optional(bool)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool)
context = optional(string)
target_group_arns = optional(list(string))
create_placement_group = optional(bool)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(bool)
force_delete = optional(bool)
termination_policies = optional(list(string))
suspended_processes = optional(list(string))
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string))
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string)
triggers = optional(list(string))
}))
use_mixed_instances_policy = optional(bool)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string))
# User data
ami_type = optional(string)
additional_cluster_dns_ips = optional(list(string))
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string)
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool)
iam_role_arn = optional(string)
# Security group
attach_cluster_primary_security_group = optional(bool, false)
create_security_group = optional(bool)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_tags = optional(map(string))

tags = optional(map(string))
})
| `{}` | no | -| [self\_managed\_node\_groups](#input\_self\_managed\_node\_groups) | Map of self-managed node group definitions to create |
map(object({
create = optional(bool, true)
# Autoscaling Group
create_autoscaling_group = optional(bool, true)
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
min_elb_capacity = optional(number)
wait_for_elb_capacity = optional(number)
default_cooldown = optional(number)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool, false)
context = optional(string)
target_group_arns = optional(list(string), [])
create_placement_group = optional(bool, false)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(bool)
force_delete = optional(bool)
force_delete_warm_pool = optional(bool)
termination_policies = optional(list(string), [])
suspended_processes = optional(list(string), [])
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string), [])
metrics_granularity = optional(string)
service_linked_role_arn = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number, 66)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string, "Rolling")
triggers = optional(list(string))
}), {
strategy = "Rolling"
preferences = {
min_healthy_percentage = 66
}
})
use_mixed_instances_policy = optional(bool, false)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
warm_pool = optional(object({
instance_reuse_policy = optional(object({
reuse_on_scale_in = optional(bool)
}))
max_group_prepared_capacity = optional(number)
min_size = optional(number)
pool_state = optional(string)
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string), {})
# User data
ami_type = optional(string, "AL2023_x86_64_STANDARD")
additional_cluster_dns_ips = optional(list(string), [])
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string, "m6i.large")
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool, true)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Self managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool, true)
iam_role_arn = optional(string)
# Security group
attach_cluster_primary_security_group = optional(bool, false)
create_security_group = optional(bool, true)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool, true)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_tags = optional(map(string), {})

tags = optional(map(string), {})
}))
| `{}` | no | +| [self\_managed\_node\_group\_defaults](#input\_self\_managed\_node\_group\_defaults) | Map of self-managed node group default configurations |
object({
create = optional(bool)
# Autoscaling Group
create_autoscaling_group = optional(bool)
use_name_prefix = optional(bool)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool)
context = optional(string)
create_placement_group = optional(bool)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(bool)
force_delete = optional(bool)
termination_policies = optional(list(string))
suspended_processes = optional(list(string))
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string))
metrics_granularity = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string)
triggers = optional(list(string))
}))
use_mixed_instances_policy = optional(bool)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string))
# User data
ami_type = optional(string)
additional_cluster_dns_ips = optional(list(string))
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string)
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool)
iam_role_arn = optional(string)
# Security group
attach_cluster_primary_security_group = optional(bool, false)
create_security_group = optional(bool)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_tags = optional(map(string))

tags = optional(map(string))
})
| `{}` | no | +| [self\_managed\_node\_groups](#input\_self\_managed\_node\_groups) | Map of self-managed node group definitions to create |
map(object({
create = optional(bool, true)
# Autoscaling Group
create_autoscaling_group = optional(bool, true)
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool, false)
context = optional(string)
create_placement_group = optional(bool, false)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(bool)
force_delete = optional(bool)
termination_policies = optional(list(string), [])
suspended_processes = optional(list(string), [])
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string), [])
metrics_granularity = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number, 66)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string, "Rolling")
triggers = optional(list(string))
}), {
strategy = "Rolling"
preferences = {
min_healthy_percentage = 66
}
})
use_mixed_instances_policy = optional(bool, false)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string), {})
# User data
ami_type = optional(string, "AL2023_x86_64_STANDARD")
additional_cluster_dns_ips = optional(list(string), [])
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string, "m6i.large")
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool, true)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Self managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool, true)
iam_role_arn = optional(string)
# Security group
attach_cluster_primary_security_group = optional(bool, false)
create_security_group = optional(bool, true)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool, true)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_tags = optional(map(string), {})

tags = optional(map(string), {})
}))
| `{}` | no | | [service\_ipv4\_cidr](#input\_service\_ipv4\_cidr) | The CIDR block to assign Kubernetes service IP addresses from. If you don't specify a block, Kubernetes assigns addresses from either the 10.100.0.0/16 or 172.20.0.0/16 CIDR blocks | `string` | `null` | no | | [service\_ipv6\_cidr](#input\_service\_ipv6\_cidr) | The CIDR block to assign Kubernetes pod and service IP addresses from if `ipv6` was specified when the cluster was created. Kubernetes assigns service addresses from the unique local address range (fc00::/7) because you can't specify a custom IPv6 CIDR block when you create the cluster | `string` | `null` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs where the nodes/node groups will be provisioned. If `control_plane_subnet_ids` is not provided, the EKS cluster control plane (ENIs) will be provisioned in these subnets | `list(string)` | `[]` | no | diff --git a/modules/self-managed-node-group/README.md b/modules/self-managed-node-group/README.md index 2ef6fdb426..11d35bcc0d 100644 --- a/modules/self-managed-node-group/README.md +++ b/modules/self-managed-node-group/README.md @@ -114,7 +114,6 @@ module "self_managed_node_group" { | [create\_placement\_group](#input\_create\_placement\_group) | Determines whether a placement group is created & used by the node group | `bool` | `false` | no | | [create\_security\_group](#input\_create\_security\_group) | Determines if a security group is created | `bool` | `true` | no | | [credit\_specification](#input\_credit\_specification) | Customize the credit specification of the instance |
object({
cpu_credits = optional(string)
})
| `null` | no | -| [default\_cooldown](#input\_default\_cooldown) | The amount of time, in seconds, after a scaling activity completes before another scaling activity can start | `number` | `null` | no | | [default\_instance\_warmup](#input\_default\_instance\_warmup) | Amount of time, in seconds, until a newly launched instance can contribute to the Amazon CloudWatch metrics. This delay lets an instance finish initializing before Amazon EC2 Auto Scaling aggregates instance metrics, resulting in more reliable usage data | `number` | `null` | no | | [desired\_size](#input\_desired\_size) | The number of Amazon EC2 instances that should be running in the autoscaling group | `number` | `1` | no | | [desired\_size\_type](#input\_desired\_size\_type) | The unit of measurement for the value specified for `desired_size`. Supported for attribute-based instance type selection only. Valid values: `units`, `vcpu`, `memory-mib` | `string` | `null` | no | @@ -164,7 +163,6 @@ module "self_managed_node_group" { | [max\_size](#input\_max\_size) | The maximum size of the autoscaling group | `number` | `3` | no | | [metadata\_options](#input\_metadata\_options) | Customize the metadata options for the instance |
object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
})
|
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 1,
"http_tokens": "required"
}
| no | | [metrics\_granularity](#input\_metrics\_granularity) | The granularity to associate with the metrics to collect. The only valid value is `1Minute` | `string` | `null` | no | -| [min\_elb\_capacity](#input\_min\_elb\_capacity) | Setting this causes Terraform to wait for this number of instances to show up healthy in the ELB only on creation. Updates will not wait on ELB instance number changes | `number` | `null` | no | | [min\_size](#input\_min\_size) | The minimum size of the autoscaling group | `number` | `0` | no | | [mixed\_instances\_policy](#input\_mixed\_instances\_policy) | Configuration block containing settings to define launch targets for Auto Scaling groups |
object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
})
| `null` | no | | [name](#input\_name) | Name of the Self managed Node Group | `string` | `""` | no | @@ -183,12 +181,10 @@ module "self_managed_node_group" { | [security\_group\_name](#input\_security\_group\_name) | Name to use on security group created | `string` | `null` | no | | [security\_group\_tags](#input\_security\_group\_tags) | A map of additional tags to add to the security group created | `map(string)` | `{}` | no | | [security\_group\_use\_name\_prefix](#input\_security\_group\_use\_name\_prefix) | Determines whether the security group name (`security_group_name`) is used as a prefix | `bool` | `true` | no | -| [service\_linked\_role\_arn](#input\_service\_linked\_role\_arn) | The ARN of the service-linked role that the ASG will use to call other AWS services | `string` | `null` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs to launch resources in. Subnets automatically determine which availability zones the group will reside. Conflicts with `availability_zones` | `list(string)` | `null` | no | | [suspended\_processes](#input\_suspended\_processes) | A list of processes to suspend for the Auto Scaling Group. The allowed values are `Launch`, `Terminate`, `HealthCheck`, `ReplaceUnhealthy`, `AZRebalance`, `AlarmNotification`, `ScheduledActions`, `AddToLoadBalancer`. Note that if you suspend either the `Launch` or `Terminate` process types, it can prevent your Auto Scaling Group from functioning properly | `list(string)` | `[]` | no | | [tag\_specifications](#input\_tag\_specifications) | The tags to apply to the resources during launch | `list(string)` |
[
"instance",
"volume",
"network-interface"
]
| no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | -| [target\_group\_arns](#input\_target\_group\_arns) | A set of `aws_alb_target_group` ARNs, for use with Application or Network Load Balancing | `list(string)` | `[]` | no | | [termination\_policies](#input\_termination\_policies) | A list of policies to decide how the instances in the Auto Scaling Group should be terminated. The allowed values are `OldestInstance`, `NewestInstance`, `OldestLaunchConfiguration`, `ClosestToNextInstanceHour`, `OldestLaunchTemplate`, `AllocationStrategy`, `Default` | `list(string)` | `[]` | no | | [timeouts](#input\_timeouts) | Timeout configurations for the autoscaling group |
object({
delete = optional(string)
})
| `null` | no | | [update\_launch\_template\_default\_version](#input\_update\_launch\_template\_default\_version) | Whether to update Default Version each update. Conflicts with `launch_template_default_version` | `bool` | `true` | no | @@ -196,8 +192,6 @@ module "self_managed_node_group" { | [use\_name\_prefix](#input\_use\_name\_prefix) | Determines whether to use `name` as is or create a unique name beginning with the `name` as the prefix | `bool` | `true` | no | | [user\_data\_template\_path](#input\_user\_data\_template\_path) | Path to a local, custom user data template file to use when rendering user data | `string` | `""` | no | | [vpc\_security\_group\_ids](#input\_vpc\_security\_group\_ids) | A list of security group IDs to associate | `list(string)` | `[]` | no | -| [wait\_for\_capacity\_timeout](#input\_wait\_for\_capacity\_timeout) | A maximum duration that Terraform should wait for ASG instances to be healthy before timing out. (See also Waiting for Capacity below.) Setting this to '0' causes Terraform to skip all Capacity Waiting behavior | `string` | `null` | no | -| [wait\_for\_elb\_capacity](#input\_wait\_for\_elb\_capacity) | Setting this will cause Terraform to wait for exactly this number of healthy instances in all attached load balancers on both create and update operations. Takes precedence over `min_elb_capacity` behavior | `number` | `null` | no | ## Outputs diff --git a/modules/self-managed-node-group/main.tf b/modules/self-managed-node-group/main.tf index 0241f1dba7..36cf4f40b0 100644 --- a/modules/self-managed-node-group/main.tf +++ b/modules/self-managed-node-group/main.tf @@ -486,7 +486,6 @@ resource "aws_autoscaling_group" "this" { availability_zones = var.availability_zones capacity_rebalance = var.capacity_rebalance context = var.context - default_cooldown = var.default_cooldown default_instance_warmup = var.default_instance_warmup desired_capacity = var.desired_size desired_capacity_type = var.desired_size_type @@ -563,7 +562,6 @@ resource "aws_autoscaling_group" "this" { max_instance_lifetime = var.max_instance_lifetime max_size = var.max_size metrics_granularity = var.metrics_granularity - min_elb_capacity = var.min_elb_capacity min_size = var.min_size ignore_failed_scaling_activities = var.ignore_failed_scaling_activities @@ -724,12 +722,11 @@ resource "aws_autoscaling_group" "this" { } } - name = var.use_name_prefix ? null : var.name - name_prefix = var.use_name_prefix ? "${var.name}-" : null - placement_group = var.placement_group - protect_from_scale_in = var.protect_from_scale_in - service_linked_role_arn = var.service_linked_role_arn - suspended_processes = var.suspended_processes + name = var.use_name_prefix ? null : var.name + name_prefix = var.use_name_prefix ? "${var.name}-" : null + placement_group = var.placement_group + protect_from_scale_in = var.protect_from_scale_in + suspended_processes = var.suspended_processes dynamic "tag" { for_each = merge( @@ -758,11 +755,8 @@ resource "aws_autoscaling_group" "this" { } } - target_group_arns = var.target_group_arns - termination_policies = var.termination_policies - vpc_zone_identifier = var.subnet_ids - wait_for_capacity_timeout = var.wait_for_capacity_timeout - wait_for_elb_capacity = var.wait_for_elb_capacity + termination_policies = var.termination_policies + vpc_zone_identifier = var.subnet_ids dynamic "timeouts" { for_each = var.timeouts != null ? [var.timeouts] : [] diff --git a/modules/self-managed-node-group/variables.tf b/modules/self-managed-node-group/variables.tf index d53c52571a..ed72c65344 100644 --- a/modules/self-managed-node-group/variables.tf +++ b/modules/self-managed-node-group/variables.tf @@ -581,30 +581,6 @@ variable "capacity_rebalance" { default = null } -variable "min_elb_capacity" { - description = "Setting this causes Terraform to wait for this number of instances to show up healthy in the ELB only on creation. Updates will not wait on ELB instance number changes" - type = number - default = null -} - -variable "wait_for_elb_capacity" { - description = "Setting this will cause Terraform to wait for exactly this number of healthy instances in all attached load balancers on both create and update operations. Takes precedence over `min_elb_capacity` behavior" - type = number - default = null -} - -variable "wait_for_capacity_timeout" { - description = "A maximum duration that Terraform should wait for ASG instances to be healthy before timing out. (See also Waiting for Capacity below.) Setting this to '0' causes Terraform to skip all Capacity Waiting behavior" - type = string - default = null -} - -variable "default_cooldown" { - description = "The amount of time, in seconds, after a scaling activity completes before another scaling activity can start" - type = number - default = null -} - variable "default_instance_warmup" { description = "Amount of time, in seconds, until a newly launched instance can contribute to the Amazon CloudWatch metrics. This delay lets an instance finish initializing before Amazon EC2 Auto Scaling aggregates instance metrics, resulting in more reliable usage data" type = number @@ -617,12 +593,6 @@ variable "protect_from_scale_in" { default = false } -variable "target_group_arns" { - description = "A set of `aws_alb_target_group` ARNs, for use with Application or Network Load Balancing" - type = list(string) - default = [] -} - variable "placement_group" { description = "The name of the placement group into which you'll launch your instances" type = string @@ -677,12 +647,6 @@ variable "metrics_granularity" { default = null } -variable "service_linked_role_arn" { - description = "The ARN of the service-linked role that the ASG will use to call other AWS services" - type = string - default = null -} - variable "initial_lifecycle_hooks" { description = "One or more Lifecycle Hooks to attach to the Auto Scaling Group before instances are launched. The syntax is exactly the same as the separate `aws_autoscaling_lifecycle_hook` resource, without the `autoscaling_group_name` attribute. Please note that this will only work when creating a new Auto Scaling Group. For all other use-cases, please use `aws_autoscaling_lifecycle_hook` resource" type = list(object({ diff --git a/node_groups.tf b/node_groups.tf index a434cf1f64..22dc76f5c3 100644 --- a/node_groups.tf +++ b/node_groups.tf @@ -403,20 +403,15 @@ module "self_managed_node_group" { availability_zones = try(each.value.availability_zones, var.self_managed_node_group_defaults.availability_zones, null) subnet_ids = coalesce(each.value.subnet_ids, var.self_managed_node_group_defaults.subnet_ids, var.subnet_ids) - min_size = try(each.value.min_size, var.self_managed_node_group_defaults.min_size, null) - max_size = try(each.value.max_size, var.self_managed_node_group_defaults.max_size, null) - desired_size = try(each.value.desired_size, var.self_managed_node_group_defaults.desired_size, null) - desired_size_type = try(each.value.desired_size_type, var.self_managed_node_group_defaults.desired_size_type, null) - capacity_rebalance = try(each.value.capacity_rebalance, var.self_managed_node_group_defaults.capacity_rebalance, null) - min_elb_capacity = try(each.value.min_elb_capacity, var.self_managed_node_group_defaults.min_elb_capacity, null) - wait_for_elb_capacity = try(each.value.wait_for_elb_capacity, var.self_managed_node_group_defaults.wait_for_elb_capacity, null) - wait_for_capacity_timeout = try(each.value.wait_for_capacity_timeout, var.self_managed_node_group_defaults.wait_for_capacity_timeout, null) - default_cooldown = try(each.value.default_cooldown, var.self_managed_node_group_defaults.default_cooldown, null) - default_instance_warmup = try(each.value.default_instance_warmup, var.self_managed_node_group_defaults.default_instance_warmup, null) - protect_from_scale_in = try(each.value.protect_from_scale_in, var.self_managed_node_group_defaults.protect_from_scale_in, null) - context = try(each.value.context, var.self_managed_node_group_defaults.context, null) - - target_group_arns = try(each.value.target_group_arns, var.self_managed_node_group_defaults.target_group_arns, null) + min_size = try(each.value.min_size, var.self_managed_node_group_defaults.min_size, null) + max_size = try(each.value.max_size, var.self_managed_node_group_defaults.max_size, null) + desired_size = try(each.value.desired_size, var.self_managed_node_group_defaults.desired_size, null) + desired_size_type = try(each.value.desired_size_type, var.self_managed_node_group_defaults.desired_size_type, null) + capacity_rebalance = try(each.value.capacity_rebalance, var.self_managed_node_group_defaults.capacity_rebalance, null) + default_instance_warmup = try(each.value.default_instance_warmup, var.self_managed_node_group_defaults.default_instance_warmup, null) + protect_from_scale_in = try(each.value.protect_from_scale_in, var.self_managed_node_group_defaults.protect_from_scale_in, null) + context = try(each.value.context, var.self_managed_node_group_defaults.context, null) + create_placement_group = try(each.value.create_placement_group, var.self_managed_node_group_defaults.create_placement_group, false) placement_group = try(each.value.placement_group, var.self_managed_node_group_defaults.placement_group, null) health_check_type = try(each.value.health_check_type, var.self_managed_node_group_defaults.health_check_type, null) @@ -429,9 +424,8 @@ module "self_managed_node_group" { suspended_processes = try(each.value.suspended_processes, var.self_managed_node_group_defaults.suspended_processes, null) max_instance_lifetime = try(each.value.max_instance_lifetime, var.self_managed_node_group_defaults.max_instance_lifetime, null) - enabled_metrics = try(each.value.enabled_metrics, var.self_managed_node_group_defaults.enabled_metrics, null) - metrics_granularity = try(each.value.metrics_granularity, var.self_managed_node_group_defaults.metrics_granularity, null) - service_linked_role_arn = try(each.value.service_linked_role_arn, var.self_managed_node_group_defaults.service_linked_role_arn, null) + enabled_metrics = try(each.value.enabled_metrics, var.self_managed_node_group_defaults.enabled_metrics, null) + metrics_granularity = try(each.value.metrics_granularity, var.self_managed_node_group_defaults.metrics_granularity, null) initial_lifecycle_hooks = try(each.value.initial_lifecycle_hooks, var.self_managed_node_group_defaults.initial_lifecycle_hooks, null) instance_maintenance_policy = try(each.value.instance_maintenance_policy, var.self_managed_node_group_defaults.instance_maintenance_policy, null) diff --git a/variables.tf b/variables.tf index 5092cf3c85..0da06a8095 100644 --- a/variables.tf +++ b/variables.tf @@ -843,26 +843,20 @@ variable "self_managed_node_groups" { desired_size = optional(number, 1) desired_size_type = optional(string) capacity_rebalance = optional(bool) - min_elb_capacity = optional(number) - wait_for_elb_capacity = optional(number) - default_cooldown = optional(number) default_instance_warmup = optional(number) protect_from_scale_in = optional(bool, false) context = optional(string) - target_group_arns = optional(list(string), []) create_placement_group = optional(bool, false) placement_group = optional(string) health_check_type = optional(string) health_check_grace_period = optional(number) ignore_failed_scaling_activities = optional(bool) force_delete = optional(bool) - force_delete_warm_pool = optional(bool) termination_policies = optional(list(string), []) suspended_processes = optional(list(string), []) max_instance_lifetime = optional(number) enabled_metrics = optional(list(string), []) metrics_granularity = optional(string) - service_linked_role_arn = optional(string) initial_lifecycle_hooks = optional(list(object({ default_result = optional(string) heartbeat_timeout = optional(number) @@ -974,14 +968,6 @@ variable "self_managed_node_groups" { }))) }) })) - warm_pool = optional(object({ - instance_reuse_policy = optional(object({ - reuse_on_scale_in = optional(bool) - })) - max_group_prepared_capacity = optional(number) - min_size = optional(number) - pool_state = optional(string) - })) timeouts = optional(object({ delete = optional(string) })) @@ -1279,13 +1265,9 @@ variable "self_managed_node_group_defaults" { desired_size = optional(number) desired_size_type = optional(string) capacity_rebalance = optional(bool) - min_elb_capacity = optional(number) - wait_for_elb_capacity = optional(number) - default_cooldown = optional(number) default_instance_warmup = optional(number) protect_from_scale_in = optional(bool) context = optional(string) - target_group_arns = optional(list(string)) create_placement_group = optional(bool) placement_group = optional(string) health_check_type = optional(string) @@ -1297,7 +1279,6 @@ variable "self_managed_node_group_defaults" { max_instance_lifetime = optional(number) enabled_metrics = optional(list(string)) metrics_granularity = optional(string) - service_linked_role_arn = optional(string) initial_lifecycle_hooks = optional(list(object({ default_result = optional(string) heartbeat_timeout = optional(number) From f34758e935f2b14fe2708df15e948f2eed7b5e9b Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Mon, 14 Jul 2025 13:32:38 -0500 Subject: [PATCH 16/25] fix: Remove data plane compute `*_defaults` variables that do not work with variable optional attributes --- README.md | 3 - node_groups.tf | 407 ++++++------ tests/eks-fargate-profile/main.tf | 10 +- tests/eks-managed-node-group/main.tf | 5 - tests/self-managed-node-group/main.tf | 22 +- variables.tf | 862 ++------------------------ 6 files changed, 283 insertions(+), 1026 deletions(-) diff --git a/README.md b/README.md index 251c46ac6c..53573cb55c 100644 --- a/README.md +++ b/README.md @@ -405,7 +405,6 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [create\_security\_group](#input\_create\_security\_group) | Determines if a security group is created for the cluster. Note: the EKS service creates a primary security group for the cluster by default | `bool` | `true` | no | | [custom\_oidc\_thumbprints](#input\_custom\_oidc\_thumbprints) | Additional list of server certificate thumbprints for the OpenID Connect (OIDC) identity provider's server certificate(s) | `list(string)` | `[]` | no | | [dataplane\_wait\_duration](#input\_dataplane\_wait\_duration) | Duration to wait after the EKS cluster has become active before creating the dataplane components (EKS managed node group(s), self-managed node group(s), Fargate profile(s)) | `string` | `"30s"` | no | -| [eks\_managed\_node\_group\_defaults](#input\_eks\_managed\_node\_group\_defaults) | Map of EKS managed node group default configurations |
object({
create = optional(bool)
kubernetes_version = optional(string)

# EKS Managed Node Group
use_name_prefix = optional(bool)
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
ami_id = optional(string)
ami_type = optional(string)
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool)
capacity_type = optional(string)
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}))
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool)
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
create_placement_group = optional(bool)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string))
attach_cluster_primary_security_group = optional(bool, false)
cluster_primary_security_group_id = optional(string)
create_security_group = optional(bool)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_tags = optional(map(string))

tags = optional(map(string), {})
})
| `{}` | no | | [eks\_managed\_node\_groups](#input\_eks\_managed\_node\_groups) | Map of EKS managed node group definitions to create |
map(object({
create = optional(bool, true)
kubernetes_version = optional(string)

# EKS Managed Node Group
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
ami_id = optional(string, "")
ami_type = optional(string, "AL2023_x86_64_STANDARD")
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool, true)
capacity_type = optional(string, "ON_DEMAND")
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool, true)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}), {
max_unavailable_percentage = 33
})
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool, false)
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
create_placement_group = optional(bool, false)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool, true)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "EKS managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string), [])
attach_cluster_primary_security_group = optional(bool, false)
cluster_primary_security_group_id = optional(string)
create_security_group = optional(bool, true)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool, true)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_tags = optional(map(string), {})

tags = optional(map(string), {})
}))
| `{}` | no | | [enable\_auto\_mode\_custom\_tags](#input\_enable\_auto\_mode\_custom\_tags) | Determines whether to enable permissions for custom tags resources created by EKS Auto Mode | `bool` | `true` | no | | [enable\_cluster\_creator\_admin\_permissions](#input\_enable\_cluster\_creator\_admin\_permissions) | Indicates whether or not to add the cluster creator (the identity used by Terraform) as an administrator via access entry | `bool` | `false` | no | @@ -421,7 +420,6 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [endpoint\_private\_access](#input\_endpoint\_private\_access) | Indicates whether or not the Amazon EKS private API server endpoint is enabled | `bool` | `true` | no | | [endpoint\_public\_access](#input\_endpoint\_public\_access) | Indicates whether or not the Amazon EKS public API server endpoint is enabled | `bool` | `false` | no | | [endpoint\_public\_access\_cidrs](#input\_endpoint\_public\_access\_cidrs) | List of CIDR blocks which can access the Amazon EKS public API server endpoint | `list(string)` |
[
"0.0.0.0/0"
]
| no | -| [fargate\_profile\_defaults](#input\_fargate\_profile\_defaults) | Map of Fargate Profile default configurations |
object({
create = optional(bool)

# Fargate profile
name = optional(string) # Will fall back to map key
subnet_ids = optional(list(string))
selectors = optional(list(object({
labels = optional(map(string))
namespace = string
})))
timeouts = optional(object({
create = optional(string)
delete = optional(string)
}))

# IAM role
create_iam_role = optional(bool)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
tags = optional(map(string), {})
})
| `{}` | no | | [fargate\_profiles](#input\_fargate\_profiles) | Map of Fargate Profile definitions to create |
map(object({
create = optional(bool, true)

# Fargate profile
name = optional(string) # Will fall back to map key
subnet_ids = optional(list(string))
selectors = optional(list(object({
labels = optional(map(string))
namespace = string
})))
timeouts = optional(object({
create = optional(string)
delete = optional(string)
}))

# IAM role
create_iam_role = optional(bool, true)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Fargate profile IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
tags = optional(map(string), {})
}))
| `{}` | no | | [force\_update\_version](#input\_force\_update\_version) | Force version update by overriding upgrade-blocking readiness checks when updating a cluster | `bool` | `null` | no | | [iam\_role\_additional\_policies](#input\_iam\_role\_additional\_policies) | Additional policies to be added to the IAM role | `map(string)` | `{}` | no | @@ -472,7 +470,6 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [security\_group\_name](#input\_security\_group\_name) | Name to use on cluster security group created | `string` | `null` | no | | [security\_group\_tags](#input\_security\_group\_tags) | A map of additional tags to add to the cluster security group created | `map(string)` | `{}` | no | | [security\_group\_use\_name\_prefix](#input\_security\_group\_use\_name\_prefix) | Determines whether cluster security group name (`cluster_security_group_name`) is used as a prefix | `bool` | `true` | no | -| [self\_managed\_node\_group\_defaults](#input\_self\_managed\_node\_group\_defaults) | Map of self-managed node group default configurations |
object({
create = optional(bool)
# Autoscaling Group
create_autoscaling_group = optional(bool)
use_name_prefix = optional(bool)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number)
max_size = optional(number)
desired_size = optional(number)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool)
context = optional(string)
create_placement_group = optional(bool)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(bool)
force_delete = optional(bool)
termination_policies = optional(list(string))
suspended_processes = optional(list(string))
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string))
metrics_granularity = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string)
triggers = optional(list(string))
}))
use_mixed_instances_policy = optional(bool)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string))
# User data
ami_type = optional(string)
additional_cluster_dns_ips = optional(list(string))
pre_bootstrap_user_data = optional(string)
post_bootstrap_user_data = optional(string)
bootstrap_extra_args = optional(string)
user_data_template_path = optional(string)
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})))
# Launch Template
create_launch_template = optional(bool)
use_custom_launch_template = optional(bool)
launch_template_id = optional(string)
launch_template_name = optional(string)
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool)
launch_template_description = optional(string)
launch_template_tags = optional(map(string))
tag_specifications = optional(list(string))
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string)
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string)
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number)
http_tokens = optional(string)
instance_metadata_tags = optional(string)
}))
enable_monitoring = optional(bool)
enable_efa_support = optional(bool)
enable_efa_only = optional(bool)
efa_indices = optional(list(string))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string))
subnet_id = optional(string)
})))
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_attach_cni_policy = optional(bool)
iam_role_additional_policies = optional(map(string))
create_iam_role_policy = optional(bool)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool)
iam_role_arn = optional(string)
# Security group
attach_cluster_primary_security_group = optional(bool, false)
create_security_group = optional(bool)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_tags = optional(map(string))

tags = optional(map(string))
})
| `{}` | no | | [self\_managed\_node\_groups](#input\_self\_managed\_node\_groups) | Map of self-managed node group definitions to create |
map(object({
create = optional(bool, true)
# Autoscaling Group
create_autoscaling_group = optional(bool, true)
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool, false)
context = optional(string)
create_placement_group = optional(bool, false)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(bool)
force_delete = optional(bool)
termination_policies = optional(list(string), [])
suspended_processes = optional(list(string), [])
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string), [])
metrics_granularity = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number, 66)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string, "Rolling")
triggers = optional(list(string))
}), {
strategy = "Rolling"
preferences = {
min_healthy_percentage = 66
}
})
use_mixed_instances_policy = optional(bool, false)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string), {})
# User data
ami_type = optional(string, "AL2023_x86_64_STANDARD")
additional_cluster_dns_ips = optional(list(string), [])
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string, "m6i.large")
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool, true)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Self managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool, true)
iam_role_arn = optional(string)
# Security group
attach_cluster_primary_security_group = optional(bool, false)
create_security_group = optional(bool, true)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool, true)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_tags = optional(map(string), {})

tags = optional(map(string), {})
}))
| `{}` | no | | [service\_ipv4\_cidr](#input\_service\_ipv4\_cidr) | The CIDR block to assign Kubernetes service IP addresses from. If you don't specify a block, Kubernetes assigns addresses from either the 10.100.0.0/16 or 172.20.0.0/16 CIDR blocks | `string` | `null` | no | | [service\_ipv6\_cidr](#input\_service\_ipv6\_cidr) | The CIDR block to assign Kubernetes pod and service IP addresses from if `ipv6` was specified when the cluster was created. Kubernetes assigns service addresses from the unique local address range (fc00::/7) because you can't specify a custom IPv6 CIDR block when you create the cluster | `string` | `null` | no | diff --git a/node_groups.tf b/node_groups.tf index 22dc76f5c3..be8c2ba178 100644 --- a/node_groups.tf +++ b/node_groups.tf @@ -226,27 +226,26 @@ module "fargate_profile" { cluster_name = time_sleep.this[0].triggers["name"] cluster_ip_family = var.ip_family name = coalesce(each.value.name, each.key) - subnet_ids = coalesce(each.value.subnet_ids, var.fargate_profile_defaults.subnet_ids, var.subnet_ids) - selectors = try(each.value.selectors, var.fargate_profile_defaults.selectors, null) - timeouts = try(each.value.timeouts, var.fargate_profile_defaults.timeouts, null) + subnet_ids = coalesce(each.value.subnet_ids, var.subnet_ids) + selectors = try(each.value.selectors, null) + timeouts = try(each.value.timeouts, null) # IAM role - create_iam_role = try(each.value.create_iam_role, var.fargate_profile_defaults.create_iam_role, null) - iam_role_arn = try(each.value.iam_role_arn, var.fargate_profile_defaults.iam_role_arn, null) - iam_role_name = try(each.value.iam_role_name, var.fargate_profile_defaults.iam_role_name, null) - iam_role_use_name_prefix = try(each.value.iam_role_use_name_prefix, var.fargate_profile_defaults.iam_role_use_name_prefix, null) - iam_role_path = try(each.value.iam_role_path, var.fargate_profile_defaults.iam_role_path, null) - iam_role_description = try(each.value.iam_role_description, var.fargate_profile_defaults.iam_role_description, null) - iam_role_permissions_boundary = try(each.value.iam_role_permissions_boundary, var.fargate_profile_defaults.iam_role_permissions_boundary, null) - iam_role_tags = try(each.value.iam_role_tags, var.fargate_profile_defaults.iam_role_tags, null) - iam_role_attach_cni_policy = try(each.value.iam_role_attach_cni_policy, var.fargate_profile_defaults.iam_role_attach_cni_policy, null) - iam_role_additional_policies = lookup(each.value, "iam_role_additional_policies", lookup(var.fargate_profile_defaults, "iam_role_additional_policies", null)) - create_iam_role_policy = try(each.value.create_iam_role_policy, var.fargate_profile_defaults.create_iam_role_policy, null) - iam_role_policy_statements = try(each.value.iam_role_policy_statements, var.fargate_profile_defaults.iam_role_policy_statements, null) + create_iam_role = try(each.value.create_iam_role, null) + iam_role_arn = try(each.value.iam_role_arn, null) + iam_role_name = try(each.value.iam_role_name, null) + iam_role_use_name_prefix = try(each.value.iam_role_use_name_prefix, null) + iam_role_path = try(each.value.iam_role_path, null) + iam_role_description = try(each.value.iam_role_description, null) + iam_role_permissions_boundary = try(each.value.iam_role_permissions_boundary, null) + iam_role_tags = try(each.value.iam_role_tags, null) + iam_role_attach_cni_policy = try(each.value.iam_role_attach_cni_policy, null) + iam_role_additional_policies = lookup(each.value, "iam_role_additional_policies", null) + create_iam_role_policy = try(each.value.create_iam_role_policy, null) + iam_role_policy_statements = try(each.value.iam_role_policy_statements, null) tags = merge( var.tags, - var.fargate_profile_defaults.tags, each.value.tags, ) } @@ -267,112 +266,111 @@ module "eks_managed_node_group" { account_id = local.account_id cluster_name = time_sleep.this[0].triggers["name"] - kubernetes_version = try(each.value.kubernetes_version, var.eks_managed_node_group_defaults.kubernetes_version, time_sleep.this[0].triggers["kubernetes_version"]) + kubernetes_version = try(each.value.kubernetes_version, time_sleep.this[0].triggers["kubernetes_version"]) # EKS Managed Node Group name = coalesce(each.value.name, each.key) - use_name_prefix = try(each.value.use_name_prefix, var.eks_managed_node_group_defaults.use_name_prefix, null) - - subnet_ids = coalesce(each.value.subnet_ids, var.eks_managed_node_group_defaults.subnet_ids, var.subnet_ids) - - min_size = try(each.value.min_size, var.eks_managed_node_group_defaults.min_size, null) - max_size = try(each.value.max_size, var.eks_managed_node_group_defaults.max_size, null) - desired_size = try(each.value.desired_size, var.eks_managed_node_group_defaults.desired_size, null) - - ami_id = try(each.value.ami_id, var.eks_managed_node_group_defaults.ami_id, null) - ami_type = try(each.value.ami_type, var.eks_managed_node_group_defaults.ami_type, null) - ami_release_version = try(each.value.ami_release_version, var.eks_managed_node_group_defaults.ami_release_version, null) - use_latest_ami_release_version = try(each.value.use_latest_ami_release_version, var.eks_managed_node_group_defaults.use_latest_ami_release_version, null) - - capacity_type = try(each.value.capacity_type, var.eks_managed_node_group_defaults.capacity_type, null) - disk_size = try(each.value.disk_size, var.eks_managed_node_group_defaults.disk_size, null) - force_update_version = try(each.value.force_update_version, var.eks_managed_node_group_defaults.force_update_version, null) - instance_types = try(each.value.instance_types, var.eks_managed_node_group_defaults.instance_types, null) - labels = try(each.value.labels, var.eks_managed_node_group_defaults.labels, null) - node_repair_config = try(each.value.node_repair_config, var.eks_managed_node_group_defaults.node_repair_config, null) - remote_access = try(each.value.remote_access, var.eks_managed_node_group_defaults.remote_access, null) - taints = try(each.value.taints, var.eks_managed_node_group_defaults.taints, null) - update_config = try(each.value.update_config, var.eks_managed_node_group_defaults.update_config, null) - timeouts = try(each.value.timeouts, var.eks_managed_node_group_defaults.timeouts, null) + use_name_prefix = try(each.value.use_name_prefix, null) + + subnet_ids = coalesce(each.value.subnet_ids, var.subnet_ids) + + min_size = try(each.value.min_size, null) + max_size = try(each.value.max_size, null) + desired_size = try(each.value.desired_size, null) + + ami_id = try(each.value.ami_id, null) + ami_type = try(each.value.ami_type, null) + ami_release_version = try(each.value.ami_release_version, null) + use_latest_ami_release_version = try(each.value.use_latest_ami_release_version, null) + + capacity_type = try(each.value.capacity_type, null) + disk_size = try(each.value.disk_size, null) + force_update_version = try(each.value.force_update_version, null) + instance_types = try(each.value.instance_types, null) + labels = try(each.value.labels, null) + node_repair_config = try(each.value.node_repair_config, null) + remote_access = try(each.value.remote_access, null) + taints = try(each.value.taints, null) + update_config = try(each.value.update_config, null) + timeouts = try(each.value.timeouts, null) # User data cluster_endpoint = try(time_sleep.this[0].triggers["endpoint"], "") cluster_auth_base64 = try(time_sleep.this[0].triggers["certificate_authority_data"], "") cluster_ip_family = var.ip_family cluster_service_cidr = try(time_sleep.this[0].triggers["service_cidr"], "") - enable_bootstrap_user_data = try(each.value.enable_bootstrap_user_data, var.eks_managed_node_group_defaults.enable_bootstrap_user_data, null) - pre_bootstrap_user_data = try(each.value.pre_bootstrap_user_data, var.eks_managed_node_group_defaults.pre_bootstrap_user_data, null) - post_bootstrap_user_data = try(each.value.post_bootstrap_user_data, var.eks_managed_node_group_defaults.post_bootstrap_user_data, null) - bootstrap_extra_args = try(each.value.bootstrap_extra_args, var.eks_managed_node_group_defaults.bootstrap_extra_args, null) - user_data_template_path = try(each.value.user_data_template_path, var.eks_managed_node_group_defaults.user_data_template_path, null) - cloudinit_pre_nodeadm = try(each.value.cloudinit_pre_nodeadm, var.eks_managed_node_group_defaults.cloudinit_pre_nodeadm, null) - cloudinit_post_nodeadm = try(each.value.cloudinit_post_nodeadm, var.eks_managed_node_group_defaults.cloudinit_post_nodeadm, null) + enable_bootstrap_user_data = try(each.value.enable_bootstrap_user_data, null) + pre_bootstrap_user_data = try(each.value.pre_bootstrap_user_data, null) + post_bootstrap_user_data = try(each.value.post_bootstrap_user_data, null) + bootstrap_extra_args = try(each.value.bootstrap_extra_args, null) + user_data_template_path = try(each.value.user_data_template_path, null) + cloudinit_pre_nodeadm = try(each.value.cloudinit_pre_nodeadm, null) + cloudinit_post_nodeadm = try(each.value.cloudinit_post_nodeadm, null) # Launch Template - create_launch_template = try(each.value.create_launch_template, var.eks_managed_node_group_defaults.create_launch_template, null) - use_custom_launch_template = try(each.value.use_custom_launch_template, var.eks_managed_node_group_defaults.use_custom_launch_template, null) - launch_template_id = try(each.value.launch_template_id, var.eks_managed_node_group_defaults.launch_template_id, null) - launch_template_name = try(each.value.launch_template_name, var.eks_managed_node_group_defaults.launch_template_name, each.key) - launch_template_use_name_prefix = try(each.value.launch_template_use_name_prefix, var.eks_managed_node_group_defaults.launch_template_use_name_prefix, null) - launch_template_version = try(each.value.launch_template_version, var.eks_managed_node_group_defaults.launch_template_version, null) - launch_template_default_version = try(each.value.launch_template_default_version, var.eks_managed_node_group_defaults.launch_template_default_version, null) - update_launch_template_default_version = try(each.value.update_launch_template_default_version, var.eks_managed_node_group_defaults.update_launch_template_default_version, null) - launch_template_description = try(each.value.launch_template_description, var.eks_managed_node_group_defaults.launch_template_description, "Custom launch template for ${try(each.value.name, each.key)} EKS managed node group") - launch_template_tags = try(each.value.launch_template_tags, var.eks_managed_node_group_defaults.launch_template_tags, null) - tag_specifications = try(each.value.tag_specifications, var.eks_managed_node_group_defaults.tag_specifications, null) - - ebs_optimized = try(each.value.ebs_optimized, var.eks_managed_node_group_defaults.ebs_optimized, null) - key_name = try(each.value.key_name, var.eks_managed_node_group_defaults.key_name, null) - disable_api_termination = try(each.value.disable_api_termination, var.eks_managed_node_group_defaults.disable_api_termination, null) - kernel_id = try(each.value.kernel_id, var.eks_managed_node_group_defaults.kernel_id, null) - ram_disk_id = try(each.value.ram_disk_id, var.eks_managed_node_group_defaults.ram_disk_id, null) - - block_device_mappings = try(each.value.block_device_mappings, var.eks_managed_node_group_defaults.block_device_mappings, null) - capacity_reservation_specification = try(each.value.capacity_reservation_specification, var.eks_managed_node_group_defaults.capacity_reservation_specification, null) - cpu_options = try(each.value.cpu_options, var.eks_managed_node_group_defaults.cpu_options, null) - credit_specification = try(each.value.credit_specification, var.eks_managed_node_group_defaults.credit_specification, null) - enclave_options = try(each.value.enclave_options, var.eks_managed_node_group_defaults.enclave_options, null) - instance_market_options = try(each.value.instance_market_options, var.eks_managed_node_group_defaults.instance_market_options, null) - license_specifications = try(each.value.license_specifications, var.eks_managed_node_group_defaults.license_specifications, null) - metadata_options = try(each.value.metadata_options, var.eks_managed_node_group_defaults.metadata_options, null) - enable_monitoring = try(each.value.enable_monitoring, var.eks_managed_node_group_defaults.enable_monitoring, null) - enable_efa_support = try(each.value.enable_efa_support, var.eks_managed_node_group_defaults.enable_efa_support, null) - enable_efa_only = try(each.value.enable_efa_only, var.eks_managed_node_group_defaults.enable_efa_only, null) - efa_indices = try(each.value.efa_indices, var.eks_managed_node_group_defaults.efa_indices, null) - create_placement_group = try(each.value.create_placement_group, var.eks_managed_node_group_defaults.create_placement_group, null) - placement = try(each.value.placement, var.eks_managed_node_group_defaults.placement, null) - network_interfaces = try(each.value.network_interfaces, var.eks_managed_node_group_defaults.network_interfaces, null) - maintenance_options = try(each.value.maintenance_options, var.eks_managed_node_group_defaults.maintenance_options, null) - private_dns_name_options = try(each.value.private_dns_name_options, var.eks_managed_node_group_defaults.private_dns_name_options, null) + create_launch_template = try(each.value.create_launch_template, null) + use_custom_launch_template = try(each.value.use_custom_launch_template, null) + launch_template_id = try(each.value.launch_template_id, null) + launch_template_name = try(each.value.launch_template_name, each.key) + launch_template_use_name_prefix = try(each.value.launch_template_use_name_prefix, null) + launch_template_version = try(each.value.launch_template_version, null) + launch_template_default_version = try(each.value.launch_template_default_version, null) + update_launch_template_default_version = try(each.value.update_launch_template_default_version, null) + launch_template_description = try(each.value.launch_template_description, "Custom launch template for ${try(each.value.name, each.key)} EKS managed node group") + launch_template_tags = try(each.value.launch_template_tags, null) + tag_specifications = try(each.value.tag_specifications, null) + + ebs_optimized = try(each.value.ebs_optimized, null) + key_name = try(each.value.key_name, null) + disable_api_termination = try(each.value.disable_api_termination, null) + kernel_id = try(each.value.kernel_id, null) + ram_disk_id = try(each.value.ram_disk_id, null) + + block_device_mappings = try(each.value.block_device_mappings, null) + capacity_reservation_specification = try(each.value.capacity_reservation_specification, null) + cpu_options = try(each.value.cpu_options, null) + credit_specification = try(each.value.credit_specification, null) + enclave_options = try(each.value.enclave_options, null) + instance_market_options = try(each.value.instance_market_options, null) + license_specifications = try(each.value.license_specifications, null) + metadata_options = try(each.value.metadata_options, null) + enable_monitoring = try(each.value.enable_monitoring, null) + enable_efa_support = try(each.value.enable_efa_support, null) + enable_efa_only = try(each.value.enable_efa_only, null) + efa_indices = try(each.value.efa_indices, null) + create_placement_group = try(each.value.create_placement_group, null) + placement = try(each.value.placement, null) + network_interfaces = try(each.value.network_interfaces, null) + maintenance_options = try(each.value.maintenance_options, null) + private_dns_name_options = try(each.value.private_dns_name_options, null) # IAM role - create_iam_role = try(each.value.create_iam_role, var.eks_managed_node_group_defaults.create_iam_role, null) - iam_role_arn = try(each.value.iam_role_arn, var.eks_managed_node_group_defaults.iam_role_arn, null) - iam_role_name = try(each.value.iam_role_name, var.eks_managed_node_group_defaults.iam_role_name, null) - iam_role_use_name_prefix = try(each.value.iam_role_use_name_prefix, var.eks_managed_node_group_defaults.iam_role_use_name_prefix, null) - iam_role_path = try(each.value.iam_role_path, var.eks_managed_node_group_defaults.iam_role_path, null) - iam_role_description = try(each.value.iam_role_description, var.eks_managed_node_group_defaults.iam_role_description, null) - iam_role_permissions_boundary = try(each.value.iam_role_permissions_boundary, var.eks_managed_node_group_defaults.iam_role_permissions_boundary, null) - iam_role_tags = try(each.value.iam_role_tags, var.eks_managed_node_group_defaults.iam_role_tags, null) - iam_role_attach_cni_policy = try(each.value.iam_role_attach_cni_policy, var.eks_managed_node_group_defaults.iam_role_attach_cni_policy, null) - iam_role_additional_policies = lookup(each.value, "iam_role_additional_policies", lookup(var.eks_managed_node_group_defaults, "iam_role_additional_policies", null)) - create_iam_role_policy = try(each.value.create_iam_role_policy, var.eks_managed_node_group_defaults.create_iam_role_policy, true) - iam_role_policy_statements = try(each.value.iam_role_policy_statements, var.eks_managed_node_group_defaults.iam_role_policy_statements, null) + create_iam_role = try(each.value.create_iam_role, null) + iam_role_arn = try(each.value.iam_role_arn, null) + iam_role_name = try(each.value.iam_role_name, null) + iam_role_use_name_prefix = try(each.value.iam_role_use_name_prefix, null) + iam_role_path = try(each.value.iam_role_path, null) + iam_role_description = try(each.value.iam_role_description, null) + iam_role_permissions_boundary = try(each.value.iam_role_permissions_boundary, null) + iam_role_tags = try(each.value.iam_role_tags, null) + iam_role_attach_cni_policy = try(each.value.iam_role_attach_cni_policy, null) + iam_role_additional_policies = lookup(each.value, "iam_role_additional_policies", null) + create_iam_role_policy = try(each.value.create_iam_role_policy, true) + iam_role_policy_statements = try(each.value.iam_role_policy_statements, null) # Security group - vpc_security_group_ids = compact(concat([local.node_security_group_id], try(each.value.vpc_security_group_ids, var.eks_managed_node_group_defaults.vpc_security_group_ids, []))) - cluster_primary_security_group_id = try(each.value.attach_cluster_primary_security_group, var.eks_managed_node_group_defaults.attach_cluster_primary_security_group, false) ? aws_eks_cluster.this[0].vpc_config[0].cluster_security_group_id : null - create_security_group = try(each.value.create_security_group, var.eks_managed_node_group_defaults.create_security_group, null) - security_group_name = try(each.value.security_group_name, var.eks_managed_node_group_defaults.security_group_name, null) - security_group_use_name_prefix = try(each.value.security_group_use_name_prefix, var.eks_managed_node_group_defaults.security_group_use_name_prefix, null) - security_group_description = try(each.value.security_group_description, var.eks_managed_node_group_defaults.security_group_description, null) - security_group_ingress_rules = try(each.value.security_group_ingress_rules, var.eks_managed_node_group_defaults.security_group_ingress_rules, null) - security_group_egress_rules = try(each.value.security_group_egress_rules, var.eks_managed_node_group_defaults.security_group_egress_rules, null) - security_group_tags = try(each.value.security_group_tags, var.eks_managed_node_group_defaults.security_group_tags, null) + vpc_security_group_ids = compact(concat([local.node_security_group_id], try(each.value.vpc_security_group_ids, []))) + cluster_primary_security_group_id = try(each.value.attach_cluster_primary_security_group, false) ? aws_eks_cluster.this[0].vpc_config[0].cluster_security_group_id : null + create_security_group = try(each.value.create_security_group, null) + security_group_name = try(each.value.security_group_name, null) + security_group_use_name_prefix = try(each.value.security_group_use_name_prefix, null) + security_group_description = try(each.value.security_group_description, null) + security_group_ingress_rules = try(each.value.security_group_ingress_rules, null) + security_group_egress_rules = try(each.value.security_group_egress_rules, null) + security_group_tags = try(each.value.security_group_tags, null) tags = merge( var.tags, - var.eks_managed_node_group_defaults.tags, each.value.tags, ) } @@ -395,134 +393,133 @@ module "self_managed_node_group" { cluster_name = time_sleep.this[0].triggers["name"] # Autoscaling Group - create_autoscaling_group = try(each.value.create_autoscaling_group, var.self_managed_node_group_defaults.create_autoscaling_group, null) + create_autoscaling_group = try(each.value.create_autoscaling_group, null) name = coalesce(each.value.name, each.key) - use_name_prefix = try(each.value.use_name_prefix, var.self_managed_node_group_defaults.use_name_prefix, null) + use_name_prefix = try(each.value.use_name_prefix, null) - availability_zones = try(each.value.availability_zones, var.self_managed_node_group_defaults.availability_zones, null) - subnet_ids = coalesce(each.value.subnet_ids, var.self_managed_node_group_defaults.subnet_ids, var.subnet_ids) + availability_zones = try(each.value.availability_zones, null) + subnet_ids = coalesce(each.value.subnet_ids, var.subnet_ids) - min_size = try(each.value.min_size, var.self_managed_node_group_defaults.min_size, null) - max_size = try(each.value.max_size, var.self_managed_node_group_defaults.max_size, null) - desired_size = try(each.value.desired_size, var.self_managed_node_group_defaults.desired_size, null) - desired_size_type = try(each.value.desired_size_type, var.self_managed_node_group_defaults.desired_size_type, null) - capacity_rebalance = try(each.value.capacity_rebalance, var.self_managed_node_group_defaults.capacity_rebalance, null) - default_instance_warmup = try(each.value.default_instance_warmup, var.self_managed_node_group_defaults.default_instance_warmup, null) - protect_from_scale_in = try(each.value.protect_from_scale_in, var.self_managed_node_group_defaults.protect_from_scale_in, null) - context = try(each.value.context, var.self_managed_node_group_defaults.context, null) + min_size = try(each.value.min_size, null) + max_size = try(each.value.max_size, null) + desired_size = try(each.value.desired_size, null) + desired_size_type = try(each.value.desired_size_type, null) + capacity_rebalance = try(each.value.capacity_rebalance, null) + default_instance_warmup = try(each.value.default_instance_warmup, null) + protect_from_scale_in = try(each.value.protect_from_scale_in, null) + context = try(each.value.context, null) - create_placement_group = try(each.value.create_placement_group, var.self_managed_node_group_defaults.create_placement_group, false) - placement_group = try(each.value.placement_group, var.self_managed_node_group_defaults.placement_group, null) - health_check_type = try(each.value.health_check_type, var.self_managed_node_group_defaults.health_check_type, null) - health_check_grace_period = try(each.value.health_check_grace_period, var.self_managed_node_group_defaults.health_check_grace_period, null) + create_placement_group = try(each.value.create_placement_group, false) + placement_group = try(each.value.placement_group, null) + health_check_type = try(each.value.health_check_type, null) + health_check_grace_period = try(each.value.health_check_grace_period, null) - ignore_failed_scaling_activities = try(each.value.ignore_failed_scaling_activities, var.self_managed_node_group_defaults.ignore_failed_scaling_activities, null) + ignore_failed_scaling_activities = try(each.value.ignore_failed_scaling_activities, null) - force_delete = try(each.value.force_delete, var.self_managed_node_group_defaults.force_delete, null) - termination_policies = try(each.value.termination_policies, var.self_managed_node_group_defaults.termination_policies, null) - suspended_processes = try(each.value.suspended_processes, var.self_managed_node_group_defaults.suspended_processes, null) - max_instance_lifetime = try(each.value.max_instance_lifetime, var.self_managed_node_group_defaults.max_instance_lifetime, null) + force_delete = try(each.value.force_delete, null) + termination_policies = try(each.value.termination_policies, null) + suspended_processes = try(each.value.suspended_processes, null) + max_instance_lifetime = try(each.value.max_instance_lifetime, null) - enabled_metrics = try(each.value.enabled_metrics, var.self_managed_node_group_defaults.enabled_metrics, null) - metrics_granularity = try(each.value.metrics_granularity, var.self_managed_node_group_defaults.metrics_granularity, null) + enabled_metrics = try(each.value.enabled_metrics, null) + metrics_granularity = try(each.value.metrics_granularity, null) - initial_lifecycle_hooks = try(each.value.initial_lifecycle_hooks, var.self_managed_node_group_defaults.initial_lifecycle_hooks, null) - instance_maintenance_policy = try(each.value.instance_maintenance_policy, var.self_managed_node_group_defaults.instance_maintenance_policy, null) - instance_refresh = try(each.value.instance_refresh, var.self_managed_node_group_defaults.instance_refresh, null) - use_mixed_instances_policy = try(each.value.use_mixed_instances_policy, var.self_managed_node_group_defaults.use_mixed_instances_policy, null) - mixed_instances_policy = try(each.value.mixed_instances_policy, var.self_managed_node_group_defaults.mixed_instances_policy, null) + initial_lifecycle_hooks = try(each.value.initial_lifecycle_hooks, null) + instance_maintenance_policy = try(each.value.instance_maintenance_policy, null) + instance_refresh = try(each.value.instance_refresh, null) + use_mixed_instances_policy = try(each.value.use_mixed_instances_policy, null) + mixed_instances_policy = try(each.value.mixed_instances_policy, null) - timeouts = try(each.value.timeouts, var.self_managed_node_group_defaults.timeouts, null) - autoscaling_group_tags = try(each.value.autoscaling_group_tags, var.self_managed_node_group_defaults.autoscaling_group_tags, null) + timeouts = try(each.value.timeouts, null) + autoscaling_group_tags = try(each.value.autoscaling_group_tags, null) # User data - ami_type = try(each.value.ami_type, var.self_managed_node_group_defaults.ami_type, null) + ami_type = try(each.value.ami_type, null) cluster_endpoint = try(time_sleep.this[0].triggers["endpoint"], "") cluster_auth_base64 = try(time_sleep.this[0].triggers["certificate_authority_data"], "") cluster_service_cidr = try(time_sleep.this[0].triggers["service_cidr"], "") - additional_cluster_dns_ips = try(each.value.additional_cluster_dns_ips, var.self_managed_node_group_defaults.additional_cluster_dns_ips, null) + additional_cluster_dns_ips = try(each.value.additional_cluster_dns_ips, null) cluster_ip_family = var.ip_family - pre_bootstrap_user_data = try(each.value.pre_bootstrap_user_data, var.self_managed_node_group_defaults.pre_bootstrap_user_data, null) - post_bootstrap_user_data = try(each.value.post_bootstrap_user_data, var.self_managed_node_group_defaults.post_bootstrap_user_data, null) - bootstrap_extra_args = try(each.value.bootstrap_extra_args, var.self_managed_node_group_defaults.bootstrap_extra_args, null) - user_data_template_path = try(each.value.user_data_template_path, var.self_managed_node_group_defaults.user_data_template_path, null) - cloudinit_pre_nodeadm = try(each.value.cloudinit_pre_nodeadm, var.self_managed_node_group_defaults.cloudinit_pre_nodeadm, null) - cloudinit_post_nodeadm = try(each.value.cloudinit_post_nodeadm, var.self_managed_node_group_defaults.cloudinit_post_nodeadm, null) + pre_bootstrap_user_data = try(each.value.pre_bootstrap_user_data, null) + post_bootstrap_user_data = try(each.value.post_bootstrap_user_data, null) + bootstrap_extra_args = try(each.value.bootstrap_extra_args, null) + user_data_template_path = try(each.value.user_data_template_path, null) + cloudinit_pre_nodeadm = try(each.value.cloudinit_pre_nodeadm, null) + cloudinit_post_nodeadm = try(each.value.cloudinit_post_nodeadm, null) # Launch Template - create_launch_template = try(each.value.create_launch_template, var.self_managed_node_group_defaults.create_launch_template, null) - launch_template_id = try(each.value.launch_template_id, var.self_managed_node_group_defaults.launch_template_id, null) - launch_template_name = try(each.value.launch_template_name, var.self_managed_node_group_defaults.launch_template_name, each.key) - launch_template_use_name_prefix = try(each.value.launch_template_use_name_prefix, var.self_managed_node_group_defaults.launch_template_use_name_prefix, null) - launch_template_version = try(each.value.launch_template_version, var.self_managed_node_group_defaults.launch_template_version, null) - launch_template_default_version = try(each.value.launch_template_default_version, var.self_managed_node_group_defaults.launch_template_default_version, null) - update_launch_template_default_version = try(each.value.update_launch_template_default_version, var.self_managed_node_group_defaults.update_launch_template_default_version, null) - launch_template_description = try(each.value.launch_template_description, var.self_managed_node_group_defaults.launch_template_description, "Custom launch template for ${try(each.value.name, each.key)} self managed node group") - launch_template_tags = try(each.value.launch_template_tags, var.self_managed_node_group_defaults.launch_template_tags, null) - tag_specifications = try(each.value.tag_specifications, var.self_managed_node_group_defaults.tag_specifications, null) - - ebs_optimized = try(each.value.ebs_optimized, var.self_managed_node_group_defaults.ebs_optimized, null) - ami_id = try(each.value.ami_id, var.self_managed_node_group_defaults.ami_id, null) - kubernetes_version = try(each.value.kubernetes_version, var.self_managed_node_group_defaults.kubernetes_version, time_sleep.this[0].triggers["kubernetes_version"]) - instance_type = try(each.value.instance_type, var.self_managed_node_group_defaults.instance_type, null) - key_name = try(each.value.key_name, var.self_managed_node_group_defaults.key_name, null) - - disable_api_termination = try(each.value.disable_api_termination, var.self_managed_node_group_defaults.disable_api_termination, null) - instance_initiated_shutdown_behavior = try(each.value.instance_initiated_shutdown_behavior, var.self_managed_node_group_defaults.instance_initiated_shutdown_behavior, null) - kernel_id = try(each.value.kernel_id, var.self_managed_node_group_defaults.kernel_id, null) - ram_disk_id = try(each.value.ram_disk_id, var.self_managed_node_group_defaults.ram_disk_id, null) - - block_device_mappings = try(each.value.block_device_mappings, var.self_managed_node_group_defaults.block_device_mappings, null) - capacity_reservation_specification = try(each.value.capacity_reservation_specification, var.self_managed_node_group_defaults.capacity_reservation_specification, null) - cpu_options = try(each.value.cpu_options, var.self_managed_node_group_defaults.cpu_options, null) - credit_specification = try(each.value.credit_specification, var.self_managed_node_group_defaults.credit_specification, null) - enclave_options = try(each.value.enclave_options, var.self_managed_node_group_defaults.enclave_options, null) - instance_requirements = try(each.value.instance_requirements, var.self_managed_node_group_defaults.instance_requirements, null) - instance_market_options = try(each.value.instance_market_options, var.self_managed_node_group_defaults.instance_market_options, null) - license_specifications = try(each.value.license_specifications, var.self_managed_node_group_defaults.license_specifications, null) - metadata_options = try(each.value.metadata_options, var.self_managed_node_group_defaults.metadata_options, null) - enable_monitoring = try(each.value.enable_monitoring, var.self_managed_node_group_defaults.enable_monitoring, null) - enable_efa_support = try(each.value.enable_efa_support, var.self_managed_node_group_defaults.enable_efa_support, null) - enable_efa_only = try(each.value.enable_efa_only, var.self_managed_node_group_defaults.enable_efa_only, null) - efa_indices = try(each.value.efa_indices, var.self_managed_node_group_defaults.efa_indices, null) - network_interfaces = try(each.value.network_interfaces, var.self_managed_node_group_defaults.network_interfaces, null) - placement = try(each.value.placement, var.self_managed_node_group_defaults.placement, null) - maintenance_options = try(each.value.maintenance_options, var.self_managed_node_group_defaults.maintenance_options, null) - private_dns_name_options = try(each.value.private_dns_name_options, var.self_managed_node_group_defaults.private_dns_name_options, null) + create_launch_template = try(each.value.create_launch_template, null) + launch_template_id = try(each.value.launch_template_id, null) + launch_template_name = try(each.value.launch_template_name, each.key) + launch_template_use_name_prefix = try(each.value.launch_template_use_name_prefix, null) + launch_template_version = try(each.value.launch_template_version, null) + launch_template_default_version = try(each.value.launch_template_default_version, null) + update_launch_template_default_version = try(each.value.update_launch_template_default_version, null) + launch_template_description = try(each.value.launch_template_description, "Custom launch template for ${try(each.value.name, each.key)} self managed node group") + launch_template_tags = try(each.value.launch_template_tags, null) + tag_specifications = try(each.value.tag_specifications, null) + + ebs_optimized = try(each.value.ebs_optimized, null) + ami_id = try(each.value.ami_id, null) + kubernetes_version = try(each.value.kubernetes_version, time_sleep.this[0].triggers["kubernetes_version"]) + instance_type = try(each.value.instance_type, null) + key_name = try(each.value.key_name, null) + + disable_api_termination = try(each.value.disable_api_termination, null) + instance_initiated_shutdown_behavior = try(each.value.instance_initiated_shutdown_behavior, null) + kernel_id = try(each.value.kernel_id, null) + ram_disk_id = try(each.value.ram_disk_id, null) + + block_device_mappings = try(each.value.block_device_mappings, null) + capacity_reservation_specification = try(each.value.capacity_reservation_specification, null) + cpu_options = try(each.value.cpu_options, null) + credit_specification = try(each.value.credit_specification, null) + enclave_options = try(each.value.enclave_options, null) + instance_requirements = try(each.value.instance_requirements, null) + instance_market_options = try(each.value.instance_market_options, null) + license_specifications = try(each.value.license_specifications, null) + metadata_options = try(each.value.metadata_options, null) + enable_monitoring = try(each.value.enable_monitoring, null) + enable_efa_support = try(each.value.enable_efa_support, null) + enable_efa_only = try(each.value.enable_efa_only, null) + efa_indices = try(each.value.efa_indices, null) + network_interfaces = try(each.value.network_interfaces, null) + placement = try(each.value.placement, null) + maintenance_options = try(each.value.maintenance_options, null) + private_dns_name_options = try(each.value.private_dns_name_options, null) # IAM role - create_iam_instance_profile = try(each.value.create_iam_instance_profile, var.self_managed_node_group_defaults.create_iam_instance_profile, null) - iam_instance_profile_arn = try(each.value.iam_instance_profile_arn, var.self_managed_node_group_defaults.iam_instance_profile_arn, null) - iam_role_name = try(each.value.iam_role_name, var.self_managed_node_group_defaults.iam_role_name, null) - iam_role_use_name_prefix = try(each.value.iam_role_use_name_prefix, var.self_managed_node_group_defaults.iam_role_use_name_prefix, true) - iam_role_path = try(each.value.iam_role_path, var.self_managed_node_group_defaults.iam_role_path, null) - iam_role_description = try(each.value.iam_role_description, var.self_managed_node_group_defaults.iam_role_description, null) - iam_role_permissions_boundary = try(each.value.iam_role_permissions_boundary, var.self_managed_node_group_defaults.iam_role_permissions_boundary, null) - iam_role_tags = try(each.value.iam_role_tags, var.self_managed_node_group_defaults.iam_role_tags, null) - iam_role_attach_cni_policy = try(each.value.iam_role_attach_cni_policy, var.self_managed_node_group_defaults.iam_role_attach_cni_policy, null) - iam_role_additional_policies = lookup(each.value, "iam_role_additional_policies", lookup(var.self_managed_node_group_defaults, "iam_role_additional_policies", null)) - create_iam_role_policy = try(each.value.create_iam_role_policy, var.self_managed_node_group_defaults.create_iam_role_policy, null) - iam_role_policy_statements = try(each.value.iam_role_policy_statements, var.self_managed_node_group_defaults.iam_role_policy_statements, null) + create_iam_instance_profile = try(each.value.create_iam_instance_profile, null) + iam_instance_profile_arn = try(each.value.iam_instance_profile_arn, null) + iam_role_name = try(each.value.iam_role_name, null) + iam_role_use_name_prefix = try(each.value.iam_role_use_name_prefix, true) + iam_role_path = try(each.value.iam_role_path, null) + iam_role_description = try(each.value.iam_role_description, null) + iam_role_permissions_boundary = try(each.value.iam_role_permissions_boundary, null) + iam_role_tags = try(each.value.iam_role_tags, null) + iam_role_attach_cni_policy = try(each.value.iam_role_attach_cni_policy, null) + iam_role_additional_policies = lookup(each.value, "iam_role_additional_policies", null) + create_iam_role_policy = try(each.value.create_iam_role_policy, null) + iam_role_policy_statements = try(each.value.iam_role_policy_statements, null) # Access entry - create_access_entry = try(each.value.create_access_entry, var.self_managed_node_group_defaults.create_access_entry, null) - iam_role_arn = try(each.value.iam_role_arn, var.self_managed_node_group_defaults.iam_role_arn, null) + create_access_entry = try(each.value.create_access_entry, null) + iam_role_arn = try(each.value.iam_role_arn, null) # Security group - vpc_security_group_ids = compact(concat([local.node_security_group_id], try(each.value.vpc_security_group_ids, var.self_managed_node_group_defaults.vpc_security_group_ids, []))) - cluster_primary_security_group_id = try(each.value.attach_cluster_primary_security_group, var.self_managed_node_group_defaults.attach_cluster_primary_security_group, false) ? aws_eks_cluster.this[0].vpc_config[0].cluster_security_group_id : null - create_security_group = try(each.value.create_security_group, var.self_managed_node_group_defaults.create_security_group, null) - security_group_name = try(each.value.security_group_name, var.self_managed_node_group_defaults.security_group_name, null) - security_group_use_name_prefix = try(each.value.security_group_use_name_prefix, var.self_managed_node_group_defaults.security_group_use_name_prefix, null) - security_group_description = try(each.value.security_group_description, var.self_managed_node_group_defaults.security_group_description, null) - security_group_ingress_rules = try(each.value.security_group_ingress_rules, var.self_managed_node_group_defaults.security_group_ingress_rules, null) - security_group_egress_rules = try(each.value.security_group_egress_rules, var.self_managed_node_group_defaults.security_group_egress_rules, null) - security_group_tags = try(each.value.security_group_tags, var.self_managed_node_group_defaults.security_group_tags, null) + vpc_security_group_ids = compact(concat([local.node_security_group_id], try(each.value.vpc_security_group_ids, []))) + cluster_primary_security_group_id = try(each.value.attach_cluster_primary_security_group, false) ? aws_eks_cluster.this[0].vpc_config[0].cluster_security_group_id : null + create_security_group = try(each.value.create_security_group, null) + security_group_name = try(each.value.security_group_name, null) + security_group_use_name_prefix = try(each.value.security_group_use_name_prefix, null) + security_group_description = try(each.value.security_group_description, null) + security_group_ingress_rules = try(each.value.security_group_ingress_rules, null) + security_group_egress_rules = try(each.value.security_group_egress_rules, null) + security_group_tags = try(each.value.security_group_tags, null) tags = merge( var.tags, - var.self_managed_node_group_defaults.tags, each.value.tags, ) } diff --git a/tests/eks-fargate-profile/main.tf b/tests/eks-fargate-profile/main.tf index 40b458bd94..795e736fc7 100644 --- a/tests/eks-fargate-profile/main.tf +++ b/tests/eks-fargate-profile/main.tf @@ -54,12 +54,6 @@ module "eks" { create_security_group = false create_node_security_group = false - fargate_profile_defaults = { - iam_role_additional_policies = { - additional = aws_iam_policy.additional.arn - } - } - fargate_profiles = { example = { name = "example" @@ -78,6 +72,10 @@ module "eks" { } ] + iam_role_additional_policies = { + additional = aws_iam_policy.additional.arn + } + # Using specific subnets instead of the subnets supplied for the cluster itself subnet_ids = [module.vpc.private_subnets[1]] diff --git a/tests/eks-managed-node-group/main.tf b/tests/eks-managed-node-group/main.tf index 22d4c5a602..7c2ffe277d 100644 --- a/tests/eks-managed-node-group/main.tf +++ b/tests/eks-managed-node-group/main.tf @@ -87,11 +87,6 @@ module "eks" { subnet_ids = module.vpc.private_subnets control_plane_subnet_ids = module.vpc.intra_subnets - eks_managed_node_group_defaults = { - ami_type = "AL2023_x86_64_STANDARD" - instance_types = ["m6i.large", "m5.large", "m5n.large", "m5zn.large"] - } - eks_managed_node_groups = { # Default node group - as provided by AWS EKS default_node_group = { diff --git a/tests/self-managed-node-group/main.tf b/tests/self-managed-node-group/main.tf index 9a19e98635..20ec5b8f46 100644 --- a/tests/self-managed-node-group/main.tf +++ b/tests/self-managed-node-group/main.tf @@ -70,20 +70,18 @@ module "eks" { provider_key_arn = module.kms.key_arn } - self_managed_node_group_defaults = { - ami_type = "AL2023_x86_64_STANDARD" - ami_id = data.aws_ami.eks_default.image_id - - # enable discovery of autoscaling groups by cluster-autoscaler - autoscaling_group_tags = { - "k8s.io/cluster-autoscaler/enabled" : true, - "k8s.io/cluster-autoscaler/${local.name}" : "owned", - } - } - self_managed_node_groups = { # Default node group - as provisioned by the module defaults - default_node_group = {} + default_node_group = { + ami_type = "AL2023_x86_64_STANDARD" + ami_id = data.aws_ami.eks_default.image_id + + # enable discovery of autoscaling groups by cluster-autoscaler + autoscaling_group_tags = { + "k8s.io/cluster-autoscaler/enabled" : true, + "k8s.io/cluster-autoscaler/${local.name}" : "owned", + } + } # Bottlerocket node group bottlerocket = { diff --git a/variables.tf b/variables.tf index 0da06a8095..837dc6e23b 100644 --- a/variables.tf +++ b/variables.tf @@ -769,61 +769,6 @@ variable "fargate_profiles" { default = {} } -variable "fargate_profile_defaults" { - description = "Map of Fargate Profile default configurations" - type = object({ - create = optional(bool) - - # Fargate profile - name = optional(string) # Will fall back to map key - subnet_ids = optional(list(string)) - selectors = optional(list(object({ - labels = optional(map(string)) - namespace = string - }))) - timeouts = optional(object({ - create = optional(string) - delete = optional(string) - })) - - # IAM role - create_iam_role = optional(bool) - iam_role_arn = optional(string) - iam_role_name = optional(string) - iam_role_use_name_prefix = optional(bool) - iam_role_path = optional(string) - iam_role_description = optional(string) - iam_role_permissions_boundary = optional(string) - iam_role_tags = optional(map(string), {}) - iam_role_attach_cni_policy = optional(bool) - iam_role_additional_policies = optional(map(string), {}) - create_iam_role_policy = optional(bool) - iam_role_policy_statements = optional(list(object({ - sid = optional(string) - actions = optional(list(string)) - not_actions = optional(list(string)) - effect = optional(string) - resources = optional(list(string)) - not_resources = optional(list(string)) - principals = optional(list(object({ - type = string - identifiers = list(string) - }))) - not_principals = optional(list(object({ - type = string - identifiers = list(string) - }))) - condition = optional(list(object({ - test = string - values = list(string) - variable = string - }))) - }))) - tags = optional(map(string), {}) - }) - default = {} -} - ################################################################################ # Self Managed Node Group ################################################################################ @@ -1251,180 +1196,87 @@ variable "self_managed_node_groups" { default = {} } -variable "self_managed_node_group_defaults" { - description = "Map of self-managed node group default configurations" - type = object({ - create = optional(bool) - # Autoscaling Group - create_autoscaling_group = optional(bool) - use_name_prefix = optional(bool) - availability_zones = optional(list(string)) - subnet_ids = optional(list(string)) - min_size = optional(number) - max_size = optional(number) - desired_size = optional(number) - desired_size_type = optional(string) - capacity_rebalance = optional(bool) - default_instance_warmup = optional(number) - protect_from_scale_in = optional(bool) - context = optional(string) - create_placement_group = optional(bool) - placement_group = optional(string) - health_check_type = optional(string) - health_check_grace_period = optional(number) - ignore_failed_scaling_activities = optional(bool) - force_delete = optional(bool) - termination_policies = optional(list(string)) - suspended_processes = optional(list(string)) - max_instance_lifetime = optional(number) - enabled_metrics = optional(list(string)) - metrics_granularity = optional(string) - initial_lifecycle_hooks = optional(list(object({ - default_result = optional(string) - heartbeat_timeout = optional(number) - lifecycle_transition = string - name = string - notification_metadata = optional(string) - notification_target_arn = optional(string) - role_arn = optional(string) - }))) - instance_maintenance_policy = optional(object({ - max_healthy_percentage = number - min_healthy_percentage = number - })) - instance_refresh = optional(object({ - preferences = optional(object({ - alarm_specification = optional(object({ - alarms = optional(list(string)) - })) - auto_rollback = optional(bool) - checkpoint_delay = optional(number) - checkpoint_percentages = optional(list(number)) - instance_warmup = optional(number) - max_healthy_percentage = optional(number) - min_healthy_percentage = optional(number) - scale_in_protected_instances = optional(string) - skip_matching = optional(bool) - standby_instances = optional(string) - })) - strategy = optional(string) - triggers = optional(list(string)) +################################################################################ +# EKS Managed Node Group +################################################################################ + +variable "eks_managed_node_groups" { + description = "Map of EKS managed node group definitions to create" + type = map(object({ + create = optional(bool, true) + kubernetes_version = optional(string) + + # EKS Managed Node Group + name = optional(string) # Will fall back to map key + use_name_prefix = optional(bool, true) + subnet_ids = optional(list(string)) + min_size = optional(number, 0) + max_size = optional(number, 3) + desired_size = optional(number, 1) + ami_id = optional(string, "") + ami_type = optional(string, "AL2023_x86_64_STANDARD") + ami_release_version = optional(string) + use_latest_ami_release_version = optional(bool, true) + capacity_type = optional(string, "ON_DEMAND") + disk_size = optional(number) + force_update_version = optional(bool) + instance_types = optional(list(string)) + labels = optional(map(string)) + node_repair_config = optional(object({ + enabled = optional(bool, true) })) - use_mixed_instances_policy = optional(bool) - mixed_instances_policy = optional(object({ - instances_distribution = optional(object({ - on_demand_allocation_strategy = optional(string) - on_demand_base_capacity = optional(number) - on_demand_percentage_above_base_capacity = optional(number) - spot_allocation_strategy = optional(string) - spot_instance_pools = optional(number) - spot_max_price = optional(string) - })) - launch_template = object({ - override = optional(list(object({ - instance_requirements = optional(object({ - accelerator_count = optional(object({ - max = optional(number) - min = optional(number) - })) - accelerator_manufacturers = optional(list(string)) - accelerator_names = optional(list(string)) - accelerator_total_memory_mib = optional(object({ - max = optional(number) - min = optional(number) - })) - accelerator_types = optional(list(string)) - allowed_instance_types = optional(list(string)) - bare_metal = optional(string) - baseline_ebs_bandwidth_mbps = optional(object({ - max = optional(number) - min = optional(number) - })) - burstable_performance = optional(string) - cpu_manufacturers = optional(list(string)) - excluded_instance_types = optional(list(string)) - instance_generations = optional(list(string)) - local_storage = optional(string) - local_storage_types = optional(list(string)) - max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number) - memory_gib_per_vcpu = optional(object({ - max = optional(number) - min = optional(number) - })) - memory_mib = optional(object({ - max = optional(number) - min = optional(number) - })) - network_bandwidth_gbps = optional(object({ - max = optional(number) - min = optional(number) - })) - network_interface_count = optional(object({ - max = optional(number) - min = optional(number) - })) - on_demand_max_price_percentage_over_lowest_price = optional(number) - require_hibernate_support = optional(bool) - spot_max_price_percentage_over_lowest_price = optional(number) - total_local_storage_gb = optional(object({ - max = optional(number) - min = optional(number) - })) - vcpu_count = optional(object({ - max = optional(number) - min = optional(number) - })) - })) - instance_type = optional(string) - launch_template_specification = optional(object({ - launch_template_id = optional(string) - launch_template_name = optional(string) - version = optional(string) - })) - weighted_capacity = optional(string) - }))) - }) + remote_access = optional(object({ + ec2_ssh_key = optional(string) + source_security_group_ids = optional(list(string)) })) + taints = optional(map(object({ + key = string + value = optional(string) + effect = string + }))) + update_config = optional(object({ + max_unavailable = optional(number) + max_unavailable_percentage = optional(number) + }), { + max_unavailable_percentage = 33 + }) timeouts = optional(object({ + create = optional(string) + update = optional(string) delete = optional(string) })) - autoscaling_group_tags = optional(map(string)) # User data - ami_type = optional(string) - additional_cluster_dns_ips = optional(list(string)) - pre_bootstrap_user_data = optional(string) - post_bootstrap_user_data = optional(string) - bootstrap_extra_args = optional(string) - user_data_template_path = optional(string) + enable_bootstrap_user_data = optional(bool, false) + pre_bootstrap_user_data = optional(string, "") + post_bootstrap_user_data = optional(string, "") + bootstrap_extra_args = optional(string, "") + user_data_template_path = optional(string, "") cloudinit_pre_nodeadm = optional(list(object({ content = string content_type = optional(string) filename = optional(string) merge_type = optional(string) - }))) + })), []) cloudinit_post_nodeadm = optional(list(object({ content = string content_type = optional(string) filename = optional(string) merge_type = optional(string) - }))) + })), []) # Launch Template - create_launch_template = optional(bool) - use_custom_launch_template = optional(bool) - launch_template_id = optional(string) - launch_template_name = optional(string) - launch_template_use_name_prefix = optional(bool) + create_launch_template = optional(bool, true) + use_custom_launch_template = optional(bool, true) + launch_template_id = optional(string, "") + launch_template_name = optional(string) # Will fall back to map key + launch_template_use_name_prefix = optional(bool, true) launch_template_version = optional(string) - update_launch_template_default_version = optional(bool) + update_launch_template_default_version = optional(bool, true) launch_template_description = optional(string) - launch_template_tags = optional(map(string)) - tag_specifications = optional(list(string)) + launch_template_tags = optional(map(string), {}) + tag_specifications = optional(list(string), ["instance", "volume", "network-interface"]) ebs_optimized = optional(bool) - ami_id = optional(string) - instance_type = optional(string) key_name = optional(string) disable_api_termination = optional(bool) - instance_initiated_shutdown_behavior = optional(string) kernel_id = optional(string) ram_disk_id = optional(string) block_device_mappings = optional(map(object({ @@ -1461,334 +1313,14 @@ variable "self_managed_node_group_defaults" { enclave_options = optional(object({ enabled = optional(bool) })) - instance_requirements = optional(object({ - accelerator_count = optional(object({ - max = optional(number) - min = optional(number) - })) - accelerator_manufacturers = optional(list(string)) - accelerator_names = optional(list(string)) - accelerator_total_memory_mib = optional(object({ - max = optional(number) - min = optional(number) - })) - accelerator_types = optional(list(string)) - allowed_instance_types = optional(list(string)) - bare_metal = optional(string) - baseline_ebs_bandwidth_mbps = optional(object({ - max = optional(number) - min = optional(number) - })) - burstable_performance = optional(string) - cpu_manufacturers = optional(list(string)) - excluded_instance_types = optional(list(string)) - instance_generations = optional(list(string)) - local_storage = optional(string) - local_storage_types = optional(list(string)) - max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number) - memory_gib_per_vcpu = optional(object({ - max = optional(number) - min = optional(number) - })) - memory_mib = optional(object({ - max = optional(number) - min = optional(number) - })) - network_bandwidth_gbps = optional(object({ - max = optional(number) - min = optional(number) - })) - network_interface_count = optional(object({ - max = optional(number) - min = optional(number) - })) - on_demand_max_price_percentage_over_lowest_price = optional(number) - require_hibernate_support = optional(bool) - spot_max_price_percentage_over_lowest_price = optional(number) - total_local_storage_gb = optional(object({ - max = optional(number) - min = optional(number) - })) - vcpu_count = optional(object({ - max = optional(number) - min = string - })) - })) - instance_market_options = optional(object({ - market_type = optional(string) - spot_options = optional(object({ - block_duration_minutes = optional(number) - instance_interruption_behavior = optional(string) - max_price = optional(string) - spot_instance_type = optional(string) - valid_until = optional(string) - })) - })) - license_specifications = optional(list(object({ - license_configuration_arn = string - }))) - metadata_options = optional(object({ - http_endpoint = optional(string) - http_protocol_ipv6 = optional(string) - http_put_response_hop_limit = optional(number) - http_tokens = optional(string) - instance_metadata_tags = optional(string) - })) - enable_monitoring = optional(bool) - enable_efa_support = optional(bool) - enable_efa_only = optional(bool) - efa_indices = optional(list(string)) - network_interfaces = optional(list(object({ - associate_carrier_ip_address = optional(bool) - associate_public_ip_address = optional(bool) - connection_tracking_specification = optional(object({ - tcp_established_timeout = optional(number) - udp_stream_timeout = optional(number) - udp_timeout = optional(number) - })) - delete_on_termination = optional(bool) - description = optional(string) - device_index = optional(number) - ena_srd_specification = optional(object({ - ena_srd_enabled = optional(bool) - ena_srd_udp_specification = optional(object({ - ena_srd_udp_enabled = optional(bool) - })) - })) - interface_type = optional(string) - ipv4_address_count = optional(number) - ipv4_addresses = optional(list(string)) - ipv4_prefix_count = optional(number) - ipv4_prefixes = optional(list(string)) - ipv6_address_count = optional(number) - ipv6_addresses = optional(list(string)) - ipv6_prefix_count = optional(number) - ipv6_prefixes = optional(list(string)) - network_card_index = optional(number) - network_interface_id = optional(string) - primary_ipv6 = optional(bool) - private_ip_address = optional(string) - security_groups = optional(list(string)) - subnet_id = optional(string) - }))) - placement = optional(object({ - affinity = optional(string) - availability_zone = optional(string) - group_name = optional(string) - host_id = optional(string) - host_resource_group_arn = optional(string) - partition_number = optional(number) - spread_domain = optional(string) - tenancy = optional(string) - })) - maintenance_options = optional(object({ - auto_recovery = optional(string) - })) - private_dns_name_options = optional(object({ - enable_resource_name_dns_aaaa_record = optional(bool) - enable_resource_name_dns_a_record = optional(bool) - hostname_type = optional(string) - })) - # IAM role - create_iam_instance_profile = optional(bool) - iam_instance_profile_arn = optional(string) - iam_role_name = optional(string) - iam_role_use_name_prefix = optional(bool) - iam_role_path = optional(string) - iam_role_description = optional(string) - iam_role_permissions_boundary = optional(string) - iam_role_tags = optional(map(string)) - iam_role_attach_cni_policy = optional(bool) - iam_role_additional_policies = optional(map(string)) - create_iam_role_policy = optional(bool) - iam_role_policy_statements = optional(list(object({ - sid = optional(string) - actions = optional(list(string)) - not_actions = optional(list(string)) - effect = optional(string) - resources = optional(list(string)) - not_resources = optional(list(string)) - principals = optional(list(object({ - type = string - identifiers = list(string) - }))) - not_principals = optional(list(object({ - type = string - identifiers = list(string) - }))) - condition = optional(list(object({ - test = string - values = list(string) - variable = string - }))) - }))) - # Access entry - create_access_entry = optional(bool) - iam_role_arn = optional(string) - # Security group - attach_cluster_primary_security_group = optional(bool, false) - create_security_group = optional(bool) - security_group_name = optional(string) - security_group_use_name_prefix = optional(bool) - security_group_description = optional(string) - security_group_ingress_rules = optional(map(object({ - name = optional(string) - cidr_ipv4 = optional(string) - cidr_ipv6 = optional(string) - description = optional(string) - from_port = optional(string) - ip_protocol = optional(string) - prefix_list_id = optional(string) - referenced_security_group_id = optional(string) - self = optional(bool) - tags = optional(map(string)) - to_port = optional(string) - }))) - security_group_egress_rules = optional(map(object({ - name = optional(string) - cidr_ipv4 = optional(string) - cidr_ipv6 = optional(string) - description = optional(string) - from_port = optional(string) - ip_protocol = optional(string) - prefix_list_id = optional(string) - referenced_security_group_id = optional(string) - self = optional(bool) - tags = optional(map(string)) - to_port = optional(string) - }))) - security_group_tags = optional(map(string)) - - tags = optional(map(string)) - }) - default = {} -} - -################################################################################ -# EKS Managed Node Group -################################################################################ - -variable "eks_managed_node_groups" { - description = "Map of EKS managed node group definitions to create" - type = map(object({ - create = optional(bool, true) - kubernetes_version = optional(string) - - # EKS Managed Node Group - name = optional(string) # Will fall back to map key - use_name_prefix = optional(bool, true) - subnet_ids = optional(list(string)) - min_size = optional(number, 0) - max_size = optional(number, 3) - desired_size = optional(number, 1) - ami_id = optional(string, "") - ami_type = optional(string, "AL2023_x86_64_STANDARD") - ami_release_version = optional(string) - use_latest_ami_release_version = optional(bool, true) - capacity_type = optional(string, "ON_DEMAND") - disk_size = optional(number) - force_update_version = optional(bool) - instance_types = optional(list(string)) - labels = optional(map(string)) - node_repair_config = optional(object({ - enabled = optional(bool, true) - })) - remote_access = optional(object({ - ec2_ssh_key = optional(string) - source_security_group_ids = optional(list(string)) - })) - taints = optional(map(object({ - key = string - value = optional(string) - effect = string - }))) - update_config = optional(object({ - max_unavailable = optional(number) - max_unavailable_percentage = optional(number) - }), { - max_unavailable_percentage = 33 - }) - timeouts = optional(object({ - create = optional(string) - update = optional(string) - delete = optional(string) - })) - # User data - enable_bootstrap_user_data = optional(bool, false) - pre_bootstrap_user_data = optional(string, "") - post_bootstrap_user_data = optional(string, "") - bootstrap_extra_args = optional(string, "") - user_data_template_path = optional(string, "") - cloudinit_pre_nodeadm = optional(list(object({ - content = string - content_type = optional(string) - filename = optional(string) - merge_type = optional(string) - })), []) - cloudinit_post_nodeadm = optional(list(object({ - content = string - content_type = optional(string) - filename = optional(string) - merge_type = optional(string) - })), []) - # Launch Template - create_launch_template = optional(bool, true) - use_custom_launch_template = optional(bool, true) - launch_template_id = optional(string, "") - launch_template_name = optional(string) # Will fall back to map key - launch_template_use_name_prefix = optional(bool, true) - launch_template_version = optional(string) - update_launch_template_default_version = optional(bool, true) - launch_template_description = optional(string) - launch_template_tags = optional(map(string), {}) - tag_specifications = optional(list(string), ["instance", "volume", "network-interface"]) - ebs_optimized = optional(bool) - key_name = optional(string) - disable_api_termination = optional(bool) - kernel_id = optional(string) - ram_disk_id = optional(string) - block_device_mappings = optional(map(object({ - device_name = optional(string) - ebs = optional(object({ - delete_on_termination = optional(bool) - encrypted = optional(bool) - iops = optional(number) - kms_key_id = optional(string) - snapshot_id = optional(string) - throughput = optional(number) - volume_initialization_rate = optional(number) - volume_size = optional(number) - volume_type = optional(string) - })) - no_device = optional(string) - virtual_name = optional(string) - }))) - capacity_reservation_specification = optional(object({ - capacity_reservation_preference = optional(string) - capacity_reservation_target = optional(object({ - capacity_reservation_id = optional(string) - capacity_reservation_resource_group_arn = optional(string) - })) - })) - cpu_options = optional(object({ - amd_sev_snp = optional(string) - core_count = optional(number) - threads_per_core = optional(number) - })) - credit_specification = optional(object({ - cpu_credits = optional(string) - })) - enclave_options = optional(object({ - enabled = optional(bool) - })) - instance_market_options = optional(object({ - market_type = optional(string) - spot_options = optional(object({ - block_duration_minutes = optional(number) - instance_interruption_behavior = optional(string) - max_price = optional(string) - spot_instance_type = optional(string) - valid_until = optional(string) + instance_market_options = optional(object({ + market_type = optional(string) + spot_options = optional(object({ + block_duration_minutes = optional(number) + instance_interruption_behavior = optional(string) + max_price = optional(string) + spot_instance_type = optional(string) + valid_until = optional(string) })) })) license_specifications = optional(list(object({ @@ -1935,266 +1467,6 @@ variable "eks_managed_node_groups" { default = {} } -variable "eks_managed_node_group_defaults" { - description = "Map of EKS managed node group default configurations" - type = object({ - create = optional(bool) - kubernetes_version = optional(string) - - # EKS Managed Node Group - use_name_prefix = optional(bool) - subnet_ids = optional(list(string)) - min_size = optional(number) - max_size = optional(number) - desired_size = optional(number) - ami_id = optional(string) - ami_type = optional(string) - ami_release_version = optional(string) - use_latest_ami_release_version = optional(bool) - capacity_type = optional(string) - disk_size = optional(number) - force_update_version = optional(bool) - instance_types = optional(list(string)) - labels = optional(map(string)) - node_repair_config = optional(object({ - enabled = optional(bool) - })) - remote_access = optional(object({ - ec2_ssh_key = optional(string) - source_security_group_ids = optional(list(string)) - })) - taints = optional(map(object({ - key = string - value = optional(string) - effect = string - }))) - update_config = optional(object({ - max_unavailable = optional(number) - max_unavailable_percentage = optional(number) - })) - timeouts = optional(object({ - create = optional(string) - update = optional(string) - delete = optional(string) - })) - # User data - enable_bootstrap_user_data = optional(bool) - pre_bootstrap_user_data = optional(string) - post_bootstrap_user_data = optional(string) - bootstrap_extra_args = optional(string) - user_data_template_path = optional(string) - cloudinit_pre_nodeadm = optional(list(object({ - content = string - content_type = optional(string) - filename = optional(string) - merge_type = optional(string) - }))) - cloudinit_post_nodeadm = optional(list(object({ - content = string - content_type = optional(string) - filename = optional(string) - merge_type = optional(string) - }))) - # Launch Template - create_launch_template = optional(bool) - use_custom_launch_template = optional(bool) - launch_template_id = optional(string) - launch_template_name = optional(string) - launch_template_use_name_prefix = optional(bool) - launch_template_version = optional(string) - update_launch_template_default_version = optional(bool) - launch_template_description = optional(string) - launch_template_tags = optional(map(string)) - tag_specifications = optional(list(string)) - ebs_optimized = optional(bool) - key_name = optional(string) - disable_api_termination = optional(bool) - kernel_id = optional(string) - ram_disk_id = optional(string) - block_device_mappings = optional(map(object({ - device_name = optional(string) - ebs = optional(object({ - delete_on_termination = optional(bool) - encrypted = optional(bool) - iops = optional(number) - kms_key_id = optional(string) - snapshot_id = optional(string) - throughput = optional(number) - volume_initialization_rate = optional(number) - volume_size = optional(number) - volume_type = optional(string) - })) - no_device = optional(string) - virtual_name = optional(string) - }))) - capacity_reservation_specification = optional(object({ - capacity_reservation_preference = optional(string) - capacity_reservation_target = optional(object({ - capacity_reservation_id = optional(string) - capacity_reservation_resource_group_arn = optional(string) - })) - })) - cpu_options = optional(object({ - amd_sev_snp = optional(string) - core_count = optional(number) - threads_per_core = optional(number) - })) - credit_specification = optional(object({ - cpu_credits = optional(string) - })) - enclave_options = optional(object({ - enabled = optional(bool) - })) - instance_market_options = optional(object({ - market_type = optional(string) - spot_options = optional(object({ - block_duration_minutes = optional(number) - instance_interruption_behavior = optional(string) - max_price = optional(string) - spot_instance_type = optional(string) - valid_until = optional(string) - })) - })) - license_specifications = optional(list(object({ - license_configuration_arn = string - }))) - metadata_options = optional(object({ - http_endpoint = optional(string) - http_protocol_ipv6 = optional(string) - http_put_response_hop_limit = optional(number) - http_tokens = optional(string) - instance_metadata_tags = optional(string) - })) - enable_monitoring = optional(bool) - enable_efa_support = optional(bool) - enable_efa_only = optional(bool) - efa_indices = optional(list(string)) - create_placement_group = optional(bool) - placement = optional(object({ - affinity = optional(string) - availability_zone = optional(string) - group_name = optional(string) - host_id = optional(string) - host_resource_group_arn = optional(string) - partition_number = optional(number) - spread_domain = optional(string) - tenancy = optional(string) - })) - network_interfaces = optional(list(object({ - associate_carrier_ip_address = optional(bool) - associate_public_ip_address = optional(bool) - connection_tracking_specification = optional(object({ - tcp_established_timeout = optional(number) - udp_stream_timeout = optional(number) - udp_timeout = optional(number) - })) - delete_on_termination = optional(bool) - description = optional(string) - device_index = optional(number) - ena_srd_specification = optional(object({ - ena_srd_enabled = optional(bool) - ena_srd_udp_specification = optional(object({ - ena_srd_udp_enabled = optional(bool) - })) - })) - interface_type = optional(string) - ipv4_address_count = optional(number) - ipv4_addresses = optional(list(string)) - ipv4_prefix_count = optional(number) - ipv4_prefixes = optional(list(string)) - ipv6_address_count = optional(number) - ipv6_addresses = optional(list(string)) - ipv6_prefix_count = optional(number) - ipv6_prefixes = optional(list(string)) - network_card_index = optional(number) - network_interface_id = optional(string) - primary_ipv6 = optional(bool) - private_ip_address = optional(string) - security_groups = optional(list(string)) - subnet_id = optional(string) - }))) - maintenance_options = optional(object({ - auto_recovery = optional(string) - })) - private_dns_name_options = optional(object({ - enable_resource_name_dns_aaaa_record = optional(bool) - enable_resource_name_dns_a_record = optional(bool) - hostname_type = optional(string) - })) - # IAM role - creat_iam_role = optional(bool) - iam_role_arn = optional(string) - iam_role_name = optional(string) - iam_role_use_name_prefix = optional(bool) - iam_role_path = optional(string) - iam_role_description = optional(string) - iam_role_permissions_boundary = optional(string) - iam_role_tags = optional(map(string)) - iam_role_attach_cni_policy = optional(bool) - iam_role_additional_policies = optional(map(string)) - create_iam_role_policy = optional(bool) - iam_role_policy_statements = optional(list(object({ - sid = optional(string) - actions = optional(list(string)) - not_actions = optional(list(string)) - effect = optional(string) - resources = optional(list(string)) - not_resources = optional(list(string)) - principals = optional(list(object({ - type = string - identifiers = list(string) - }))) - not_principals = optional(list(object({ - type = string - identifiers = list(string) - }))) - condition = optional(list(object({ - test = string - values = list(string) - variable = string - }))) - }))) - # Security group - vpc_security_group_ids = optional(list(string)) - attach_cluster_primary_security_group = optional(bool, false) - cluster_primary_security_group_id = optional(string) - create_security_group = optional(bool) - security_group_name = optional(string) - security_group_use_name_prefix = optional(bool) - security_group_description = optional(string) - security_group_ingress_rules = optional(map(object({ - name = optional(string) - cidr_ipv4 = optional(string) - cidr_ipv6 = optional(string) - description = optional(string) - from_port = optional(string) - ip_protocol = optional(string) - prefix_list_id = optional(string) - referenced_security_group_id = optional(string) - self = optional(bool) - tags = optional(map(string)) - to_port = optional(string) - }))) - security_group_egress_rules = optional(map(object({ - name = optional(string) - cidr_ipv4 = optional(string) - cidr_ipv6 = optional(string) - description = optional(string) - from_port = optional(string) - ip_protocol = optional(string) - prefix_list_id = optional(string) - referenced_security_group_id = optional(string) - self = optional(bool) - tags = optional(map(string)) - to_port = optional(string) - }))) - security_group_tags = optional(map(string)) - - tags = optional(map(string), {}) - }) - default = {} -} - variable "putin_khuylo" { description = "Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo!" type = bool From 73762df176f81dc585a579277f4ddf2e0660b02e Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Mon, 14 Jul 2025 13:33:15 -0500 Subject: [PATCH 17/25] fix: Ignore changes to `bootstrap_self_managed_addons` to aid in upgrade --- main.tf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main.tf b/main.tf index 4f016b3752..abb8c3c23e 100644 --- a/main.tf +++ b/main.tf @@ -196,7 +196,8 @@ resource "aws_eks_cluster" "this" { lifecycle { ignore_changes = [ - access_config[0].bootstrap_cluster_creator_admin_permissions + access_config[0].bootstrap_cluster_creator_admin_permissions, + bootstrap_self_managed_addons, ] } } From 2fd94b7699237c24cb46605f2bf52ee1e246d281 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Tue, 15 Jul 2025 09:52:02 -0500 Subject: [PATCH 18/25] feat: Add support for `region` argument on relevant resources --- README.md | 3 +- docs/UPGRADE-21.0.md | 73 ++++++++++++++++++++ main.tf | 24 +++++++ modules/eks-managed-node-group/README.md | 1 + modules/eks-managed-node-group/main.tf | 20 ++++++ modules/eks-managed-node-group/variables.tf | 6 ++ modules/fargate-profile/README.md | 1 + modules/fargate-profile/main.tf | 4 ++ modules/fargate-profile/variables.tf | 6 ++ modules/karpenter/README.md | 1 + modules/karpenter/main.tf | 14 ++++ modules/karpenter/variables.tf | 6 ++ modules/self-managed-node-group/README.md | 1 + modules/self-managed-node-group/main.tf | 20 ++++++ modules/self-managed-node-group/variables.tf | 6 ++ node_groups.tf | 10 +++ variables.tf | 20 ++++-- 17 files changed, 208 insertions(+), 8 deletions(-) create mode 100644 docs/UPGRADE-21.0.md diff --git a/README.md b/README.md index 53573cb55c..ab80755086 100644 --- a/README.md +++ b/README.md @@ -443,7 +443,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [kms\_key\_service\_users](#input\_kms\_key\_service\_users) | A list of IAM ARNs for [key service users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-service-integration) | `list(string)` | `[]` | no | | [kms\_key\_source\_policy\_documents](#input\_kms\_key\_source\_policy\_documents) | List of IAM policy documents that are merged together into the exported document. Statements must have unique `sid`s | `list(string)` | `[]` | no | | [kms\_key\_users](#input\_kms\_key\_users) | A list of IAM ARNs for [key users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-users) | `list(string)` | `[]` | no | -| [kubernetes\_version](#input\_kubernetes\_version) | Kubernetes `.` version to use for the EKS cluster (i.e.: `1.27`) | `string` | `null` | no | +| [kubernetes\_version](#input\_kubernetes\_version) | Kubernetes `.` version to use for the EKS cluster (i.e.: `1.33`) | `string` | `null` | no | | [name](#input\_name) | Name of the EKS cluster | `string` | `""` | no | | [node\_iam\_role\_additional\_policies](#input\_node\_iam\_role\_additional\_policies) | Additional policies to be added to the EKS Auto node IAM role | `map(string)` | `{}` | no | | [node\_iam\_role\_description](#input\_node\_iam\_role\_description) | Description of the EKS Auto node IAM role | `string` | `null` | no | @@ -463,6 +463,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [outpost\_config](#input\_outpost\_config) | Configuration for the AWS Outpost to provision the cluster on |
object({
control_plane_instance_type = optional(string)
control_plane_placement = optional(object({
group_name = string
}))
outpost_arns = list(string)
})
| `null` | no | | [prefix\_separator](#input\_prefix\_separator) | The separator to use between the prefix and the generated timestamp for resource names | `string` | `"-"` | no | | [putin\_khuylo](#input\_putin\_khuylo) | Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo! | `bool` | `true` | no | +| [region](#input\_region) | Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration | `string` | `null` | no | | [remote\_network\_config](#input\_remote\_network\_config) | Configuration block for the cluster remote network configuration |
object({
remote_node_networks = object({
cidrs = optional(list(string))
})
remote_pod_networks = optional(object({
cidrs = optional(list(string))
}))
})
| `null` | no | | [security\_group\_additional\_rules](#input\_security\_group\_additional\_rules) | List of additional security group rules to add to the cluster security group created. Set `source_node_security_group = true` inside rules to set the `node_security_group` as source |
map(object({
protocol = optional(string, "tcp")
from_port = number
to_port = number
type = optional(string, "ingress")
description = optional(string)
cidr_blocks = optional(list(string))
ipv6_cidr_blocks = optional(list(string))
prefix_list_ids = optional(list(string))
self = optional(bool)
source_node_security_group = optional(bool, false)
source_security_group_id = optional(string)
}))
| `{}` | no | | [security\_group\_description](#input\_security\_group\_description) | Description of the cluster security group created | `string` | `"EKS cluster security group"` | no | diff --git a/docs/UPGRADE-21.0.md b/docs/UPGRADE-21.0.md new file mode 100644 index 0000000000..2fa1e096c9 --- /dev/null +++ b/docs/UPGRADE-21.0.md @@ -0,0 +1,73 @@ +# Upgrade from v20.x to v21.x + +If you have any questions regarding this upgrade process, please consult the [`examples`](https://github.com/terraform-aws-modules/terraform-aws-eks/tree/master/examples) directory: +If you find a bug, please open an issue with supporting configuration to reproduce. + +## List of backwards incompatible changes + +- Terraform `v1.5.7` is now minimum supported version +- AWS provider `v6.0.0` is now minimum supported version + +## Additional changes + +### Added + +- Support for `region` parameter to specify the AWS region for the resources created if different from the provider region. + +### Modified + +- Variable definitions now contain detailed `object` types in place of the previously used any type. + +### Variable and output changes + +1. Removed variables: + + - + +2. Renamed variables: + + - + +3. Added variables: + + - + +4. Removed outputs: + + - + +5. Renamed outputs: + + - + +6. Added outputs: + + - + +## Upgrade Migrations + +### Before 20.x Example + +```hcl +module "eks" { + source = "terraform-aws-modules/eks/aws" + version = "~> 20.0" + + # Truncated for brevity ... + +} +``` + +### After 21.x Example + +```hcl +module "eks" { + source = "terraform-aws-modules/eks/aws" + version = "~> 21.0" + + # Truncated for brevity ... + +} +``` + +### State Changes diff --git a/main.tf b/main.tf index abb8c3c23e..fe018270ed 100644 --- a/main.tf +++ b/main.tf @@ -36,6 +36,8 @@ locals { resource "aws_eks_cluster" "this" { count = local.create ? 1 : 0 + region = var.region + name = var.name role_arn = local.role_arn version = var.kubernetes_version @@ -210,6 +212,8 @@ resource "aws_ec2_tag" "cluster_primary_security_group" { k => v if local.create && k != "Name" && var.create_primary_security_group_tags } + region = var.region + resource_id = aws_eks_cluster.this[0].vpc_config[0].cluster_security_group_id key = each.key value = each.value @@ -218,6 +222,8 @@ resource "aws_ec2_tag" "cluster_primary_security_group" { resource "aws_cloudwatch_log_group" "this" { count = local.create && var.create_cloudwatch_log_group ? 1 : 0 + region = var.region + name = "/aws/eks/${var.name}/cluster" retention_in_days = var.cloudwatch_log_group_retention_in_days kms_key_id = var.cloudwatch_log_group_kms_key_id @@ -283,6 +289,8 @@ locals { resource "aws_eks_access_entry" "this" { for_each = { for k, v in local.merged_access_entries : k => v if local.create } + region = var.region + cluster_name = aws_eks_cluster.this[0].id kubernetes_groups = try(each.value.kubernetes_groups, null) principal_arn = each.value.principal_arn @@ -298,6 +306,8 @@ resource "aws_eks_access_entry" "this" { resource "aws_eks_access_policy_association" "this" { for_each = { for k, v in local.flattened_access_entries : "${v.entry_key}_${v.pol_key}" => v if local.create } + region = var.region + access_scope { namespaces = each.value.association_access_scope_namespaces type = each.value.association_access_scope_type @@ -323,6 +333,8 @@ module "kms" { create = local.create && var.create_kms_key && local.enable_encryption_config # not valid on Outposts + region = var.region + description = coalesce(var.kms_key_description, "${var.name} cluster encryption key") key_usage = "ENCRYPT_DECRYPT" deletion_window_in_days = var.kms_key_deletion_window_in_days @@ -377,6 +389,8 @@ locals { resource "aws_security_group" "cluster" { count = local.create_security_group ? 1 : 0 + region = var.region + name = var.security_group_use_name_prefix ? null : local.security_group_name name_prefix = var.security_group_use_name_prefix ? "${local.security_group_name}${var.prefix_separator}" : null description = var.security_group_description @@ -399,6 +413,8 @@ resource "aws_security_group_rule" "cluster" { var.security_group_additional_rules ) : k => v if local.create_security_group } + region = var.region + security_group_id = aws_security_group.cluster[0].id protocol = each.value.protocol from_port = each.value.from_port @@ -734,6 +750,8 @@ resource "aws_iam_role_policy_attachment" "custom" { data "aws_eks_addon_version" "this" { for_each = var.addons != null && local.create && !local.create_outposts_local_cluster ? var.addons : {} + region = var.region + addon_name = coalesce(each.value.name, each.key) kubernetes_version = coalesce(var.kubernetes_version, aws_eks_cluster.this[0].version) most_recent = each.value.most_recent @@ -743,6 +761,8 @@ resource "aws_eks_addon" "this" { # Not supported on outposts for_each = var.addons != null && local.create && !local.create_outposts_local_cluster ? { for k, v in var.addons : k => v if !v.before_compute } : {} + region = var.region + cluster_name = aws_eks_cluster.this[0].id addon_name = coalesce(each.value.name, each.key) @@ -786,6 +806,8 @@ resource "aws_eks_addon" "before_compute" { # Not supported on outposts for_each = var.addons != null && local.create && !local.create_outposts_local_cluster ? { for k, v in var.addons : k => v if v.before_compute } : {} + region = var.region + cluster_name = aws_eks_cluster.this[0].id addon_name = coalesce(each.value.name, each.key) @@ -826,6 +848,8 @@ resource "aws_eks_addon" "before_compute" { resource "aws_eks_identity_provider_config" "this" { for_each = var.identity_providers != null && local.create && !local.create_outposts_local_cluster ? var.identity_providers : {} + region = var.region + cluster_name = aws_eks_cluster.this[0].id oidc { diff --git a/modules/eks-managed-node-group/README.md b/modules/eks-managed-node-group/README.md index be15277ee4..dc9d1128da 100644 --- a/modules/eks-managed-node-group/README.md +++ b/modules/eks-managed-node-group/README.md @@ -177,6 +177,7 @@ module "eks_managed_node_group" { | [pre\_bootstrap\_user\_data](#input\_pre\_bootstrap\_user\_data) | User data that is injected into the user data script ahead of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | | [private\_dns\_name\_options](#input\_private\_dns\_name\_options) | The options for the instance hostname. The default values are inherited from the subnet |
object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
})
| `null` | no | | [ram\_disk\_id](#input\_ram\_disk\_id) | The ID of the ram disk | `string` | `null` | no | +| [region](#input\_region) | Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration | `string` | `null` | no | | [remote\_access](#input\_remote\_access) | Configuration block with remote access settings. Only valid when `use_custom_launch_template` = `false` |
object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
})
| `null` | no | | [security\_group\_description](#input\_security\_group\_description) | Description of the security group created | `string` | `null` | no | | [security\_group\_egress\_rules](#input\_security\_group\_egress\_rules) | Security group egress rules to add to the security group created |
map(object({
name = optional(string)

cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
}))
| `{}` | no | diff --git a/modules/eks-managed-node-group/main.tf b/modules/eks-managed-node-group/main.tf index df8bde2fd0..33d64dc578 100644 --- a/modules/eks-managed-node-group/main.tf +++ b/modules/eks-managed-node-group/main.tf @@ -43,6 +43,8 @@ module "user_data" { data "aws_ec2_instance_type" "this" { count = var.create && var.enable_efa_support ? 1 : 0 + region = var.region + instance_type = local.efa_instance_type } @@ -78,6 +80,8 @@ locals { resource "aws_launch_template" "this" { count = var.create && var.create_launch_template && var.use_custom_launch_template ? 1 : 0 + region = var.region + dynamic "block_device_mappings" { for_each = var.block_device_mappings != null ? var.block_device_mappings : {} @@ -364,6 +368,8 @@ resource "aws_launch_template" "this" { data "aws_eks_cluster_versions" "this" { count = var.create && var.kubernetes_version == null ? 1 : 0 + region = var.region + cluster_type = "eks" version_status = "STANDARD_SUPPORT" } @@ -405,6 +411,8 @@ locals { data "aws_ssm_parameter" "ami" { count = var.create && var.use_latest_ami_release_version ? 1 : 0 + region = var.region + name = local.ssm_ami_type_to_ssm_param[var.ami_type] } @@ -421,6 +429,8 @@ locals { resource "aws_eks_node_group" "this" { count = var.create ? 1 : 0 + region = var.region + # Required cluster_name = var.cluster_name node_role_arn = var.create_iam_role ? aws_iam_role.this[0].arn : var.iam_role_arn @@ -658,6 +668,8 @@ locals { resource "aws_placement_group" "this" { count = local.create_placement_group ? 1 : 0 + region = var.region + name = "${var.cluster_name}-${var.name}" strategy = "cluster" @@ -701,12 +713,16 @@ locals { data "aws_subnet" "this" { count = local.create_security_group ? 1 : 0 + region = var.region + id = element(var.subnet_ids, 0) } resource "aws_security_group" "this" { count = local.create_security_group ? 1 : 0 + region = var.region + name = var.security_group_use_name_prefix ? null : local.security_group_name name_prefix = var.security_group_use_name_prefix ? "${local.security_group_name}-" : null description = var.security_group_description @@ -726,6 +742,8 @@ resource "aws_security_group" "this" { resource "aws_vpc_security_group_ingress_rule" "this" { for_each = { for k, v in local.security_group_ingress_rules : k => v if length(local.security_group_ingress_rules) > 0 && local.create_security_group } + region = var.region + cidr_ipv4 = each.value.cidr_ipv4 cidr_ipv6 = each.value.cidr_ipv6 description = each.value.description @@ -746,6 +764,8 @@ resource "aws_vpc_security_group_ingress_rule" "this" { resource "aws_vpc_security_group_egress_rule" "this" { for_each = { for k, v in local.security_group_egress_rules : k => v if length(local.security_group_egress_rules) > 0 && local.create_security_group } + region = var.region + cidr_ipv4 = each.value.cidr_ipv4 cidr_ipv6 = each.value.cidr_ipv6 description = each.value.description diff --git a/modules/eks-managed-node-group/variables.tf b/modules/eks-managed-node-group/variables.tf index e16c98af27..8fb6de34e0 100644 --- a/modules/eks-managed-node-group/variables.tf +++ b/modules/eks-managed-node-group/variables.tf @@ -11,6 +11,12 @@ variable "tags" { default = {} } +variable "region" { + description = "Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration" + type = string + default = null +} + variable "partition" { description = "The AWS partition - pass through value to reduce number of GET requests from data sources" type = string diff --git a/modules/fargate-profile/README.md b/modules/fargate-profile/README.md index c93a3d2da9..bf199e1c41 100644 --- a/modules/fargate-profile/README.md +++ b/modules/fargate-profile/README.md @@ -78,6 +78,7 @@ No modules. | [iam\_role\_use\_name\_prefix](#input\_iam\_role\_use\_name\_prefix) | Determines whether the IAM role name (`iam_role_name`) is used as a prefix | `bool` | `true` | no | | [name](#input\_name) | Name of the EKS Fargate Profile | `string` | `""` | no | | [partition](#input\_partition) | The AWS partition - pass through value to reduce number of GET requests from data sources | `string` | `""` | no | +| [region](#input\_region) | Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration | `string` | `null` | no | | [selectors](#input\_selectors) | Configuration block(s) for selecting Kubernetes Pods to execute with this Fargate Profile |
list(object({
labels = optional(map(string))
namespace = string
}))
| `null` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs for the EKS Fargate Profile | `list(string)` | `[]` | no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | diff --git a/modules/fargate-profile/main.tf b/modules/fargate-profile/main.tf index aa0f348abd..78c94357f4 100644 --- a/modules/fargate-profile/main.tf +++ b/modules/fargate-profile/main.tf @@ -1,5 +1,7 @@ data "aws_region" "current" { count = var.create ? 1 : 0 + + region = var.region } data "aws_partition" "current" { count = var.create && var.partition == "" ? 1 : 0 @@ -159,6 +161,8 @@ resource "aws_iam_role_policy" "this" { resource "aws_eks_fargate_profile" "this" { count = var.create ? 1 : 0 + region = var.region + cluster_name = var.cluster_name fargate_profile_name = var.name pod_execution_role_arn = var.create_iam_role ? aws_iam_role.this[0].arn : var.iam_role_arn diff --git a/modules/fargate-profile/variables.tf b/modules/fargate-profile/variables.tf index 5afa5f1c65..64e210dbe0 100644 --- a/modules/fargate-profile/variables.tf +++ b/modules/fargate-profile/variables.tf @@ -11,6 +11,12 @@ variable "tags" { default = {} } +variable "region" { + description = "Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration" + type = string + default = null +} + variable "partition" { description = "The AWS partition - pass through value to reduce number of GET requests from data sources" type = string diff --git a/modules/karpenter/README.md b/modules/karpenter/README.md index 1095260fa0..cf6102af48 100644 --- a/modules/karpenter/README.md +++ b/modules/karpenter/README.md @@ -168,6 +168,7 @@ No modules. | [queue\_kms\_master\_key\_id](#input\_queue\_kms\_master\_key\_id) | The ID of an AWS-managed customer master key (CMK) for Amazon SQS or a custom CMK | `string` | `null` | no | | [queue\_managed\_sse\_enabled](#input\_queue\_managed\_sse\_enabled) | Boolean to enable server-side encryption (SSE) of message content with SQS-owned encryption keys | `bool` | `true` | no | | [queue\_name](#input\_queue\_name) | Name of the SQS queue | `string` | `null` | no | +| [region](#input\_region) | Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration | `string` | `null` | no | | [rule\_name\_prefix](#input\_rule\_name\_prefix) | Prefix used for all event bridge rules | `string` | `"Karpenter"` | no | | [service\_account](#input\_service\_account) | Service account to associate with the Karpenter Pod Identity | `string` | `"karpenter"` | no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | diff --git a/modules/karpenter/main.tf b/modules/karpenter/main.tf index 11606c97e2..2afe3482ff 100644 --- a/modules/karpenter/main.tf +++ b/modules/karpenter/main.tf @@ -1,5 +1,7 @@ data "aws_region" "current" { count = var.create ? 1 : 0 + + region = var.region } data "aws_partition" "current" { count = var.create ? 1 : 0 @@ -93,6 +95,8 @@ resource "aws_iam_role_policy_attachment" "controller_additional" { resource "aws_eks_pod_identity_association" "karpenter" { count = local.create_iam_role && var.enable_pod_identity && var.create_pod_identity_association ? 1 : 0 + region = var.region + cluster_name = var.cluster_name namespace = var.namespace service_account = var.service_account @@ -114,6 +118,8 @@ locals { resource "aws_sqs_queue" "this" { count = local.enable_spot_termination ? 1 : 0 + region = var.region + name = local.queue_name message_retention_seconds = 300 sqs_managed_sse_enabled = var.queue_managed_sse_enabled ? var.queue_managed_sse_enabled : null @@ -165,6 +171,8 @@ data "aws_iam_policy_document" "queue" { resource "aws_sqs_queue_policy" "this" { count = local.enable_spot_termination ? 1 : 0 + region = var.region + queue_url = aws_sqs_queue.this[0].url policy = data.aws_iam_policy_document.queue[0].json } @@ -213,6 +221,8 @@ locals { resource "aws_cloudwatch_event_rule" "this" { for_each = { for k, v in local.events : k => v if local.enable_spot_termination } + region = var.region + name_prefix = "${var.rule_name_prefix}${each.value.name}-" description = each.value.description event_pattern = jsonencode(each.value.event_pattern) @@ -226,6 +236,8 @@ resource "aws_cloudwatch_event_rule" "this" { resource "aws_cloudwatch_event_target" "this" { for_each = { for k, v in local.events : k => v if local.enable_spot_termination } + region = var.region + rule = aws_cloudwatch_event_rule.this[each.key].name target_id = "KarpenterInterruptionQueueTarget" arn = aws_sqs_queue.this[0].arn @@ -309,6 +321,8 @@ resource "aws_iam_role_policy_attachment" "node_additional" { resource "aws_eks_access_entry" "node" { count = var.create && var.create_access_entry ? 1 : 0 + region = var.region + cluster_name = var.cluster_name principal_arn = var.create_node_iam_role ? aws_iam_role.node[0].arn : var.node_iam_role_arn type = var.access_entry_type diff --git a/modules/karpenter/variables.tf b/modules/karpenter/variables.tf index 4cac5a2ce1..64a74bee7b 100644 --- a/modules/karpenter/variables.tf +++ b/modules/karpenter/variables.tf @@ -16,6 +16,12 @@ variable "cluster_name" { default = "" } +variable "region" { + description = "Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration" + type = string + default = null +} + ################################################################################ # Karpenter controller IAM Role ################################################################################ diff --git a/modules/self-managed-node-group/README.md b/modules/self-managed-node-group/README.md index 11d35bcc0d..2b6e20b3a5 100644 --- a/modules/self-managed-node-group/README.md +++ b/modules/self-managed-node-group/README.md @@ -175,6 +175,7 @@ module "self_managed_node_group" { | [private\_dns\_name\_options](#input\_private\_dns\_name\_options) | The options for the instance hostname. The default values are inherited from the subnet |
object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
})
| `null` | no | | [protect\_from\_scale\_in](#input\_protect\_from\_scale\_in) | Allows setting instance protection. The autoscaling group will not select instances with this setting for termination during scale in events | `bool` | `false` | no | | [ram\_disk\_id](#input\_ram\_disk\_id) | The ID of the ram disk | `string` | `null` | no | +| [region](#input\_region) | Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration | `string` | `null` | no | | [security\_group\_description](#input\_security\_group\_description) | Description of the security group created | `string` | `null` | no | | [security\_group\_egress\_rules](#input\_security\_group\_egress\_rules) | Security group egress rules to add to the security group created |
map(object({
name = optional(string)

cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
}))
| `{}` | no | | [security\_group\_ingress\_rules](#input\_security\_group\_ingress\_rules) | Security group ingress rules to add to the security group created |
map(object({
name = optional(string)

cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
}))
| `{}` | no | diff --git a/modules/self-managed-node-group/main.tf b/modules/self-managed-node-group/main.tf index 36cf4f40b0..c3467407a7 100644 --- a/modules/self-managed-node-group/main.tf +++ b/modules/self-managed-node-group/main.tf @@ -44,6 +44,8 @@ locals { data "aws_ssm_parameter" "ami" { count = var.create ? 1 : 0 + region = var.region + name = local.ami_type_to_ssm_param[var.ami_type] } @@ -82,6 +84,8 @@ module "user_data" { data "aws_ec2_instance_type" "this" { count = var.create && var.enable_efa_support ? 1 : 0 + region = var.region + instance_type = var.instance_type } @@ -117,6 +121,8 @@ locals { resource "aws_launch_template" "this" { count = var.create && var.create_launch_template ? 1 : 0 + region = var.region + dynamic "block_device_mappings" { for_each = var.block_device_mappings != null ? var.block_device_mappings : {} @@ -483,6 +489,8 @@ locals { resource "aws_autoscaling_group" "this" { count = var.create && var.create_autoscaling_group ? 1 : 0 + region = var.region + availability_zones = var.availability_zones capacity_rebalance = var.capacity_rebalance context = var.context @@ -932,6 +940,8 @@ locals { resource "aws_placement_group" "this" { count = local.create_placement_group ? 1 : 0 + region = var.region + name = "${var.cluster_name}-${var.name}" strategy = "cluster" @@ -945,6 +955,8 @@ resource "aws_placement_group" "this" { resource "aws_eks_access_entry" "this" { count = var.create && var.create_access_entry ? 1 : 0 + region = var.region + cluster_name = var.cluster_name principal_arn = var.create_iam_instance_profile ? aws_iam_role.this[0].arn : var.iam_role_arn type = startswith(var.ami_type, "WINDOWS_") ? "EC2_WINDOWS" : "EC2_LINUX" @@ -989,12 +1001,16 @@ locals { data "aws_subnet" "this" { count = local.create_security_group ? 1 : 0 + region = var.region + id = element(var.subnet_ids, 0) } resource "aws_security_group" "this" { count = local.create_security_group ? 1 : 0 + region = var.region + name = var.security_group_use_name_prefix ? null : local.security_group_name name_prefix = var.security_group_use_name_prefix ? "${local.security_group_name}-" : null description = var.security_group_description @@ -1014,6 +1030,8 @@ resource "aws_security_group" "this" { resource "aws_vpc_security_group_ingress_rule" "this" { for_each = { for k, v in local.security_group_ingress_rules : k => v if length(local.security_group_ingress_rules) > 0 && local.create_security_group } + region = var.region + cidr_ipv4 = each.value.cidr_ipv4 cidr_ipv6 = each.value.cidr_ipv6 description = each.value.description @@ -1034,6 +1052,8 @@ resource "aws_vpc_security_group_ingress_rule" "this" { resource "aws_vpc_security_group_egress_rule" "this" { for_each = { for k, v in local.security_group_egress_rules : k => v if length(local.security_group_egress_rules) > 0 && local.create_security_group } + region = var.region + cidr_ipv4 = each.value.cidr_ipv4 cidr_ipv6 = each.value.cidr_ipv6 description = each.value.description diff --git a/modules/self-managed-node-group/variables.tf b/modules/self-managed-node-group/variables.tf index ed72c65344..149eed3d2f 100644 --- a/modules/self-managed-node-group/variables.tf +++ b/modules/self-managed-node-group/variables.tf @@ -11,6 +11,12 @@ variable "tags" { default = {} } +variable "region" { + description = "Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration" + type = string + default = null +} + variable "partition" { description = "The AWS partition - pass through value to reduce number of GET requests from data sources" type = string diff --git a/node_groups.tf b/node_groups.tf index be8c2ba178..13fd2a4df7 100644 --- a/node_groups.tf +++ b/node_groups.tf @@ -168,6 +168,8 @@ locals { resource "aws_security_group" "node" { count = local.create_node_sg ? 1 : 0 + region = var.region + name = var.node_security_group_use_name_prefix ? null : local.node_sg_name name_prefix = var.node_security_group_use_name_prefix ? "${local.node_sg_name}${var.prefix_separator}" : null description = var.node_security_group_description @@ -194,6 +196,8 @@ resource "aws_security_group_rule" "node" { var.node_security_group_additional_rules, ) : k => v if local.create_node_sg } + region = var.region + security_group_id = aws_security_group.node[0].id protocol = each.value.protocol from_port = each.value.from_port @@ -218,6 +222,8 @@ module "fargate_profile" { create = each.value.create + region = var.region + # Pass through values to reduce GET requests from data sources partition = local.partition account_id = local.account_id @@ -261,6 +267,8 @@ module "eks_managed_node_group" { create = each.value.create + region = var.region + # Pass through values to reduce GET requests from data sources partition = local.partition account_id = local.account_id @@ -386,6 +394,8 @@ module "self_managed_node_group" { create = each.value.create + region = var.region + # Pass through values to reduce GET requests from data sources partition = local.partition account_id = local.account_id diff --git a/variables.tf b/variables.tf index 837dc6e23b..036cf34f95 100644 --- a/variables.tf +++ b/variables.tf @@ -4,18 +4,24 @@ variable "create" { default = true } -variable "tags" { - description = "A map of tags to add to all resources" - type = map(string) - default = {} -} - variable "prefix_separator" { description = "The separator to use between the prefix and the generated timestamp for resource names" type = string default = "-" } +variable "region" { + description = "Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration" + type = string + default = null +} + +variable "tags" { + description = "A map of tags to add to all resources" + type = map(string) + default = {} +} + ################################################################################ # Cluster ################################################################################ @@ -27,7 +33,7 @@ variable "name" { } variable "kubernetes_version" { - description = "Kubernetes `.` version to use for the EKS cluster (i.e.: `1.27`)" + description = "Kubernetes `.` version to use for the EKS cluster (i.e.: `1.33`)" type = string default = null } From 576c2cfee7c0edffd4f3c21892ebe4257e51bdb2 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Tue, 15 Jul 2025 12:38:08 -0500 Subject: [PATCH 19/25] feat: Initial pass on upgrade guide --- README.md | 4 - docs/UPGRADE-21.0.md | 264 +++++++++++++++++++++++++++++++++++++- docs/compute_resources.md | 38 ------ docs/faq.md | 24 ++-- 4 files changed, 274 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index ab80755086..0e95a37438 100644 --- a/README.md +++ b/README.md @@ -84,10 +84,6 @@ module "eks" { control_plane_subnet_ids = ["subnet-xyzde987", "subnet-slkjf456", "subnet-qeiru789"] # EKS Managed Node Group(s) - eks_managed_node_group_defaults = { - instance_types = ["m6i.large", "m5.large", "m5n.large", "m5zn.large"] - } - eks_managed_node_groups = { example = { # Starting on 1.30, AL2023 is the default AMI type for EKS managed node groups diff --git a/docs/UPGRADE-21.0.md b/docs/UPGRADE-21.0.md index 2fa1e096c9..1a2d5c741c 100644 --- a/docs/UPGRADE-21.0.md +++ b/docs/UPGRADE-21.0.md @@ -7,42 +7,196 @@ If you find a bug, please open an issue with supporting configuration to reprodu - Terraform `v1.5.7` is now minimum supported version - AWS provider `v6.0.0` is now minimum supported version +- TLS provider `v4.0.0` is now minimum supported version +- The `aws-auth` sub-module has been removed. Users who wish to utilize its functionality can continue to do so by specifying a `v20.x` version, or `~> v20.0` version constraint in their module source. +- `bootstrap_self_managed_addons` is now hardcoded to `false`. This is a legacy setting and instead users should utilize the EKS addons API, which is what this module does by default. In conjunction with this change, the `bootstrap_self_managed_addons` is now ignored by the module to aid in upgrading without disruption (otherwise it would require cluster re-creation). +- When enabling `enable_efa_support` or creating placement groups within a node group, users must now specify the correct `subnet_ids`; the module no longer tries to automatically select a suitable subnet. +- EKS managed node group: + - IMDS now default to a hop limit of 1 (previously was 2) + - `ami_type` now defaults to `AL2023_x86_64_STANDARD` + - `enable_monitoring` is now set to `false` by default + - `enable_efa_only` is now set to `true` by default + - `use_latest_ami_release_version` is now set to `true` by default + - Support for autoscaling group schedules has been removed +- Self-managed node group: + - IMDS now default to a hop limit of 1 (previously was 2) + - `ami_type` now defaults to `AL2023_x86_64_STANDARD` + - `enable_monitoring` is now set to `false` by default + - `enable_efa_only` is now set to `true` by default + - Support for autoscaling group schedules has been removed +- Karpenter: + - Native support for IAM roles for service accounts (IRSA) has been removed; EKS Pod Identity is now enabled by default + - Karpenter controller policy for prior to Karpenter `v1` have been removed (i.e. `v0.33`); the `v1` policy is now used by default + - `create_pod_identity_association` is now set to `true` by default +- `addons.resolve_conflicts_on_create` is now set to `"NONE"` by default (was `"OVERWRITE"`). +- `addons.most_recent` is now set to `true` by default (was `false`). +- `cluster_identity_providers.issuer_url` is now required to be set by users; the prior incorrect default has been removed. See https://github.com/terraform-aws-modules/terraform-aws-eks/pull/3055 and https://github.com/kubernetes/kubernetes/pull/123561 for more details. ## Additional changes ### Added - Support for `region` parameter to specify the AWS region for the resources created if different from the provider region. +- Both the EKS managed and self-managed node groups now support creating their own security groups (again). This is primarily motivated by the changes for EFA support; previously users would need to specify `enable_efa_support` both at the cluster level (to add the appropriate security group rules to the shared node security group) as well as the node group level. However, its not always desirable to have these rules across ALL node groups when they are really only required on the node group where EFA is utilized. And similarly for other use cases, users can create custom rules for a specific node group instead of apply across ALL node groups. ### Modified - Variable definitions now contain detailed `object` types in place of the previously used any type. +- The embedded KMS key module definition has been updated to `v4.0` to support the same version requirements as well as the new `region` argument. ### Variable and output changes 1. Removed variables: - - + - `enable_efa_support` - users only need to set this within the node group configuration, as the module no longer manages EFA support at the cluster level. + - `enable_security_groups_for_pods` - users can instead attach the `arn:aws:iam::aws:policy/AmazonEKSVPCResourceController` policy via `iam_role_additional_policies` if using security groups for pods. + - `eks-managed-node-group` sub-module + - `cluster_service_ipv4_cidr` - users should use `cluster_service_cidr` instead (for either IPv4 or IPv6). + - `elastic_gpu_specifications` + - `elastic_inference_accelerator` + - `platform` - this is superseded by `ami_type` + - `placement_group_strategy` - set to `cluster` by the module + - `placement_group_az` - users will need to specify the correct subnet in `subnet_ids` + - `create_schedule` + - `schedules` + - `self-managed-node-group` sub-module + - `elastic_gpu_specifications` + - `elastic_inference_accelerator` + - `platform` - this is superseded by `ami_type` + - `create_schedule` + - `schedules` + - `placement_group_az` - users will need to specify the correct subnet in `subnet_ids` + - `hibernation_options` - not valid in EKS + - `min_elb_capacity` - not valid in EKS + - `wait_for_elb_capacity` - not valid in EKS + - `wait_for_capacity_timeout` - not valid in EKS + - `default_cooldown` - not valid in EKS + - `target_group_arns` - not valid in EKS + - `service_linked_role_arn` - not valid in EKS + - `warm_pool` - not valid in EKS + - `fargate-profile` sub-module + - None + - `karpenter` sub-module + - `enable_v1_permissions` - v1 permissions are now the default + - `enable_irsa` + - `irsa_oidc_provider_arn` + - `irsa_namespace_service_accounts` + - `irsa_assume_role_condition_test` 2. Renamed variables: - - + - Variables prefixed with `cluster_*` have been stripped of the prefix to better match the underlying API: + - `cluster_name` -> `name` + - `cluster_version` -> `kubernetes_version` + - `cluster_enabled_log_types` -> `enabled_log_types` + - `cluster_force_update_version` -> `force_update_version` + - `cluster_compute_config` -> `compute_config` + - `cluster_upgrade_policy` -> `upgrade_policy` + - `cluster_remote_network_config` -> `remote_network_config` + - `cluster_zonal_shift_config` -> `zonal_shift_config` + - `cluster_additional_security_group_ids` -> `additional_security_group_ids` + - `cluster_endpoint_private_access` -> `endpoint_private_access` + - `cluster_endpoint_public_access` -> `endpoint_public_access` + - `cluster_endpoint_public_access_cidrs` -> `endpoint_public_access_cidrs` + - `cluster_ip_family` -> `ip_family` + - `cluster_service_ipv4_cidr` -> `service_ipv4_cidr` + - `cluster_service_ipv6_cidr` -> `service_ipv6_cidr` + - `cluster_encryption_config` -> `encryption_config` + - `create_cluster_primary_security_group_tags` -> `create_primary_security_group_tags` + - `cluster_timeouts` -> `timeouts` + - `create_cluster_security_group` -> `create_security_group` + - `cluster_security_group_id` -> `security_group_id` + - `cluster_security_group_name` -> `security_group_name` + - `cluster_security_group_use_name_prefix` -> `security_group_use_name_prefix` + - `cluster_security_group_description` -> `security_group_description` + - `cluster_security_group_additional_rules` -> `security_group_additional_rules` + - `cluster_security_group_tags` -> `security_group_tags` + - `cluster_encryption_policy_use_name_prefix` -> `encryption_policy_use_name_prefix` + - `cluster_encryption_policy_name` -> `encryption_policy_name` + - `cluster_encryption_policy_description` -> `encryption_policy_description` + - `cluster_encryption_policy_path` -> `encryption_policy_path` + - `cluster_encryption_policy_tags` -> `encryption_policy_tags` + - `cluster_addons` -> `addons` + - `cluster_addons_timeouts` -> `addons_timeouts` + - `cluster_identity_providers` -> `identity_providers` + - `eks-managed-node-group` sub-module + - `cluster_version` -> `kubernetes_version` + - `self-managed-node-group` sub-module + - `cluster_version` -> `kubernetes_version` + - `delete_timeout` -> `timeouts` + - `fargate-profile` sub-module + - None + - `karpenter` sub-module + - None 3. Added variables: - - + - `region` + - `eks-managed-node-group` sub-module + - `region` + - `partition` - added to reduce number of `GET` requests from data sources when possible + - `account_id` - added to reduce number of `GET` requests from data sources when possible + - `create_security_group` + - `security_group_name` + - `security_group_use_name_prefix` + - `security_group_description` + - `security_group_ingress_rules` + - `security_group_egress_rules` + - `security_group_tags` + - `self-managed-node-group` sub-module + - `region` + - `partition` - added to reduce number of `GET` requests from data sources when possible + - `account_id` - added to reduce number of `GET` requests from data sources when possible + - `create_security_group` + - `security_group_name` + - `security_group_use_name_prefix` + - `security_group_description` + - `security_group_ingress_rules` + - `security_group_egress_rules` + - `security_group_tags` + - `fargate-profile` sub-module + - `region` + - `partition` - added to reduce number of `GET` requests from data sources when possible + - `account_id` - added to reduce number of `GET` requests from data sources when possible + - `karpenter` sub-module + - `region` 4. Removed outputs: - - + - `eks-managed-node-group` sub-module + - `platform` - this is superseded by `ami_type` + - `autoscaling_group_schedule_arns` + - `self-managed-node-group` sub-module + - `platform` - this is superseded by `ami_type` + - `autoscaling_group_schedule_arns` + - `fargate-profile` sub-module + - None + - `karpenter` sub-module + - None 5. Renamed outputs: - - + - `eks-managed-node-group` sub-module + - None + - `self-managed-node-group` sub-module + - None + - `fargate-profile` sub-module + - None + - `karpenter` sub-module + - None 6. Added outputs: - - + - `eks-managed-node-group` sub-module + - `security_group_arn` + - `security_group_id` + - `self-managed-node-group` sub-module + - `security_group_arn` + - `security_group_id` + - `fargate-profile` sub-module + - None + - `karpenter` sub-module + - None ## Upgrade Migrations @@ -54,7 +208,56 @@ module "eks" { version = "~> 20.0" # Truncated for brevity ... + # Not all renamed variables are shown here, please refer to the full list above. + enable_efa_support = true + + eks_managed_node_group_defaults = { + iam_role_additional_policies = { + AmazonSSMManagedInstanceCore = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" + } + } + + eks_managed_node_groups = { + efa = { + ami_type = "AL2023_x86_64_NVIDIA" + instance_types = ["p5e.48xlarge"] + + enable_efa_support = true + enable_efa_only = true + } + } + + self_managed_node_groups = { + example = { + use_mixed_instances_policy = true + mixed_instances_policy = { + instances_distribution = { + on_demand_base_capacity = 0 + on_demand_percentage_above_base_capacity = 0 + on_demand_allocation_strategy = "lowest-price" + spot_allocation_strategy = "price-capacity-optimized" + } + + # ASG configuration + override = [ + { + instance_requirements = { + cpu_manufacturers = ["intel"] + instance_generations = ["current", "previous"] + spot_max_price_percentage_over_lowest_price = 100 + + vcpu_count = { + min = 1 + } + + allowed_instance_types = ["t*", "m*"] + } + } + ] + } + } + } } ``` @@ -66,7 +269,56 @@ module "eks" { version = "~> 21.0" # Truncated for brevity ... + # Not all renamed variables are shown here, please refer to the full list above. + + eks_managed_node_groups = { + efa = { + ami_type = "AL2023_x86_64_NVIDIA" + instance_types = ["p5e.48xlarge"] + + iam_role_additional_policies = { + AmazonSSMManagedInstanceCore = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" + } + + enable_efa_support = true + + subnet_ids = element(module.vpc.private_subnets, 0) + } + } + + self_managed_node_groups = { + example = { + use_mixed_instances_policy = true + mixed_instances_policy = { + instances_distribution = { + on_demand_base_capacity = 0 + on_demand_percentage_above_base_capacity = 0 + on_demand_allocation_strategy = "lowest-price" + spot_allocation_strategy = "price-capacity-optimized" + } + + # ASG configuration + # Need to wrap in `launch_template` now + launch_template = { + override = [ + { + instance_requirements = { + cpu_manufacturers = ["intel"] + instance_generations = ["current", "previous"] + spot_max_price_percentage_over_lowest_price = 100 + + vcpu_count = { + min = 1 + } + allowed_instance_types = ["t*", "m*"] + } + } + ] + } + } + } + } } ``` diff --git a/docs/compute_resources.md b/docs/compute_resources.md index 7838ce616b..8685e10073 100644 --- a/docs/compute_resources.md +++ b/docs/compute_resources.md @@ -153,41 +153,3 @@ See the [`examples/self-managed-node-group/` example](https://github.com/terrafo ### Fargate Profiles Fargate profiles are straightforward to use and therefore no further details are provided here. See the [`tests/fargate-profile/` tests](https://github.com/terraform-aws-modules/terraform-aws-eks/tree/master/tests/fargate-profile) for a working example of various configurations. - -### Default Configurations - -Each type of compute resource (EKS managed node group, self managed node group, or Fargate profile) provides the option for users to specify a default configuration. These default configurations can be overridden from within the compute resource's individual definition. The order of precedence for configurations (from highest to least precedence): - -- Compute resource individual configuration - - Compute resource family default configuration (`eks_managed_node_group_defaults`, `self_managed_node_group_defaults`, `fargate_profile_defaults`) - - Module default configuration (see `variables.tf` and `node_groups.tf`) - -For example, the following creates 4 AWS EKS Managed Node Groups: - -```hcl - eks_managed_node_group_defaults = { - ami_type = "AL2023_x86_64_STANDARD" - disk_size = 50 - instance_types = ["m6i.large", "m5.large", "m5n.large", "m5zn.large"] - } - - eks_managed_node_groups = { - # Uses module default configurations overridden by configuration above - default = {} - - # This further overrides the instance types used - compute = { - instance_types = ["c5.large", "c6i.large", "c6d.large"] - } - - # This further overrides the instance types - persistent = { - instance_types = ["r5.xlarge", "r6i.xlarge", "r5b.xlarge"] - } - - # This overrides the OS used - bottlerocket = { - ami_type = "BOTTLEROCKET_x86_64" - } - } -``` diff --git a/docs/faq.md b/docs/faq.md index 27b873e72a..69d8c90e7f 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -23,24 +23,32 @@ By default, EKS creates a cluster primary security group that is created outside ```hcl create_node_security_group = false # default is true - eks_managed_node_group_defaults = { - attach_cluster_primary_security_group = true # default is false + eks_managed_node_group = { + example = { + attach_cluster_primary_security_group = true # default is false + } } # Or for self-managed - self_managed_node_group_defaults = { - attach_cluster_primary_security_group = true # default is false + self_managed_node_group = { + example = { + attach_cluster_primary_security_group = true # default is false + } } ``` 2. By not attaching the cluster primary security group. The cluster primary security group has quite broad access and the module has instead provided a security group with the minimum amount of access to launch an empty EKS cluster successfully and users are encouraged to open up access when necessary to support their workload. ```hcl - eks_managed_node_group_defaults = { - attach_cluster_primary_security_group = true # default is false + eks_managed_node_group = { + example = { + attach_cluster_primary_security_group = true # default is false + } } # Or for self-managed - self_managed_node_group_defaults = { - attach_cluster_primary_security_group = true # default is false + self_managed_node_group = { + example = { + attach_cluster_primary_security_group = true # default is false + } } ``` From e4c63d24d32829f721207f7ec387d8b09806e349 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Thu, 17 Jul 2025 16:22:30 -0500 Subject: [PATCH 20/25] fix: Updates from testing and validating EKS managed node group --- README.md | 6 +++--- docs/compute_resources.md | 2 -- examples/eks-managed-node-group/eks-al2023.tf | 2 -- examples/self-managed-node-group/eks-al2023.tf | 2 -- main.tf | 6 +++--- modules/eks-managed-node-group/README.md | 4 ++-- modules/eks-managed-node-group/main.tf | 18 +++++++++--------- modules/eks-managed-node-group/variables.tf | 4 ++-- modules/self-managed-node-group/README.md | 4 ++-- modules/self-managed-node-group/main.tf | 2 +- modules/self-managed-node-group/variables.tf | 4 ++-- node_groups.tf | 8 ++++---- tests/eks-managed-node-group/main.tf | 9 ++------- tests/self-managed-node-group/main.tf | 2 -- variables.tf | 14 +++++++------- 15 files changed, 37 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 0e95a37438..6770c7a234 100644 --- a/README.md +++ b/README.md @@ -377,7 +377,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [access\_entries](#input\_access\_entries) | Map of access entries to add to the cluster |
map(object({
# Access entry
kubernetes_groups = optional(list(string))
principal_arn = string
type = optional(string, "STANDARD")
user_name = optional(string)
tags = optional(map(string), {})
# Access policy association
policy_associations = optional(map(object({
policy_arn = string
access_scope = object({
type = string
})
namespaces = optional(list(string))
})), {})
}))
| `{}` | no | +| [access\_entries](#input\_access\_entries) | Map of access entries to add to the cluster |
map(object({
# Access entry
kubernetes_groups = optional(list(string))
principal_arn = string
type = optional(string, "STANDARD")
user_name = optional(string)
tags = optional(map(string), {})
# Access policy association
policy_associations = optional(map(object({
policy_arn = string
access_scope = object({
namespaces = optional(list(string))
type = string
})
})))
}))
| `{}` | no | | [additional\_security\_group\_ids](#input\_additional\_security\_group\_ids) | List of additional, externally created security group IDs to attach to the cluster control plane | `list(string)` | `[]` | no | | [addons](#input\_addons) | Map of cluster addon configurations to enable for the cluster. Addon name can be the map keys or set with `name` |
map(object({
name = optional(string) # will fall back to map key
before_compute = optional(bool, false)
most_recent = optional(bool, true)
addon_version = optional(string)
configuration_values = optional(string)
pod_identity_association = optional(list(object({
role_arn = string
service_account = string
})))
preserve = optional(bool, true)
resolve_conflicts_on_create = optional(string, "NONE")
resolve_conflicts_on_update = optional(string, "OVERWRITE")
service_account_role_arn = optional(string)
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
tags = optional(map(string), {})
}))
| `null` | no | | [addons\_timeouts](#input\_addons\_timeouts) | Create, update, and delete timeout configurations for the cluster addons |
object({
create = optional(string)
update = optional(string)
delete = optional(string)
})
| `null` | no | @@ -401,7 +401,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [create\_security\_group](#input\_create\_security\_group) | Determines if a security group is created for the cluster. Note: the EKS service creates a primary security group for the cluster by default | `bool` | `true` | no | | [custom\_oidc\_thumbprints](#input\_custom\_oidc\_thumbprints) | Additional list of server certificate thumbprints for the OpenID Connect (OIDC) identity provider's server certificate(s) | `list(string)` | `[]` | no | | [dataplane\_wait\_duration](#input\_dataplane\_wait\_duration) | Duration to wait after the EKS cluster has become active before creating the dataplane components (EKS managed node group(s), self-managed node group(s), Fargate profile(s)) | `string` | `"30s"` | no | -| [eks\_managed\_node\_groups](#input\_eks\_managed\_node\_groups) | Map of EKS managed node group definitions to create |
map(object({
create = optional(bool, true)
kubernetes_version = optional(string)

# EKS Managed Node Group
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
ami_id = optional(string, "")
ami_type = optional(string, "AL2023_x86_64_STANDARD")
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool, true)
capacity_type = optional(string, "ON_DEMAND")
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool, true)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}), {
max_unavailable_percentage = 33
})
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool, false)
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
create_placement_group = optional(bool, false)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool, true)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "EKS managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string), [])
attach_cluster_primary_security_group = optional(bool, false)
cluster_primary_security_group_id = optional(string)
create_security_group = optional(bool, true)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool, true)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_tags = optional(map(string), {})

tags = optional(map(string), {})
}))
| `{}` | no | +| [eks\_managed\_node\_groups](#input\_eks\_managed\_node\_groups) | Map of EKS managed node group definitions to create |
map(object({
create = optional(bool, true)
kubernetes_version = optional(string)

# EKS Managed Node Group
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
subnet_ids = optional(list(string))
min_size = optional(number, 1)
max_size = optional(number, 3)
desired_size = optional(number, 1)
ami_id = optional(string, "")
ami_type = optional(string, "AL2023_x86_64_STANDARD")
ami_release_version = optional(string)
use_latest_ami_release_version = optional(bool, true)
capacity_type = optional(string, "ON_DEMAND")
disk_size = optional(number)
force_update_version = optional(bool)
instance_types = optional(list(string))
labels = optional(map(string))
node_repair_config = optional(object({
enabled = optional(bool, true)
}))
remote_access = optional(object({
ec2_ssh_key = optional(string)
source_security_group_ids = optional(list(string))
}))
taints = optional(map(object({
key = string
value = optional(string)
effect = string
})))
update_config = optional(object({
max_unavailable = optional(number)
max_unavailable_percentage = optional(number)
}), {
max_unavailable_percentage = 33
})
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
# User data
enable_bootstrap_user_data = optional(bool, false)
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
key_name = optional(string)
disable_api_termination = optional(bool)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
create_placement_group = optional(bool, false)
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
creat_iam_role = optional(bool, true)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "EKS managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Security group
vpc_security_group_ids = optional(list(string), [])
attach_cluster_primary_security_group = optional(bool, false)
cluster_primary_security_group_id = optional(string)
create_security_group = optional(bool, true)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool, true)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_tags = optional(map(string), {})

tags = optional(map(string), {})
}))
| `{}` | no | | [enable\_auto\_mode\_custom\_tags](#input\_enable\_auto\_mode\_custom\_tags) | Determines whether to enable permissions for custom tags resources created by EKS Auto Mode | `bool` | `true` | no | | [enable\_cluster\_creator\_admin\_permissions](#input\_enable\_cluster\_creator\_admin\_permissions) | Indicates whether or not to add the cluster creator (the identity used by Terraform) as an administrator via access entry | `bool` | `false` | no | | [enable\_irsa](#input\_enable\_irsa) | Determines whether to create an OpenID Connect Provider for EKS to enable IRSA | `bool` | `true` | no | @@ -467,7 +467,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [security\_group\_name](#input\_security\_group\_name) | Name to use on cluster security group created | `string` | `null` | no | | [security\_group\_tags](#input\_security\_group\_tags) | A map of additional tags to add to the cluster security group created | `map(string)` | `{}` | no | | [security\_group\_use\_name\_prefix](#input\_security\_group\_use\_name\_prefix) | Determines whether cluster security group name (`cluster_security_group_name`) is used as a prefix | `bool` | `true` | no | -| [self\_managed\_node\_groups](#input\_self\_managed\_node\_groups) | Map of self-managed node group definitions to create |
map(object({
create = optional(bool, true)
# Autoscaling Group
create_autoscaling_group = optional(bool, true)
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number, 0)
max_size = optional(number, 3)
desired_size = optional(number, 1)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool, false)
context = optional(string)
create_placement_group = optional(bool, false)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(bool)
force_delete = optional(bool)
termination_policies = optional(list(string), [])
suspended_processes = optional(list(string), [])
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string), [])
metrics_granularity = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number, 66)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string, "Rolling")
triggers = optional(list(string))
}), {
strategy = "Rolling"
preferences = {
min_healthy_percentage = 66
}
})
use_mixed_instances_policy = optional(bool, false)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string), {})
# User data
ami_type = optional(string, "AL2023_x86_64_STANDARD")
additional_cluster_dns_ips = optional(list(string), [])
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string, "m6i.large")
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}), {})
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool, true)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Self managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool, true)
iam_role_arn = optional(string)
# Security group
attach_cluster_primary_security_group = optional(bool, false)
create_security_group = optional(bool, true)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool, true)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_tags = optional(map(string), {})

tags = optional(map(string), {})
}))
| `{}` | no | +| [self\_managed\_node\_groups](#input\_self\_managed\_node\_groups) | Map of self-managed node group definitions to create |
map(object({
create = optional(bool, true)
# Autoscaling Group
create_autoscaling_group = optional(bool, true)
name = optional(string) # Will fall back to map key
use_name_prefix = optional(bool, true)
availability_zones = optional(list(string))
subnet_ids = optional(list(string))
min_size = optional(number, 1)
max_size = optional(number, 3)
desired_size = optional(number, 1)
desired_size_type = optional(string)
capacity_rebalance = optional(bool)
default_instance_warmup = optional(number)
protect_from_scale_in = optional(bool, false)
context = optional(string)
create_placement_group = optional(bool, false)
placement_group = optional(string)
health_check_type = optional(string)
health_check_grace_period = optional(number)
ignore_failed_scaling_activities = optional(bool)
force_delete = optional(bool)
termination_policies = optional(list(string), [])
suspended_processes = optional(list(string), [])
max_instance_lifetime = optional(number)
enabled_metrics = optional(list(string), [])
metrics_granularity = optional(string)
initial_lifecycle_hooks = optional(list(object({
default_result = optional(string)
heartbeat_timeout = optional(number)
lifecycle_transition = string
name = string
notification_metadata = optional(string)
notification_target_arn = optional(string)
role_arn = optional(string)
})))
instance_maintenance_policy = optional(object({
max_healthy_percentage = number
min_healthy_percentage = number
}))
instance_refresh = optional(object({
preferences = optional(object({
alarm_specification = optional(object({
alarms = optional(list(string))
}))
auto_rollback = optional(bool)
checkpoint_delay = optional(number)
checkpoint_percentages = optional(list(number))
instance_warmup = optional(number)
max_healthy_percentage = optional(number)
min_healthy_percentage = optional(number, 66)
scale_in_protected_instances = optional(string)
skip_matching = optional(bool)
standby_instances = optional(string)
}))
strategy = optional(string, "Rolling")
triggers = optional(list(string))
}), {
strategy = "Rolling"
preferences = {
min_healthy_percentage = 66
}
})
use_mixed_instances_policy = optional(bool, false)
mixed_instances_policy = optional(object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
}))
timeouts = optional(object({
delete = optional(string)
}))
autoscaling_group_tags = optional(map(string), {})
# User data
ami_type = optional(string, "AL2023_x86_64_STANDARD")
additional_cluster_dns_ips = optional(list(string), [])
pre_bootstrap_user_data = optional(string, "")
post_bootstrap_user_data = optional(string, "")
bootstrap_extra_args = optional(string, "")
user_data_template_path = optional(string, "")
cloudinit_pre_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
cloudinit_post_nodeadm = optional(list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
})), [])
# Launch Template
create_launch_template = optional(bool, true)
use_custom_launch_template = optional(bool, true)
launch_template_id = optional(string, "")
launch_template_name = optional(string) # Will fall back to map key
launch_template_use_name_prefix = optional(bool, true)
launch_template_version = optional(string)
update_launch_template_default_version = optional(bool, true)
launch_template_description = optional(string)
launch_template_tags = optional(map(string), {})
tag_specifications = optional(list(string), ["instance", "volume", "network-interface"])
ebs_optimized = optional(bool)
ami_id = optional(string)
instance_type = optional(string, "m6i.large")
key_name = optional(string)
disable_api_termination = optional(bool)
instance_initiated_shutdown_behavior = optional(string)
kernel_id = optional(string)
ram_disk_id = optional(string)
block_device_mappings = optional(map(object({
device_name = optional(string)
ebs = optional(object({
delete_on_termination = optional(bool)
encrypted = optional(bool)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_initialization_rate = optional(number)
volume_size = optional(number)
volume_type = optional(string)
}))
no_device = optional(string)
virtual_name = optional(string)
})))
capacity_reservation_specification = optional(object({
capacity_reservation_preference = optional(string)
capacity_reservation_target = optional(object({
capacity_reservation_id = optional(string)
capacity_reservation_resource_group_arn = optional(string)
}))
}))
cpu_options = optional(object({
amd_sev_snp = optional(string)
core_count = optional(number)
threads_per_core = optional(number)
}))
credit_specification = optional(object({
cpu_credits = optional(string)
}))
enclave_options = optional(object({
enabled = optional(bool)
}))
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = string
}))
}))
instance_market_options = optional(object({
market_type = optional(string)
spot_options = optional(object({
block_duration_minutes = optional(number)
instance_interruption_behavior = optional(string)
max_price = optional(string)
spot_instance_type = optional(string)
valid_until = optional(string)
}))
}))
license_specifications = optional(list(object({
license_configuration_arn = string
})))
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
}), {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
})
enable_monitoring = optional(bool, false)
enable_efa_support = optional(bool, false)
enable_efa_only = optional(bool, true)
efa_indices = optional(list(string), [0])
network_interfaces = optional(list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
})), [])
placement = optional(object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
}))
maintenance_options = optional(object({
auto_recovery = optional(string)
}))
private_dns_name_options = optional(object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
}))
# IAM role
create_iam_instance_profile = optional(bool, true)
iam_instance_profile_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool, true)
iam_role_path = optional(string)
iam_role_description = optional(string, "Self managed node group IAM role")
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string), {})
iam_role_attach_cni_policy = optional(bool, true)
iam_role_additional_policies = optional(map(string), {})
create_iam_role_policy = optional(bool, true)
iam_role_policy_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Access entry
create_access_entry = optional(bool, true)
iam_role_arn = optional(string)
# Security group
attach_cluster_primary_security_group = optional(bool, false)
create_security_group = optional(bool, true)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool, true)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_egress_rules = optional(map(object({
name = optional(string)
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
self = optional(bool, false)
tags = optional(map(string), {})
to_port = optional(string)
})), {})
security_group_tags = optional(map(string), {})

tags = optional(map(string), {})
}))
| `{}` | no | | [service\_ipv4\_cidr](#input\_service\_ipv4\_cidr) | The CIDR block to assign Kubernetes service IP addresses from. If you don't specify a block, Kubernetes assigns addresses from either the 10.100.0.0/16 or 172.20.0.0/16 CIDR blocks | `string` | `null` | no | | [service\_ipv6\_cidr](#input\_service\_ipv6\_cidr) | The CIDR block to assign Kubernetes pod and service IP addresses from if `ipv6` was specified when the cluster was created. Kubernetes assigns service addresses from the unique local address range (fc00::/7) because you can't specify a custom IPv6 CIDR block when you create the cluster | `string` | `null` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs where the nodes/node groups will be provisioned. If `control_plane_subnet_ids` is not provided, the EKS cluster control plane (ENIs) will be provisioned in these subnets | `list(string)` | `[]` | no | diff --git a/docs/compute_resources.md b/docs/compute_resources.md index 8685e10073..e7dee7660c 100644 --- a/docs/compute_resources.md +++ b/docs/compute_resources.md @@ -73,8 +73,6 @@ Refer to the [EKS Managed Node Group documentation](https://docs.aws.amazon.com/ kubelet: config: shutdownGracePeriod: 30s - featureGates: - DisableKubeletCloudCredentialProviders: true EOT content_type = "application/node.eks.aws" }] diff --git a/examples/eks-managed-node-group/eks-al2023.tf b/examples/eks-managed-node-group/eks-al2023.tf index e1dd71d38c..b58733c163 100644 --- a/examples/eks-managed-node-group/eks-al2023.tf +++ b/examples/eks-managed-node-group/eks-al2023.tf @@ -42,8 +42,6 @@ module "eks_al2023" { kubelet: config: shutdownGracePeriod: 30s - featureGates: - DisableKubeletCloudCredentialProviders: true EOT } ] diff --git a/examples/self-managed-node-group/eks-al2023.tf b/examples/self-managed-node-group/eks-al2023.tf index 29dd80ee86..03452bc1a5 100644 --- a/examples/self-managed-node-group/eks-al2023.tf +++ b/examples/self-managed-node-group/eks-al2023.tf @@ -41,8 +41,6 @@ module "eks_al2023" { kubelet: config: shutdownGracePeriod: 30s - featureGates: - DisableKubeletCloudCredentialProviders: true EOT } ] diff --git a/main.tf b/main.tf index fe018270ed..6358db3917 100644 --- a/main.tf +++ b/main.tf @@ -243,7 +243,7 @@ resource "aws_cloudwatch_log_group" "this" { locals { # This replaces the one time logic from the EKS API with something that can be # better controlled by users through Terraform - bootstrap_cluster_creator_admin_permissions = { + bootstrap_cluster_creator_admin_permissions = { for k, v in { cluster_creator = { principal_arn = try(data.aws_iam_session_context.current[0].issuer_arn, "") type = "STANDARD" @@ -257,11 +257,11 @@ locals { } } } - } + } : k => v if var.enable_cluster_creator_admin_permissions } # Merge the bootstrap behavior with the entries that users provide merged_access_entries = merge( - { for k, v in local.bootstrap_cluster_creator_admin_permissions : k => v if var.enable_cluster_creator_admin_permissions }, + local.bootstrap_cluster_creator_admin_permissions, var.access_entries, ) diff --git a/modules/eks-managed-node-group/README.md b/modules/eks-managed-node-group/README.md index dc9d1128da..b7d3c7e8bf 100644 --- a/modules/eks-managed-node-group/README.md +++ b/modules/eks-managed-node-group/README.md @@ -167,12 +167,12 @@ module "eks_managed_node_group" { | [maintenance\_options](#input\_maintenance\_options) | The maintenance options for the instance |
object({
auto_recovery = optional(string)
})
| `null` | no | | [max\_size](#input\_max\_size) | Maximum number of instances/nodes | `number` | `3` | no | | [metadata\_options](#input\_metadata\_options) | Customize the metadata options for the instance |
object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
})
|
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 1,
"http_tokens": "required"
}
| no | -| [min\_size](#input\_min\_size) | Minimum number of instances/nodes | `number` | `0` | no | +| [min\_size](#input\_min\_size) | Minimum number of instances/nodes | `number` | `1` | no | | [name](#input\_name) | Name of the EKS managed node group | `string` | `""` | no | | [network\_interfaces](#input\_network\_interfaces) | Customize network interfaces to be attached at instance boot time |
list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
}))
| `[]` | no | | [node\_repair\_config](#input\_node\_repair\_config) | The node auto repair configuration for the node group |
object({
enabled = optional(bool, true)
})
| `null` | no | | [partition](#input\_partition) | The AWS partition - pass through value to reduce number of GET requests from data sources | `string` | `""` | no | -| [placement](#input\_placement) | The placement of the instance |
object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
})
| `{}` | no | +| [placement](#input\_placement) | The placement of the instance |
object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
})
| `null` | no | | [post\_bootstrap\_user\_data](#input\_post\_bootstrap\_user\_data) | User data that is appended to the user data script after of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | | [pre\_bootstrap\_user\_data](#input\_pre\_bootstrap\_user\_data) | User data that is injected into the user data script ahead of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | | [private\_dns\_name\_options](#input\_private\_dns\_name\_options) | The options for the instance hostname. The default values are inherited from the subnet |
object({
enable_resource_name_dns_aaaa_record = optional(bool)
enable_resource_name_dns_a_record = optional(bool)
hostname_type = optional(string)
})
| `null` | no | diff --git a/modules/eks-managed-node-group/main.tf b/modules/eks-managed-node-group/main.tf index 33d64dc578..d07c38633d 100644 --- a/modules/eks-managed-node-group/main.tf +++ b/modules/eks-managed-node-group/main.tf @@ -305,17 +305,17 @@ resource "aws_launch_template" "this" { } dynamic "placement" { - for_each = length(var.placement) > 0 || local.create_placement_group ? [var.placement] : [] + for_each = var.placement != null || local.create_placement_group ? [var.placement] : [] content { - affinity = placement.value.affinity - availability_zone = placement.value.availability_zone - group_name = try(coalesce(aws_placement_group.this[0].name, placement.value.group_name), null) - host_id = placement.value.host_id - host_resource_group_arn = placement.value.host_resource_group_arn - partition_number = placement.value.partition_number - spread_domain = placement.value.spread_domain - tenancy = placement.value.tenancy + affinity = try(placement.value.affinity, null) + availability_zone = try(placement.value.availability_zone, null) + group_name = try(aws_placement_group.this[0].name, placement.value.group_name) + host_id = try(placement.value.host_id, null) + host_resource_group_arn = try(placement.value.host_resource_group_arn, null) + partition_number = try(placement.value.partition_number, null) + spread_domain = try(placement.value.spread_domain, null) + tenancy = try(placement.value.tenancy, null) } } diff --git a/modules/eks-managed-node-group/variables.tf b/modules/eks-managed-node-group/variables.tf index 8fb6de34e0..96eccee9bd 100644 --- a/modules/eks-managed-node-group/variables.tf +++ b/modules/eks-managed-node-group/variables.tf @@ -391,7 +391,7 @@ variable "placement" { spread_domain = optional(string) tenancy = optional(string) }) - default = {} + default = null } variable "create_placement_group" { @@ -436,7 +436,7 @@ variable "subnet_ids" { variable "min_size" { description = "Minimum number of instances/nodes" type = number - default = 0 + default = 1 } variable "max_size" { diff --git a/modules/self-managed-node-group/README.md b/modules/self-managed-node-group/README.md index 2b6e20b3a5..beaa7a9d7d 100644 --- a/modules/self-managed-node-group/README.md +++ b/modules/self-managed-node-group/README.md @@ -163,12 +163,12 @@ module "self_managed_node_group" { | [max\_size](#input\_max\_size) | The maximum size of the autoscaling group | `number` | `3` | no | | [metadata\_options](#input\_metadata\_options) | Customize the metadata options for the instance |
object({
http_endpoint = optional(string, "enabled")
http_protocol_ipv6 = optional(string)
http_put_response_hop_limit = optional(number, 1)
http_tokens = optional(string, "required")
instance_metadata_tags = optional(string)
})
|
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 1,
"http_tokens": "required"
}
| no | | [metrics\_granularity](#input\_metrics\_granularity) | The granularity to associate with the metrics to collect. The only valid value is `1Minute` | `string` | `null` | no | -| [min\_size](#input\_min\_size) | The minimum size of the autoscaling group | `number` | `0` | no | +| [min\_size](#input\_min\_size) | The minimum size of the autoscaling group | `number` | `1` | no | | [mixed\_instances\_policy](#input\_mixed\_instances\_policy) | Configuration block containing settings to define launch targets for Auto Scaling groups |
object({
instances_distribution = optional(object({
on_demand_allocation_strategy = optional(string)
on_demand_base_capacity = optional(number)
on_demand_percentage_above_base_capacity = optional(number)
spot_allocation_strategy = optional(string)
spot_instance_pools = optional(number)
spot_max_price = optional(string)
}))
launch_template = object({
override = optional(list(object({
instance_requirements = optional(object({
accelerator_count = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_manufacturers = optional(list(string))
accelerator_names = optional(list(string))
accelerator_total_memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
accelerator_types = optional(list(string))
allowed_instance_types = optional(list(string))
bare_metal = optional(string)
baseline_ebs_bandwidth_mbps = optional(object({
max = optional(number)
min = optional(number)
}))
burstable_performance = optional(string)
cpu_manufacturers = optional(list(string))
excluded_instance_types = optional(list(string))
instance_generations = optional(list(string))
local_storage = optional(string)
local_storage_types = optional(list(string))
max_spot_price_as_percentage_of_optimal_on_demand_price = optional(number)
memory_gib_per_vcpu = optional(object({
max = optional(number)
min = optional(number)
}))
memory_mib = optional(object({
max = optional(number)
min = optional(number)
}))
network_bandwidth_gbps = optional(object({
max = optional(number)
min = optional(number)
}))
network_interface_count = optional(object({
max = optional(number)
min = optional(number)
}))
on_demand_max_price_percentage_over_lowest_price = optional(number)
require_hibernate_support = optional(bool)
spot_max_price_percentage_over_lowest_price = optional(number)
total_local_storage_gb = optional(object({
max = optional(number)
min = optional(number)
}))
vcpu_count = optional(object({
max = optional(number)
min = optional(number)
}))
}))
instance_type = optional(string)
launch_template_specification = optional(object({
launch_template_id = optional(string)
launch_template_name = optional(string)
version = optional(string)
}))
weighted_capacity = optional(string)
})))
})
})
| `null` | no | | [name](#input\_name) | Name of the Self managed Node Group | `string` | `""` | no | | [network\_interfaces](#input\_network\_interfaces) | Customize network interfaces to be attached at instance boot time |
list(object({
associate_carrier_ip_address = optional(bool)
associate_public_ip_address = optional(bool)
connection_tracking_specification = optional(object({
tcp_established_timeout = optional(number)
udp_stream_timeout = optional(number)
udp_timeout = optional(number)
}))
delete_on_termination = optional(bool)
description = optional(string)
device_index = optional(number)
ena_srd_specification = optional(object({
ena_srd_enabled = optional(bool)
ena_srd_udp_specification = optional(object({
ena_srd_udp_enabled = optional(bool)
}))
}))
interface_type = optional(string)
ipv4_address_count = optional(number)
ipv4_addresses = optional(list(string))
ipv4_prefix_count = optional(number)
ipv4_prefixes = optional(list(string))
ipv6_address_count = optional(number)
ipv6_addresses = optional(list(string))
ipv6_prefix_count = optional(number)
ipv6_prefixes = optional(list(string))
network_card_index = optional(number)
network_interface_id = optional(string)
primary_ipv6 = optional(bool)
private_ip_address = optional(string)
security_groups = optional(list(string), [])
subnet_id = optional(string)
}))
| `[]` | no | | [partition](#input\_partition) | The AWS partition - pass through value to reduce number of GET requests from data sources | `string` | `""` | no | -| [placement](#input\_placement) | The placement of the instance |
object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
})
| `{}` | no | +| [placement](#input\_placement) | The placement of the instance |
object({
affinity = optional(string)
availability_zone = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
partition_number = optional(number)
spread_domain = optional(string)
tenancy = optional(string)
})
| `null` | no | | [placement\_group](#input\_placement\_group) | The name of the placement group into which you'll launch your instances | `string` | `null` | no | | [post\_bootstrap\_user\_data](#input\_post\_bootstrap\_user\_data) | User data that is appended to the user data script after of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | | [pre\_bootstrap\_user\_data](#input\_pre\_bootstrap\_user\_data) | User data that is injected into the user data script ahead of the EKS bootstrap script. Not used when `ami_type` = `BOTTLEROCKET_*` | `string` | `""` | no | diff --git a/modules/self-managed-node-group/main.tf b/modules/self-managed-node-group/main.tf index c3467407a7..514dc526cd 100644 --- a/modules/self-managed-node-group/main.tf +++ b/modules/self-managed-node-group/main.tf @@ -428,7 +428,7 @@ resource "aws_launch_template" "this" { content { affinity = placement.value.affinity availability_zone = placement.value.availability_zone - group_name = try(coalesce(aws_placement_group.this[0].name, placement.value.group_name), null) + group_name = try(aws_placement_group.this[0].name, placement.value.group_name) host_id = placement.value.host_id host_resource_group_arn = placement.value.host_resource_group_arn partition_number = placement.value.partition_number diff --git a/modules/self-managed-node-group/variables.tf b/modules/self-managed-node-group/variables.tf index 149eed3d2f..0e805796a8 100644 --- a/modules/self-managed-node-group/variables.tf +++ b/modules/self-managed-node-group/variables.tf @@ -326,7 +326,7 @@ variable "placement" { spread_domain = optional(string) tenancy = optional(string) }) - default = {} + default = null } variable "create_placement_group" { @@ -548,7 +548,7 @@ variable "subnet_ids" { variable "min_size" { description = "The minimum size of the autoscaling group" type = number - default = 0 + default = 1 } variable "max_size" { diff --git a/node_groups.tf b/node_groups.tf index 13fd2a4df7..9661e22629 100644 --- a/node_groups.tf +++ b/node_groups.tf @@ -319,12 +319,12 @@ module "eks_managed_node_group" { create_launch_template = try(each.value.create_launch_template, null) use_custom_launch_template = try(each.value.use_custom_launch_template, null) launch_template_id = try(each.value.launch_template_id, null) - launch_template_name = try(each.value.launch_template_name, each.key) + launch_template_name = coalesce(each.value.launch_template_name, each.key) launch_template_use_name_prefix = try(each.value.launch_template_use_name_prefix, null) launch_template_version = try(each.value.launch_template_version, null) launch_template_default_version = try(each.value.launch_template_default_version, null) update_launch_template_default_version = try(each.value.update_launch_template_default_version, null) - launch_template_description = try(each.value.launch_template_description, "Custom launch template for ${try(each.value.name, each.key)} EKS managed node group") + launch_template_description = coalesce(each.value.launch_template_description, "Custom launch template for ${coalesce(each.value.name, each.key)} EKS managed node group") launch_template_tags = try(each.value.launch_template_tags, null) tag_specifications = try(each.value.tag_specifications, null) @@ -461,12 +461,12 @@ module "self_managed_node_group" { # Launch Template create_launch_template = try(each.value.create_launch_template, null) launch_template_id = try(each.value.launch_template_id, null) - launch_template_name = try(each.value.launch_template_name, each.key) + launch_template_name = coalesce(each.value.launch_template_name, each.key) launch_template_use_name_prefix = try(each.value.launch_template_use_name_prefix, null) launch_template_version = try(each.value.launch_template_version, null) launch_template_default_version = try(each.value.launch_template_default_version, null) update_launch_template_default_version = try(each.value.update_launch_template_default_version, null) - launch_template_description = try(each.value.launch_template_description, "Custom launch template for ${try(each.value.name, each.key)} self managed node group") + launch_template_description = coalesce(each.value.launch_template_description, "Custom launch template for ${coalesce(each.value.name, each.key)} self managed node group") launch_template_tags = try(each.value.launch_template_tags, null) tag_specifications = try(each.value.tag_specifications, null) diff --git a/tests/eks-managed-node-group/main.tf b/tests/eks-managed-node-group/main.tf index 7c2ffe277d..76cd5cbd35 100644 --- a/tests/eks-managed-node-group/main.tf +++ b/tests/eks-managed-node-group/main.tf @@ -105,8 +105,7 @@ module "eks" { placement_group = { create_placement_group = true - # forces the subnet lookup to be restricted to this availability zone - placement_group_az = element(local.azs, 3) + subnet_ids = slice(module.vpc.private_subnets, 0, 1) } # AL2023 node group utilizing new user data format which utilizes nodeadm @@ -126,8 +125,6 @@ module "eks" { kubelet: config: shutdownGracePeriod: 30s - featureGates: - DisableKubeletCloudCredentialProviders: true EOT } ] @@ -229,8 +226,6 @@ module "eks" { kubelet: config: shutdownGracePeriod: 30s - featureGates: - DisableKubeletCloudCredentialProviders: true EOT content_type = "application/node.eks.aws" }] @@ -279,7 +274,7 @@ module "eks" { metadata_options = { http_endpoint = "enabled" http_tokens = "required" - http_put_response_hop_limit = 1 + http_put_response_hop_limit = 2 instance_metadata_tags = "disabled" } diff --git a/tests/self-managed-node-group/main.tf b/tests/self-managed-node-group/main.tf index 20ec5b8f46..9f5ae7552e 100644 --- a/tests/self-managed-node-group/main.tf +++ b/tests/self-managed-node-group/main.tf @@ -228,8 +228,6 @@ module "eks" { kubelet: config: shutdownGracePeriod: 30s - featureGates: - DisableKubeletCloudCredentialProviders: true EOT content_type = "application/node.eks.aws" }] diff --git a/variables.tf b/variables.tf index 036cf34f95..39dd07b992 100644 --- a/variables.tf +++ b/variables.tf @@ -215,10 +215,10 @@ variable "access_entries" { policy_associations = optional(map(object({ policy_arn = string access_scope = object({ - type = string + namespaces = optional(list(string)) + type = string }) - namespaces = optional(list(string)) - })), {}) + }))) })) default = {} } @@ -789,7 +789,7 @@ variable "self_managed_node_groups" { use_name_prefix = optional(bool, true) availability_zones = optional(list(string)) subnet_ids = optional(list(string)) - min_size = optional(number, 0) + min_size = optional(number, 1) max_size = optional(number, 3) desired_size = optional(number, 1) desired_size_type = optional(string) @@ -1118,7 +1118,7 @@ variable "self_managed_node_groups" { partition_number = optional(number) spread_domain = optional(string) tenancy = optional(string) - }), {}) + })) maintenance_options = optional(object({ auto_recovery = optional(string) })) @@ -1216,7 +1216,7 @@ variable "eks_managed_node_groups" { name = optional(string) # Will fall back to map key use_name_prefix = optional(bool, true) subnet_ids = optional(list(string)) - min_size = optional(number, 0) + min_size = optional(number, 1) max_size = optional(number, 3) desired_size = optional(number, 1) ami_id = optional(string, "") @@ -1357,7 +1357,7 @@ variable "eks_managed_node_groups" { partition_number = optional(number) spread_domain = optional(string) tenancy = optional(string) - }), {}) + })) network_interfaces = optional(list(object({ associate_carrier_ip_address = optional(bool) associate_public_ip_address = optional(bool) From a2b25b242d636a92de4c5c058507b19674c5d6a0 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Mon, 21 Jul 2025 16:14:27 -0500 Subject: [PATCH 21/25] fix: Updates from testing and validating self-managed node group --- docs/UPGRADE-21.0.md | 6 ++++-- modules/self-managed-node-group/main.tf | 16 ++++++++-------- tests/self-managed-node-group/main.tf | 6 ++++-- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/docs/UPGRADE-21.0.md b/docs/UPGRADE-21.0.md index 1a2d5c741c..d5c59f2b5b 100644 --- a/docs/UPGRADE-21.0.md +++ b/docs/UPGRADE-21.0.md @@ -208,7 +208,7 @@ module "eks" { version = "~> 20.0" # Truncated for brevity ... - # Not all renamed variables are shown here, please refer to the full list above. + # Renamed variables are not shown here, please refer to the full list above. enable_efa_support = true @@ -269,7 +269,7 @@ module "eks" { version = "~> 21.0" # Truncated for brevity ... - # Not all renamed variables are shown here, please refer to the full list above. + # Renamed variables are not shown here, please refer to the full list above. eks_managed_node_groups = { efa = { @@ -323,3 +323,5 @@ module "eks" { ``` ### State Changes + +No state changes required. diff --git a/modules/self-managed-node-group/main.tf b/modules/self-managed-node-group/main.tf index 514dc526cd..710d276602 100644 --- a/modules/self-managed-node-group/main.tf +++ b/modules/self-managed-node-group/main.tf @@ -423,17 +423,17 @@ resource "aws_launch_template" "this" { } dynamic "placement" { - for_each = length(var.placement) > 0 || local.create_placement_group ? [var.placement] : [] + for_each = var.placement != null || local.create_placement_group ? [var.placement] : [] content { - affinity = placement.value.affinity - availability_zone = placement.value.availability_zone + affinity = try(placement.value.affinity, null) + availability_zone = try(placement.value.availability_zone, null) group_name = try(aws_placement_group.this[0].name, placement.value.group_name) - host_id = placement.value.host_id - host_resource_group_arn = placement.value.host_resource_group_arn - partition_number = placement.value.partition_number - spread_domain = placement.value.spread_domain - tenancy = placement.value.tenancy + host_id = try(placement.value.host_id, null) + host_resource_group_arn = try(placement.value.host_resource_group_arn, null) + partition_number = try(placement.value.partition_number, null) + spread_domain = try(placement.value.spread_domain, null) + tenancy = try(placement.value.tenancy, null) } } diff --git a/tests/self-managed-node-group/main.tf b/tests/self-managed-node-group/main.tf index 9f5ae7552e..8629039e7d 100644 --- a/tests/self-managed-node-group/main.tf +++ b/tests/self-managed-node-group/main.tf @@ -45,13 +45,15 @@ module "eks" { most_recent = true } eks-pod-identity-agent = { - most_recent = true + before_compute = true + most_recent = true } kube-proxy = { most_recent = true } vpc-cni = { - most_recent = true + before_compute = true + most_recent = true pod_identity_association = [{ role_arn = module.aws_vpc_cni_ipv4_pod_identity.iam_role_arn service_account = "aws-node" From f62280d8e924bf7fe949d76888d18b34f95de244 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Mon, 21 Jul 2025 16:52:29 -0500 Subject: [PATCH 22/25] docs: Ensure addon ussage documented is aligned --- README.md | 8 ++++++-- docs/README.md | 1 + examples/eks-managed-node-group/eks-al2023.tf | 12 ++++++++---- .../eks-managed-node-group/eks-bottlerocket.tf | 12 ++++++++---- examples/karpenter/main.tf | 14 +++++++++----- examples/self-managed-node-group/eks-al2023.tf | 12 ++++++++---- .../self-managed-node-group/eks-bottlerocket.tf | 12 ++++++++---- 7 files changed, 48 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 6770c7a234..235307d38e 100644 --- a/README.md +++ b/README.md @@ -68,9 +68,13 @@ module "eks" { addons = { coredns = {} - eks-pod-identity-agent = {} + eks-pod-identity-agent = { + before_compute = true + } kube-proxy = {} - vpc-cni = {} + vpc-cni = { + before_compute = true + } } # Optional diff --git a/docs/README.md b/docs/README.md index 144826b4cf..960db18448 100644 --- a/docs/README.md +++ b/docs/README.md @@ -11,3 +11,4 @@ - [Upgrade to v18.x](https://github.com/terraform-aws-modules/terraform-aws-eks/blob/master/docs/UPGRADE-18.0.md) - [Upgrade to v19.x](https://github.com/terraform-aws-modules/terraform-aws-eks/blob/master/docs/UPGRADE-19.0.md) - [Upgrade to v20.x](https://github.com/terraform-aws-modules/terraform-aws-eks/blob/master/docs/UPGRADE-20.0.md) + - [Upgrade to v21.x](https://github.com/terraform-aws-modules/terraform-aws-eks/blob/master/docs/UPGRADE-21.0.md) diff --git a/examples/eks-managed-node-group/eks-al2023.tf b/examples/eks-managed-node-group/eks-al2023.tf index b58733c163..7203c01c81 100644 --- a/examples/eks-managed-node-group/eks-al2023.tf +++ b/examples/eks-managed-node-group/eks-al2023.tf @@ -8,10 +8,14 @@ module "eks_al2023" { # EKS Addons addons = { - coredns = {} - eks-pod-identity-agent = {} - kube-proxy = {} - vpc-cni = {} + coredns = {} + eks-pod-identity-agent = { + before_compute = true + } + kube-proxy = {} + vpc-cni = { + before_compute = true + } } vpc_id = module.vpc.vpc_id diff --git a/examples/eks-managed-node-group/eks-bottlerocket.tf b/examples/eks-managed-node-group/eks-bottlerocket.tf index 037028ce68..2fd3816dbe 100644 --- a/examples/eks-managed-node-group/eks-bottlerocket.tf +++ b/examples/eks-managed-node-group/eks-bottlerocket.tf @@ -8,10 +8,14 @@ module "eks_bottlerocket" { # EKS Addons addons = { - coredns = {} - eks-pod-identity-agent = {} - kube-proxy = {} - vpc-cni = {} + coredns = {} + eks-pod-identity-agent = { + before_compute = true + } + kube-proxy = {} + vpc-cni = { + before_compute = true + } } vpc_id = module.vpc.vpc_id diff --git a/examples/karpenter/main.tf b/examples/karpenter/main.tf index 3884bb5a36..6f652327c3 100644 --- a/examples/karpenter/main.tf +++ b/examples/karpenter/main.tf @@ -63,10 +63,14 @@ module "eks" { endpoint_public_access = true addons = { - coredns = {} - eks-pod-identity-agent = {} - kube-proxy = {} - vpc-cni = {} + coredns = {} + eks-pod-identity-agent = { + before_compute = true + } + kube-proxy = {} + vpc-cni = { + before_compute = true + } } vpc_id = module.vpc.vpc_id @@ -139,7 +143,7 @@ resource "helm_release" "karpenter" { repository_username = data.aws_ecrpublic_authorization_token.token.user_name repository_password = data.aws_ecrpublic_authorization_token.token.password chart = "karpenter" - version = "1.5.2" + version = "1.6.0" wait = false values = [ diff --git a/examples/self-managed-node-group/eks-al2023.tf b/examples/self-managed-node-group/eks-al2023.tf index 03452bc1a5..e074735ebb 100644 --- a/examples/self-managed-node-group/eks-al2023.tf +++ b/examples/self-managed-node-group/eks-al2023.tf @@ -8,10 +8,14 @@ module "eks_al2023" { # EKS Addons addons = { - coredns = {} - eks-pod-identity-agent = {} - kube-proxy = {} - vpc-cni = {} + coredns = {} + eks-pod-identity-agent = { + before_compute = true + } + kube-proxy = {} + vpc-cni = { + before_compute = true + } } vpc_id = module.vpc.vpc_id diff --git a/examples/self-managed-node-group/eks-bottlerocket.tf b/examples/self-managed-node-group/eks-bottlerocket.tf index bb46e90631..6f0a2dc5ef 100644 --- a/examples/self-managed-node-group/eks-bottlerocket.tf +++ b/examples/self-managed-node-group/eks-bottlerocket.tf @@ -8,10 +8,14 @@ module "eks_bottlerocket" { # EKS Addons addons = { - coredns = {} - eks-pod-identity-agent = {} - kube-proxy = {} - vpc-cni = {} + coredns = {} + eks-pod-identity-agent = { + before_compute = true + } + kube-proxy = {} + vpc-cni = { + before_compute = true + } } vpc_id = module.vpc.vpc_id From a40b85a18784201a625d9385a0b439afbabc9046 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Mon, 21 Jul 2025 17:06:08 -0500 Subject: [PATCH 23/25] feat: Switch to dualstack OIDC issuer URL --- docs/UPGRADE-21.0.md | 1 + main.tf | 4 ++-- outputs.tf | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/UPGRADE-21.0.md b/docs/UPGRADE-21.0.md index d5c59f2b5b..695c8c80f2 100644 --- a/docs/UPGRADE-21.0.md +++ b/docs/UPGRADE-21.0.md @@ -31,6 +31,7 @@ If you find a bug, please open an issue with supporting configuration to reprodu - `addons.resolve_conflicts_on_create` is now set to `"NONE"` by default (was `"OVERWRITE"`). - `addons.most_recent` is now set to `true` by default (was `false`). - `cluster_identity_providers.issuer_url` is now required to be set by users; the prior incorrect default has been removed. See https://github.com/terraform-aws-modules/terraform-aws-eks/pull/3055 and https://github.com/kubernetes/kubernetes/pull/123561 for more details. +- The OIDC issuer URL for IAM roles for service accounts (IRSA) has been changed to use the new dual stack`oidc-eks` endpoint instead of `oidc.eks`. This is to align with https://github.com/aws/containers-roadmap/issues/2038#issuecomment-2278450601 ## Additional changes diff --git a/main.tf b/main.tf index 6358db3917..94989384e2 100644 --- a/main.tf +++ b/main.tf @@ -444,7 +444,7 @@ data "tls_certificate" "this" { # Not available on outposts count = local.create_oidc_provider && var.include_oidc_root_ca_thumbprint ? 1 : 0 - url = aws_eks_cluster.this[0].identity[0].oidc[0].issuer + url = local.dualstack_oidc_issuer_url } resource "aws_iam_openid_connect_provider" "oidc_provider" { @@ -453,7 +453,7 @@ resource "aws_iam_openid_connect_provider" "oidc_provider" { client_id_list = distinct(compact(concat(["sts.amazonaws.com"], var.openid_connect_audiences))) thumbprint_list = concat(local.oidc_root_ca_thumbprint, var.custom_oidc_thumbprints) - url = aws_eks_cluster.this[0].identity[0].oidc[0].issuer + url = local.dualstack_oidc_issuer_url tags = merge( { Name = "${var.name}-eks-irsa" }, diff --git a/outputs.tf b/outputs.tf index f082de8c17..95afd4365b 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,4 +1,5 @@ locals { + # https://github.com/aws/containers-roadmap/issues/2038#issuecomment-2278450601 dualstack_oidc_issuer_url = try(replace(replace(aws_eks_cluster.this[0].identity[0].oidc[0].issuer, "https://oidc.eks.", "https://oidc-eks."), ".amazonaws.com/", ".api.aws/"), null) } From 8dccd3c6bb1646cf580b6e648a6bed4a5d52a5b6 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Tue, 22 Jul 2025 14:31:36 -0500 Subject: [PATCH 24/25] feat: Allow sourcing over overriding the Karpenter assume role policy --- modules/karpenter/README.md | 3 ++- modules/karpenter/main.tf | 26 +++++++++++++------------- modules/karpenter/variables.tf | 18 ++++++++++++------ 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/modules/karpenter/README.md b/modules/karpenter/README.md index cf6102af48..85e472b225 100644 --- a/modules/karpenter/README.md +++ b/modules/karpenter/README.md @@ -138,7 +138,6 @@ No modules. | [create\_instance\_profile](#input\_create\_instance\_profile) | Whether to create an IAM instance profile | `bool` | `false` | no | | [create\_node\_iam\_role](#input\_create\_node\_iam\_role) | Determines whether an IAM role is created or to use an existing IAM role | `bool` | `true` | no | | [create\_pod\_identity\_association](#input\_create\_pod\_identity\_association) | Determines whether to create pod identity association | `bool` | `true` | no | -| [enable\_pod\_identity](#input\_enable\_pod\_identity) | Determines whether to enable support for EKS pod identity | `bool` | `true` | no | | [enable\_spot\_termination](#input\_enable\_spot\_termination) | Determines whether to enable native spot termination handling | `bool` | `true` | no | | [iam\_policy\_description](#input\_iam\_policy\_description) | IAM policy description | `string` | `"Karpenter controller IAM policy"` | no | | [iam\_policy\_name](#input\_iam\_policy\_name) | Name of the IAM policy | `string` | `"KarpenterController"` | no | @@ -148,9 +147,11 @@ No modules. | [iam\_role\_description](#input\_iam\_role\_description) | IAM role description | `string` | `"Karpenter controller IAM role"` | no | | [iam\_role\_max\_session\_duration](#input\_iam\_role\_max\_session\_duration) | Maximum API session duration in seconds between 3600 and 43200 | `number` | `null` | no | | [iam\_role\_name](#input\_iam\_role\_name) | Name of the IAM role | `string` | `"KarpenterController"` | no | +| [iam\_role\_override\_assume\_policy\_documents](#input\_iam\_role\_override\_assume\_policy\_documents) | A list of IAM policy documents to override the default assume role policy document for the Karpenter controller IAM role | `list(string)` | `[]` | no | | [iam\_role\_path](#input\_iam\_role\_path) | Path of the IAM role | `string` | `"/"` | no | | [iam\_role\_permissions\_boundary\_arn](#input\_iam\_role\_permissions\_boundary\_arn) | Permissions boundary ARN to use for the IAM role | `string` | `null` | no | | [iam\_role\_policies](#input\_iam\_role\_policies) | Policies to attach to the IAM role in `{'static_name' = 'policy_arn'}` format | `map(string)` | `{}` | no | +| [iam\_role\_source\_assume\_policy\_documents](#input\_iam\_role\_source\_assume\_policy\_documents) | A list of IAM policy documents to use as a source for the assume role policy document for the Karpenter controller IAM role | `list(string)` | `[]` | no | | [iam\_role\_tags](#input\_iam\_role\_tags) | A map of additional tags to add the the IAM role | `map(string)` | `{}` | no | | [iam\_role\_use\_name\_prefix](#input\_iam\_role\_use\_name\_prefix) | Determines whether the name of the IAM role (`iam_role_name`) is used as a prefix | `bool` | `true` | no | | [namespace](#input\_namespace) | Namespace to associate with the Karpenter Pod Identity | `string` | `"kube-system"` | no | diff --git a/modules/karpenter/main.tf b/modules/karpenter/main.tf index 2afe3482ff..bc9c8e823b 100644 --- a/modules/karpenter/main.tf +++ b/modules/karpenter/main.tf @@ -28,20 +28,20 @@ locals { data "aws_iam_policy_document" "controller_assume_role" { count = local.create_iam_role ? 1 : 0 - # Pod Identity - dynamic "statement" { - for_each = var.enable_pod_identity ? [1] : [] + override_policy_documents = var.iam_role_override_assume_policy_documents + source_policy_documents = var.iam_role_source_assume_policy_documents - content { - actions = [ - "sts:AssumeRole", - "sts:TagSession", - ] + # Pod Identity + statement { + sid = "PodIdentity" + actions = [ + "sts:AssumeRole", + "sts:TagSession", + ] - principals { - type = "Service" - identifiers = ["pods.eks.amazonaws.com"] - } + principals { + type = "Service" + identifiers = ["pods.eks.amazonaws.com"] } } } @@ -93,7 +93,7 @@ resource "aws_iam_role_policy_attachment" "controller_additional" { ################################################################################ resource "aws_eks_pod_identity_association" "karpenter" { - count = local.create_iam_role && var.enable_pod_identity && var.create_pod_identity_association ? 1 : 0 + count = local.create_iam_role && var.create_pod_identity_association ? 1 : 0 region = var.region diff --git a/modules/karpenter/variables.tf b/modules/karpenter/variables.tf index 64a74bee7b..f0725f6a58 100644 --- a/modules/karpenter/variables.tf +++ b/modules/karpenter/variables.tf @@ -98,6 +98,18 @@ variable "iam_policy_description" { default = "Karpenter controller IAM policy" } +variable "iam_role_override_assume_policy_documents" { + description = "A list of IAM policy documents to override the default assume role policy document for the Karpenter controller IAM role" + type = list(string) + default = [] +} + +variable "iam_role_source_assume_policy_documents" { + description = "A list of IAM policy documents to use as a source for the assume role policy document for the Karpenter controller IAM role" + type = list(string) + default = [] +} + variable "iam_policy_statements" { description = "A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed" type = list(object({ @@ -136,12 +148,6 @@ variable "ami_id_ssm_parameter_arns" { default = [] } -variable "enable_pod_identity" { - description = "Determines whether to enable support for EKS pod identity" - type = bool - default = true -} - ################################################################################ # Pod Identity Association ################################################################################ From 522ad5e9fa76b249bf71b93636c556b0a6e351b0 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Tue, 22 Jul 2025 14:33:07 -0500 Subject: [PATCH 25/25] fix: Use `Bool` instead of `StringEquals` for DenyHTTP queue policy --- modules/karpenter/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/karpenter/main.tf b/modules/karpenter/main.tf index bc9c8e823b..7eba2cb5d8 100644 --- a/modules/karpenter/main.tf +++ b/modules/karpenter/main.tf @@ -153,7 +153,7 @@ data "aws_iam_policy_document" "queue" { ] resources = [aws_sqs_queue.this[0].arn] condition { - test = "StringEquals" + test = "Bool" variable = "aws:SecureTransport" values = [ "false"