ECS Fargate CloudFormation SAM: Container Deployments

AWS Containers and Infrastructure as Code: ECS, Fargate, CloudFormation, and SAM

Introduction

Container orchestration and Infrastructure as Code (IaC) are fundamental to modern cloud applications. AWS provides Amazon ECS and Fargate for running containerized workloads, CloudFormation for declarative infrastructure management, and SAM (Serverless Application Model) for simplified serverless deployments.

This guide explores ECS task definitions, Fargate serverless containers, CloudFormation stack management, and SAM template syntax. We'll cover container deployment patterns, blue/green deployments, and production best practices.


AWS Developer Certification Series

📚 View Complete AWS Developer Certification Guide - Master all 7 parts with our comprehensive learning path.

This is Part V (Current Article) of our comprehensive 7-part AWS developer guide:

  1. Part I: IAM EC2 & Auto Scaling
  2. Part II: RDS Aurora & DynamoDB
  3. Part III: SQS SNS & Kinesis
  4. Part IV: Lambda API Gateway
  5. Part V: ECS Fargate & IaC (Current Article)
  6. Part VI: Cognito KMS Security
  7. Part VII: CodePipeline & Monitoring

← Part IV: Lambda API Gateway | Part VI: Cognito KMS Security →


Amazon ECS (Elastic Container Service)

ECS Architecture

ECS orchestrates Docker containers across EC2 instances or serverless Fargate, with built-in load balancing and auto-scaling.

   ECS Cluster   

   Fargate Launch Type   

   EC2 Launch Type   

   pull image   

   pull image   

  EC2 Instance  

  ECS Agent  

  EC2 Instance  

  ECS Agent  

  Fargate Task  

  Serverless  

  Fargate Task  

  Serverless  

  ECS Service  

  Maintains Tasks  

  Application Load Balancer  

  ECR  

  Container Registry  

Key Concepts:

  • Cluster: Logical grouping of tasks or services
  • Task Definition: Blueprint for containers (image, CPU, memory, ports)
  • Task: Running instance of task definition
  • Service: Maintains desired number of tasks, integrates with load balancer
  • ECS Agent: Runs on EC2 instances to communicate with ECS control plane

EC2 vs Fargate Launch Types

Feature EC2 Launch Type Fargate Launch Type
Infrastructure Manage EC2 instances Serverless (no servers)
Pricing EC2 instance cost Per vCPU/GB-hour
Scaling Manual + Auto Scaling Automatic
Use Case Cost optimization, control Simplicity, pay-per-use
Storage EBS, EFS Ephemeral (20GB) + EFS

ECS Task Definition

Example task definition (JSON):

{
  "family": "web-app",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512",
  "containerDefinitions": [
    {
      "name": "nginx",
      "image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latest",
      "portMappings": [
        {
          "containerPort": 80,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {
          "name": "ENVIRONMENT",
          "value": "production"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/web-app",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "healthCheck": {
        "command": ["CMD-SHELL", "curl -f http://localhost/ || exit 1"],
        "interval": 30,
        "timeout": 5,
        "retries": 3
      }
    }
  ],
  "taskRoleArn": "arn:aws:iam::123456789012:role/ecsTaskRole",
  "executionRoleArn": "arn:aws:iam::123456789012:role/ecsExecutionRole"
}

Register task definition:

aws ecs register-task-definition --cli-input-json file://task-definition.json

Running ECS Tasks

Run task (one-off execution):

aws ecs run-task \
  --cluster production \
  --task-definition web-app:5 \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=[subnet-12345],securityGroups=[sg-67890],assignPublicIp=ENABLED}"

Create service (maintains desired count):

aws ecs create-service \
  --cluster production \
  --service-name web-service \
  --task-definition web-app:5 \
  --desired-count 3 \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=[subnet-12345],securityGroups=[sg-67890]}" \
  --load-balancers "targetGroupArn=arn:aws:elasticloadbalancing:...,containerName=nginx,containerPort=80"

ECS Service Auto Scaling

Target tracking scaling:

# Register scalable target
aws application-autoscaling register-scalable-target \
  --service-namespace ecs \
  --resource-id service/production/web-service \
  --scalable-dimension ecs:service:DesiredCount \
  --min-capacity 2 \
  --max-capacity 10

# Create scaling policy (CPU-based)
aws application-autoscaling put-scaling-policy \
  --service-namespace ecs \
  --resource-id service/production/web-service \
  --scalable-dimension ecs:service:DesiredCount \
  --policy-name cpu-scaling \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration '{
    "TargetValue": 70.0,
    "PredefinedMetricSpecification": {
      "PredefinedMetricType": "ECSServiceAverageCPUUtilization"
    }
  }'

Amazon ECR (Elastic Container Registry)

ECR Basics

ECR stores Docker images with built-in scanning, encryption, and lifecycle policies.

Push image to ECR:

# Authenticate Docker to ECR
aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com

# Tag image
docker tag my-app:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latest

# Push to ECR
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latest

Lifecycle policy (auto-delete old images):

{
  "rules": [
    {
      "rulePriority": 1,
      "description": "Keep last 10 images",
      "selection": {
        "tagStatus": "any",
        "countType": "imageCountMoreThan",
        "countNumber": 10
      },
      "action": {
        "type": "expire"
      }
    }
  ]
}

AWS CloudFormation

CloudFormation Architecture

CloudFormation provisions infrastructure using declarative templates (JSON/YAML).

   AWS Resources   

   creates   

   provisions   

   provisions   

   provisions   

   provisions   

  CloudFormation Template  

  YAML/JSON  

  CloudFormation Stack  

  Resource Group  

  VPC  

  EC2 Instances  

  RDS Database  

  Load Balancer  

Template Components:

  • Resources (required): AWS resources to create
  • Parameters: Input values for customization
  • Mappings: Static key-value pairs
  • Outputs: Values to export or display
  • Conditions: Control resource creation

CloudFormation Template Example

AWSTemplateFormatVersion: '2010-09-09'
Description: 'Simple web application stack'

Parameters:
  InstanceType:
    Type: String
    Default: t3.micro
    AllowedValues: [t3.micro, t3.small, t3.medium]

  Environment:
    Type: String
    Default: dev
    AllowedValues: [dev, staging, prod]

Mappings:
  RegionMap:
    us-east-1:
      AMI: ami-0c55b159cbfafe1f0
    us-west-2:
      AMI: ami-0d1cd67c26f5fca19

Conditions:
  IsProduction: !Equals [!Ref Environment, prod]

Resources:
  WebServerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow HTTP
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0

  WebServer:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: !Ref InstanceType
      ImageId: !FindInMap [RegionMap, !Ref 'AWS::Region', AMI]
      SecurityGroups:
        - !Ref WebServerSecurityGroup
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          yum update -y
          yum install -y httpd
          systemctl start httpd
          systemctl enable httpd
          echo "Hello from ${Environment}" > /var/www/html/index.html

Outputs:
  WebsiteURL:
    Description: URL of the website
    Value: !Sub 'http://${WebServer.PublicDnsName}'
    Export:
      Name: !Sub '${AWS::StackName}-URL'

CloudFormation Stack Operations

Create stack:

aws cloudformation create-stack \
  --stack-name my-web-app \
  --template-body file://template.yaml \
  --parameters ParameterKey=Environment,ParameterValue=prod \
  --capabilities CAPABILITY_IAM

Update stack:

aws cloudformation update-stack \
  --stack-name my-web-app \
  --template-body file://template-v2.yaml \
  --parameters ParameterKey=InstanceType,ParameterValue=t3.small

Delete stack:

aws cloudformation delete-stack --stack-name my-web-app

Describe stack events (troubleshooting):

aws cloudformation describe-stack-events --stack-name my-web-app

AWS SAM (Serverless Application Model)

SAM Overview

SAM simplifies serverless deployments with concise CloudFormation syntax for Lambda, API Gateway, and DynamoDB.

SAM Template Example:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Serverless API with Lambda and DynamoDB

Globals:
  Function:
    Runtime: nodejs18.x
    Timeout: 30
    Environment:
      Variables:
        TABLE_NAME: !Ref UsersTable

Resources:
  # API Gateway
  ApiGateway:
    Type: AWS::Serverless::Api
    Properties:
      StageName: prod
      Cors:
        AllowOrigin: "'*'"
        AllowHeaders: "'Content-Type,Authorization'"

  # Lambda Function
  GetUserFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: ./src
      Handler: index.handler
      Events:
        GetUser:
          Type: Api
          Properties:
            RestApiId: !Ref ApiGateway
            Path: /users/{id}
            Method: GET
      Policies:
        - DynamoDBReadPolicy:
            TableName: !Ref UsersTable

  # DynamoDB Table
  UsersTable:
    Type: AWS::Serverless::SimpleTable
    Properties:
      PrimaryKey:
        Name: userId
        Type: String
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5

Outputs:
  ApiUrl:
    Description: API Gateway endpoint
    Value: !Sub 'https://${ApiGateway}.execute-api.${AWS::Region}.amazonaws.com/prod'

SAM CLI Commands

Build and deploy:

# Initialize new SAM project
sam init --runtime nodejs18.x --name my-app

# Build application
sam build

# Deploy to AWS
sam deploy --guided

# Local testing
sam local start-api
sam local invoke GetUserFunction -e events/test.json

Package for deployment:

# Package and upload to S3
sam package \
  --template-file template.yaml \
  --output-template-file packaged.yaml \
  --s3-bucket my-deployment-bucket

# Deploy packaged template
sam deploy \
  --template-file packaged.yaml \
  --stack-name my-serverless-app \
  --capabilities CAPABILITY_IAM

Production Best Practices

ECS Best Practices

  1. Task Definitions: Use versioning, immutable task definitions
  2. Service Discovery: Use AWS Cloud Map for service-to-service communication
  3. Fargate vs EC2: Use Fargate for simplicity, EC2 for cost optimization (Reserved Instances)
  4. Secrets: Store in Secrets Manager or Parameter Store, reference in task definition
  5. Logging: Enable CloudWatch Logs with structured logging
  6. Health Checks: Configure ELB health checks and container health checks

CloudFormation Best Practices

  1. Modular Templates: Use nested stacks for reusability
  2. Parameters: Externalize environment-specific values
  3. Change Sets: Preview changes before applying (like Terraform plan)
  4. Stack Policies: Prevent accidental deletion of critical resources
  5. Cross-Stack References: Use Outputs and !ImportValue for dependencies
  6. Rollback: Enable automatic rollback on failure

SAM Best Practices

  1. Local Testing: Use sam local for development before deploying
  2. Environment Variables: Use Globals section for shared config
  3. Policies: Use SAM policy templates (DynamoDBReadPolicy, S3CrudPolicy)
  4. Canary Deployments: Use AutoPublishAlias with CodeDeploy for gradual rollouts
  5. Layers: Share dependencies across functions

Monitoring and Troubleshooting

ECS Metrics (CloudWatch):

  • CPUUtilization - Task CPU usage
  • MemoryUtilization - Task memory usage
  • RunningTasksCount - Number of running tasks

CloudFormation Events:

  • CREATE_IN_PROGRESSCREATE_COMPLETE
  • UPDATE_IN_PROGRESSUPDATE_COMPLETE
  • ROLLBACK_IN_PROGRESS (on failure)

Common Issues:

  • ECS task fails to start: Check task role permissions, security groups, subnet routes
  • CloudFormation rollback: Check stack events for resource creation failures
  • SAM deployment fails: Verify S3 bucket permissions, IAM capabilities

Exam Tips

Key Concepts:

  1. ECS task placement strategies: Binpack (cost), Random, Spread (availability)
  2. Fargate: Serverless, no EC2 management, pay per vCPU/GB
  3. CloudFormation intrinsic functions: !Ref, !GetAtt, !Sub, !Join
  4. SAM Transform: AWS::Serverless-2016-10-31 enables SAM syntax
  5. ECS Service: Maintains desired task count, integrates with ALB/NLB

Common Scenarios:

  • "Need serverless containers" → Fargate
  • "Cost-optimize containers" → ECS EC2 with Reserved Instances
  • "Deploy Lambda + API Gateway" → SAM
  • "Manage infrastructure as code" → CloudFormation
  • "Rollback failed deployment" → CloudFormation automatic rollback
  • "Blue/Green deployment for ECS" → CodeDeploy with ECS

Frequently Asked Questions

Q: What is the difference between ECS and Fargate?

ECS (Elastic Container Service) is the orchestration platform that manages container deployment. Fargate is a serverless compute engine for ECS that eliminates EC2 instance management. ECS can run on EC2 instances you manage or on Fargate. Use Fargate for simplicity, EC2 for cost optimization with Reserved Instances.

Q: How does AWS CloudFormation work?

CloudFormation is Infrastructure as Code that provisions AWS resources using JSON or YAML templates. You define desired resources, parameters, and dependencies. CloudFormation creates, updates, or deletes resources to match the template. It provides rollback on failure, change sets for previewing updates, and drift detection.

Q: When should I use SAM instead of CloudFormation?

SAM (Serverless Application Model) extends CloudFormation specifically for serverless applications with simplified syntax. Use SAM for Lambda, API Gateway, and DynamoDB projects. SAM includes local testing, built-in deployment commands, and policy templates. Use CloudFormation for complex infrastructure mixing serverless and traditional services.

Q: What are ECS task placement strategies?

Task placement strategies determine how ECS distributes tasks across EC2 instances. Binpack minimizes instances for cost efficiency by filling instances before adding new ones. Spread maximizes availability by distributing across availability zones or instances. Random distributes evenly without specific logic. Combine strategies for optimal placement.

Q: How do I manage secrets in ECS containers?

Store secrets in AWS Secrets Manager or Systems Manager Parameter Store, then reference them in task definitions using secretOptions or environment variables. ECS retrieves secrets at task startup and injects them securely. Never hardcode secrets in Docker images or task definitions. Enable encryption for sensitive data.

Q: What is CloudFormation drift detection?

Drift detection identifies when actual resource configurations differ from CloudFormation template definitions, typically from manual console changes. CloudFormation compares live resources against templates and reports differences. Use drift detection to maintain infrastructure consistency and prevent configuration drift from causing unexpected behavior.

Q: How does ECS service auto-scaling work?

ECS service auto-scaling uses Application Auto Scaling to adjust desired task count based on CloudWatch metrics like CPU or memory utilization. Target tracking policies automatically scale tasks to maintain metrics at target values. Step scaling provides granular control with multiple thresholds. Scheduled scaling handles predictable traffic patterns.


Conclusion

AWS container orchestration with ECS and Fargate, combined with Infrastructure as Code through CloudFormation and SAM, provides powerful tools for deploying and managing modern applications. ECS offers flexibility between EC2 and serverless Fargate, CloudFormation enables declarative infrastructure management, and SAM simplifies serverless deployments.

Choose ECS EC2 for cost optimization and control, Fargate for serverless simplicity, CloudFormation for complex infrastructure, and SAM for serverless applications. Understanding task definitions, stack management, and deployment patterns is essential for both production architectures and the AWS Certified Developer Associate exam.