amazon-web-servicesamazon-ecsaws-code-deployblue-green-deployment

The ELB could not be updated due to the following error: Primary taskset target group is not behind any rule for listener


I try AWS CodeDeploy for ECS Blue/Green Deployment.

I use terraform to definition codedeploy.

this below my terraform code.

resource "aws_codedeploy_app" "ecs_dev" {
  compute_platform = "ECS"
  name             = "code-deploy-ecs-${local.env}"
}

resource "aws_codedeploy_deployment_group" "ecs_dev" {
  app_name               = aws_codedeploy_app.ecs_dev.name
  deployment_config_name = "CodeDeployDefault.ECSAllAtOnce"
  deployment_group_name  = "ecs-dev"
  service_role_arn       = aws_iam_role.code_deploy_ecs.arn

  auto_rollback_configuration {
    enabled = true
    events  = ["DEPLOYMENT_FAILURE"]
  }

  deployment_style {
    deployment_option = "WITH_TRAFFIC_CONTROL"
    deployment_type   = "BLUE_GREEN"
  }

  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 = 10
    }

  }

  ecs_service {
    cluster_name = "cluster-name"
    service_name = "ecs-dev"
  }

  load_balancer_info {
    target_group_pair_info {

      prod_traffic_route {
        listener_arns = "listener_arn" # created from aws console
      }

      # green
      target_group {
        name = "green-target-group" # created from aws console
      }

      # blue
      target_group {
        name = aws_lb_target_group.blue.name
      }
    }
  }
}

resource "aws_lb_target_group" "blue" {
  name        = "blue-target-group"
  port        = 80
  protocol    = "HTTP"
  vpc_id      = "ecs-vpc"
  target_type = "instance"

  health_check {
    interval            = 30
    timeout             = 5
    healthy_threshold   = 5
    unhealthy_threshold = 2
    protocol            = "HTTP"
    port                = "traffic-port"
    path                = each.value.health_check_path
  }
}

When I successfully configured CodeDeploy itself and deployed a new task in ECS, the following error occurred.

The ELB could not be updated due to the following error: Primary taskset target group is not behind any rule for listener

What this means is not clear to me. If there is any other information you would like to know, I will provide it.

Thank you for your time.


Solution

  • The target group for the ECS blue/green deployment should be attached to some load balancer, so add a listener and rule for the target group. In my case, I have added the listener with a fixed port by data and attach the target group by add a rule.

    # Code Deploy
    
    resource "aws_codedeploy_app" "new" {
      compute_platform = "ECS"
      name             = local.name_code_deploy
    }
    
    resource "aws_codedeploy_deployment_group" "new" {
      app_name               = aws_codedeploy_app.new.name
      deployment_group_name  = local.name_deployment_group
      deployment_config_name = "CodeDeployDefault.ECSAllAtOnce"
      service_role_arn       = "arn:${var.partition}:iam::${var.account}:role/AWSCodeDeployRoleForECS"
    
      auto_rollback_configuration {
        enabled = true
        events  = ["DEPLOYMENT_FAILURE"]
      }
    
      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 = 0
        }
      }
    
      deployment_style {
        deployment_option = "WITH_TRAFFIC_CONTROL"
        deployment_type   = "BLUE_GREEN"
      }
    
      ecs_service {
        cluster_name = data.aws_ecs_cluster.default.cluster_name
        service_name = aws_ecs_service.new.name
      }
    
      load_balancer_info {
        target_group_pair_info {
          prod_traffic_route {
            listener_arns = [data.aws_lb_listener.default.arn]
          }
          target_group {
            name = aws_lb_target_group.blue.name
          }
          target_group {
            name = aws_lb_target_group.green.name
          }
        }
      }
    }
    
    # ECS Service 
    
    resource "aws_ecs_service" "new" {
      name          = local.name_ecs_service
      cluster       = data.aws_ecs_cluster.default.id
      desired_count = var.service_count
    
      deployment_controller {
        type = "CODE_DEPLOY"
      }
    
      enable_ecs_managed_tags           = true
      enable_execute_command            = true
      launch_type                       = "FARGATE"
      scheduling_strategy               = "REPLICA"
      health_check_grace_period_seconds = 120
    
      load_balancer {
        target_group_arn = aws_lb_target_group.green.arn # Blue/Green Check!
        container_name   = local.name_ecs_container
        container_port   = var.task_port
      }
    
      network_configuration {
        subnets = var.subnets_web
        security_groups = [
          aws_security_group.ecs_service.id
        ]
        assign_public_ip = false
      }
      propagate_tags  = "SERVICE"
      task_definition = aws_ecs_task_definition.new.family
    
      lifecycle {
        ignore_changes = [
          task_definition,
          desired_count
        ]
      }
    }
    
    # ELB Listener
    
    resource "aws_lb_target_group" "blue" {
      name        = local.name_tg_blue
      port        = var.task_port
      protocol    = "HTTP"
      target_type = "ip"
      vpc_id      = data.aws_vpc.default.id
    
      health_check {
        enabled             = true
        path                = var.alb_health_path
        healthy_threshold   = 2
        unhealthy_threshold = 3
      }
    }
    
    resource "aws_lb_target_group" "green" {
      name        = local.name_tg_green
      port        = var.task_port
      protocol    = "HTTP"
      target_type = "ip"
      vpc_id      = data.aws_vpc.default.id
    
      health_check {
        enabled             = true
        path                = var.alb_health_path
        healthy_threshold   = 2
        unhealthy_threshold = 3
      }
    }
    
    resource "aws_lb_listener_rule" "new" {
      listener_arn = data.aws_lb_listener.default.arn
    
      action {
        type             = "forward"
        target_group_arn = aws_lb_target_group.green.arn # Blue/Green Check!
      }
    
      condition {
        host_header {
          values = var.alb_domain
        }
      }
    }
    
    # Other resources
    
    data "aws_vpc" "default" {
      id = var.vpc_id
    }
    
    data "aws_ecs_cluster" "default" {
      cluster_name = var.cluster_name
    }
    
    data "aws_lb" "default" {
      name = var.alb_front_name
    }
    
    data "aws_lb_listener" "default" {
      load_balancer_arn = data.aws_lb.default.arn
      port = var.listener_port
    }