AWS ECS & Fargate
Duration: 110 min
AWS ECS (Elastic Container Service) is a fully managed container orchestration service. Fargate is a serverless compute engine for ECS that eliminates the need to manage EC2 instances. This module covers ECS task definitions, services, load balancing, and auto-scaling.
ECS Fundamentals
ECS components:
- Task Definition: Blueprint for Docker containers (like Kubernetes Pod spec)
- Task: Running instance of a task definition
- Service: Manages long-running tasks and ensures desired count
- Cluster: Logical grouping of resources
- Container Registry: ECR stores Docker images
ECS Task Definitions
Task definitions specify how Docker containers should run:
{
"family": "my-app",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"containerDefinitions": [
{
"name": "my-app",
"image": "123456789.dkr.ecr.us-east-1.amazonaws.com/my-app:latest",
"portMappings": [
{
"containerPort": 8080,
"hostPort": 8080,
"protocol": "tcp"
}
],
"environment": [
{
"name": "LOG_LEVEL",
"value": "INFO"
}
],
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:us-east-1:123456789:secret:db-password"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/my-app",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
}
},
"healthCheck": {
"command": ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"],
"interval": 30,
"timeout": 5,
"retries": 3,
"startPeriod": 60
}
}
]
}Register task definition:
# Register task definition
aws ecs register-task-definition \
--cli-input-json file://task-definition.json
# List task definitions
aws ecs list-task-definitions
# Describe task definition
aws ecs describe-task-definition \
--task-definition my-app:1ECS Services
Services manage long-running tasks:
# Create ECS cluster
aws ecs create-cluster --cluster-name production
# Create service
aws ecs create-service \
--cluster production \
--service-name my-app \
--task-definition my-app:1 \
--desired-count 3 \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[subnet-12345],securityGroups=[sg-12345],assignPublicIp=ENABLED}" \
--load-balancers targetGroupArn=arn:aws:elasticloadbalancing:us-east-1:123456789:targetgroup/my-app/abc123,containerName=my-app,containerPort=8080
# Update service
aws ecs update-service \
--cluster production \
--service my-app \
--desired-count 5
# Describe service
aws ecs describe-services \
--cluster production \
--services my-app
# List tasks in service
aws ecs list-tasks \
--cluster production \
--service-name my-appFargate Networking
Fargate tasks require VPC networking:
# Create VPC
aws ec2 create-vpc --cidr-block 10.0.0.0/16
# Create subnet
aws ec2 create-subnet \
--vpc-id vpc-12345 \
--cidr-block 10.0.1.0/24 \
--availability-zone us-east-1a
# Create security group
aws ec2 create-security-group \
--group-name ecs-sg \
--description "Security group for ECS tasks" \
--vpc-id vpc-12345
# Allow inbound traffic
aws ec2 authorize-security-group-ingress \
--group-id sg-12345 \
--protocol tcp \
--port 8080 \
--source-security-group-id sg-12345Application Load Balancer Integration
# Create target group
aws elbv2 create-target-group \
--name my-app-tg \
--protocol HTTP \
--port 8080 \
--vpc-id vpc-12345 \
--target-type ip \
--health-check-enabled \
--health-check-path /health \
--health-check-interval-seconds 30 \
--health-check-timeout-seconds 5 \
--healthy-threshold-count 2 \
--unhealthy-threshold-count 3
# Create load balancer
aws elbv2 create-load-balancer \
--name my-app-alb \
--subnets subnet-12345 subnet-67890 \
--security-groups sg-12345 \
--scheme internet-facing \
--type application
# Create listener
aws elbv2 create-listener \
--load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:123456789:loadbalancer/app/my-app-alb/abc123 \
--protocol HTTP \
--port 80 \
--default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:us-east-1:123456789:targetgroup/my-app-tg/abc123Auto-Scaling
Auto Scaling adjusts task count based on metrics:
# Register scalable target
aws application-autoscaling register-scalable-target \
--service-namespace ecs \
--resource-id service/production/my-app \
--scalable-dimension ecs:service:DesiredCount \
--min-capacity 2 \
--max-capacity 10
# Create scaling policy (CPU-based)
aws application-autoscaling put-scaling-policy \
--policy-name cpu-scaling \
--service-namespace ecs \
--resource-id service/production/my-app \
--scalable-dimension ecs:service:DesiredCount \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration '{
"TargetValue": 70.0,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ECSServiceAverageCPUUtilization"
},
"ScaleOutCooldown": 60,
"ScaleInCooldown": 300
}'
# Create scaling policy (Memory-based)
aws application-autoscaling put-scaling-policy \
--policy-name memory-scaling \
--service-namespace ecs \
--resource-id service/production/my-app \
--scalable-dimension ecs:service:DesiredCount \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration '{
"TargetValue": 80.0,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ECSServiceAverageMemoryUtilization"
},
"ScaleOutCooldown": 60,
"ScaleInCooldown": 300
}'CloudWatch Logs Integration
# Create log group
aws logs create-log-group --log-group-name /ecs/my-app
# Set retention
aws logs put-retention-policy \
--log-group-name /ecs/my-app \
--retention-in-days 7
# View logs
aws logs tail /ecs/my-app --follow
# Get log events
aws logs get-log-events \
--log-group-name /ecs/my-app \
--log-stream-name ecs/my-app/abc123Terraform for ECS
# Create ECS cluster
resource "aws_ecs_cluster" "main" {
name = "production"
setting {
name = "containerInsights"
value = "enabled"
}
}
# Register task definition
resource "aws_ecs_task_definition" "app" {
family = "my-app"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = "256"
memory = "512"
container_definitions = jsonencode([
{
name = "my-app"
image = "123456789.dkr.ecr.us-east-1.amazonaws.com/my-app:latest"
essential = true
portMappings = [
{
containerPort = 8080
hostPort = 8080
protocol = "tcp"
}
]
logConfiguration = {
logDriver = "awslogs"
options = {
"awslogs-group" = aws_cloudwatch_log_group.ecs.name
"awslogs-region" = "us-east-1"
"awslogs-stream-prefix" = "ecs"
}
}
}
])
}
# Create ECS service
resource "aws_ecs_service" "app" {
name = "my-app"
cluster = aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.app.arn
desired_count = 3
launch_type = "FARGATE"
network_configuration {
subnets = [aws_subnet.private.id]
security_groups = [aws_security_group.ecs.id]
assign_public_ip = false
}
load_balancer {
target_group_arn = aws_lb_target_group.app.arn
container_name = "my-app"
container_port = 8080
}
depends_on = [aws_lb_listener.app]
}
# Auto-scaling
resource "aws_appautoscaling_target" "ecs_target" {
max_capacity = 10
min_capacity = 2
resource_id = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.app.name}"
scalable_dimension = "ecs:service:DesiredCount"
service_namespace = "ecs"
}
resource "aws_appautoscaling_policy" "ecs_policy_cpu" {
name = "cpu-autoscaling"
policy_type = "TargetTrackingScaling"
resource_id = aws_appautoscaling_target.ecs_target.resource_id
scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension
service_namespace = aws_appautoscaling_target.ecs_target.service_namespace
target_tracking_scaling_policy_configuration {
predefined_metric_specification {
predefined_metric_type = "ECSServiceAverageCPUUtilization"
}
target_value = 70.0
}
}❓ What is AWS Fargate?
❓ What is an ECS Task Definition?
❓ What is the purpose of an ECS Service?
❓ What networking mode is required for Fargate?
❓ What metric can be used for ECS auto-scaling?