Blue-green deployment is a software release strategy that minimizes downtime and risk by running two identical environments, “blue” and “green.” At any given time, one environment (e.g., blue) is live and serving traffic, while the other (green) is idle and used for staging new updates. Once the updates are tested and validated in the green environment, traffic is switched from blue to green, allowing for a seamless transition and easy rollback if issues arise. AWS CodeDeploy automates the blue-green deployment process by managing the deployment of applications to separate load balancer target groups. It allows for seamless traffic shift between the blue and green target groups, ensuring a smooth transition and minimal downtime. CodeDeploy monitors the deployment’s health, enabling automatic rollbacks if any issues are detected during the switch.

In this note, I explain how to create a blue-green deployment process for the Amazon ECS Fargate service using CodeDeploy. I used Terraform to provision all the AWS cloud resources and automated the deployment process with GitHub Actions.

This note builds upon the concepts discussed in my previous notes, so it would be helpful to examine them before you start. If you are short on time, do not miss note #3 since the AWS cloud resources discussed there overlap with those in this note.

1. Provision of the underlying infrastructure to host an Amazon ECS service 2. Push a Docker image to Amazon Elastic Container Registry (Amazon ECR) 3. Create a service/task from the Docker image and host it on Amazon ECS Optionally, if you are interested, you may also go through these two notes: 4. Enabling Health Checks and CloudWatch Logs for AWS Fargate Tasks 5. Protecting Credentials and Variables in AWS Fargate Containers using AWS Secrets Manager

I will walk through the Terraform code to provision all the AWS Cloud resources; hence, it’d be helpful to access the GitHub code repository with the Terraform code. Here is the link: GitHub: kunduso/add-aws-ecr-ecs-fargate. Please note that the branch name = enable-blue-green-deployment.

Step 1: Create Amazon ECS resources There are four AWS cloud resources required: 1. ECS execution role 2. ECS task role 3. ECS task definition 4. ECS service I’ve covered these in detail in note #3; you can read about them there. However, there is one change in the resource "aws_ecs_service"; the deployment_controller property with the type = "CODE_DEPLOY" value. 104-image-1 This property enables CodeDeploy to manage deployment to the Amazon ECS service. Please note that if you have an existing Amazon ECS service and then make this change, Terraform will destroy that Amazon ECS service and recreate it.

Step 2: Create an IAM role for AWS Code Deploy The CodeDeploy service requires an IAM role to manage deployments. The below code creates the IAM role and attaches the assume_role_policy to it. Then, it attaches a managed policy arn:aws:iam::aws:policy/AWSCodeDeployRoleForECS to the IAM role that enables it to manage deployments and load balancer to target group attachments/detachments. 104-image-2 Step 3: Create a CodeDeploy application and deployment group Two CodeDeploy resources are required for this use case -the aws_codedeploy_app and the aws_codedeploy_deployment_group . The app stores the type of compute_platform, which can be ECS, Lambda, or Server, as of October 2024. Since our use case is on Amazon ECS, that is the value in the Terraform code. The deployment group consists of properties to manage the deployment, such as the deployment_config_name, blue_green_deployment_config, ecs_service, deployment_style, auto_rollback_configuration, and load_balancer_info. 104-image-3 Through these properties, CodeDeploy manages blue-green deployment. For updated information on the values supported by these properties, please check Terraform AWS Registry: aws_codedeploy_deployment_group.

Step 4: Create the CodeDeploy deployment The last set of AWS cloud resources to create is to support a CodeDeploy deployment. That is managed by: 1. Creating the appspec content, 2. Creating a shell script to run the AWS CLI command aws deploy create-deployment, and finally 3. Running the shell script on the GitHub-hosted runner using the terraform_data AWS cloud resource. 104-image-4 I will now walk through the process with screenshots of a blue-green deployment process. Two target groups are required for an Amazon ECS supporting blue-green deployment. When an application is live and serving traffic, the requests route from the load balancer to one of the attached target groups (blue) and from there to the containers attached to that target group. As you can see from the image below, before CodeDeploy started a new Blue-Green deployment, two tasks were running version #74 of the task definition. 104-image-5 As you can see in the image below, both these tasks/containers were registered with the app-6-blue target group, which was associated with the load balancer: app-6. 104-image-6 You can see from the image below that the app-6-green target group was not associated with the load balancer. Moreover, there were no containers registered with that target group. 104-image-7 Then, when the terraform apply command was executed, a new version of the local_file.code_deploy_sh was created, which triggered the resource terraform_data to be recreated. That was managed by the property triggers_replace = local_file.code_deploy_sh. The logic in the terraform_data runs the code_deploy.sh file, which triggers a CodeDeploy deployment using the AWS CLI. The image below shows a CodeDeploy deployment in progress. 104-image-8 As part of the CodeDeploy deployment, new ECS tasks were started, as seen in the image below. 104-image-9 As you can see, the new tasks are on version #75 of the task definition. After a few seconds, the Health status changed from Unknown to Healthy. Compare the images above and below. 104-image-10 Then, on the Load balancer page, the app-6-green target group started listing the two tasks, but the Health status was Unused. 104-image-11 After a few seconds, it changed from Unused to Initial. That is when the two tasks were getting registered with the app-6-green target group. 104-image-12 A few seconds later, when the Health Status changed to Healthy, you can see that the load balancer’s traffic routing changed to the app-6-green target group from app-6-blue target group. 104-image-13 And under the app-6-blue target group, the two tasks were deregistered. 104-image-14 With that change, the CodeDeploy deployment was completed. 104-image-15 To verify, I navigated to the Amazon ECS console and checked the tasks. As you can see from the image below, the new two tasks (#75) were up and running while the older tasks (#74) were being stopped. 104-image-16 So, the process of Blue-Green deployment is as follows: When a newer version of the ECS task definition is available, Amazon ECS spins up new containers and waits for the container health check status to be Healthy. After that, the containers are registered with a target group (green) that isn’t attached to the load balancer. After the containers are successfully registered with the target group (green), CodeDeploy routes traffic from the load balancer to the green target group and stops sending traffic to the blue target group. Then, depending on the specifications of the aws_codedeploy_deployment_group resource, the containers in the old target group are managed. In this use case, the action was to TERMINATE the containers after a minute of detaching from the load balancer. 104-image-17 That brings us to the end of all the Terraform-managed AWS cloud resources to enable blue-green deployment using AWS Code Deploy. Please check the Use-Case 2: Update GitHub Actions Workflow with Deploy Job section of note#3 to continue with the next steps. And, let me know if you have any questions.