TerraformでDynamicブロックを活用してECSサービスにアタッチするターゲットグループを可変させる
Tags: alb, ecs, terraform
Published: 2022-12-07 01:12:01

ECSサービスは、ALBのターゲットグループに5つまでアタッチさせることができ、[今年の3月よりアタッチの変更にあたりサービスの再作成が不要となった](https://aws.amazon.com/jp/about-aws/whats-new/2022/03/amazon-ecs-service-api-updating-elastic-load-balancers-service-registries-tag-propagation-ecs-managed-tags/)。
あらかじめ定義した数だけアタッチさせるためにはload_balancerブロックを複数定義しなければならないが、[Dynamicブロック](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
    }
...
  }
}
```

ALBのターゲットグループに5つまでしかアタッチできないため、servicesには5つのサービスの定義までしかできない。5つ単位でservices2, services3...と定義していく。

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" {
  task_definition     = aws_ecs_task_definition.service.arn
  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" {
  task_definition     = aws_ecs_task_definition.service.arn
  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")
      })
    ])
  )
}
```