Search code examples
amazon-web-servicesamazon-ecsterraform-provider-awsblue-green-deployment

How can I update and ECS service adding an addition load balance to which a service talks to without downtime?


We use terraform to manage our AWS resources and have the code to change the service from one to two load balancers.

However, terraform wants to destroy the service prior to recreating it. AWS cli docs indicate the reason - the API can only modify LBs during service creation and not on update.

It seems we need a blue/green deploy with the one LB and two LB services existing at the same time on the same cluster. I expect we'll need to create multiple task sets and the rest of the blue/green approach prior to this change (we'd planned for this anyway just not at this moment)

Does anyone have a good example for this scenario or know of any other approaches beyond full blue/green deployment?


Solution

  • As of June 2024 it's possible to update (add/remove) load balancers for ECS service using simple JS script. I have the same problem and AWS CLI doesn't have option to update load balancers for existing service but you can use AWS SDK for JS and AWS CloudShell to run JS script.

    I created simple script which updates load balancers for given ECS service. Before running it you must create target group and assign it to load balancer. After that copy ARN of target group(s) you like to assign service to into below script.

    Before running script, install AWS SDK for JS version 3 using: npm i @aws-sdk/client-ecs

    In below code I marked using TODO places where you need to put container details, cluster name and target groups:

    import { ECSClient, UpdateServiceCommand } from "@aws-sdk/client-ecs";
    const client = new ECSClient();
    
    const containerName = 'YOUR CONTAINER NAME' // TODO
    const containerPort = 80 // TODO: change it if needed
    
    const input = {
      service: 'YOUR SERVICE NAME', // TODO
      cluster: 'YOUR_CLUSTER_NAME', // TODO
      loadBalancers: [
        {
          "targetGroupArn": "arn:aws:elasticloadbalancing:eu-west-1:1234567:targetgroup/target-group-1/123456", // TODO: first target group
          "containerName": containerName,
          "containerPort": containerPort
        },
        {
          "targetGroupArn": "arn:aws:elasticloadbalancing:eu-west-1:1234567:targetgroup/target-group-2/123456", // TODO: second target group
          "containerName": containerName,
          "containerPort": containerPort
        }
      ]
    }
    
    const command = new UpdateServiceCommand(input);
    const response = await client.send(command);
    
    console.log(response)
    

    IMPORTANT: Please save it with .mjs (ES module) not .js extension! It's required because in script I use ES modules import and await.

    If everything goes ok, you will see response with details of your service with updated configuration. Otherwise, you will error with details.