--- subcategory: "EKS (Elastic Kubernetes)" layout: "aws" page_title: "AWS: aws_eks_node_group" description: |- Manages an EKS Node Group --- # Resource: aws_eks_node_group Manages an EKS Node Group, which can provision and optionally update an Auto Scaling Group of Kubernetes worker nodes compatible with EKS. Additional documentation about this functionality can be found in the [EKS User Guide](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html). ## Example Usage ```terraform resource "aws_eks_node_group" "example" { cluster_name = aws_eks_cluster.example.name node_group_name = "example" node_role_arn = aws_iam_role.example.arn subnet_ids = aws_subnet.example[*].id scaling_config { desired_size = 1 max_size = 2 min_size = 1 } update_config { max_unavailable = 1 } # Ensure that IAM Role permissions are created before and deleted after EKS Node Group handling. # Otherwise, EKS will not be able to properly delete EC2 Instances and Elastic Network Interfaces. depends_on = [ aws_iam_role_policy_attachment.example-AmazonEKSWorkerNodePolicy, aws_iam_role_policy_attachment.example-AmazonEKS_CNI_Policy, aws_iam_role_policy_attachment.example-AmazonEC2ContainerRegistryReadOnly, ] } ``` ### Ignoring Changes to Desired Size You can utilize the generic Terraform resource [lifecycle configuration block](https://www.terraform.io/docs/configuration/meta-arguments/lifecycle.html) with `ignore_changes` to create an EKS Node Group with an initial size of running instances, then ignore any changes to that count caused externally (e.g., Application Autoscaling). ```terraform resource "aws_eks_node_group" "example" { # ... other configurations ... scaling_config { # Example: Create EKS Node Group with 2 instances to start desired_size = 2 # ... other configurations ... } # Optional: Allow external changes without Terraform plan difference lifecycle { ignore_changes = [scaling_config[0].desired_size] } } ``` ### Tracking the latest EKS Node Group AMI releases You can have the node group track the latest version of the Amazon EKS optimized Amazon Linux AMI for a given EKS version by querying an Amazon provided SSM parameter. Replace `standard` in the parameter name below with `nvidia` to retrieve the accelerated AMI version. Replace `x86_64` in the parameter name below with `arm64` to retrieve the ARM version. ```terraform data "aws_ssm_parameter" "eks_ami_release_version" { name = "/aws/service/eks/optimized-ami/${aws_eks_cluster.example.version}/amazon-linux-2023/x86_64/standard/recommended/release_version" } resource "aws_eks_node_group" "example" { cluster_name = aws_eks_cluster.example.name node_group_name = "example" version = aws_eks_cluster.example.version release_version = nonsensitive(data.aws_ssm_parameter.eks_ami_release_version.value) node_role_arn = aws_iam_role.example.arn subnet_ids = aws_subnet.example[*].id } ``` ### Example IAM Role for EKS Node Group ```terraform resource "aws_iam_role" "example" { name = "eks-node-group-example" assume_role_policy = jsonencode({ Statement = [{ Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ec2.amazonaws.com" } }] Version = "2012-10-17" }) } resource "aws_iam_role_policy_attachment" "example-AmazonEKSWorkerNodePolicy" { policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy" role = aws_iam_role.example.name } resource "aws_iam_role_policy_attachment" "example-AmazonEKS_CNI_Policy" { policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy" role = aws_iam_role.example.name } resource "aws_iam_role_policy_attachment" "example-AmazonEC2ContainerRegistryReadOnly" { policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" role = aws_iam_role.example.name } ``` ### Example Subnets for EKS Node Group ```terraform data "aws_availability_zones" "available" { state = "available" } resource "aws_subnet" "example" { count = 2 availability_zone = data.aws_availability_zones.available.names[count.index] cidr_block = cidrsubnet(aws_vpc.example.cidr_block, 8, count.index) vpc_id = aws_vpc.example.id } ``` ## Argument Reference The following arguments are required: * `cluster_name` - (Required) Name of the EKS Cluster. * `node_role_arn` - (Required) ARN of the IAM Role that provides permissions for the EKS Node Group. * `scaling_config` - (Required) Configuration block with scaling settings. See [`scaling_config`](#scaling_config-configuration-block) below for details. * `subnet_ids` - (Required) Identifiers of EC2 Subnets to associate with the EKS Node Group. The following arguments are optional: * `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `ami_type` - (Optional) Type of 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. Terraform will only perform drift detection if a configuration value is provided. * `capacity_type` - (Optional) Type of capacity associated with the EKS Node Group. Valid values: `ON_DEMAND`, `SPOT`. Terraform will only perform drift detection if a configuration value is provided. * `disk_size` - (Optional) Disk size in GiB for worker nodes. Defaults to `50` for Windows, `20` all other node groups. Terraform will only perform drift detection if a configuration value is provided. * `force_update_version` - (Optional) Force version update if existing pods are unable to be drained due to a pod disruption budget issue. * `instance_types` - (Optional) List of instance types associated with the EKS Node Group. Defaults to `["t3.medium"]`. Terraform will only perform drift detection if a configuration value is provided. * `labels` - (Optional) 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. * `launch_template` - (Optional) Configuration block with Launch Template settings. See [`launch_template`](#launch_template-configuration-block) below for details. Conflicts with `remote_access`. * `node_group_name` - (Optional) Name of the EKS Node Group. If omitted, Terraform will assign a random, unique name. Conflicts with `node_group_name_prefix`. The node group name can't be longer than 63 characters. It must start with a letter or digit, but can also include hyphens and underscores for the remaining characters. * `node_group_name_prefix` - (Optional) Creates a unique name beginning with the specified prefix. Conflicts with `node_group_name`. * `node_repair_config` - (Optional) The node auto repair configuration for the node group. See [`node_repair_config`](#node_repair_config-configuration-block) below for details. * `release_version` - (Optional) AMI version of the EKS Node Group. Defaults to latest version for Kubernetes version. * `remote_access` - (Optional) Configuration block with remote access settings. See [`remote_access`](#remote_access-configuration-block) below for details. Conflicts with `launch_template`. * `tags` - (Optional) Key-value map of resource tags. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. * `taint` - (Optional) The Kubernetes taints to be applied to the nodes in the node group. Maximum of 50 taints per node group. See [taint](#taint-configuration-block) below for details. * `update_config` - (Optional) Configuration block with update settings. See [`update_config`](#update_config-configuration-block) below for details. * `version` - (Optional) Kubernetes version. Defaults to EKS Cluster Kubernetes version. Terraform will only perform drift detection if a configuration value is provided. * `warm_pool_config` - (Optional) Configuration block with EC2 Auto Scaling warm pool settings. Including this block enables the warm pool; removing it disables and removes the warm pool. See [`warm_pool_config`](#warm_pool_config-configuration-block) below for details. ### launch_template Configuration Block ~> **NOTE:** Either `id` or `name` must be specified. * `id` - (Optional) Identifier of the EC2 Launch Template. Conflicts with `name`. * `name` - (Optional) Name of the EC2 Launch Template. Conflicts with `id`. * `version` - (Required) EC2 Launch Template version number. While the API accepts values like `$Default` and `$Latest`, the API will convert the value to the associated version number (e.g., `1`) on read and Terraform will show a difference on next plan. Using the `default_version` or `latest_version` attribute of the `aws_launch_template` resource or data source is recommended for this argument. ### node_repair_config Configuration Block * `enabled` - (Optional) Specifies whether to enable node auto repair for the node group. Node auto repair is disabled by default. Defaults to `false`. * `max_parallel_nodes_repaired_count` - (Optional) Maximum number of nodes that can be repaired concurrently or in parallel, expressed as a count of unhealthy nodes. Conflicts with `max_parallel_nodes_repaired_percentage`. * `max_parallel_nodes_repaired_percentage` - (Optional) Maximum number of nodes that can be repaired concurrently or in parallel, expressed as a percentage of unhealthy nodes. Conflicts with `max_parallel_nodes_repaired_count`. * `max_unhealthy_node_threshold_count` - (Optional) Count threshold of unhealthy nodes, above which node auto repair actions will stop. Conflicts with `max_unhealthy_node_threshold_percentage`. * `max_unhealthy_node_threshold_percentage` - (Optional) Percentage threshold of unhealthy nodes, above which node auto repair actions will stop. Conflicts with `max_unhealthy_node_threshold_count`. * `node_repair_config_overrides` - (Optional) Granular overrides for specific repair actions. See [`node_repair_config_overrides`](#node_repair_config_overrides-configuration-block) below for details. ### node_repair_config_overrides Configuration Block * `min_repair_wait_time_mins` - (Required) Minimum time in minutes to wait before attempting to repair a node with the specified `node_monitoring_condition` and `node_unhealthy_reason`. * `node_monitoring_condition` - (Required) Unhealthy condition reported by the node monitoring agent that this override applies to. * `node_unhealthy_reason` - (Required) Reason reported by the node monitoring agent that this override applies to. * `repair_action` - (Required) Repair action to take for nodes when all of the specified conditions are met. Valid values are defined by the EKS API. ### remote_access Configuration Block * `ec2_ssh_key` - (Optional) EC2 Key Pair name that provides access for remote communication with the worker nodes in the EKS Node Group. If you specify this configuration, but do not specify `source_security_group_ids` when you create an EKS Node Group, either port 3389 for Windows, or port 22 for all other operating systems is opened on the worker nodes to the Internet (0.0.0.0/0). For Windows nodes, this will allow you to use RDP, for all others this allows you to SSH into the worker nodes. * `source_security_group_ids` - (Optional) Set of EC2 Security Group IDs to allow SSH access (port 22) from on the worker nodes. If you specify `ec2_ssh_key`, but do not specify this configuration when you create an EKS Node Group, port 22 on the worker nodes is opened to the Internet (0.0.0.0/0). ### scaling_config Configuration Block * `desired_size` - (Required) Desired number of worker nodes. * `max_size` - (Required) Maximum number of worker nodes. * `min_size` - (Required) Minimum number of worker nodes. ### taint Configuration Block * `key` - (Required) The key of the taint. Maximum length of 63. * `value` - (Optional) The value of the taint. Maximum length of 63. * `effect` - (Required) The effect of the taint. Valid values: `NO_SCHEDULE`, `NO_EXECUTE`, `PREFER_NO_SCHEDULE`. ### update_config Configuration Block The following arguments are mutually exclusive. * `max_unavailable` - (Optional) Desired max number of unavailable worker nodes during node group update. * `max_unavailable_percentage` - (Optional) Desired max percentage of unavailable worker nodes during node group update. * `update_strategy` - (Optional) Strategy to use for updating the node group. Valid values: `MINIMAL` and `DEFAULT`. ### warm_pool_config Configuration Block Including a `warm_pool_config` block enables the warm pool for the node group. To disable and remove the warm pool, remove the `warm_pool_config` block. * `max_group_prepared_capacity` - (Optional) Maximum number of instances that are allowed to be in the warm pool combined with the Auto Scaling Group. Use `-1` to specify an unlimited capacity. * `min_size` - (Optional) Minimum number of instances to maintain in the warm pool. Defaults to `0`. * `pool_state` - (Optional) Instance state to transition warm pool instances to. Valid values: `STOPPED`, `RUNNING`, `HIBERNATED`. Defaults to `STOPPED`. * `reuse_on_scale_in` - (Optional) Whether to return instances in the Auto Scaling Group to the warm pool on scale in. Not supported on Bottlerocket. Defaults to `false`. ## Attribute Reference This resource exports the following attributes in addition to the arguments above: * `arn` - ARN of the EKS Node Group. * `id` - EKS Cluster name and EKS Node Group name separated by a colon (`:`). * `resources` - List of objects containing information about underlying resources. * `autoscaling_groups` - List of objects containing information about AutoScaling Groups. * `name` - Name of the AutoScaling Group. * `remote_access_security_group_id` - Identifier of the remote access EC2 Security Group. * `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block). * `status` - Status of the EKS Node Group. ## Timeouts [Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): * `create` - (Default `60m`) * `update` - (Default `60m`) * `delete` - (Default `60m`) ## Import In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute. For example: ```terraform import { to = aws_eks_node_group.example identity = { cluster_name = "example-cluster" node_group_name = "example-group" } } resource "aws_eks_node_group" "example" { ### Configuration omitted for brevity ### } ``` ### Identity Schema #### Required * `cluster_name` (String) Name of the EKS Cluster. * `node_group_name` (String) Name of the node group. #### Optional * `account_id` (String) AWS Account where this resource is managed. * `region` (String) Region where this resource is managed. In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Node Groups using the `cluster_name` and `node_group_name` separated by a colon (`:`). For example: ```terraform import { to = aws_eks_node_group.example id = "example-cluster:example-group" } ``` Using `terraform import`, import Node Groups using the `cluster_name` and `node_group_name` separated by a colon (`:`). For example: ```console % terraform import aws_eks_node_group.example example-cluster:example-group ```