Terraform中为ECS服务按需创建ALB负载均衡器的问题
问题描述
在同一ECS集群下创建多个ECS服务,仅部分服务需配置前置ALB负载均衡器。已在service_config变量中添加alb_enabled标识,用于动态创建ALB目标组,但关闭该标识时,ECS服务因目标组不存在报错。不想通过拆分模块解决,寻求可行替代方案。
相关配置代码:
service_config = { "test-service-efs" = { auto_scaling = { scale_in = { max_capacity = 1 min_capacity = 1 schedule = "00 16 * * ? 2199" } scale_out = { max_capacity = 1 min_capacity = 1 schedule = "00 16 * * ? 2199" } } desired_count = 1 is_public = false name = "test-service-efs" alb_enabled = false } }
resource "aws_ecs_service" "ecs_service" { for_each = var.service_config name = "${each.value.name}-service" cluster = aws_ecs_cluster.ecs_cluster.id task_definition = aws_ecs_task_definition.ecs_task_definition[each.key].arn launch_type = "FARGATE" desired_count = each.value.desired_count network_configuration { subnets = var.private_subnets assign_public_ip = each.value.is_public security_groups = var.security_groups } load_balancer { target_group_arn = aws_alb_target_group.alb_target_group[each.key].arn container_name = each.value.name container_port = 3000 } lifecycle { ignore_changes = [task_definition, tags, desired_count ] } tags = var.tags } #Dynamically create the alb target groups for app services resource "aws_alb_target_group" "alb_target_group" { for_each = { for k, v in var.service_config : k => v if v.alb_enabled } name = "${each.value.name}-tg" port = 3000 protocol = "HTTP" target_type = "ip" vpc_id = "vpc-xxxxxxxxxxxx" }
报错信息:
Error: Invalid index on modules\ecs\main.tf line 79, in resource "aws_ecs_service" "ecs_service": 79: target_group_arn = aws_alb_target_group.alb_target_group[each.key].arn aws_alb_target_group.alb_target_group is object with no attributes each.key is "test-service-efs" The given key does not identify an element in this collection value
解决方案
方案一:使用动态块生成负载均衡配置
利用Terraform的dynamic块特性,仅当alb_enabled为true时才生成load_balancer配置块,彻底避免引用不存在的目标组。修改ECS服务资源配置如下:
resource "aws_ecs_service" "ecs_service" { for_each = var.service_config name = "${each.value.name}-service" cluster = aws_ecs_cluster.ecs_cluster.id task_definition = aws_ecs_task_definition.ecs_task_definition[each.key].arn launch_type = "FARGATE" desired_count = each.value.desired_count network_configuration { subnets = var.private_subnets assign_public_ip = each.value.is_public security_groups = var.security_groups } # 仅当alb_enabled为true时,生成load_balancer配置块 dynamic "load_balancer" { for_each = each.value.alb_enabled ? [1] : [] content { target_group_arn = aws_alb_target_group.alb_target_group[each.key].arn container_name = each.value.name container_port = 3000 } } lifecycle { ignore_changes = [task_definition, tags, desired_count ] } tags = var.tags }
核心逻辑:通过dynamic块的for_each条件判断,当alb_enabled为true时生成负载均衡配置块;为false时则不生成该块,从根源上消除无效资源引用。
方案二:使用lookup函数兼容旧版本(备选)
如果你的Terraform版本不支持动态块,可以通过lookup函数结合本地映射处理,但需注意部分旧版本对null值的兼容性:
# 先创建本地映射,关联需要ALB的服务与目标组ARN locals { alb_service_tg_arns = { for k, v in aws_alb_target_group.alb_target_group : k => v.arn } } resource "aws_ecs_service" "ecs_service" { for_each = var.service_config name = "${each.value.name}-service" cluster = aws_ecs_cluster.ecs_cluster.id task_definition = aws_ecs_task_definition.ecs_task_definition[each.key].arn launch_type = "FARGATE" desired_count = each.value.desired_count network_configuration { subnets = var.private_subnets assign_public_ip = each.value.is_public security_groups = var.security_groups } # 仅当服务开启ALB时传入有效目标组ARN;否则传入null load_balancer { target_group_arn = lookup(local.alb_service_tg_arns, each.key, null) container_name = each.value.name container_port = 3000 } lifecycle { ignore_changes = [task_definition, tags, desired_count ] } tags = var.tags }
注意:此方案在部分旧版Terraform中可能因target_group_arn为null而报错,优先推荐方案一的动态块实现。
内容的提问来源于stack exchange,提问作者Alan Rochford
相关产品推荐
相关产品推荐

