Deploying an Amazon ECS service using a blue/green deployment
Learn how to create an Amazon ECS service containing a Fargate task that uses the blue/green deployment type with the AWS CLI.
Note
Support for performing a blue/green deployment has been added for AWS CloudFormation. For more information, see Perform Amazon ECS blue/green deployments through CodeDeploy using AWS CloudFormation in the AWS CloudFormation User Guide.
Prerequisites
This tutorial assumes that you have completed the following prerequisites:
-
The latest version of the AWS CLI is installed and configured. For more information about installing or upgrading the AWS CLI, see Installing or updating to the latest version of the AWS CLI.
-
The steps in Set up to use Amazon ECS have been completed.
-
Your AWS user has the required permissions specified in the AmazonECS_FullAccess IAM policy example.
-
You have a VPC and security group created to use. For more information, see Create a virtual private cloud.
-
The Amazon ECS CodeDeploy IAM role is created. For more information, see Amazon ECS CodeDeploy IAM Role.
Step 1: Create an Application Load Balancer
Amazon ECS services using the blue/green deployment type require the use of either an Application Load Balancer or a Network Load Balancer. This tutorial uses an Application Load Balancer.
To create an Application Load Balancer
-
Use the create-load-balancer command to create an Application Load Balancer. Specify two subnets that aren't from the same Availability Zone as well as a security group.
aws elbv2 create-load-balancer \ --name
bluegreen-alb
\ --subnetssubnet-abcd1234
subnet-abcd5678
\ --security-groupssg-abcd1234
\ --regionus-east-1
The output includes the Amazon Resource Name (ARN) of the load balancer, with the following format:
arn:aws:elasticloadbalancing:
region
:aws_account_id
:loadbalancer/app/bluegreen-alb/e5ba62739c16e642
-
Use the create-target-group command to create a target group. This target group will route traffic to the original task set in your service.
aws elbv2 create-target-group \ --name
bluegreentarget1
\ --protocolHTTP
\ --port80
\ --target-type ip \ --vpc-idvpc-abcd1234
\ --regionus-east-1
The output includes the ARN of the target group, with the following format:
arn:aws:elasticloadbalancing:
region
:aws_account_id
:targetgroup/bluegreentarget1/209a844cd01825a4 -
Use the create-listener command to create a load balancer listener with a default rule that forwards requests to the target group.
aws elbv2 create-listener \ --load-balancer-arn arn:aws:elasticloadbalancing:
region
:aws_account_id
:loadbalancer/app/bluegreen-alb/e5ba62739c16e642
\ --protocol HTTP \ --port 80 \ --default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:region
:aws_account_id
:targetgroup/bluegreentarget1/209a844cd01825a4
\ --regionus-east-1
The output includes the ARN of the listener, with the following format:
arn:aws:elasticloadbalancing:
region
:aws_account_id
:listener/app/bluegreen-alb/e5ba62739c16e642/665750bec1b03bd4
Step 2: Create an Amazon ECS cluster
Use the create-cluster
command to create a cluster named tutorial-bluegreen-cluster
to use.
aws ecs create-cluster \ --cluster-name
tutorial-bluegreen-cluster
\ --regionus-east-1
The output includes the ARN of the cluster, with the following format:
arn:aws:ecs:region
:aws_account_id
:cluster/tutorial-bluegreen-cluster
Step 3: Register a task definition
Use the register-task-definition command to register a task definition that is
compatible with Fargate. It requires the use of the awsvpc
network mode. The following is the example task definition used for this
tutorial.
First, create a file named fargate-task.json
with the following contents.
Ensure that you use the ARN for your task execution role. For more information, see
Amazon ECS task execution IAM role.
{ "family": "
tutorial-task-def
", "networkMode": "awsvpc", "containerDefinitions": [ { "name": "sample-app", "image": "httpd:2.4", "portMappings": [ { "containerPort": 80, "hostPort": 80, "protocol": "tcp" } ], "essential": true, "entryPoint": [ "sh", "-c" ], "command": [ "/bin/sh -c \"echo '<html> <head> <title>Amazon ECS Sample App</title> <style>body {margin-top: 40px; background-color: #00FFFF;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon ECS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a container in Amazon ECS.</p> </div></body></html>' > /usr/local/apache2/htdocs/index.html && httpd-foreground\"" ] } ], "requiresCompatibilities": [ "FARGATE" ], "cpu": "256", "memory": "512", "executionRoleArn": "arn:aws:iam::aws_account_id
:role/ecsTaskExecutionRole
" }
Then register the task definition using the fargate-task.json
file that
you created.
aws ecs register-task-definition \ --cli-input-json file://
fargate-task.json
\ --regionus-east-1
Step 4: Create an Amazon ECS service
Use the create-service command to create a service.
First, create a file named service-bluegreen.json
with the following
contents.
{ "cluster": "
tutorial-bluegreen-cluster
", "serviceName": "service-bluegreen
", "taskDefinition": "tutorial-task-def
", "loadBalancers": [ { "targetGroupArn": "arn:aws:elasticloadbalancing:region
:aws_account_id
:targetgroup/bluegreentarget1/209a844cd01825a4
", "containerName": "sample-app", "containerPort": 80 } ], "launchType": "FARGATE", "schedulingStrategy": "REPLICA", "deploymentController": { "type": "CODE_DEPLOY" }, "platformVersion": "LATEST
", "networkConfiguration": { "awsvpcConfiguration": { "assignPublicIp": "ENABLED", "securityGroups": [ "sg-abcd1234
" ], "subnets": [ "subnet-abcd1234
", "subnet-abcd5678
" ] } }, "desiredCount": 1 }
Then create your service using the service-bluegreen.json
file that you
created.
aws ecs create-service \ --cli-input-json file://
service-bluegreen.json
\ --regionus-east-1
The output includes the ARN of the service, with the following format:
arn:aws:ecs:region
:aws_account_id
:service/service-bluegreen
Obtain the DNS name of the load balancer using the following command.
aws elbv2 describe-load-balancers --name bluegreen-alb --query 'LoadBalancers[*].DNSName'
Enter the DNS name in your web browser and you should see a webpage that displays the sample app with a blue background.
Step 5: Create the AWS CodeDeploy resources
Use the following steps to create your CodeDeploy application, the Application Load Balancer target group for the CodeDeploy deployment group, and the CodeDeploy deployment group.
To create CodeDeploy resources
-
Use the create-application command to create a CodeDeploy application. Specify the
ECS
compute platform.aws deploy create-application \ --application-name
tutorial-bluegreen-app
\ --compute-platformECS
\ --regionus-east-1
The output includes the application ID, with the following format:
{ "applicationId": "b8e9c1ef-3048-424e-9174-885d7dc9dc11" }
-
Use the create-target-group command to create a second Application Load Balancer target group, which will be used when creating your CodeDeploy deployment group.
aws elbv2 create-target-group \ --name
bluegreentarget2
\ --protocolHTTP
\ --port80
\ --target-type ip \ --vpc-id "vpc-0b6dd82c67d8012a1
" \ --regionus-east-1
The output includes the ARN for the target group, with the following format:
arn:aws:elasticloadbalancing:
region
:aws_account_id
:targetgroup/bluegreentarget2/708d384187a3cfdc -
Use the create-deployment-group command to create a CodeDeploy deployment group.
First, create a file named
tutorial-deployment-group.json
with the following contents. This example uses the resource that you created. For theserviceRoleArn
, specify the ARN of your Amazon ECS CodeDeploy IAM role. For more information, see Amazon ECS CodeDeploy IAM Role.{ "applicationName": "
tutorial-bluegreen-app
", "autoRollbackConfiguration": { "enabled": true, "events": [ "DEPLOYMENT_FAILURE" ] }, "blueGreenDeploymentConfiguration": { "deploymentReadyOption": { "actionOnTimeout": "CONTINUE_DEPLOYMENT", "waitTimeInMinutes": 0 }, "terminateBlueInstancesOnDeploymentSuccess": { "action": "TERMINATE", "terminationWaitTimeInMinutes": 5 } }, "deploymentGroupName": "tutorial-bluegreen-dg
", "deploymentStyle": { "deploymentOption": "WITH_TRAFFIC_CONTROL", "deploymentType": "BLUE_GREEN" }, "loadBalancerInfo": { "targetGroupPairInfoList": [ { "targetGroups": [ { "name": "bluegreentarget1
" }, { "name": "bluegreentarget2
" } ], "prodTrafficRoute": { "listenerArns": [ "arn:aws:elasticloadbalancing:region
:aws_account_id
:listener/app/bluegreen-alb/e5ba62739c16e642/665750bec1b03bd4
" ] } } ] }, "serviceRoleArn": "arn:aws:iam::aws_account_id
:role/ecsCodeDeployRole
", "ecsServices": [ { "serviceName": "service-bluegreen
", "clusterName": "tutorial-bluegreen-cluster
" } ] }Then create the CodeDeploy deployment group.
aws deploy create-deployment-group \ --cli-input-json file://
tutorial-deployment-group.json
\ --regionus-east-1
The output includes the deployment group ID, with the following format:
{ "deploymentGroupId": "6fd9bdc6-dc51-4af5-ba5a-0a4a72431c88" }
Step 6: Create and monitor a CodeDeploy deployment
Before creating a CodeDeploy deployment, update the task definition command
in fargate-task.json
as follows to change the sample app background color
to green.
{ ... "containerDefinitions": [ { ... "command": [ "/bin/sh -c \"echo '<html> <head> <title>Amazon ECS Sample App</title> <style>body {margin-top: 40px; background-color: #097969;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon ECS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a container in Amazon ECS.</p> </div></body></html>' > /usr/local/apache2/htdocs/index.html && httpd-foreground\"" ] } ], ... }
Register the updated task definition using the following command.
aws ecs register-task-definition \ --cli-input-json file://
fargate-task.json
\ --regionus-east-1
Now, use the following steps to create and upload an application specification file (AppSpec file) and an CodeDeploy deployment.
To create and monitor a CodeDeploy deployment
-
Create and upload an AppSpec file using the following steps.
-
Create a file named
appspec.yaml
with the contents of the CodeDeploy deployment group. This example uses the updated task definition.version: 0.0 Resources: - TargetService: Type: AWS::ECS::Service Properties: TaskDefinition: "arn:aws:ecs:
region
:aws_account_id
:task-definition/tutorial-task-def:2
" LoadBalancerInfo: ContainerName: "sample-app
" ContainerPort: 80 PlatformVersion: "LATEST" -
Use the s3 mb command to create an Amazon S3 bucket for the AppSpec file.
aws s3 mb s3://
tutorial-bluegreen-bucket
-
Use the s3 cp command to upload the AppSpec file to the Amazon S3 bucket.
aws s3 cp ./appspec.yaml s3://
tutorial-bluegreen-bucket
/appspec.yaml
-
-
Create the CodeDeploy deployment using the following steps.
-
Create a file named
create-deployment.json
with the contents of the CodeDeploy deployment. This example uses the resources that you created earlier in the tutorial.{ "applicationName": "
tutorial-bluegreen-app
", "deploymentGroupName": "tutorial-bluegreen-dg
", "revision": { "revisionType": "S3", "s3Location": { "bucket": "tutorial-bluegreen-bucket
", "key": "appspec.yaml
", "bundleType": "YAML" } } } -
Use the create-deployment command to create the deployment.
aws deploy create-deployment \ --cli-input-json file://
create-deployment.json
\ --regionus-east-1
The output includes the deployment ID, with the following format:
{ "deploymentId": "d-RPCR1U3TW" }
-
-
Use the get-deployment-target command to get the details of the deployment, specifying the
deploymentId
from the previous output.aws deploy get-deployment-target \ --deployment-id "
d-IMJU3A8TW
" \ --target-idtutorial-bluegreen-cluster:service-bluegreen
\ --regionus-east-1
Initially, the deployment status is
InProgress
. Traffic is directed to the original task set, which has ataskSetLabel
ofBLUE
, a status ofPRIMARY
, and atrafficWeight
of100.0
. The replacement task set has ataskSetLabel
ofGREEN
, a status ofACTIVE
, and atrafficWeight
of0.0
. The web browser you entered the DNS name in still displays the sample app with a blue background.{ "deploymentTarget": { "deploymentTargetType": "ECSTarget", "ecsTarget": { "deploymentId": "d-RPCR1U3TW", "targetId": "tutorial-bluegreen-cluster:service-bluegreen", "targetArn": "arn:aws:ecs:
region
:aws_account_id
:service/service-bluegreen", "lastUpdatedAt": "2023-08-10T12:07:24.797000-05:00", "lifecycleEvents": [ { "lifecycleEventName": "BeforeInstall", "startTime": "2023-08-10T12:06:22.493000-05:00", "endTime": "2023-08-10T12:06:22.790000-05:00", "status": "Succeeded" }, { "lifecycleEventName": "Install", "startTime": "2023-08-10T12:06:22.936000-05:00", "status": "InProgress" }, { "lifecycleEventName": "AfterInstall", "status": "Pending" }, { "lifecycleEventName": "BeforeAllowTraffic", "status": "Pending" }, { "lifecycleEventName": "AllowTraffic", "status": "Pending" }, { "lifecycleEventName": "AfterAllowTraffic", "status": "Pending" } ], "status": "InProgress", "taskSetsInfo": [ { "identifer": "ecs-svc/9223370493423413672", "desiredCount": 1, "pendingCount": 0, "runningCount": 1, "status": "ACTIVE", "trafficWeight": 0.0, "targetGroup": { "name": "bluegreentarget2" }, "taskSetLabel": "Green" }, { "identifer": "ecs-svc/9223370493425779968", "desiredCount": 1, "pendingCount": 0, "runningCount": 1, "status": "PRIMARY", "trafficWeight": 100.0, "targetGroup": { "name": "bluegreentarget1" }, "taskSetLabel": "Blue" } ] } } }Continue to retrieve the deployment details using the command until the deployment status is
Succeeded
, as shown in the following output. Traffic is now redirected to the replacement task set, which now has a status ofPRIMARY
and atrafficWeight
of100.0
. Refresh the web browser you entered the load balancer DNS name in, and you should now see the sample app with a green background.{ "deploymentTarget": { "deploymentTargetType": "ECSTarget", "ecsTarget": { "deploymentId": "d-RPCR1U3TW", "targetId": "tutorial-bluegreen-cluster:service-bluegreen", "targetArn": "arn:aws:ecs:
region
:aws_account_id
:service/service-bluegreen", "lastUpdatedAt": "2023-08-10T12:07:24.797000-05:00", "lifecycleEvents": [ { "lifecycleEventName": "BeforeInstall", "startTime": "2023-08-10T12:06:22.493000-05:00", "endTime": "2023-08-10T12:06:22.790000-05:00", "status": "Succeeded" }, { "lifecycleEventName": "Install", "startTime": "2023-08-10T12:06:22.936000-05:00", "endTime": "2023-08-10T12:08:25.939000-05:00", "status": "Succeeded" }, { "lifecycleEventName": "AfterInstall", "startTime": "2023-08-10T12:08:26.089000-05:00", "endTime": "2023-08-10T12:08:26.403000-05:00", "status": "Succeeded" }, { "lifecycleEventName": "BeforeAllowTraffic", "startTime": "2023-08-10T12:08:26.926000-05:00", "endTime": "2023-08-10T12:08:27.256000-05:00", "status": "Succeeded" }, { "lifecycleEventName": "AllowTraffic", "startTime": "2023-08-10T12:08:27.416000-05:00", "endTime": "2023-08-10T12:08:28.195000-05:00", "status": "Succeeded" }, { "lifecycleEventName": "AfterAllowTraffic", "startTime": "2023-08-10T12:08:28.715000-05:00", "endTime": "2023-08-10T12:08:28.994000-05:00", "status": "Succeeded" } ], "status": "Succeeded", "taskSetsInfo": [ { "identifer": "ecs-svc/9223370493425779968", "desiredCount": 1, "pendingCount": 0, "runningCount": 1, "status": "ACTIVE", "trafficWeight": 0.0, "targetGroup": { "name": "bluegreentarget1" }, "taskSetLabel": "Blue" }, { "identifer": "ecs-svc/9223370493423413672", "desiredCount": 1, "pendingCount": 0, "runningCount": 1, "status": "PRIMARY", "trafficWeight": 100.0, "targetGroup": { "name": "bluegreentarget2" }, "taskSetLabel": "Green" } ] } } }
Step 7: Clean up
When you have finished this tutorial, clean up the resources associated with it to avoid incurring charges for resources that you aren't using.
Cleaning up the tutorial resources
-
Use the delete-deployment-group command to delete the CodeDeploy deployment group.
aws deploy delete-deployment-group \ --application-name
tutorial-bluegreen-app
\ --deployment-group-nametutorial-bluegreen-dg
\ --regionus-east-1
-
Use the delete-application command to delete the CodeDeploy application.
aws deploy delete-application \ --application-name
tutorial-bluegreen-app
\ --regionus-east-1
-
Use the delete-service command to delete the Amazon ECS service. Using the
--force
flag allows you to delete a service even if it has not been scaled down to zero tasks.aws ecs delete-service \ --service arn:aws:ecs:
region
:aws_account_id
:service/service-bluegreen
\ --force \ --regionus-east-1
-
Use the delete-cluster command to delete the Amazon ECS cluster.
aws ecs delete-cluster \ --cluster
tutorial-bluegreen-cluster
\ --regionus-east-1
-
Use the s3 rm command to delete the AppSpec file from the Amazon S3 bucket.
aws s3 rm s3://
tutorial-bluegreen-bucket/appspec.yaml
-
Use the s3 rb command to delete the Amazon S3 bucket.
aws s3 rb s3://
tutorial-bluegreen-bucket
-
Use the delete-load-balancer command to delete the Application Load Balancer.
aws elbv2 delete-load-balancer \ --load-balancer-arn arn:aws:elasticloadbalancing:
region
:aws_account_id
:loadbalancer/app/bluegreen-alb/e5ba62739c16e642
\ --regionus-east-1
-
Use the delete-target-group command to delete the two Application Load Balancer target groups.
aws elbv2 delete-target-group \ --target-group-arn arn:aws:elasticloadbalancing:
region
:aws_account_id
:targetgroup/bluegreentarget1/209a844cd01825a4
\ --regionus-east-1
aws elbv2 delete-target-group \ --target-group-arn arn:aws:elasticloadbalancing:
region
:aws_account_id
:targetgroup/bluegreentarget2/708d384187a3cfdc
\ --regionus-east-1