aws_lb 的动态子网映射
Posted
技术标签:
【中文标题】aws_lb 的动态子网映射【英文标题】:Dynamic subnet mappings for aws_lb 【发布时间】:2018-08-23 09:09:59 【问题描述】:我正在尝试使用 Terraform 创建一个网络负载平衡器,重要的是它与受保护不被破坏的弹性 IP 相关联。
我的代码如下:
resource "aws_lb" "balancer"
name = "$var.name-nlb"
internal = "$var.internal"
load_balancer_type = "network"
subnets = ["$data.aws_subnet_ids.selected.ids"]
subnet_mapping
subnet_id = "someid"
allocation_id = "someid"
subnet_mapping
subnet_id = "someid"
allocation_id = "someid"
subnet_mapping
subnet_id = "someid"
allocation_id = "someid"
tags = "$merge(var.tags,
map("Terraform", "true"),
map("Environment", var.environment))"
我所追求的是动态地制作subnet_mapping
块,因为此代码位于模块中,我想根据传入的子网数量创建映射数量。或者传入预定义的块。
有没有办法做到这一点?对我来说重要的是相关的弹性 IP 需要保留。
【问题讨论】:
您真的有不同数量的子网的案例吗?您是否在具有不同数量可用区的多个区域中运行?如果没有,您可以简化很多事情。 取决于,它是我发布到内部存储库的一个模块,我无法假设其他人如何使用它。 不,我不能做出这样的假设,这不是我要问的。所以真正的问题是,我要问的实际上是可能的,因为如果不是(你不能使用 count)那么你是对的,你可以简化它。 那么答案是否定的。 Terraform 目前不允许您动态设置子资源计数。 @krystanhonour 我使用 random_shuffle 管理动态子网,我使用 lifecyle 忽略与子网相关的更改。同样,这很乏味,因为您需要一次又一次地污染 random_shuffle 模块。这就是我管理分散在多个可用区的基础设施的方式。 【参考方案1】:您可以使用 Terraform 0.12 中的动态块功能。
resource "aws_lb" "balancer"
name = "$var.name-nlb"
load_balancer_type = "network"
dynamic "subnet_mapping"
for_each = aws_subnet.public.*.id
content
subnet_id = subnet_mapping.value
allocation_id = aws_eip.lb[subnet_mapping.key].id
【讨论】:
是的,最近这已成为一个非问题,将接受这一点,因为升级到新的闪亮修复了问题及其最干净的解决方案。正如在先前接受的答案中提到的那样【参考方案2】:正如Hendrik's answer 中所述,现在可以通过使用dynamic
blocks 功能在 Terraform 0.12 中实现:
文档中显示了比上述链接答案更简单的示例:
resource "aws_security_group" "example"
name = "example" # can use expressions here
dynamic "ingress"
for_each = var.service_ports
content
from_port = ingress.value
to_port = ingress.value
protocol = "tcp"
原文:
Terraform 目前不允许您在资源节/子资源上使用 count
元参数。
有一个issue tracking this on Github,但目前还没有任何工作正在处理它 AFAIK。
在该线程 (apparentlymart) 中回复的 Hashicorp 员工目前正在开发新版本的 HCL,该版本将来可能会支持类似的功能。
【讨论】:
谢谢,烦人,但看起来我不是唯一需要这个的人。【参考方案3】:一个非常丑陋的解决方案可能是为每个可能数量的 AZ 创建一个资源。 ex(代码未经测试):
data "aws_availability_zones" "available"
resource "aws_lb" "lb_2_azs"
count = "$length(data.aws_availability_zones.available.names) == 2 ? 1 : 0 "
... all the rest of the stuff here ...
resource "aws_lb" "lb_3_azs"
count = "$length(data.aws_availability_zones.available.names) == 3 ? 1 : 0 "
... all the rest of the stuff here ...
然后在您的模块中输出类似这样的东西可能会起作用:
output "lb_id"
value = "$element(concat(aws_lb.lb_2_azs.*.id, aws_lb.lb_3_azs.*.id, list("")), 0)"
如何处理监听器和 LB 可能需要的其他资源:
resource "aws_lb_listener" "listener"
count = "$length(concat(aws_lb.lb_2_azs.*.id, aws_lb.lb_3_azs.*.id))"
load_balancer_arn = "$element(concat(aws_lb.lb_2_azs.*.id, aws_lb.lb_3_azs.*.id, list("")), 0)"
... rest of the resource settings ...
我还没有测试过之前的代码,但这里有一些我知道是可行的。我有一个 consul 模块,如果它不用于保险库,它会创建一个 NLB:
resource "aws_lb" "consul"
name = "$var.lb_name"
count = "$var.for_vault ? 0 : 1"
internal = true
subnets = ["$var.subnet_ids"]
load_balancer_type = "network"
idle_timeout = 60
resource "aws_lb_listener" "consul"
count = "$var.for_vault ? 0 : 1"
load_balancer_arn = "$aws_lb.consul.arn"
port = 8500
protocol = "TCP"
default_action
target_group_arn = "$aws_lb_target_group.consul.arn"
type = "forward"
您可以对 aws_lb_target_group 和您需要的任何其他资源使用相同的计数技巧来引用任何 aws_lb 资源。
【讨论】:
你如何处理监听器规则和目标组?您需要为此参考 aws_lb 资源的 Arn,如果它不存在,因为它不是由 count 为 0 创建的,则 Terraform 将出错。以上是关于aws_lb 的动态子网映射的主要内容,如果未能解决你的问题,请参考以下文章
在linux中,啥是配置静态和动态的IP地址、子网掩码、默认网关,如何实现