Creating and Operating AWS CodePipeline for Blue/Green Deployments
SHARE THE BLOG
Introduction
The primary objective of this article is to explain how to create an AWS CodePipeline that uses blue/green deployment for container applications when a new Docker image is pushed to the Elastic Container Registry (ECR). This pipeline recognizes changes in your Docker image stored in ECR, and leverages AWS CodeDeploy to divert and deploy traffic to an Amazon Elastic Container Service (ECS) cluster and load balancer.
Prerequisites
Before we proceed with the step-by-step instructions, ensure that you have:
- A CodeCommit repository.
- An Amazon EC2 Linux instance with Docker installed for creating an image. This prerequisite can be ignored if you already possess an image for use.
Business Case
Imagine a globally recognized streaming company like Netflix, known for its robust usage of AWS services and the vast number of subscribers it caters to daily. As Netflix frequently introduces new features and enhancements, it faces the daunting challenge of maintaining high availability and ensuring seamless streaming experiences during deployments.
In the past, traditional deployment methods could have potentially led to service interruptions, affecting the user experience, and possibly introducing errors due to rushed or improperly executed updates. The time and resources needed to troubleshoot and rectify these errors can be significant.
Now, consider Netflix leveraging an automated Continuous Integration/Continuous Deployment (CI/CD) pipeline using AWS services, including CodePipeline, CodeCommit, CodeDeploy, ECS, and ECR. The aim is to employ a blue/green deployment strategy, creating a near-identical, but inactive ‘staging’ environment.
Whenever developers push changes to the Docker image stored in ECR or the codebase in CodeCommit, it triggers the AWS CodePipeline. The pipeline then automatically deploys the updated Docker image to an ECS cluster using CodeDeploy. Once the updates have been thoroughly checked in the staging environment, the live traffic is switched over, virtually eliminating service downtime.
This implementation of a blue/green deployment strategy could lead to substantial benefits for a company like Netflix:
- Decreased downtime during deployments, leading to uninterrupted streaming experiences.
- Increased reliability of their deployments, reducing the number of failed deployments and subsequent troubleshooting efforts.
- Improved speed at which new features and updates can be delivered, keeping up with the dynamic demands of the users.
- More focused time for developers on creating and improving features rather than dealing with deployment errors.
- Enhanced customer satisfaction by providing a seamless and continuously improving viewing experience.
Such an automated CI/CD pipeline could align with Netflix’s goal of delivering high-quality, uninterrupted streaming services while continuously innovating to provide new features and updates to millions of users worldwide.
Step-by-Step Guide
Step 1: Create an Image and Push it to an AWS ECR Repository
1.1. Construct a Dockerfile.
1.2. Use the command docker build -t nginx . to build a Docker image.
1.3. To view the created image, use the command docker images.
Next, push your Docker image to an AWS ECR repository:
1.4. Create an AWS ECR repository with the command aws ecr create-repository –repository-name nginx.
1.5. Assign a tag to your Docker image using docker tag nginx:latest aws_account_id.dkr.ecr.us-east-1.amazonaws.com/nginx:latest.
1.6. Log in to your Docker account with AWS ECR using the command aws ecr get-login-password –region us-east-2 | docker login –username AWS –password-stdin 944163165741.dkr.ecr.us-east-2.amazonaws.com.
1.7. Push the Docker image to your AWS account using docker push aws_account_id.dkr.ecr.us-east-1.amazonaws.com/nginx:latest.
Step 2: Create Task Definition
2.1. Construct a task definition for your image. Create a file named taskdef.json. For the image field, input your image name such as nginx. This value gets updated each time your pipeline runs.
// Code Language is YAML
{
"executionRoleArn": "arn:aws:iam::944163165741:role/ecsTaskExecutionRole",
"containerDefinitions": [
{
"name": "sample-website",
"image": "",
"essential": true,
"portMappings": [
{
"hostPort": 80,
"protocol": "tcp",
"containerPort": 80
}
]
}
],
"requiresCompatibilities": [
"FARGATE"
],
"networkMode": "awsvpc",
"cpu": "256",
"memory": "512",
"family": "ecs-demo"
}
2.2. Register your task definition with the taskdef.json file using the command aws ecs register-task-definition –cli-input-json file://taskdef.json.
2.3. After your task definition has been registered, edit your file to eliminate the image name and include <IMAGE1_NAME> as placeholder text in the image field.
Step 3: Create an Appspec.yml file
Create an appspec.yaml file, which is utilized for CodeDeploy deployments. For TaskDefinition, maintain <TASK_DEFINITION> as placeholder text. This value gets updated each time your pipeline runs.
// Code Language is YAML
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition:
LoadBalancerInfo:
ContainerName: "sample-website"
ContainerPort: 80
Step 4: Push the Files to Your CodeCommit Repository
Access your repository from the Repositories list and upload taskdef.json and appspec.yaml files.
Step 5: Create Your Application Load Balancer and Target Groups
5.1. Validate your default Virtual Private Cloud (VPC) with a ‘Yes’ in the Default VPC column. This VPC contains default subnets for you to select.
5.2. Confirm that you have two subnets with a ‘Yes’ in the Default subnet column, and that the subnets you aim to use are in different Availability Zones.
5.3. To verify that each subnet you intend to use is a public subnet, confirm that a gateway row is included in the route table.
5.4. Use the AWS Management Console to create an Amazon EC2 Application Load Balancer (ALB)
Step 6: Create your Amazon ECS Cluster and Service
In this step, you will create an ECS cluster and service where CodeDeploy directs traffic during deployment (to an Amazon ECS cluster rather than EC2 instances).
6.1. Create an Amazon ECS cluster with “Networking only cluster” template that uses AWS Fargate, and then create an Amazon ECS service. Use the AWS CLI to create your service in Amazon ECS.
6.2. Create a JSON file and name it create-service.json. In the taskDefinition field, paste the name of the created task definition in it like “ecs-demo:15” (the family and revision number in your file). Use the subnet names, security group, and your first target group ARN you created with your load balancer.
// Code Language is YAML
{
"taskDefinition": "ecs-demo:15",
"cluster": "ahmedsalem-demo",
"loadBalancers": [
{
"targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:944163165741:targetgroup/target-group-1/80ae4025e82d99dd",
"containerName": "sample-website",
"containerPort": 80
}
],
"desiredCount": 1,
"launchType": "FARGATE",
"schedulingStrategy": "REPLICA",
"deploymentController": {
"type": "CODE_DEPLOY"
},
"networkConfiguration": {
"awsvpcConfiguration": {
"subnets": [
"subnet-0556b778",
"subnet-ed2f8486"
],
"securityGroups": [
"sg-c07de9b2"
],
"assignPublicIp": "ENABLED"
}
}
}
6.3. Run the create-service command, specifying the JSON file: aws ecs create-service –service-name my-service –cli-input-json file://create-service.json
6.4. Run the describe-services command to verify that your service was created: aws ecs describe-services –cluster cluster-name –services service-name
Step 7: Create your CodeDeploy Application and Deployment Group
7.1. Create a CodeDeploy application.
7.2. Create a CodeDeploy deployment group where you enter a name of the deployment group and a service role that grants CodeDeploy access to Amazon ECS. In Environment configuration, choose your Amazon ECS cluster name and service name. Select the name of the load balancer that serves traffic to your Amazon ECS service. Choose the port and protocol for the listener that serves production traffic to your Amazon ECS service. Choose the port and protocol for the test listener. Select the target groups you created for your load balancer to direct traffic during your deployment. Choose Reroute traffic immediately to determine how long after a successful deployment to reroute traffic to your updated Amazon ECS task. Choose Create deployment group.
Step 8: Create your Pipeline
Your pipeline should consist of the following stages:
8.1. A CodeCommit action where the source artifacts are the task definition and the AppSpec file.
8.2. A source stage with an Amazon ECR source action where the source artifact is the image file.
8.3. A deployment stage with an Amazon ECS deploy action where the deployment runs with a CodeDeploy application and deployment group.
Step 9: Make a Change to Your Pipeline and Verify Deployment
Make a change to your image and then push the change to your Amazon ECR repository. This triggers your pipeline to run. Verify that your image source change is deployed.
Step 10: Confirm that the Service is Running
Finally, to ensure that your service is running, copy the LoadBalancer DNS name and paste it into your browser’s address bar. This should load the application, verifying that the service is running and functioning as expected.
Conclusion
By leveraging AWS CodePipeline, AWS CodeCommit, AWS CodeDeploy, and other services such as Amazon ECS and ECR, developers and operations teams can automate their software release processes, deploy reliably, and maintain the high availability of their services. This continuous integration and continuous delivery (CI/CD) model reduces the risk of deployment failures and accelerates feature delivery, enhancing productivity and system reliability.
The blue/green deployment model further enhances this process by allowing a “live” environment and a nearly identical but inactive “staging” environment. The software is installed on the staging environment, and when it’s ready, traffic is switched from the live environment to the staging one. This approach virtually eliminates service downtime and reduces the risk associated with deployments, as teams can rapidly revert to the previous version in case of any issues.
This comprehensive guide provides step-by-step instructions on setting up an automated CI/CD pipeline that employs the blue/green deployment strategy. Following these steps meticulously will help ensure the seamless setup and execution of your pipeline, ensuring your containerized applications are reliably deployed and updated.
Remember, although this guide offers a basic template for setting up a CI/CD pipeline using AWS services, the specifics can vary depending on the requirements of your particular project. Always consider your unique use cases and requirements when implementing CI/CD pipelines or any other development practices.