I am using terraform, to deploy blue-green for a ECS service failing with The ELB could not be updated due to the following error: Primary taskset target group must be behind listener arn:aws:elasticloadbalancing:eu-west-1:12345674865:listener-rule/app/alb/123/456/789.

Since there are multiple ecs service I deploy, I therefore have modules and these are called from service directory.

I have modules for

code-depoly

resource "aws_codedeploy_app" "ecs" {
  compute_platform = "ECS"
  name             = "${var.service_name}-ecs-app"
}

resource "aws_codedeploy_deployment_config" "config_deploy" {
  deployment_config_name = "${var.service_name}-ecs-app"
  compute_platform       = "ECS"

  traffic_routing_config {
    type = "AllAtOnce"
  }
}

resource "aws_codedeploy_deployment_group" "ecs" {
  app_name               = aws_codedeploy_app.ecs.name
  deployment_group_name  = "${var.app_name}-dg"
  deployment_config_name = aws_codedeploy_deployment_config.config_deploy.deployment_config_name
  service_role_arn       = aws_iam_role.codedeploy.arn

  blue_green_deployment_config {
    deployment_ready_option {
      action_on_timeout = "CONTINUE_DEPLOYMENT"
    }

    terminate_blue_instances_on_deployment_success {
      action                           = "TERMINATE"
      termination_wait_time_in_minutes = 1

    }
  }

  ecs_service {
    cluster_name = var.cluster_name
    service_name = var.service_name
  }

  deployment_style {
    deployment_option = "WITH_TRAFFIC_CONTROL"
    deployment_type   = "BLUE_GREEN"
  }
  auto_rollback_configuration {
    enabled = true
    events  = ["DEPLOYMENT_FAILURE"]
  }

  load_balancer_info {
    target_group_pair_info {
      prod_traffic_route {
        listener_arns = [var.listener_arn]
      }

      target_group {
        name = var.target_group_blue 
      }

      target_group {
        name = var.target_group_green
      }
    }
  }
}

resource "aws_iam_role" "codedeploy" {
  name               = "rol-codedeploy-${var.service_name}"
  assume_role_policy = data.aws_iam_policy_document.assume_by_codedeploy.json
}

resource "aws_iam_role_policy" "codedeploy" {
  name = "pol-codedeploy-${var.service_name}"
  role   = aws_iam_role.codedeploy.name
  policy = data.aws_iam_policy_document.codedeploy.json
}

resource "local_file" "appspec_yaml" {

  content = templatefile("${path.module}/appspec.yaml.tftpl", {

    code_deploy_app_name   = aws_codedeploy_app.ecs.name
    code_deploy_group_name = aws_codedeploy_deployment_group.ecs.deployment_group_name
    task_def_arn           = var.task_definition
    container_port         = var.container_port
  })
  filename = "${path.module}/appspec.yaml"
}

}

ecs_service_blue_green


resource "aws_ecs_service" "blue_green" {
  count                 = var.create_blue_green ? 1 : 0
  name                  = var.name
  cluster               = var.cluster
  force_new_deployment  = var.force_new_deployment
  wait_for_steady_state = var.wait_for_steady_state
  # Use latest active revision
  task_definition                    = var.task_definition
  propagate_tags                     = "TASK_DEFINITION"
  desired_count                      = var.desired_count
  deployment_minimum_healthy_percent = var.deployment_minimum_healthy_percent
  deployment_maximum_percent         = var.deployment_maximum_percent
  health_check_grace_period_seconds  = try(var.health_check_grace_period_seconds, 10)
  scheduling_strategy                = "REPLICA"
  launch_type                        = try(var.launch_type, null)

  /* deployment_circuit_breaker {
    rollback = false
    enable   = false
  } */


  deployment_controller {
    type = var.deployment_controller
  }

  network_configuration {
    subnets          = var.subnets
    security_groups  = var.security_groups
    assign_public_ip = var.assign_public_ip
  }

  dynamic "load_balancer" {
    for_each = var.load_balancer
    content {
      container_name   = lookup(load_balancer.value, "container_name", null)
      target_group_arn = lookup(load_balancer.value, "target_group_arn", null)
      container_port   = lookup(load_balancer.value, "container_port", null)
    }
  }

  dynamic "service_registries" {
    for_each = var.service_registries
    content {
      registry_arn   = lookup(service_registries.value, "registry_arn", null)
      container_name = lookup(service_registries.value, "container_name", null)
      container_port = lookup(service_registries.value, "container_port", null)
      port           = lookup(service_registries.value, "port", null)
    }
  }

  dynamic "capacity_provider_strategy" {
    for_each = var.capacity_provider_strategy
    content {
      capacity_provider = try(capacity_provider_strategy.value.capacity_provider, null)
      weight            = try(capacity_provider_strategy.value.weight, null)
      base              = lookup(capacity_provider_strategy.value, "base", null)
    }
  }

  tags = merge(
    {
      "Name" = var.name
    },
    var.tags,
    var.ecs_service_tags,
  )
  timeouts {
    create = try(var.timeouts.create, null)
    update = try(var.timeouts.update, null)
    delete = try(var.timeouts.delete, null)
  }

  lifecycle {
    ignore_changes = [capacity_provider_strategy, desired_count, task_definition, load_balancer ]
  }

}

Service creation

locals{
  tg_routing = {
    blue  = 80
    green = 8080
  }

  default_tg_routing = {
    blue = 80
  }

  target_group = var.create_blue_green ? local.tg_routing : local.default_tg_routing
  deployment_controller = var.create_blue_green ? "CODE_DEPLOY" : "ECS"



module "service" {
  source                             = "../../modules/ecs-service"
  create_blue_green                  = var.create_blue_green
  depends_on                         = [module.target_groups]
  name                               = "${local.name}-service-01"
  cluster                            = var.cluster_arn
  task_definition                    = aws_ecs_task_definition.this.arn
  desired_count                      = var.desired_count
  deployment_minimum_healthy_percent = "100"
  deployment_maximum_percent         = "200"
  subnets                            = data.aws_subnets.workload.ids
  security_groups                    = [module.service_security_group.id]
  wait_for_steady_state              = local.wait_for_steady_state
  load_balancer = [{
    container_name   = "ServiceContainer"
    target_group_arn = module.target_groups["blue"].arn
    container_port   = var.container_port
  }]
  deployment_controller      = local.deployment_controller
  capacity_provider_strategy = [var.capacity_provider]
  tags                       = var.tags
  ecs_service_tags           = { Description = "${var.app_name} application Service.", Environment = terraform.workspace }
}

module "target_groups" {
  for_each = local.target_group
  source                        = "../../modules/lb-target-group"
  vpc_id                        = data.aws_vpc.vpc.id
  name                          = "${local.stage_code}-${var.app_name}-tg-${each.key}"
  port                          = "${each.value}"
  protocol                      = "HTTP"
  target_type                   = "ip"
  load_balancing_algorithm_type = "round_robin"

  health_check = [{
    enabled             = true
    interval            = 30
    path                = "/${var.app_name}/health-check"
    port                = "traffic-port"
    healthy_threshold   = 3
    unhealthy_threshold = 3
    timeout             = 6
    protocol            = "HTTP"
    matcher             = "200-399"
  }]

  tags = {
    createdby = "terraform"
    owner     = "DevOps"
  }

  target_group_tags = {
    targetgroup = "${local.stage_code}-${var.app_name}-tg"
  }
}


module "listener-rule_blue" {
  source       = "../../modules/lb-listener-rule"
  listener_arn = var.listener_arn

  actions = [{
    type             = "forward"
    target_group_arn = module.target_groups["blue"].arn
  }]

  conditions = [{
    path_patterns = ["/${var.app_name}/*"]
  }]

}



resource "aws_alb_listener" "lb_listener_8080" {
  load_balancer_arn = "arn:aws:elasticloadbalancing:eu-west-1:123456789:loadbalancer/app/alb/123"
  port              = "8080"
  protocol          = "HTTP"
  default_action {
    type = "fixed-response"

    fixed_response {
      content_type = "text/plain"
      message_body = "Not found."
      status_code  = "404"
    }
  }
  lifecycle {
    ignore_changes = [default_action]
  }
}

module "listener-rule_green" {
  source       = "../../modules/lb-listener-rule"
  listener_arn = aws_alb_listener.lb_listener_8080.arn

  actions = [{
    type             = "forward"
    target_group_arn = module.target_groups["blue"].arn
  }]

  conditions = [{
    path_patterns = ["/${var.app_name}/*"]
  }]
}

I expect the service to be created with new task definition revision and the blue green swap to happen. Any help would be greatly appreciated.

0

There are 0 best solutions below