将每个 EIP 附加到 Terraform 中的每个 Nat Gateway

Attach each EIP to each Nat Gatway in Terraform

我正在创建两个 public 子网,每个子网都包含一个 nat gateay。我的代码尝试为每个子网创建这些 nats,然后将 eip 分配给每个子网。然而,由于我的 for each 启动了代码块,看起来分配 ID 变成了 us-east-* 而不是 eip 的 ID。

Variables.tf:

    variable "public_subnet_numbers" {
  type = map(number)
 
  description = "Map of AZ to a number that should be used for public subnets"
 
  default = {
    "us-east-1a" = 1
    "us-east-1b" = 2
    #"us-east-1c" = 3
  }
}
 
variable "private_subnet_numbers" {
  type = map(number)
 
  description = "Map of AZ to a number that should be used for private subnets"
 
  default = {
    "us-east-1a" = 4
    "us-east-1b" = 5
    #"us-east-1c" = 6
  }
}
 
variable "vpc_cidr" {
  type        = string
  description = "The IP range to use for the VPC"
  default     = "192.168.0.0/16"
}

Main.tf:

    resource "aws_eip" "nat" {
  count = 2
  vpc = true
 
  lifecycle {
    # prevent_destroy = true
  }
 
  tags = {
    Name        = "cf-${var.infra_env}-eip"
    Project     = "cf.io"
    Environment = var.infra_env
    VPC         = aws_vpc.vpc.id
    ManagedBy   = "terraform"
    Role        = "private"
  }
}
 

resource "aws_nat_gateway" "ngw" {
  for_each = var.private_subnet_numbers
  subnet_id = each.value.id #aws_subnet.public[each.key].id
  allocation_id = aws_eip.nat[each.key].id
 
 
  tags = {
    Name        = "cf-${var.infra_env}-ngw"
    Project     = "cf.io"
    VPC         = aws_vpc.vpc.id
    Environment = var.infra_env
    ManagedBy   = "terraform"
    Role        = "private"
  }
}

错误:

    Error: Invalid index
│ 
│   on ../terraform/modules/networking/gateways.tf line 42, in resource "aws_nat_gateway" "ngw":
│   42:   allocation_id = aws_eip.nat[each.key].id
│     ├────────────────
│     │ aws_eip.nat is tuple with 2 elements
│     │ each.key is "us-east-1a"
│ 
│ The given key does not identify an element in this collection value: a number is required.
╵
╷
│ Error: Invalid index
│ 
│   on ../terraform/modules/networking/gateways.tf line 42, in resource "aws_nat_gateway" "ngw":
│   42:   allocation_id = aws_eip.nat[each.key].id
│     ├────────────────
│     │ aws_eip.nat is tuple with 2 elements
│     │ each.key is "us-east-1b"
│ 
│ The given key does not identify an element in this collection value: a number is required.

您正在混合 countfor_each。解决这个问题的最简单方法是在您的 EIP 创建中也使用 for_each,这是有道理的,因为您正在为每个 NAT 创建一个 EIP。如果您稍后决定添加另一个子网,这也会使您的代码更好地工作,您不需要进入并将 count2 更改为 3

否则,您需要使用index functioneach值转换为索引号。

正如 Mark B 提到的,不建议混合使用 countfor_each。在您当前的设置中,仅使用 for_each 是基于 private_subnet_numbers 变量的方法。

在您的 aws_eip.nat 资源中将 count 更改为 for_each

resource "aws_eip" "nat" {
  for_each = var.private_subnet_numbers
  vpc = true
}

接下来在您的资源 aws_nat_gateway.ngw 中,您应该使用 each

引用 subnet ids
resource "aws_nat_gateway" "ngw" {
  for_each      = var.private_subnet_numbers
  subnet_id     = aws_subnet.public[each.key].id
  ....
}

为了清晰起见,代码作为一个整体

resource "aws_vpc" "vpc" {
 ... vpc configurations ...
}

resource "aws_subnet" "public" {
  for_each = var.private_subnet_numbers
  vpc_id   = aws_vpc.vpc.id
 ... subnet configurations ...
}

resource "aws_eip" "nat" {
  for_each = var.private_subnet_numbers
  vpc      = true

  lifecycle {
    # prevent_destroy = true
  }

  tags = {
    Name        = "cf-${var.infra_env}-eip"
    Project     = "cf.io"
    Environment = var.infra_env
    VPC         = aws_vpc.vpc.id
    ManagedBy   = "terraform"
    Role        = "private"
  }
}

resource "aws_nat_gateway" "ngw" {
  for_each      = var.private_subnet_numbers
  subnet_id     = aws_subnet.public[each.key].id
  allocation_id = aws_eip.nat[each.key].id


  tags = {
    Name        = "cf-${var.infra_env}-ngw"
    Project     = "cf.io"
    VPC         = aws_vpc.vpc.id
    Environment = var.infra_env
    ManagedBy   = "terraform"
    Role        = "private"
  }
}