Rolling Deployment

Prerequisites

Before starting this demonstration, ensure you have:

  • An existing ECS cluster
  • A task definition for your application
  • Appropriate IAM permissions for ECS and CloudWatch
  • Network infrastructure (VPC, subnets, security groups)

Step 1: Configure the ECS Service

Deploy an ECS service with rolling deployment configuration:

module "web_service" {
  source  = "registry.patterneddesigns.ca/patterneddesigns/ecs-service/aws"
  version = "2.0.0"

  service_name        = "web-app"
  cluster_arn         = aws_ecs_cluster.main.arn
  task_definition_arn = aws_ecs_task_definition.web.arn
  desired_count       = 4

  network_configuration = {
    subnets          = var.private_subnet_ids
    security_groups  = [aws_security_group.ecs_tasks.id]
    assign_public_ip = false
  }

  load_balancer = {
    target_group_arn = aws_lb_target_group.web.arn
    container_name   = "web"
    container_port   = 80
  }

  deployment_configuration = {
    maximum_percent         = 200
    minimum_healthy_percent = 100
  }

  health_check_grace_period_seconds = 60
}

Step 2: Understand Deployment Parameters

The deployment configuration controls how rolling updates behave:

ParameterValueBehavior
maximum_percent200Allows doubling tasks during deployment
minimum_healthy_percent100Maintains all original tasks until new ones are healthy

With these settings and desired_count = 4:

  • ECS starts 4 new tasks (200% of 4 = 8 total)
  • Waits for new tasks to pass health checks
  • Drains and terminates old tasks
  • Result: Zero downtime during the update

Step 3: Configure Health Checks

Proper health checks are critical for safe rolling deployments:

resource "aws_lb_target_group" "web" {
  name        = "web-target-group"
  port        = 80
  protocol    = "HTTP"
  vpc_id      = var.vpc_id
  target_type = "ip"

  health_check {
    enabled             = true
    healthy_threshold   = 2
    interval            = 15
    matcher             = "200"
    path                = "/health"
    port                = "traffic-port"
    protocol            = "HTTP"
    timeout             = 5
    unhealthy_threshold = 3
  }

  deregistration_delay = 30
}

Key settings:

  • healthy_threshold = 2: Two consecutive successful checks before receiving traffic
  • interval = 15: Check every 15 seconds
  • deregistration_delay = 30: Allow 30 seconds for in-flight requests to complete

Step 4: Trigger a Deployment

Update the task definition and apply changes:

# Update the task definition image
aws ecs register-task-definition \
  --cli-input-json file://task-definition.json

# Apply Terraform changes
terraform apply

Monitor the deployment:

# Watch deployment status
aws ecs describe-services \
  --cluster main \
  --services web-app \
  --query 'services[0].deployments'

# View running tasks
aws ecs list-tasks \
  --cluster main \
  --service-name web-app

Step 5: Verify Zero-Downtime

During deployment, verify continuous availability:

# Continuous health check
while true; do
  curl -s -o /dev/null -w "%{http_code}" https://your-app.example.com/health
  echo ""
  sleep 1
done

All requests should return 200 throughout the deployment process.

Rollback Strategy

If issues are detected, ECS supports automatic rollback:

module "web_service" {
  # ... other configuration ...

  deployment_circuit_breaker = {
    enable   = true
    rollback = true
  }
}

With circuit breaker enabled:

  • ECS monitors deployment health
  • Automatically rolls back if tasks fail to stabilize
  • Restores the previous task definition version