Leverage Terraform's Dynamic Blocks to vary the target groups attached to the ECS service
Tags: alb, ecs, terraform
Published: 2022-12-07 01:25:21

Up to five ECS services can be attached to the ALB target group, [and since March of this year, the change in attach has eliminated the need to recreate the service](https://aws.amazon.com/about-aws/whats-new/2022/03/amazon-ecs-service-api-updating-elastic-load-balancers-service-registries-tag-propagation-ecs-managed-tags/). In order to attach a predefined number of blocks load_balancer multiple blocks must be defined, but I will introduce how it can be realized by utilizing [Dynamic blocks](https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks).

main.tf
```
module "module" {
  services = {
    service1 = {
      container_name    = "serviceA"
      port              = 8881
    }
    service2 = {
      container_name    = "serviceB"
      port              = 8882
    }
...
  }
  services2 = {
    service6 = {
      container_name    = "serviceF"
      port              = 8886
    }
    service7 = {
      container_name    = "serviceG"
      port              = 8887
    }
...
  }
}
```

We can attach up to five ALB target groups, so you can only define a maximum of five services in a service. Service 2, Service 3... So, I defined as.

alb.tf
```
resource "aws_alb_target_group" "services" {
  for_each                      = merge(var.services, var.services2, ...)
  name                          = "${each.key}"
  port                          = lookup(each.value, "port")
}
```

ecs.tf
```
resource "aws_ecs_service" "services" {
  dynamic "load_balancer" {
    for_each = var.services
    content {
      container_name   = load_balancer.value["container_name"]
      container_port   = aws_alb_target_group.schools[load_balancer.key].port
      target_group_arn = aws_alb_target_group.schools[load_balancer.key].arn
    }
  }
}

resource "aws_ecs_service" "services2" {
  dynamic "load_balancer" {
    for_each = var.services2
    content {
      container_name   = load_balancer.value["container_name"]
      container_port   = aws_alb_target_group.schools[load_balancer.key].port
      target_group_arn = aws_alb_target_group.schools[load_balancer.key].arn
    }
  }
}

resource "aws_ecs_task_definition" "services" {
  container_definitions = jsonencode(concat(
    [
      {
        cpu               = 0
        disableNetworking = false
        name              = "nginx"
      }
    ],
    [for name, service in var.services : merge(
      {
        cpu = 0
        disableNetworking = false
        portMappings = [
          {
            containerPort = aws_alb_target_group.service[name].port
            hostPort      = aws_alb_target_group.service[name].port
            protocol      = "tcp"
          }
        ]
        environment = [
          {
            name  = "PORT"
            value = "${tostring(aws_alb_target_group.services[name].port)}"
          }
        ]
        name              = lookup(service, "container_name")
      })
    ])
  )
}

resource "aws_ecs_task_definition" "services2" {
  container_definitions = jsonencode(concat(
    [
      {
        cpu               = 0
        disableNetworking = false
        name              = "nginx"
      }
    ],
    [for name, service in var.services2 : merge(
      {
        cpu = 0
        disableNetworking = false
        portMappings = [
          {
            containerPort = aws_alb_target_group.service[name].port
            hostPort      = aws_alb_target_group.service[name].port
            protocol      = "tcp"
          }
        ]
        environment = [
          {
            name  = "PORT"
            value = "${tostring(aws_alb_target_group.services[name].port)}"
          }
        ]
        name              = lookup(service, "container_name")
      })
    ])
  )
}
```