diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f451b69..85adacb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,6 +25,7 @@ repos: - id: trailing-whitespace args: [--markdown-linebreak-ext=md] exclude: CHANGELOG.md + - id: check-yaml - id: check-merge-conflict - id: check-executables-have-shebangs diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml deleted file mode 100644 index 266f0c7..0000000 --- a/.pre-commit-hooks.yaml +++ /dev/null @@ -1,170 +0,0 @@ -#### THESE ARE NOT ENABLED, THEY ARE FOR REFERENCE -# - id: infracost_breakdown -# name: Infracost breakdown -# description: Check terraform infrastructure cost -# entry: hooks/infracost_breakdown.sh -# language: script -# require_serial: true -# files: \.(tf(vars)?|hcl)$ -# exclude: \.terraform/.*$ - -# - id: terraform_fmt -# name: Terraform fmt -# description: Rewrites all Terraform configuration files to a canonical format. -# entry: hooks/terraform_fmt.sh -# language: script -# files: (\.tf|\.tfvars)$ -# exclude: \.terraform/.*$ - -# - id: terraform_docs -# name: Terraform docs -# description: Inserts input and output documentation into README.md (using terraform-docs). -# require_serial: true -# entry: hooks/terraform_docs.sh -# language: script -# files: (\.tf|\.terraform\.lock\.hcl)$ -# exclude: \.terraform/.*$ - -# - id: terraform_docs_without_aggregate_type_defaults -# name: Terraform docs (without aggregate type defaults) -# description: Inserts input and output documentation into README.md (using terraform-docs). Identical to terraform_docs. -# require_serial: true -# entry: hooks/terraform_docs.sh -# language: script -# files: (\.tf)$ -# exclude: \.terraform/.*$ - -# - id: terraform_docs_replace -# name: Terraform docs (overwrite README.md) -# description: Overwrite content of README.md with terraform-docs. -# require_serial: true -# entry: terraform_docs_replace -# language: python -# files: (\.tf)$ -# exclude: \.terraform/.*$ - -# - id: terraform_validate -# name: Terraform validate -# description: Validates all Terraform configuration files. -# require_serial: true -# entry: hooks/terraform_validate.sh -# language: script -# files: \.(tf(vars)?|terraform\.lock\.hcl)$ -# exclude: \.terraform/.*$ - -# - id: terraform_providers_lock -# name: Lock terraform provider versions -# description: Updates provider signatures in dependency lock files. -# require_serial: true -# entry: hooks/terraform_providers_lock.sh -# language: script -# files: (\.terraform\.lock\.hcl)$ -# exclude: \.terraform/.*$ - -# - id: terraform_tflint -# name: Terraform validate with tflint -# description: Validates all Terraform configuration files with TFLint. -# require_serial: true -# entry: hooks/terraform_tflint.sh -# language: script -# files: (\.tf|\.tfvars)$ -# exclude: \.terraform/.*$ - -# - id: terragrunt_fmt -# name: Terragrunt fmt -# description: Rewrites all Terragrunt configuration files to a canonical format. -# entry: hooks/terragrunt_fmt.sh -# language: script -# files: (\.hcl)$ -# exclude: \.terraform/.*$ - -# - id: terragrunt_validate -# name: Terragrunt validate -# description: Validates all Terragrunt configuration files. -# entry: hooks/terragrunt_validate.sh -# language: script -# files: (\.hcl)$ -# exclude: \.terraform/.*$ - -# - id: terragrunt_validate_inputs -# name: Terragrunt validate inputs -# description: Validates Terragrunt unused and undefined inputs. -# entry: hooks/terragrunt_validate_inputs.sh -# language: script -# files: (\.hcl)$ -# exclude: \.terraform/.*$ - -# - id: terragrunt_providers_lock -# name: Terragrunt providers lock -# description: Updates provider signatures in dependency lock files using terragrunt. -# entry: hooks/terragrunt_providers_lock.sh -# language: script -# files: (terragrunt|\.terraform\.lock)\.hcl$ -# exclude: \.(terraform/.*|terragrunt-cache)$ - -# - id: terraform_tfsec -# name: Terraform validate with tfsec (deprecated, use "terraform_trivy") -# description: Static analysis of Terraform templates to spot potential security issues. -# require_serial: true -# entry: hooks/terraform_tfsec.sh -# files: \.tf(vars)?$ -# language: script - -# - id: terraform_trivy -# name: Terraform validate with trivy -# description: Static analysis of Terraform templates to spot potential security issues. -# require_serial: true -# entry: hooks/terraform_trivy.sh -# files: \.tf(vars)?$ -# language: script - -# - id: checkov -# name: checkov (deprecated, use "terraform_checkov") -# description: Runs checkov on Terraform templates. -# entry: checkov -d . -# language: python -# pass_filenames: false -# always_run: false -# files: \.tf$ -# exclude: \.terraform/.*$ -# require_serial: true - -# - id: terraform_checkov -# name: Checkov -# description: Runs checkov on Terraform templates. -# entry: hooks/terraform_checkov.sh -# language: script -# always_run: false -# files: \.tf$ -# exclude: \.terraform/.*$ -# require_serial: true - -# - id: terraform_wrapper_module_for_each -# name: Terraform wrapper with for_each in module -# description: Generate Terraform wrappers with for_each in module. -# entry: hooks/terraform_wrapper_module_for_each.sh -# language: script -# pass_filenames: false -# always_run: false -# require_serial: true -# files: \.tf$ -# exclude: \.terraform/.*$ - -# - id: terrascan -# name: terrascan -# description: Runs terrascan on Terraform templates. -# language: script -# entry: hooks/terrascan.sh -# files: \.tf$ -# exclude: \.terraform/.*$ -# require_serial: true - -# - id: tfupdate -# name: tfupdate -# description: Runs tfupdate on Terraform templates. -# language: script -# entry: hooks/tfupdate.sh -# args: -# - --args=terraform -# files: \.tf$ -# require_serial: true diff --git a/README.md b/README.md index 9bcb169..fd79403 100644 --- a/README.md +++ b/README.md @@ -20,22 +20,22 @@ The module deploys Karpenter needed AWS resources, namely in IAM. It copies the | [terraform](#requirement\_terraform) | >= 0.13 | | [aws](#requirement\_aws) | >= 5.14.0 | | [helm](#requirement\_helm) | >= 2.11.0 | -| [kubectl](#requirement\_kubectl) | >= 1.14.0 | +| [kubernetes](#requirement\_kubernetes) | >= 2.23.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | 5.73.0 | -| [helm](#provider\_helm) | 2.16.1 | -| [kubectl](#provider\_kubectl) | 1.14.0 | +| [aws](#provider\_aws) | 5.84.0 | +| [helm](#provider\_helm) | 2.17.0 | +| [kubernetes](#provider\_kubernetes) | 2.35.1 | ## Modules | Name | Source | Version | |------|--------|---------| | [images](#module\_images) | git@github.e.it.census.gov:terraform-modules/aws-ecr-copy-images.git/ | tf-upgrade | -| [karpenter\_resources](#module\_karpenter\_resources) | git@github.e.it.census.gov:SCT-Engineering/terraform-aws-eks.git//modules/karpenter | v20.24.3 | +| [karpenter\_resources](#module\_karpenter\_resources) | git@github.e.it.census.gov:SCT-Engineering/terraform-aws-eks.git//modules/karpenter | v20.33.1 | ## Resources @@ -43,13 +43,11 @@ The module deploys Karpenter needed AWS resources, namely in IAM. It copies the |------|------| | [aws_iam_instance_profile.karpenter_node_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | | [helm_release.karpenter](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource | -| [kubectl_manifest.karpenter_ec2_node_class](https://registry.terraform.io/providers/gavinbunney/kubectl/latest/docs/resources/manifest) | resource | -| [kubectl_manifest.karpenter_node_pool](https://registry.terraform.io/providers/gavinbunney/kubectl/latest/docs/resources/manifest) | resource | +| [kubernetes_manifest.karpenter_node_class](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource | +| [kubernetes_manifest.karpenter_node_pool](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource | | [aws_arn.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/arn) | data source | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | -| [aws_default_tags.default_tags](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/default_tags) | data source | | [aws_ecr_image.karpenter_image](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecr_image) | data source | -| [aws_ecr_image.kubectl_image](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecr_image) | data source | ## Inputs @@ -57,11 +55,10 @@ The module deploys Karpenter needed AWS resources, namely in IAM. It copies the |------|-------------|------|---------|:--------:| | [cluster\_endpoint](#input\_cluster\_endpoint) | Endpoint for your Kubernetes API server | `string` | n/a | yes | | [cluster\_name](#input\_cluster\_name) | EKS cluster name name component used through out the EKS cluster describing its purpose (ex: dice-dev) | `string` | n/a | yes | -| [karpenter\_helm\_chart](#input\_karpenter\_helm\_chart) | Which helm chart of karpenter | `string` | `"1.0.6"` | no | +| [karpenter\_helm\_chart](#input\_karpenter\_helm\_chart) | Which helm chart of karpenter | `string` | `"1.1.1"` | no | | [karpenter\_helm\_repo](#input\_karpenter\_helm\_repo) | Helm repo for official karpenter chart | `string` | `"oci://public.ecr.aws/karpenter"` | no | | [karpenter\_node\_group\_name](#input\_karpenter\_node\_group\_name) | The cluster node group that will host karpenter, should not be a karpenter managed node group | `string` | n/a | yes | -| [karpenter\_tag](#input\_karpenter\_tag) | Which tag of karpenter image | `string` | `"1.0.6"` | no | -| [kubectl\_tag](#input\_kubectl\_tag) | Which tag of kubectl image | `string` | `"1.30.4"` | no | +| [karpenter\_tag](#input\_karpenter\_tag) | Which tag of karpenter image | `string` | `"1.1.1"` | no | | [oidc\_provider\_arn](#input\_oidc\_provider\_arn) | The ARN of the OIDC Provider if `enable_irsa = true` | `string` | n/a | yes | | [profile](#input\_profile) | AWS config profile | `string` | `""` | no | | [region](#input\_region) | AWS region | `string` | n/a | yes | diff --git a/aws_data.tf b/aws_data.tf index e7211e8..2c6aade 100644 --- a/aws_data.tf +++ b/aws_data.tf @@ -3,5 +3,3 @@ data "aws_caller_identity" "current" {} data "aws_arn" "current" { arn = data.aws_caller_identity.current.arn } - -data "aws_default_tags" "default_tags" {} diff --git a/copy_images.tf b/copy_images.tf index c98c243..4c05c03 100644 --- a/copy_images.tf +++ b/copy_images.tf @@ -1,6 +1,5 @@ locals { karpenter_key = format("%v#%v", "karpenter/controller", var.karpenter_tag) - kubectl_key = format("%v#%v", "bitnami/kubectl", var.kubectl_tag) image_config = [ { @@ -12,15 +11,6 @@ locals { source_tag = var.karpenter_tag tag = var.karpenter_tag }, - { - enabled = true - dest_path = null - name = "bitnami/kubectl" - source_image = "bitnami/kubectl" - source_registry = "docker.io" - source_tag = var.kubectl_tag - tag = var.kubectl_tag - }, ] } diff --git a/ec2_node_class.yaml.tpl b/ec2_node_class.yaml.tpl deleted file mode 100644 index baf320e..0000000 --- a/ec2_node_class.yaml.tpl +++ /dev/null @@ -1,63 +0,0 @@ ---- -apiVersion: karpenter.k8s.aws/v1 -kind: EC2NodeClass -metadata: - name: ${cluster_name}-karpenter-node-class - annotations: - kubernetes.io/description: "EC2NodeClass for running ${amd_ami_family} nodes" -spec: - kubelet: - evictionHard: - memory.available: 5% - nodefs.available: 10% - nodefs.inodesFree: 10% - evictionSoft: - memory.available: 500Mi - nodefs.available: 15% - nodefs.inodesFree: 15% - evictionSoftGracePeriod: - memory.available: 1m - nodefs.available: 1m30s - nodefs.inodesFree: 2m - evictionMaxPodGracePeriod: 60 - imageGCHighThresholdPercent: 85 - imageGCLowThresholdPercent: 80 - - # Required, resolves a default ami and userdata - amiFamily: ${amd_ami_family} - amiSelectorTerms: - - alias: ${amd_ami_alias}@latest # Bottlerocket - # Required, discovers subnets to attach to instances - # Each term in the array of subnetSelectorTerms is ORed together - # Within a single term, all conditions are ANDed - subnetSelectorTerms: - - tags: - Name: "${subnets_name}" - "kubernetes.io/cluster/${cluster_name}": "shared" - - # Required, discovers security groups to attach to instances - # Each term in the array of securityGroupSelectorTerms is ORed together - # Within a single term, all conditions are ANDed - securityGroupSelectorTerms: - - tags: - Name: "${cluster_name}-node" - - # Optional, IAM instance profile to use for the node identity. - # Must specify one of "role" or "instanceProfile" for Karpenter to launch nodes - instanceProfile: "${cluster_name}-karpenter-instance-profile" - - # Optional, use instance-store volumes for node ephemeral-storage - instanceStorePolicy: RAID0 - - # Optional, configures IMDS for the instance - metadataOptions: - httpEndpoint: enabled - httpProtocolIPv6: enabled - httpPutResponseHopLimit: 2 - httpTokens: required - - # Optional, configures detailed monitoring for the instance - detailedMonitoring: true - - # Add finops tags to karpenter provisioned nodes - tags: ${tags} diff --git a/ec2_node_pool.yaml.tpl b/ec2_node_pool.yaml.tpl deleted file mode 100644 index 5062239..0000000 --- a/ec2_node_pool.yaml.tpl +++ /dev/null @@ -1,67 +0,0 @@ ---- -apiVersion: karpenter.sh/v1 -kind: NodePool -metadata: - name: ${cluster_name}-node-pool-general - annotations: - kubernetes.io/description: "General purpose NodePool for generic workloads" -spec: - template: - spec: - requirements: - - key: kubernetes.io/arch - operator: In - values: ["amd64"] - - key: kubernetes.io/os - operator: In - values: ["linux"] - - key: "karpenter.k8s.aws/instance-hypervisor" - operator: In - values: ["nitro"] - - key: karpenter.sh/capacity-type - operator: In - values: ["spot", "on-demand"] - # - key: karpenter.k8s.aws/instance-category - # operator: In - # values: ["c", "m", "r", "i", "d", "t"] - # - key: karpenter.k8s.aws/instance-generation - # operator: Gt - # values: ["2"] - nodeClassRef: - group: karpenter.k8s.aws - kind: EC2NodeClass - name: ${cluster_name}-karpenter-node-class - # kubelet: - # containerRuntime: containerd - # systemReserved: - # cpu: 100m - # memory: 100Mi - disruption: - consolidationPolicy: WhenEmptyOrUnderutilized - consolidateAfter: 5m - expireAfter: 72h - # limits: - # cpu: 1000 - # memory: 1000Gi - # nvidia.com/gpu: 2 - # topologySpreadConstraints: - # - maxSkew: 99 - # topologyKey: "topology.kubernetes.io/zone" - # whenUnsatisfiable: ScheduleAnyway - # - maxSkew: 99 - # topologyKey: "kubernetes.io/hostname" - # whenUnsatisfiable: ScheduleAnyway - # - maxSkew: 99 - # topologyKey: "karpenter.sh/capacity-type" - # whenUnsatisfiable: ScheduleAnyway - # budgets: - # - nodes: "50%" - # reasons: - # - "Empty" - # - "Drifted" - # - nodes: "5" - # - nodes: "0" - # schedule: "@daily" - # duration: 10m - # reasons: - # - "Underutilized" diff --git a/main.tf b/main.tf index d1ce7e9..4393215 100644 --- a/main.tf +++ b/main.tf @@ -1,12 +1,13 @@ locals { - namespace = "karpenter" - container_subnets_name = var.subnets_name + namespace = "karpenter" + amd_ami_family = "Bottlerocket" + amd_ami_alias = "bottlerocket" } # Replicating from here: https://github.e.it.census.gov/SCT-Engineering/terraform-aws-eks/tree/master/modules/karpenter # Karpenter IRSA roles and policies module "karpenter_resources" { - source = "git@github.e.it.census.gov:SCT-Engineering/terraform-aws-eks.git//modules/karpenter?ref=v20.24.3" + source = "git@github.e.it.census.gov:SCT-Engineering/terraform-aws-eks.git//modules/karpenter?ref=v20.33.1" cluster_name = var.cluster_name enable_irsa = true @@ -30,14 +31,6 @@ data "aws_ecr_image" "karpenter_image" { image_tag = module.images.images[local.karpenter_key].tag } -data "aws_ecr_image" "kubectl_image" { - depends_on = [ - module.images, - ] - repository_name = module.images.images[local.kubectl_key].dest_repository - image_tag = module.images.images[local.kubectl_key].tag -} - resource "helm_release" "karpenter" { depends_on = [ data.aws_ecr_image.karpenter_image @@ -109,21 +102,6 @@ resource "helm_release" "karpenter" { name = "controller.image.digest" value = data.aws_ecr_image.karpenter_image.id } - set { - name = "postInstallHook.image.repository" - value = format("%v/%v", - module.images.images[local.kubectl_key].dest_registry, - module.images.images[local.kubectl_key].dest_repository - ) - } - set { - name = "postInstallHook.image.tag" - value = module.images.images[local.kubectl_key].tag - } - set { - name = "postInstallHook.image.digest" - value = data.aws_ecr_image.kubectl_image.id - } set { name = "controller.env[0].name" value = "AWS_REGION" @@ -132,27 +110,10 @@ resource "helm_release" "karpenter" { name = "controller.env[0].value" value = var.region } - # set { - # name = "resources.requests.cpu" - # value = 1 - # } - # set { - # name = "resources.requests.memory" - # value = "1Gi" - # } - # set { - # name = "resources.limits.cpu" - # value = 1 - # } - # set { - # name = "resources.limits.memory" - # value = "1Gi" - # } set { name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn" value = module.karpenter_resources.iam_role_arn } - timeout = 300 } @@ -160,28 +121,3 @@ resource "aws_iam_instance_profile" "karpenter_node_instance_profile" { name = "${var.cluster_name}-karpenter-instance-profile" role = module.karpenter_resources.node_iam_role_name } - -# SHOULD PROBABLY PUT THESE OBJECTS INTO A HELM CHART -# Create karpenter default -resource "kubectl_manifest" "karpenter_ec2_node_class" { - depends_on = [ - helm_release.karpenter, - ] - yaml_body = templatefile("${path.module}/ec2_node_class.yaml.tpl", { - cluster_name = var.cluster_name - tags = jsonencode(data.aws_default_tags.default_tags.tags) - amd_ami_family = "Bottlerocket" - amd_ami_alias = "bottlerocket" - subnets_name = local.container_subnets_name - }) -} - -# Create karpenter default NodePool -resource "kubectl_manifest" "karpenter_node_pool" { - depends_on = [ - kubectl_manifest.karpenter_ec2_node_class, - ] - yaml_body = templatefile("${path.module}/ec2_node_pool.yaml.tpl", { - cluster_name = var.cluster_name - }) -} diff --git a/node_class.tf b/node_class.tf new file mode 100644 index 0000000..e5b981e --- /dev/null +++ b/node_class.tf @@ -0,0 +1,67 @@ +resource "kubernetes_manifest" "karpenter_node_class" { + depends_on = [aws_iam_instance_profile.karpenter_node_instance_profile] + + manifest = { + apiVersion = "${helm_release.karpenter.name}.k8s.aws/v1" + kind = "EC2NodeClass" + metadata = { + name = "${var.cluster_name}-${helm_release.karpenter.name}-node-class" + annotations = { + "kubernetes.io/description" = "EC2NodeClass for running ${local.amd_ami_family} nodes" + } + } + spec = { + amiFamily = local.amd_ami_family + amiSelectorTerms = [ + { + alias = "${local.amd_ami_alias}@latest" + } + ] + detailedMonitoring = true + instanceProfile = aws_iam_instance_profile.karpenter_node_instance_profile.name + instanceStorePolicy = "RAID0" + kubelet = { + evictionHard = { + "memory.available" = "5%" + "nodefs.available" = "10%" + "nodefs.inodesFree" = "10%" + } + evictionMaxPodGracePeriod = 60 + evictionSoft = { + "memory.available" = "500Mi" + "nodefs.available" = "15%" + "nodefs.inodesFree" = "15%" + } + evictionSoftGracePeriod = { + "memory.available" = "1m" + "nodefs.available" = "1m30s" + "nodefs.inodesFree" = "2m" + } + imageGCHighThresholdPercent = 85 + imageGCLowThresholdPercent = 80 + } + metadataOptions = { + httpEndpoint = "enabled" + httpProtocolIPv6 = "enabled" + httpPutResponseHopLimit = 2 + httpTokens = "required" + } + securityGroupSelectorTerms = [ + { + tags = { + Name = "${var.cluster_name}-node" + } + } + ] + subnetSelectorTerms = [ + { + tags = { + Name = var.subnets_name + "kubernetes.io/cluster/${var.cluster_name}" = "shared" + } + } + ] + tags = var.tags + } + } +} diff --git a/node_pool.tf b/node_pool.tf new file mode 100644 index 0000000..a270888 --- /dev/null +++ b/node_pool.tf @@ -0,0 +1,58 @@ +resource "kubernetes_manifest" "karpenter_node_pool" { + depends_on = [kubernetes_manifest.karpenter_node_class] + manifest = { + apiVersion = "${helm_release.karpenter.name}.sh/v1" + kind = "NodePool" + metadata = { + name = "${var.cluster_name}-${helm_release.karpenter.name}-node-pool" + annotations = { + "kubernetes.io/description" = "General purpose NodePool for generic workloads" + } + } + spec = { + template = { + spec = { + requirements = [ + { + key = "kubernetes.io/arch" + operator = "In" + values = ["amd64"] + }, + { + key = "kubernetes.io/os" + operator = "In" + values = ["linux"] + }, + { + key = "${helm_release.karpenter.name}.k8s.aws/instance-hypervisor" + operator = "In" + values = ["nitro"] + }, + { + key = "${helm_release.karpenter.name}.sh/capacity-type" + operator = "In" + values = ["spot", "on-demand"] + }, + { + key = "${helm_release.karpenter.name}.k8s.aws/instance-generation" + operator = "Gt" + values = ["2"] + } + ] + nodeClassRef = { + group = "${helm_release.karpenter.name}.k8s.aws" + kind = "EC2NodeClass" + name = "${var.cluster_name}-${helm_release.karpenter.name}-node-class" + } + expireAfter = "72h" + terminationGracePeriod = "8h" + } + } + disruption = { + consolidationPolicy = "WhenEmptyOrUnderutilized" + consolidateAfter = "30s" + } + tags = var.tags + } + } +} diff --git a/requirements.tf b/requirements.tf index 4eab89e..ae62e15 100644 --- a/requirements.tf +++ b/requirements.tf @@ -10,9 +10,9 @@ terraform { source = "hashicorp/helm" version = ">= 2.11.0" } - kubectl = { - source = "gavinbunney/kubectl" - version = ">= 1.14.0" + kubernetes = { + source = "hashicorp/kubernetes" + version = ">= 2.23.0" } } } diff --git a/variables.tf b/variables.tf index d73f57e..bd99185 100644 --- a/variables.tf +++ b/variables.tf @@ -39,19 +39,13 @@ variable "karpenter_helm_repo" { variable "karpenter_helm_chart" { description = "Which helm chart of karpenter" type = string - default = "1.0.6" + default = "1.1.1" } variable "karpenter_tag" { description = "Which tag of karpenter image" type = string - default = "1.0.6" -} - -variable "kubectl_tag" { - description = "Which tag of kubectl image" - type = string - default = "1.30.4" + default = "1.1.1" } variable "subnets_name" {