Terraform AWS subnet_id 列表被视为 ec2 实例的单值字符串
Posted
技术标签:
【中文标题】Terraform AWS subnet_id 列表被视为 ec2 实例的单值字符串【英文标题】:Terraform AWS subnet_id list is treated as single value string for ec2 instance 【发布时间】:2019-09-26 18:59:35 【问题描述】:我有创建 VPC 的代码,其中有 2 个私有子网、2xec2 私有实例和公共堡垒。
ec2 代码使用 VPC 模块 subnet_ids 的 output.tf。由于有 2 个私有子网,因此生成了 2 个子网 ID。当这些生成的子网 ID 被输入到 ec2 实例而不是一个子网 ID 时,它会同时输入 2 个子网 ID 作为单个值。
结果 terraform 找不到该子网 ID 值,创建失败。
错误: 子网 ID 'subnet-0*************,subnet-0*************' 不存在
编辑子网* vpc.tf
private_subnets = "10.10.20.#/#,10.10.20.#/#"
instanceec2.tf
subnet_id = "$module.vpc.private_subnets"
以下是模块:
vpc_main.tf
// Private subnet/s
resource "aws_subnet" "private"
vpc_id = "$aws_vpc.vpc.id"
cidr_block = "$element(split(",", var.private_subnets), count.index)"
availability_zone = "$element(split(",", var.azs), count.index)"
count = "$length(split(",", var.private_subnets))"
tags
Name = "$var.name-private-$element(split(",", var.azs), count.index)"
Team = "$var.team"
Environment = "$var.environment"
Service = "$var.service"
Product = "$var.product"
Owner = "$var.owner"
Description = "$var.description"
managed_by = "terraform"
resource "aws_route_table" "private"
vpc_id = "$aws_vpc.vpc.id"
count = "$length(split(",", var.private_subnets))"
tags
Name = "$var.name-private-$element(split(",", var.azs), count.index)"
Team = "$var.team"
Environment = "$var.environment"
Service = "$var.service"
Product = "$var.product"
Owner = "$var.owner"
Description = "$var.description"
managed_by = "terraform"
resource "aws_route_table_association" "private"
subnet_id = "$element(aws_subnet.private.*.id, count.index)"
route_table_id = "$element(aws_route_table.private.*.id, count.index)"
count = "$length(split(",", var.private_subnets))"
``````
vpc_outputs.tf
```````
output "private_subnets"
value = "$join(",", aws_subnet.private.*.id)"
期望值只有一个子网ID作为值:
错误:提供 2 个子网 ID 作为一个值。
aws_instance.ec2-instance[0]:发生 1 个错误:
aws_instance.ec2-instance.0:启动源实例时出错:InvalidSubnetID.NotFound:子网 ID 'subnet-0**********,subnet-0********* **' 不存在【问题讨论】:
错误是否来自 terraform plan -out vpc-main.tf?如果不是,该命令提供什么输出? 错误来自 terraform apply。该命令提供私有子网 ID。 【参考方案1】:您将在输出变量中加入子网 ID:
output "private_subnets"
value = "$join(",", aws_subnet.private.*.id)"
当您从 instanceec2.tf
访问此输出值时,您将只会收到此连接的 ID 字符串。
因此,您必须再次像以前一样删除收到的值,并使用您的 ec2 资源的计数索引访问相应的个人 ID:
resource "aws_instance" "default"
count = "$length(split(",", module.vpc.private_subnets))"
subnet_id = "$element(split(",", module.vpc.private_subnets), count.index)"
....
这应该可以解决你的问题。
或者,您也可以将子网 ID 直接输出为列表:
output "private_subnets"
description = "The IDs of the private subnets as list"
value = ["$aws_subnet.private.*.id"]
然后通过以下方式访问它们:
subnet_id = "$element(module.vpc.private_subnets, count.index)"
【讨论】:
count.index 不起作用,因为 outputs.tf 属于 VPC 模块,我在不同的模块 ec2.tf 中使用该输出。 当然可以,但我认为您也会在 EC2 实例资源定义中使用count = ...
。您还可以为大于 ID 数组长度的实例指定计数。例如,计数为 3 时,Terraform 会将子网 0 分配给实例 0,子网 1 分配给实例 1,子网 0 再次分配给实例 3,依此类推。
"Join" 和 "Split" 对我有用,'list' 和 'element' 方式不是。非常感谢!【参考方案2】:
由于您已“加入”结果,如果您只需要一个子网值,则必须再次拆分。 类似的东西:
element(split(",", var.private_subnets), 0)
【讨论】:
我想给多个子网,但作为一个值。我有 2 个子网,其中 ec2 实例必须存在。它也应该是动态的,不指定 0、1 等。 每个 ec2 实例只能驻留在一个子网中。它不能跨越多个子网。 是有道理的,那么如何在位于不同 AZ 的实例之间进行同步呢?两个 AZ 是否具有相同的 VPC_ids、subnet_ids 和 instance_id 以及相同的实例。 2AZ 是否意味着克隆?所有属性都一样??非常感谢您的回答。 实例之间的同步是什么意思?以上是关于Terraform AWS subnet_id 列表被视为 ec2 实例的单值字符串的主要内容,如果未能解决你的问题,请参考以下文章
使用 terraform 在非默认 VPC 中创建 AWS RDS 实例