Answers: <p>The underlaying issue was an IAM permission error. After clicking through the stack, the &quot;tasks&quot; in the cluster didn't start because of missing permissions/roles.</p>
  
Answers: CC BY-SA 4.0
Answers: 2021-12-06T19:58:09.250Z
Answers: 2021-12-06T19:58:09.250Z
Answers: Patrick
Answers: <p>I've had the same case. After hours of digging around Load Balancer, Target Group, Listener and Cluster/Service configurations, discovered the reason. It was about the <strong>production port configured in the Deployment Group</strong>.</p>
  <p>A Blue/green deployment expects the Load Balancer's listener for the app's &quot;production port&quot; to be directed to a target group so it can change that group with the other one.</p>
  <p>In my case, I had listeners for port 80, 90 (for test) and 443.</p>
  <p>The Deployment Group was configured for port 80 as the production port but the load balancer's listener for port 80 did not have a target group behind it. All it had was a re-route to 443.</p>
  <p>So the problem was about the Deployment Group configuration. I changed the production port in the Deployment Configuration to port 443 and everything started working.</p>
  
Answers: CC BY-SA 4.0
Answers: 2024-09-09T14:18:39.303Z
Answers: 2024-09-09T14:18:39.303Z
Answers: e-mre
Body: <p>I've been trying for hours to get a basic CodePipeline up and running with ECS Green/Blue. We're creating a prototype, so everything is in a single repo for now, and the <code>Dockerfile</code>, <code>taskdef.json</code>, <code>appspec.yaml</code> are all in a subfolder. I'm getting the following error:</p>
  <p><code>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:123:listener/app/api-lb/123/123</code></p>
  <p>It's a standard pipeline:</p>
  <ol>
  <li>CodeCommit</li>
  <li>CodeBuild</li>
  <li>CodeDeploy to ECS</li>
  </ol>
  <p>Commit and Build work and I'm passing the artifacts to the last step. Deployment fails though, with the error mentioned above.</p>
  <p>I have no idea what exactly the &quot;primary taskset target group&quot; is. Both target groups <em>are</em> behind a listener.</p>
  <p>I know there are Terraform modules for this, but I wanted to modify/extend this after it works, so I decided to start from scratch. Went through a dozen different articles, but I can't figure out what's wrong with my ECS config.</p>
  <p>I created a repo with all the files <a href="https://github.com/zentered/terraform-ecs-green-blue-pipeline" rel="nofollow noreferrer">here</a>, here are the relevant the lb, ecs and CodeDeploy configs:</p>
  <p><em>lb</em>:</p>
  <pre><code>resource &quot;aws_lb&quot; &quot;lb&quot; {
    name               = &quot;${var.name}-lb&quot;
    internal           = false
    load_balancer_type = &quot;application&quot;
    subnets            = [aws_default_subnet.default_az1.id, aws_default_subnet.default_az2.id]
    security_groups    = [aws_security_group.blue_green.id]
  }
  
  resource &quot;aws_lb_target_group&quot; &quot;blue&quot; {
    name        = &quot;${var.name}-blue&quot;
    port        = 80
    target_type = &quot;ip&quot;
    protocol    = &quot;HTTP&quot;
    vpc_id      = aws_default_vpc.default.id
    depends_on = [
      aws_lb.lb
    ]
    health_check {
      path                = &quot;/&quot;
      protocol            = &quot;HTTP&quot;
      matcher             = &quot;200&quot;
      interval            = &quot;10&quot;
      timeout             = &quot;5&quot;
      unhealthy_threshold = &quot;3&quot;
      healthy_threshold   = &quot;3&quot;
    }
    tags = {
      Name = var.name
    }
  }
  
  resource &quot;aws_lb_target_group&quot; &quot;green&quot; {
    name        = &quot;${var.name}-green&quot;
    port        = 80
    target_type = &quot;ip&quot;
    protocol    = &quot;HTTP&quot;
    vpc_id      = aws_default_vpc.default.id
    depends_on = [
      aws_lb.lb
    ]
    health_check {
      path                = &quot;/&quot;
      protocol            = &quot;HTTP&quot;
      matcher             = &quot;200&quot;
      interval            = &quot;10&quot;
      timeout             = &quot;5&quot;
      unhealthy_threshold = &quot;3&quot;
      healthy_threshold   = &quot;3&quot;
    }
    tags = {
      Name = var.name
    }
  }
  
  resource &quot;aws_lb_listener&quot; &quot;green&quot; {
    load_balancer_arn = aws_lb.lb.arn
    port              = &quot;80&quot;
    protocol          = &quot;HTTP&quot;
    default_action {
      type             = &quot;forward&quot;
      target_group_arn = aws_lb_target_group.green.arn
    }
    depends_on = [aws_lb_target_group.green]
  }
  
  resource &quot;aws_lb_listener&quot; &quot;blue&quot; {
    load_balancer_arn = aws_lb.lb.arn
    port              = &quot;8080&quot;
    protocol          = &quot;HTTP&quot;
    default_action {
      type             = &quot;forward&quot;
      target_group_arn = aws_lb_target_group.blue.arn
    }
    depends_on = [aws_lb_target_group.blue]
  }
  </code></pre>
  <p><em>codedeploy</em></p>
  <pre><code>resource &quot;aws_codedeploy_app&quot; &quot;app&quot; {
    compute_platform = &quot;ECS&quot;
    name             = var.name
  }
  
  resource &quot;aws_codedeploy_deployment_group&quot; &quot;group&quot; {
    app_name               = var.name
    deployment_config_name = &quot;CodeDeployDefault.ECSAllAtOnce&quot;
    deployment_group_name  = &quot;${var.name}-group-1&quot;
    service_role_arn       = aws_iam_role.codedeploy-service.arn
  
    auto_rollback_configuration {
      enabled = true
      events  = [&quot;DEPLOYMENT_FAILURE&quot;]
    }
  
    blue_green_deployment_config {
      deployment_ready_option {
        action_on_timeout = &quot;CONTINUE_DEPLOYMENT&quot;
      }
  
      terminate_blue_instances_on_deployment_success {
        action = &quot;TERMINATE&quot;
      }
    }
  
    deployment_style {
      deployment_option = &quot;WITH_TRAFFIC_CONTROL&quot;
      deployment_type   = &quot;BLUE_GREEN&quot;
    }
  
    ecs_service {
      cluster_name = aws_ecs_cluster.cluster.name
      service_name = aws_ecs_service.api.name
    }
  
    load_balancer_info {
      target_group_pair_info {
        prod_traffic_route {
          listener_arns = [aws_lb_listener.green.arn]
        }
  
        test_traffic_route {
          listener_arns = [aws_lb_listener.blue.arn]
        }
  
        target_group {
          name = aws_lb_target_group.blue.name
        }
  
        target_group {
          name = aws_lb_target_group.green.name
        }
      }
    }
  }
  </code></pre>
  <p><em>ecs</em>:</p>
  <pre><code>resource &quot;aws_ecs_cluster&quot; &quot;cluster&quot; {
    name = var.name
  
    configuration {
      execute_command_configuration {
        kms_key_id = aws_kms_key.keys.arn
        logging    = &quot;OVERRIDE&quot;
  
        log_configuration {
          cloud_watch_encryption_enabled = true
          cloud_watch_log_group_name     = aws_cloudwatch_log_group.logs.name
        }
      }
    }
  }
  
  resource &quot;aws_ecs_task_definition&quot; &quot;api&quot; {
    family                   = &quot;api&quot;
    memory                   = 512
    cpu                      = 256
    requires_compatibilities = [&quot;FARGATE&quot;]
    network_mode             = &quot;awsvpc&quot;
    execution_role_arn       = aws_iam_role.ecs-task-service.arn
  
    container_definitions = jsonencode([
      {
        name      = var.name,
        image     = &quot;${aws_ecr_repository.repo.repository_url}:latest&quot;
        essential = true
        portMappings = [
          {
            &quot;containerPort&quot; = 8080,
            &quot;hostPort&quot;      = 8080
          }
        ],
        environment = [],
        log_options = {
          awslogs-region        = var.region
          awslogs-group         = var.name
          awslogs-stream-prefix = &quot;ecs-service&quot;
        }
      }
    ])
  }
  
  resource &quot;aws_ecs_service&quot; &quot;api&quot; {
    name            = var.name
    cluster         = aws_ecs_cluster.cluster.id
    task_definition = aws_ecs_task_definition.api.arn
    launch_type     = &quot;FARGATE&quot;
    desired_count   = 1
    depends_on      = [aws_lb_listener.green, aws_lb_listener.blue, aws_iam_role_policy.ecs-service-base-policy]
  
    deployment_controller {
      type = &quot;CODE_DEPLOY&quot;
    }
  
    load_balancer {
      target_group_arn = aws_lb_target_group.blue.arn
      container_name   = var.name
      container_port   = 8080
    }
  
    network_configuration {
      subnets = [aws_default_subnet.default_az1.id, aws_default_subnet.default_az2.id, aws_default_subnet.default_az3.id]
      security_groups = [
        aws_security_group.ecs.id
      ]
      assign_public_ip = false
    }
  
    lifecycle {
      ignore_changes = [
        load_balancer,
        desired_count,
        task_definition
      ]
    }
  }
  </code></pre>
  <p>Any hints on what I'm doing wrong? Thanks!</p>
  
Comments: CC BY-SA 4.0
Comments: 2021-12-03T19:55:51.697Z
Comments: Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking.
Comments: Community
Tags: <amazon-web-services><terraform><amazon-ecs><aws-codepipeline>
Title: AWS ECS Green/Blue with CodePipeline: The ELB could not be updated due to the following error: Primary taskset target group must be behind listener
UserDisplayName: Patrick
ThreadText: # AWS ECS Green/Blue with CodePipeline: The ELB could not be updated due to the following error: Primary taskset target group must be behind listener
  
  (Asked by: username_0 on 2021-12-03)
  
  I've been trying for hours to get a basic CodePipeline up and running with ECS Green/Blue. We're creating a prototype, so everything is in a single repo for now, and the `Dockerfile`, `taskdef.json`, `appspec.yaml` are all in a subfolder. I'm getting the following error:
  
  `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:123:listener/app/api-lb/123/123`
  
  It's a standard pipeline:
  
  1. CodeCommit
  2. CodeBuild
  3. CodeDeploy to ECS
  
  Commit and Build work and I'm passing the artifacts to the last step. Deployment fails though, with the error mentioned above.
  
  I have no idea what exactly the "primary taskset target group" is. Both target groups *are* behind a listener.
  
  I know there are Terraform modules for this, but I wanted to modify/extend this after it works, so I decided to start from scratch. Went through a dozen different articles, but I can't figure out what's wrong with my ECS config.
  
  I created a repo with all the files [here](https://github.com/zentered/terraform-ecs-green-blue-pipeline), here are the relevant the lb, ecs and CodeDeploy configs:
  
  *lb*:
  
  ```
  resource "aws_lb" "lb" {
    name               = "${var.name}-lb"
    internal           = false
    load_balancer_type = "application"
    subnets            = [aws_default_subnet.default_az1.id, aws_default_subnet.default_az2.id]
    security_groups    = [aws_security_group.blue_green.id]
  }
  
  resource "aws_lb_target_group" "blue" {
    name        = "${var.name}-blue"
    port        = 80
    target_type = "ip"
    protocol    = "HTTP"
    vpc_id      = aws_default_vpc.default.id
    depends_on = [
      aws_lb.lb
    ]
    health_check {
      path                = "/"
      protocol            = "HTTP"
      matcher             = "200"
      interval            = "10"
      timeout             = "5"
      unhealthy_threshold = "3"
      healthy_threshold   = "3"
    }
    tags = {
      Name = var.name
    }
  }
  
  resource "aws_lb_target_group" "green" {
    name        = "${var.name}-green"
    port        = 80
    target_type = "ip"
    protocol    = "HTTP"
    vpc_id      = aws_default_vpc.default.id
    depends_on = [
      aws_lb.lb
    ]
    health_check {
      path                = "/"
      protocol            = "HTTP"
      matcher             = "200"
      interval            = "10"
      timeout             = "5"
      unhealthy_threshold = "3"
      healthy_threshold   = "3"
    }
    tags = {
      Name = var.name
    }
  }
  
  resource "aws_lb_listener" "green" {
    load_balancer_arn = aws_lb.lb.arn
    port              = "80"
    protocol          = "HTTP"
    default_action {
      type             = "forward"
      target_group_arn = aws_lb_target_group.green.arn
    }
    depends_on = [aws_lb_target_group.green]
  }
  
  resource "aws_lb_listener" "blue" {
    load_balancer_arn = aws_lb.lb.arn
    port              = "8080"
    protocol          = "HTTP"
    default_action {
      type             = "forward"
      target_group_arn = aws_lb_target_group.blue.arn
    }
    depends_on = [aws_lb_target_group.blue]
  }
  
  ```
  
  *codedeploy*
  
  ```
  resource "aws_codedeploy_app" "app" {
    compute_platform = "ECS"
    name             = var.name
  }
  
  resource "aws_codedeploy_deployment_group" "group" {
    app_name               = var.name
    deployment_config_name = "CodeDeployDefault.ECSAllAtOnce"
    deployment_group_name  = "${var.name}-group-1"
    service_role_arn       = aws_iam_role.codedeploy-service.arn
  
    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"
      }
    }
  
    deployment_style {
      deployment_option = "WITH_TRAFFIC_CONTROL"
      deployment_type   = "BLUE_GREEN"
    }
  
    ecs_service {
      cluster_name = aws_ecs_cluster.cluster.name
      service_name = aws_ecs_service.api.name
    }
  
    load_balancer_info {
      target_group_pair_info {
        prod_traffic_route {
          listener_arns = [aws_lb_listener.green.arn]
        }
  
        test_traffic_route {
          listener_arns = [aws_lb_listener.blue.arn]
        }
  
        target_group {
          name = aws_lb_target_group.blue.name
        }
  
        target_group {
          name = aws_lb_target_group.green.name
        }
      }
    }
  }
  
  ```
  
  *ecs*:
  
  ```
  resource "aws_ecs_cluster" "cluster" {
    name = var.name
  
    configuration {
      execute_command_configuration {
        kms_key_id = aws_kms_key.keys.arn
        logging    = "OVERRIDE"
  
        log_configuration {
          cloud_watch_encryption_enabled = true
          cloud_watch_log_group_name     = aws_cloudwatch_log_group.logs.name
        }
      }
    }
  }
  
  resource "aws_ecs_task_definition" "api" {
    family                   = "api"
    memory                   = 512
    cpu                      = 256
    requires_compatibilities = ["FARGATE"]
    network_mode             = "awsvpc"
    execution_role_arn       = aws_iam_role.ecs-task-service.arn
  
    container_definitions = jsonencode([
      {
        name      = var.name,
        image     = "${aws_ecr_repository.repo.repository_url}:latest"
        essential = true
        portMappings = [
          {
            "containerPort" = 8080,
            "hostPort"      = 8080
          }
        ],
        environment = [],
        log_options = {
          awslogs-region        = var.region
          awslogs-group         = var.name
          awslogs-stream-prefix = "ecs-service"
        }
      }
    ])
  }
  
  resource "aws_ecs_service" "api" {
    name            = var.name
    cluster         = aws_ecs_cluster.cluster.id
    task_definition = aws_ecs_task_definition.api.arn
    launch_type     = "FARGATE"
    desired_count   = 1
    depends_on      = [aws_lb_listener.green, aws_lb_listener.blue, aws_iam_role_policy.ecs-service-base-policy]
  
    deployment_controller {
      type = "CODE_DEPLOY"
    }
  
    load_balancer {
      target_group_arn = aws_lb_target_group.blue.arn
      container_name   = var.name
      container_port   = 8080
    }
  
    network_configuration {
      subnets = [aws_default_subnet.default_az1.id, aws_default_subnet.default_az2.id, aws_default_subnet.default_az3.id]
      security_groups = [
        aws_security_group.ecs.id
      ]
      assign_public_ip = false
    }
  
    lifecycle {
      ignore_changes = [
        load_balancer,
        desired_count,
        task_definition
      ]
    }
  }
  
  ```
  
  Any hints on what I'm doing wrong? Thanks!
  
  **Tags:** amazon-web-services, terraform, amazon-ecs, aws-codepipeline
  
  > **Comments:**
  > **username_1**: Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking.  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_0 on 2021-12-06. Score: 2 | Accepted answer
  
  The underlaying issue was an IAM permission error. After clicking through the stack, the "tasks" in the cluster didn't start because of missing permissions/roles.
  
  
  ---
  
  ### Answer by username_2 on 2024-09-09. Score: 0
  
  I've had the same case. After hours of digging around Load Balancer, Target Group, Listener and Cluster/Service configurations, discovered the reason. It was about the **production port configured in the Deployment Group**.
  
  A Blue/green deployment expects the Load Balancer's listener for the app's "production port" to be directed to a target group so it can change that group with the other one.
  
  In my case, I had listeners for port 80, 90 (for test) and 443.
  
  The Deployment Group was configured for port 80 as the production port but the load balancer's listener for port 80 did not have a target group behind it. All it had was a re-route to 443.
  
  So the problem was about the Deployment Group configuration. I changed the production port in the Deployment Configuration to port 443 and everything started working.
  
  
  ---
  
  