diff --git a/README.md b/README.md index 368326f..681e1a2 100644 --- a/README.md +++ b/README.md @@ -486,7 +486,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple | [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 | | [deletion\_protection](#input\_deletion\_protection) | Whether to enable deletion protection for the cluster. When enabled, the cluster cannot be deleted unless deletion protection is first disabled | `bool` | `null` | no | -| [eks\_managed\_node\_groups](#input\_eks\_managed\_node\_groups) | Map of EKS managed node group definitions to create |
map(object({
create = optional(bool)
kubernetes_version = optional(string)

# EKS Managed Node Group
name = optional(string) # Will fall back to map key
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)
max_parallel_nodes_repaired_count = optional(number)
max_parallel_nodes_repaired_percentage = optional(number)
max_unhealthy_node_threshold_count = optional(number)
max_unhealthy_node_threshold_percentage = optional(number)
node_repair_config_overrides = optional(list(object({
min_repair_wait_time_mins = number
node_monitoring_condition = string
node_unhealthy_reason = string
repair_action = 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)
}))
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) # Will fall back to map key
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
launch_template_default_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
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
})))
})))
# 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))
}))
| `null` | no | +| [eks\_managed\_node\_groups](#input\_eks\_managed\_node\_groups) | Map of EKS managed node group definitions to create |
map(object({
create = optional(bool)
kubernetes_version = optional(string)

# EKS Managed Node Group
name = optional(string) # Will fall back to map key
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)
max_parallel_nodes_repaired_count = optional(number)
max_parallel_nodes_repaired_percentage = optional(number)
max_unhealthy_node_threshold_count = optional(number)
max_unhealthy_node_threshold_percentage = optional(number)
node_repair_config_overrides = optional(list(object({
min_repair_wait_time_mins = number
node_monitoring_condition = string
node_unhealthy_reason = string
repair_action = 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)
update_strategy = optional(string)
}))
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) # Will fall back to map key
launch_template_use_name_prefix = optional(bool)
launch_template_version = optional(string)
launch_template_default_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
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
})))
})))
# 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))
}))
| `null` | 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 | diff --git a/modules/eks-managed-node-group/README.md b/modules/eks-managed-node-group/README.md index f3ca2fb..453410c 100644 --- a/modules/eks-managed-node-group/README.md +++ b/modules/eks-managed-node-group/README.md @@ -190,7 +190,7 @@ module "eks_managed_node_group" { | [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 |
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\_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)
update_strategy = optional(string)
})
|
{
"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 `kubernetes_version` must be supplied in order to enable this feature | `bool` | `true` | no | diff --git a/modules/eks-managed-node-group/main.tf b/modules/eks-managed-node-group/main.tf index aa9bd93..e153147 100644 --- a/modules/eks-managed-node-group/main.tf +++ b/modules/eks-managed-node-group/main.tf @@ -510,6 +510,7 @@ resource "aws_eks_node_group" "this" { content { max_unavailable_percentage = update_config.value.max_unavailable_percentage max_unavailable = update_config.value.max_unavailable + update_strategy = update_config.value.update_strategy } } diff --git a/modules/eks-managed-node-group/variables.tf b/modules/eks-managed-node-group/variables.tf index 7f5180f..430d146 100644 --- a/modules/eks-managed-node-group/variables.tf +++ b/modules/eks-managed-node-group/variables.tf @@ -565,6 +565,7 @@ variable "update_config" { type = object({ max_unavailable = optional(number) max_unavailable_percentage = optional(number) + update_strategy = optional(string) }) default = { max_unavailable_percentage = 33 diff --git a/variables.tf b/variables.tf index 252f154..d3eab6a 100644 --- a/variables.tf +++ b/variables.tf @@ -1276,6 +1276,7 @@ variable "eks_managed_node_groups" { update_config = optional(object({ max_unavailable = optional(number) max_unavailable_percentage = optional(number) + update_strategy = optional(string) })) timeouts = optional(object({ create = optional(string)