使用每个地形在不同的 AZ 中创建不同的 EC2 实例

Creating different EC2 instances in separate AZs using for each terraform

我正在尝试使用 Terraform 在不同的 AZ 中部署不同的 EC2 实例。然后,我将 EC2 实例所在的子网关联到带有 NAT 网关的路由 table。我在将子网与路由 table 上的 nat 网关相关联时卡住了。以下是我的代码和错误。任何建议都会有所帮助。

resource "aws_instance" "private" {
  for_each      = var.priv_subnet
  ami           = var.ec2_amis[var.region]
  instance_type = each.key
  key_name      = aws_key_pair.main.key_name
  subnet_id     = aws_subnet.private[each.key].id

  tags = {
    Name = each.value.tag
  }
}

resource "aws_route_table" "nat" {
  for_each = var.pub_subnet
  vpc_id   = aws_vpc.main.id

  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.main[each.key].id
  }

  tags = {
    Name = "${var.vpc_tags}_${each.key}_PrivRT"
  }
}

resource "aws_route_table_association" "nat" {
  for_each       = aws_subnet.private
  route_table_id = aws_route_table.nat[each.key].id
  subnet_id      = each.value.id
}
resource "aws_subnet" "private" {
  for_each                = var.priv_subnet
  vpc_id                  = aws_vpc.tableau.id
  cidr_block              = cidrsubnet(aws_vpc.main.cidr_block, 8, each.value.subnet)
  availability_zone       = each.value.availability_zone
  map_public_ip_on_launch = false
  tags = {
    Name = "PrivSub-${each.value.availability_zone}"
  }
}

resource "aws_eip" "main" {
  for_each = aws_subnet.public
  vpc      = true

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_nat_gateway" "tableau" {
  for_each      = aws_subnet.public
  subnet_id     = each.value.id
  allocation_id = aws_eip.main[each.key].id
}

resource "aws_subnet" "public" {
  for_each                = var.pub_subnet
  vpc_id                  = aws_vpc.main.id
  cidr_block              = cidrsubnet(aws_vpc.main.cidr_block, 8, each.value)
  availability_zone       = each.key
  map_public_ip_on_launch = true
  tags = {
    Name = "PubSub-${each.key}"
  }
}

变量

variable "priv_subnet" {


 type = map(object({
    availability_zone = string
    subnet            = string
    tag               = string
  }))
  default = {
    "m5.2xlarge" = {
      availability_zone = "us-west-2a"
      subnet            = 4
      tag               = "Primary"
    }
    "m5.4xlarge" = {
      availability_zone = "us-west-2b"
      subnet            = 5
      tag               = "Worker1"
    }
    "m5.4xlarge" = {
      availability_zone = "us-west-2c"
      subnet            = 6
      tag               = "Worker2"
    }
  }
}

variable "pub_subnet" {
  default = {
    "us-west-2a" = 1
    "us-west-2b" = 2
    "us-west-2c" = 3
  }
}

错误

Error: Invalid index

  on vpc.tf line 99, in resource "aws_route_table_association" "nat":
  99:   route_table_id = aws_route_table.nat[each.key].id
    |----------------
    | aws_route_table.nat is object with 3 attributes
    | each.key is "m5.2xlarge"

The given key does not identify an element in this collection value.


Error: Invalid index

  on vpc.tf line 99, in resource "aws_route_table_association" "nat":
  99:   route_table_id = aws_route_table.nat[each.key].id
    |----------------
    | aws_route_table.nat is object with 3 attributes
    | each.key is "m5.4xlarge"

The given key does not identify an element in this collection value.

我理解错误消息,但不确定如何将路由适当地分配给此路由 table。

aws_route_table_association 中的 each.key 将是来自 priv_subnet 的实例类型,例如m5.2xlarge。但是,aws_route_table.nat 键将是 AZ 名称,例如 us-east-1a,来自 var.pub_subnet.

显然,这是行不通的。解决此问题的一种方法是 修改 您的 priv_subnet 变量以使用子网名称作为键,而不是实例类型。更改可能需要进一步更改您的代码。

variable "priv_subnet" {

 type = map(object({
    instance_type     = string
    subnet            = string
    tag               = string
  }))

  default = {
    "us-west-2a" = {
      instance_type = "m5.2xlarge"
      subnet            = 4
      tag               = "Primary"
    }
    "us-west-2b" = {
      instance_type     = "m5.4xlarge"
      subnet            = 5
      tag               = "Worker1"
    }
    "us-west-2c" = {
      instance_type     = "m5.4xlarge"
      subnet            = 6
      tag               = "Worker2"
    }
  }
}

这样你就会在 var.pub_subnetvar.priv_subnet 之间建立 one-to-one 关系,这在我看来会简化事情。