Skip to main content
The self-managed-node-group sub-module creates an EC2 Auto Scaling Group that bootstraps into an EKS cluster. Unlike EKS managed node groups, self-managed node groups give you full control over the ASG configuration, including mixed instance policies, lifecycle hooks, instance refresh strategies, and detailed scaling metrics. The module is called internally by the root EKS module for each entry in the self_managed_node_groups variable, or it can be used standalone.

Auto Scaling Group

Full ASG configuration including mixed instances policy, lifecycle hooks, capacity rebalancing, instance refresh, and scaling metrics.

Launch Template

EC2 launch template with full control over AMI, instance type, EBS volumes, network interfaces, metadata options, and placement.

IAM Instance Profile

An IAM role and instance profile with standard EKS node policies. Automatically registers an EKS access entry so nodes can join the cluster.

Security Group

Dedicated security group with configurable ingress and egress rules.

Usage

Key inputs

Cluster connectivity

cluster_name
string
required
Name of the EKS cluster. Used in the bootstrap user data.
cluster_endpoint
string
HTTPS endpoint of the EKS cluster API server. Required for bootstrap user data generation.
cluster_auth_base64
string
Base64-encoded cluster certificate authority data. Required for bootstrap user data generation.
cluster_service_cidr
string
Service CIDR of the EKS cluster. Used to configure the node’s IP routing for cluster services.

Auto Scaling Group

min_size
number
default:"1"
Minimum number of instances in the ASG.
max_size
number
default:"3"
Maximum number of instances in the ASG.
desired_size
number
default:"1"
Desired number of instances.
subnet_ids
list(string)
Subnet IDs across which the ASG distributes instances.
use_mixed_instances_policy
bool
default:"false"
Use a mixed instances policy to blend Spot and On-Demand instances with multiple instance types.
mixed_instances_policy
object({...})
Configuration for the mixed instances policy. Includes instances_distribution (On-Demand base capacity, Spot strategy) and launch_template.override (list of instance types).
instance_refresh
object({...})
Rolling instance refresh configuration. Defaults to strategy = "Rolling" with min_healthy_percentage = 66.
capacity_rebalance
bool
Enable proactive capacity rebalancing for Spot instances. AWS will launch a replacement Spot instance before the existing one is interrupted.
protect_from_scale_in
bool
default:"false"
Protect instances from scale-in termination. Useful when using Karpenter or another external autoscaler that manages termination.
termination_policies
list(string)
default:"[]"
Ordered list of policies for determining which instances to terminate during scale-in. Valid values: OldestInstance, NewestInstance, OldestLaunchTemplate, AllocationStrategy, Default.
enabled_metrics
list(string)
default:"[]"
CloudWatch ASG metrics to enable. Available metrics include GroupDesiredCapacity, GroupInServiceInstances, GroupTotalInstances, and more.
initial_lifecycle_hooks
list(object({...}))
Lifecycle hooks to attach to the ASG before instances launch. Useful for custom initialization or draining logic.

Launch template

instance_type
string
default:"m6i.large"
EC2 instance type for the launch template. Mutually exclusive with instance_requirements.
ami_id
string
Custom AMI ID. When omitted, the module looks up the latest EKS-optimized AMI via SSM based on ami_type and kubernetes_version.
ami_type
string
default:"AL2023_x86_64_STANDARD"
AMI family to use for automatic AMI lookup. Common values: AL2023_x86_64_STANDARD, AL2023_ARM_64_STANDARD, BOTTLEROCKET_x86_64.
kubernetes_version
string
Kubernetes version used to look up the default AMI when ami_id is not provided.
block_device_mappings
map(object({...}))
EBS volume configurations for root and additional volumes.
metadata_options
object({...})
IMDSv2 settings. Defaults to http_tokens = "required" (IMDSv2 enforced).
enable_efa_support
bool
default:"false"
Enable Elastic Fabric Adapter (EFA) network interfaces for HPC and tightly-coupled workloads.

Bootstrap

pre_bootstrap_user_data
string
Script injected before the EKS bootstrap script. Not applicable to Bottlerocket AMIs.
post_bootstrap_user_data
string
Script appended after the EKS bootstrap script.
bootstrap_extra_args
string
Additional arguments passed to the bootstrap script. For Bottlerocket, these are TOML settings.

IAM

create_iam_instance_profile
bool
default:"true"
Create a new IAM instance profile. Set to false and provide iam_instance_profile_arn to use an existing profile.
iam_instance_profile_arn
string
ARN of an existing IAM instance profile. Required when create_iam_instance_profile = false.
iam_role_additional_policies
map(string)
default:"{}"
Additional managed policies to attach to the node IAM role.
create_access_entry
bool
default:"true"
Create an EKS access entry for the node IAM role so that instances can join the cluster. Set to false when you manage access entries externally.

Key outputs

OutputDescription
autoscaling_group_idID of the Auto Scaling Group
autoscaling_group_arnARN of the Auto Scaling Group
autoscaling_group_nameName of the Auto Scaling Group
autoscaling_group_min_sizeConfigured minimum size
autoscaling_group_max_sizeConfigured maximum size
autoscaling_group_desired_capacityConfigured desired capacity
iam_role_arnARN of the node IAM role
iam_role_nameName of the node IAM role
iam_instance_profile_arnARN of the EC2 instance profile
launch_template_idID of the EC2 launch template
launch_template_arnARN of the EC2 launch template
launch_template_nameName of the EC2 launch template
launch_template_latest_versionLatest version number
security_group_idID of the node security group
security_group_arnARN of the node security group
image_idAMI ID resolved and used by the launch template
user_dataBase64-encoded user data rendered for the instances
access_entry_arnARN of the EKS access entry
Self-managed nodes require explicit bootstrap configuration (cluster_endpoint and cluster_auth_base64). The root EKS module passes these automatically; when calling the sub-module standalone you must supply them from module.eks.* outputs.
The instance_refresh block defaults to a rolling strategy with min_healthy_percentage = 66. Changing the launch template will automatically trigger an instance refresh. Ensure your workloads tolerate rolling restarts before applying changes in production.

Build docs developers (and LLMs) love