diff --git a/README.md b/README.md index acb18cf..8422a9b 100644 --- a/README.md +++ b/README.md @@ -267,7 +267,7 @@ If you provide explicit EIPs for all zones, no new aws_eip.nat_gateway_eips reso - Most of the time, except when the instance is actively being replaced, NAT traffic should be routed through the NAT instance and NOT through the NAT Gateway. You can monitor the logs for the text "Failed connectivity tests! Replacing route" to be alerted to NAT instance failures. -- There are four Elastic IP addresses for the NAT instances and four for the NAT Gateways. Be sure to add all eight addresses to any external allow lists if necessary. +- There is always (at least) one Elastic IP address per AZ for the NAT instances and one for each of the NAT Gateways. Be sure to add all addresses to any external allow lists if necessary. - If you plan on running this in a dual stack network (IPv4 and IPv6), you may notice that it takes ~10 minutes for an alternat node to start. In that case, you can use the `nat_instance_user_data_pre_install` variable to prefer IPv4 over IPv6 before running any user data. diff --git a/main.tf b/main.tf index 2029f83..c521e54 100644 --- a/main.tf +++ b/main.tf @@ -35,12 +35,10 @@ locals { : {} ) - # Must provide exactly 1 EIP per AZ - # var.nat_instance_eip_ids ignored if doesn't match AZ count - reuse_nat_instance_eips = length(var.nat_instance_eip_ids) == length(var.vpc_az_maps) - nat_instance_eip_ids = local.reuse_nat_instance_eips ? var.nat_instance_eip_ids : (var.prevent_destroy_eips ? aws_eip.protected_nat_instance_eips[*].id : aws_eip.nat_instance_eips[*].id) - nat_instance_eips = var.prevent_destroy_eips ? aws_eip.protected_nat_instance_eips : aws_eip.nat_instance_eips - nat_gateway_eips = var.prevent_destroy_eips ? aws_eip.protected_nat_gateway_eips : aws_eip.nat_gateway_eips + desired_nat_instance_eip_count = length(var.vpc_az_maps) + (var.allow_launch_before_terminating ? 1 : 0) + created_nat_instance_eip_count = var.nat_instance_eip_ids == null ? local.desired_nat_instance_eip_count : 0 + created_nat_instance_eip_resources = var.prevent_destroy_eips ? aws_eip.protected_nat_instance_eips : aws_eip.nat_instance_eips + nat_instance_eip_ids = var.nat_instance_eip_ids == null ? local.created_nat_instance_eip_resources[*].id : var.nat_instance_eip_ids created_ngw_eip_alloc_ids = try({ for az, e in aws_eip.nat_gateway_eips : az => e.id }, {}) protected_ngw_eip_alloc_ids = try({ for az, e in aws_eip.protected_nat_gateway_eips : az => e.id }, {}) @@ -53,12 +51,11 @@ locals { local.protected_ngw_eip_alloc_ids, local.explicit_ngw_eip_alloc_ids ) + created_nat_gateway_eip_resources = var.prevent_destroy_eips ? aws_eip.protected_nat_gateway_eips : aws_eip.nat_gateway_eips } resource "aws_eip" "protected_nat_instance_eips" { - count = (local.reuse_nat_instance_eips - ? 0 - : var.prevent_destroy_eips ? length(var.vpc_az_maps) : 0) + count = var.prevent_destroy_eips ? local.created_nat_instance_eip_count : 0 tags = merge(var.tags, { "Name" = "alternat-instance-${count.index}" @@ -70,9 +67,7 @@ resource "aws_eip" "protected_nat_instance_eips" { } resource "aws_eip" "nat_instance_eips" { - count = (local.reuse_nat_instance_eips - ? 0 - : (var.prevent_destroy_eips ? 0 : length(var.vpc_az_maps))) + count = var.prevent_destroy_eips ? 0 : local.created_nat_instance_eip_count tags = merge(var.tags, { "Name" = "alternat-instance-${count.index}" @@ -114,6 +109,11 @@ resource "aws_autoscaling_group" "nat_instance" { health_check_grace_period = var.enable_launch_script_lifecycle_hook ? 0 : 300 + instance_maintenance_policy { + min_healthy_percentage = var.allow_launch_before_terminating ? 100 : 0 + max_healthy_percentage = var.allow_launch_before_terminating ? 200 : 100 + } + dynamic "tag" { for_each = merge( var.tags, @@ -127,6 +127,13 @@ resource "aws_autoscaling_group" "nat_instance" { propagate_at_launch = true } } + + lifecycle { + precondition { + condition = length(local.nat_instance_eip_ids) >= local.desired_nat_instance_eip_count + error_message = "The number of provided NAT instance EIP IDs must be at least ${local.desired_nat_instance_eip_count}." + } + } } resource "aws_autoscaling_lifecycle_hook" "nat_instance_launch_script" { diff --git a/outputs.tf b/outputs.tf index 190be7b..49beec0 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,18 +1,11 @@ - output "nat_instance_eips" { - description = "List of Elastic IP addresses used by the NAT instances. This will be empty if EIPs are provided in var.nat_instance_eip_ids." - value = (local.reuse_nat_instance_eips - ? [] - : local.nat_instance_eips[*].public_ip) + description = "List of Elastic IP addresses created for the NAT instances." + value = [for eip in local.created_nat_instance_eip_resources : eip.public_ip] } output "nat_gateway_eips" { - description = "List of Elastic IP addresses used by the standby NAT gateways." - value = [ - for eip in local.nat_gateway_eips - : eip.public_ip - if var.create_nat_gateways - ] + description = "List of Elastic IP addresses created for the standby NAT gateways." + value = [for eip in local.created_nat_gateway_eip_resources : eip.public_ip] } output "nat_instance_security_group_id" { diff --git a/variables.tf b/variables.tf index 90a7533..722d01d 100644 --- a/variables.tf +++ b/variables.tf @@ -164,13 +164,9 @@ variable "nat_instance_type" { } variable "nat_instance_eip_ids" { - description = <<-EOT - Allocation IDs of Elastic IPs to associate with the NAT instances. If not specified, EIPs will be created. - - Note: if the number of EIPs does not match the number of subnets specified in `vpc_public_subnet_ids`, this variable will be ignored. - EOT + description = "Allocation IDs of Elastic IPs to associate with the NAT instances. If not specified, EIPs will be created." type = list(string) - default = [] + default = null } variable "fallback_ngw_eip_allocation_ids" { @@ -317,3 +313,9 @@ variable "enable_launch_script_lifecycle_hook" { type = bool default = false } + +variable "allow_launch_before_terminating" { + description = "Whether to allow the ASG to launch new instances before terminating others." + type = bool + default = false +} diff --git a/versions.tf b/versions.tf index dcde8d5..d6b5efd 100644 --- a/versions.tf +++ b/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.1" + required_version = ">= 1.2" required_providers { aws = {