ANU*_*uri 10 amazon-web-services terraform terraform-provider-aws
当尝试通过 terraform 在 AWS 中创建 elb(经典负载均衡器)时,我发送了从另一个模块创建的公共子网 ID 列表。在本例中,我有 4 个子网,跨越 3 个可用区。当我尝试运行 terraform 时,我有来自 az-1a 的 2 个子网,我收到一条错误消息same az can't be used twice for ELB
resource "aws_elb" "loadbalancer" {
name = "loadbalancer-terraform"
subnets = var.public_subnets
listener {
instance_port = 80
instance_protocol = "http"
lb_port = 80
lb_protocol = "http"
}
depends_on = [aws_autoscaling_group.private_ec2]
}
Run Code Online (Sandbox Code Playgroud)
有什么方法可以从给定列表中选择子网,这样我只能从不同的 AZ 获取子网 id。
subnetid1 -- az1-a
subnetid2 -- az1-b
subnetid3 -- az1-c
subnetid4 -- az1-a
Run Code Online (Sandbox Code Playgroud)
现在我需要获得子网 1,2 和 3 或子网 2,3 和 4 的输出。
Mar*_*ins 18
听起来这个问题分解为两个更小的问题:
对于第一步,如果我们还没有由当前配置管理的相关子网(这里似乎就是这种情况 - 您正在从输入变量接收它们),那么我们可以使用数据aws_subnet源来读取有关的信息给定其 ID 的子网。因为这里有多个子网,所以我们将使用资源for_each来查找每个子网。
data "aws_subnet" "public" {
for_each = toset(var.public_subnets)
id = each.key
}
Run Code Online (Sandbox Code Playgroud)
上面的内容将data.aws_subnet.public显示为从子网 ID 到子网对象的映射,每个子网对象都具有availability_zone指定每个子网属于哪个区域的属性。对于我们的第二步,反转该映射会更方便,因此键是可用区域,值是子网 ID:
locals {
availability_zone_subnets = {
for s in data.aws_subnet.public : s.availability_zone => s.id...
}
}
Run Code Online (Sandbox Code Playgroud)
上面是一个for表达式,在本例中使用...后缀来激活分组模式,因为我们期望每个可用区找到多个子网。因此,local.availability_zone_subnets将生成一张从可用区域名称到一个或多个子网 ID 列表的映射,如下所示:
{
"az1-a" = ["subnetid1", "subnetid4"]
"az1-b" = ["subnetid2"]
"az1-c" = ["subnetid3"]
}
Run Code Online (Sandbox Code Playgroud)
这为我们提供了实现问题第二部分所需的信息:从每个列表中选择任何一个元素。“任何一个”最简单的定义是通过使用[0]取第一个元素来取第一个。
resource "aws_elb" "loadbalancer" {
depends_on = [aws_autoscaling_group.private_ec2]
name = "loadbalancer-terraform"
subnets = [for subnet_ids in local.availability_zone_subnets : subnet_ids[0]]
listener {
instance_port = 80
instance_protocol = "http"
lb_port = 80
lb_protocol = "http"
}
}
Run Code Online (Sandbox Code Playgroud)
上述解决方案有一些需要考虑的重要注意事项:
取每个子网 id 列表的第一个元素意味着配置可能对 中 元素的顺序敏感var.public_subnets,但是上面的这种特定组合隐式地避免了toset(var.public_subnets)最初的 中的元素for_each,这会丢弃 的原始顺序var.public_subnets并导致所有下游表达式按子网 ID 的词法排序对结果进行排序。换句话说,这将在进行词法排序时选择 id 为“最低”的子网。
我真的不喜欢这种决定被隐含,因为它可能会让未来的维护人员感到困惑,他们可能会改变设计,并惊讶地发现它现在为每个可用区域选择不同的子网。我可以看到几种不同的方法来缓解这种情况,如果我正在编写一个长期存在的模块,我可能会同时使用这两种方法:
确保其类型约束是variable "public_subnets"has ,而不是,明确该模块丢弃调用者给出的子网顺序。如果这样做,您可以更改为 just ,因为它已经是一个集合了。type = set(string)type = list(string)toset(var.public_subnets)var.public_subnets
在for为每个可用区域选择第一个子网的最终表达式中,包括对 的显式调用sort。这个调用与我的示例中其余部分的实现方式是多余的,但我认为这对未来的读者来说是一个很好的线索,它使用词法排序来决定要使用哪个子网:
subnets = [
for subnet_ids in local.availability_zone_subnets : sort(subnet_ids)[0]
]
Run Code Online (Sandbox Code Playgroud)
这些更改实际上都不会立即影响行为,但是这样的添加对未来的维护人员很有帮助,因为他们阅读以前可能不熟悉的模块,因此他们不需要阅读整个模块来理解较小的部分它的。
| 归档时间: |
|
| 查看次数: |
8321 次 |
| 最近记录: |