Documentation Index Fetch the complete documentation index at: https://mintlify.com/terraform-aws-modules/terraform-aws-ecs/llms.txt
Use this file to discover all available pages before exploring further.
Blue/green deployments replace running tasks with a new version while keeping the old version alive until traffic has been shifted and validated. This eliminates downtime during deploys and allows fast rollback if the new version fails health checks.
This module supports two approaches:
ECS-native blue/green Configured via deployment_configuration.strategy = "BLUE_GREEN". Managed entirely by ECS without CodeDeploy. Simpler to set up.
CodeDeploy blue/green Uses ignore_task_definition_changes = true and an external aws_codedeploy_deployment_group. Required when CodeDeploy manages the deployment lifecycle.
ECS-native blue/green
The fargate example uses the ECS-native blue/green strategy with two ALB target groups:
module "ecs_service" {
source = "terraform-aws-modules/ecs/aws//modules/service"
name = local . name
cluster_arn = module . ecs_cluster . arn
cpu = 1024
memory = 4096
# Blue/green deployment
deployment_configuration = {
strategy = "BLUE_GREEN"
bake_time_in_minutes = 2
}
load_balancer = {
service = {
target_group_arn = module.alb.target_groups[ "ex-ecs" ].arn
container_name = local.container_name
container_port = local.container_port
# for blue/green deployments
advanced_configuration = {
alternate_target_group_arn = module.alb.target_groups[ "ex-ecs-alternate" ].arn
production_listener_rule = module.alb.listener_rules[ "ex-http/production" ].arn
test_listener_rule = module.alb.listener_rules[ "ex-http/test" ].arn
}
}
}
subnet_ids = module . vpc . private_subnets
security_group_ingress_rules = {
alb_3000 = {
description = "Service port"
from_port = local.container_port
ip_protocol = "tcp"
referenced_security_group_id = module.alb.security_group_id
}
}
security_group_egress_rules = {
all = {
ip_protocol = "-1"
cidr_ipv4 = "0.0.0.0/0"
}
}
tags = local . tags
}
You also need two ALB target groups and two listener rules (production and test):
module "alb" {
source = "terraform-aws-modules/alb/aws"
version = "~> 10.0"
# ... other config
listeners = {
ex-http = {
port = 80
protocol = "HTTP"
fixed_response = {
content_type = "text/plain"
message_body = "404: Page not found"
status_code = "404"
}
rules = {
production = {
priority = 1
actions = [
{
weighted_forward = {
target_groups = [
{
target_group_key = "ex-ecs"
weight = 100
},
{
target_group_key = "ex-ecs-alternate"
weight = 0
}
]
}
}
]
conditions = [
{
path_pattern = {
values = [ "/*" ]
}
}
]
}
test = {
priority = 2
actions = [
{
weighted_forward = {
target_groups = [
{
target_group_key = "ex-ecs-alternate"
weight = 100
}
]
}
}
]
conditions = [
{
path_pattern = {
values = [ "/*" ]
}
}
]
}
}
}
}
target_groups = {
ex-ecs = {
backend_protocol = "HTTP"
backend_port = local.container_port
target_type = "ip"
deregistration_delay = 5
load_balancing_cross_zone_enabled = true
health_check = {
enabled = true
healthy_threshold = 5
interval = 30
matcher = "200"
path = "/"
port = "traffic-port"
protocol = "HTTP"
timeout = 5
unhealthy_threshold = 2
}
create_attachment = false
}
ex-ecs-alternate = {
backend_protocol = "HTTP"
backend_port = local.container_port
target_type = "ip"
deregistration_delay = 5
load_balancing_cross_zone_enabled = true
health_check = {
enabled = true
healthy_threshold = 5
interval = 30
matcher = "200"
path = "/"
port = "traffic-port"
protocol = "HTTP"
timeout = 5
unhealthy_threshold = 2
}
create_attachment = false
}
}
}
CodeDeploy blue/green
For CodeDeploy-managed deployments, ECS hands off the deployment lifecycle to CodeDeploy. In this model, CodeDeploy (not Terraform) updates the service’s task definition and load balancer configuration during each deploy.
The role of ignore_task_definition_changes
Set ignore_task_definition_changes = true to instruct the module to ignore changes to the service’s task_definition and load_balancer arguments. This is required because:
CodeDeploy changes the task definition during each deployment to point to the new image.
CodeDeploy shifts the load balancer from the blue target group to the green target group.
Without this flag, Terraform would conflict with CodeDeploy by trying to revert those changes on the next terraform apply.
Changing ignore_task_definition_changes after the service has been created forces Terraform to destroy and recreate the ECS service . This causes downtime. Decide on this value before the first deployment and do not change it afterward.
Complete CodeDeploy example
module "ecs_service" {
source = "terraform-aws-modules/ecs/aws//modules/service"
# ... omitted for brevity
ignore_task_definition_changes = true
}
resource "aws_lb_target_group" "this" {
for_each = {
blue = {}
green = {}
}
name = each . key
# ... omitted for brevity
}
resource "aws_codedeploy_app" "this" {
name = "my-app"
compute_platform = "ECS"
}
resource "aws_codedeploy_deployment_group" "this" {
deployment_group_name = "my-deployment-group"
app_name = aws_codedeploy_app . this . name
deployment_config_name = "CodeDeployDefault.ECSAllAtOnce"
deployment_style {
deployment_option = "WITH_TRAFFIC_CONTROL"
deployment_type = "BLUE_GREEN"
}
# ... omitted for brevity
load_balancer_info {
target_group_pair_info {
prod_traffic_route {
listener_arns = [ "my-listener-arn" ]
}
target_group {
name = aws_lb_target_group . this [ "blue" ] . name
}
target_group {
name = aws_lb_target_group . this [ "green" ] . name
}
}
}
}
Traffic shifting strategies
The deployment_config_name in the aws_codedeploy_deployment_group controls how traffic shifts:
Config name Behavior CodeDeployDefault.ECSAllAtOnceShifts all traffic to the new version at once. CodeDeployDefault.ECSLinear10PercentEvery1MinuteShifts 10% every minute until 100%. CodeDeployDefault.ECSLinear10PercentEvery3MinutesShifts 10% every 3 minutes until 100%. CodeDeployDefault.ECSCanary10Percent5MinutesShifts 10% initially, then 90% after 5 minutes. CodeDeployDefault.ECSCanary10Percent15MinutesShifts 10% initially, then 90% after 15 minutes.
You can also define a custom deployment configuration with finer control over step percentages and bake times.
Canary deployments (EC2 capacity)
The ec2-autoscaling example demonstrates a canary strategy using the ECS-native deployment configuration:
module "ecs_service" {
source = "terraform-aws-modules/ecs/aws//modules/service"
# ... other config
deployment_configuration = {
strategy = "CANARY"
canary_configuration = {
canary_percent = 10.0
canary_bake_time_in_minutes = 5
}
}
}
This routes 10% of traffic to the new version for 5 minutes before shifting the remainder.