By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
(For AWS Solutions Architect – Associate & Real-World Deployments)
You’re a cloud engineer at a startup migrating a monolithic app to containers. Your CTO asks: "Should we use ECS, EKS, or Fargate? And why?"
Wrong answer: "ECS is simpler, EKS is for Kubernetes, Fargate is serverless." Right answer: "ECS is cheaper for AWS-native workloads, EKS gives us Kubernetes portability, and Fargate removes node management—but costs 20% more. Here’s the cost/ops tradeoff for our 50-container microservice."
Why this matters in production:- Cost: Fargate saves ops time but costs ~$0.0405/vCPU-hour vs ~$0.0116 for ECS on EC2 (us-east-1, 2024). A 100-container app could cost $2,500/month extra on Fargate.- Ops overhead: EKS requires Kubernetes expertise (etcd, CNI, kube-proxy). ECS is "AWS-managed Kubernetes-lite." - Vendor lock-in: EKS lets you lift-and-shift to GKE/Azure AKS. ECS locks you into AWS.- Security: Fargate runs containers in isolated VMs (stronger security). ECS/EKS on EC2 shares kernel risks (container escapes).
Scenario: You inherit a legacy Java app running on EC2. It’s a mess of JARs, cron jobs, and hardcoded IPs. Your goal: Containerize it with zero downtime, minimal ops overhead, and cost under $500/month. Which service do you pick?
latest
amzn2-ami-ecs-hvm-2.0.20240122-x86_64-ebs
node_disk_pressure
t3.medium
AdministratorAccess
aws --version
docker --version
App code (app.py):
app.py
from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return "Hello from ECS Fargate!" if __name__ == '__main__': app.run(host='0.0.0.0', port=80)
Dockerfile:
FROM python:3.9-slim WORKDIR /app COPY app.py .RUN pip install flask CMD ["python", "app.py"]
Build and push 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 # Create ECR repo aws ecr create-repository --repository-name flask-app --region us-east-1 # Build, tag, and push docker build -t flask-app .docker tag flask-app:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/flask-app:latest docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/flask-app:latest
# Create VPC aws ec2 create-vpc --cidr-block 10.0.0.0/16 --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=ecs-vpc}]' # Create private subnets (2 AZs for HA) aws ec2 create-subnet --vpc-id vpc-12345678 --cidr-block 10.0.1.0/24 --availability-zone us-east-1a --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=private-subnet-1a}]' aws ec2 create-subnet --vpc-id vpc-12345678 --cidr-block 10.0.2.0/24 --availability-zone us-east-1b --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=private-subnet-1b}]' # Create NAT Gateway (for Fargate to pull images) aws ec2 create-nat-gateway --subnet-id subnet-12345678 --allocation-id eipalloc-12345678
aws ecs create-cluster --cluster-name fargate-cluster --capacity-providers FARGATE
task-definition.json:
task-definition.json
{ "family": "flask-app", "networkMode": "awsvpc", "executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole", "containerDefinitions": [ { "name": "flask-app", "image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/flask-app:latest", "portMappings": [ { "containerPort": 80, "hostPort": 80, "protocol": "tcp" } ], "essential": true, "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/ecs/flask-app", "awslogs-region": "us-east-1", "awslogs-stream-prefix": "ecs" } } } ], "requiresCompatibilities": ["FARGATE"], "cpu": "256", "memory": "512" }
Register the task:
aws ecs register-task-definition --cli-input-json file://task-definition.json
# Create ALB aws elbv2 create-load-balancer --name fargate-alb --subnets subnet-12345678 subnet-87654321 --security-groups sg-12345678 # Create target group aws elbv2 create-target-group --name fargate-tg --protocol HTTP --port 80 --vpc-id vpc-12345678 --target-type ip # Create listener aws elbv2 create-listener --load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/fargate-alb/1234567890abcdef --protocol HTTP --port 80 --default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/fargate-tg/1234567890abcdef
aws ecs create-service \ --cluster fargate-cluster \ --service-name flask-service \ --task-definition flask-app:1 \ --desired-count 2 \ --launch-type FARGATE \ --network-configuration "awsvpcConfiguration={subnets=[subnet-12345678,subnet-87654321],securityGroups=[sg-12345678],assignPublicIp=DISABLED}" \ --load-balancers "targetGroupArn=arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/fargate-tg/1234567890abcdef,containerName=flask-app,containerPort=80"
Check ALB DNS: bash aws elbv2 describe-load-balancers --names fargate-alb --query 'LoadBalancers[0].DNSName' --output text Open the DNS name in a browser—you should see "Hello from ECS Fargate!".
bash aws elbv2 describe-load-balancers --names fargate-alb --query 'LoadBalancers[0].DNSName' --output text
Check ECS service: bash aws ecs describe-services --cluster fargate-cluster --services flask-service Look for "runningCount": 2.
bash aws ecs describe-services --cluster fargate-cluster --services flask-service
"runningCount": 2
Check CloudWatch Logs: bash aws logs get-log-events --log-group-name /ecs/flask-app --log-stream-name ecs/flask-app/<task-id>
bash aws logs get-log-events --log-group-name /ecs/flask-app --log-stream-name ecs/flask-app/<task-id>
bash aws iam create-role --role-name ecsTaskRole --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ecs-tasks.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
json "secrets": [ { "name": "DB_PASSWORD", "valueFrom": "arn:aws:ssm:us-east-1:123456789012:parameter/db/password" } ]
bash aws ecs create-capacity-provider --name spot-cp --auto-scaling-group-provider autoScalingGroupArn=arn:aws:autoscaling:us-east-1:123456789012:autoScalingGroup:12345678-1234-1234-1234-123456789012:autoScalingGroupName/ecs-asg,managedScaling={status=ENABLED},managedTerminationProtection=DISABLED
256 CPU / 512 MB
CPUUtilization
MemoryUtilization
bash aws ecs update-service --cluster fargate-cluster --service flask-service --task-definition flask-app:2 --force-new-deployment
bash aws elbv2 modify-target-group --target-group-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/fargate-tg/1234567890abcdef --health-check-path /health --health-check-interval-seconds 30
bash aws ecs tag-resource --resource-arn arn:aws:ecs:us-east-1:123456789012:cluster/fargate-cluster --tags key=Environment,value=Production
CPUUtilization > 80%
MemoryUtilization > 90%
bash aws cloudwatch put-metric-alarm --alarm-name HighCPU-Fargate --metric-name CPUUtilization --namespace AWS/ECS --statistic Average --period 60 --threshold 80 --comparison-operator GreaterThanThreshold --evaluation-periods 2 --alarm-actions arn:aws:sns:us-east-1:123456789012:Alerts
json "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/ecs/flask-app", "awslogs-region": "us-east-1", "awslogs-stream-prefix": "ecs" } }, "environment": [ { "name": "AWS_XRAY_DAEMON_ADDRESS", "value": "xray-daemon:2000" } ]
/health
CannotPullContainerError
AmazonECSTaskExecutionRolePolicy
Trap: EKS is overkill unless you need Kubernetes portability.
"Your EKS cluster is failing to schedule Pods. What’s the issue?"
Trap: "Not enough CPU/memory" is a distractor—EKS fails silently on networking.
"How do you reduce costs for a steady-state ECS workload?"
Challenge: Deploy a multi-container ECS Fargate task with: - A Flask app (port 80).- A Redis sidecar (port 6379).- The Flask app should connect to Redis at localhost:6379.
localhost:6379
Solution:1. Update task-definition.json: ```json "containerDefinitions": [ { "name": "flask-app", "image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/flask-app:latest", "portMappings": [{"containerPort": 80, "hostPort": 80}], "environment": [{"name": "REDIS_HOST", "value": "localhost"}], "essential": true }, { "name": "redis", "image": "redis:alpine", "portMappings": [{"containerPort": 6379, "hostPort": 6379}
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.