DevOps Elastic Hayway
Document

SUBSCRIBE TO GET FULL ACCESS TO THE E-BOOKS FOR FREE 🎁SUBSCRIBE NOW

Professional Dropdown with Icon

SUBSCRIBE NOW TO GET FREE ACCESS TO EBOOKS

AWSLesson 36 / 479 min readUpdated September 13, 2026

ECS : service Fargate simple

À la fin de ce tutoriel, vous créerez un cluster ECS, une task definition Fargate (image publique nginx:alpine), un service desiredCount=1 sans ALB, exposerez le port 80 via IP publique + Security Group, testerez avec curl, puis nettoierez (desired 0, delete-service, delete-cluster) — en ca-central-1, profil lab.

Niveau : Intermédiaire · Temps estimé : 60–75 min · Versions testées : ECS / Fargate 2026, AWS CLI v2 · Dernière vérification : 2026-09-10 · Region : ca-central-1

Slug : aws-ecs-fargate · Série : AWS Solutions Architect · Mot-clé SEO : ECS Fargate

← Précédent : Elastic Beanstalk · → Suivant : EKS concepts · Hub : Démarrer avec AWS

Prérequis

  • Profil AWS CLI lab avec droits ECS, EC2 (SG/VPC), IAM (rôles de service), CloudWatch Logs
  • AWS CLI v2, jq ou --query CLI, curl
  • Notions VPC / Security Groups et un premier contact PaaS (Beanstalk)
  • Budget d’alerte : Fargate facture à l’heure (vCPU + mémoire) — lab court, nettoyage immédiat
export AWS_PROFILE=lab
export AWS_DEFAULT_REGION=ca-central-1
aws sts get-caller-identity

Vérifiez l’identité lab — jamais un compte de production. Aucun secret dans les fichiers de ce lab.

Ce que nous allons construire

Client ──HTTP:80──► IP publique ENI (assignPublicIp)
                         │
                         ▼
                   Task Fargate (awsvpc)
                   └── container nginx:alpine :80
                         │
                   Cluster ECS « lab-ecs »
                   Service desiredCount=1
                         │
                   (option) awslogs → CloudWatch

(Schéma — alt : « Client HTTP vers IP publique ENI Fargate, task nginx:alpine dans un service ECS desiredCount=1 sans ALB ».)

Pas d’Application Load Balancer dans ce lab : l’ALB est une option utile en prod (HTTPS, health, multi-AZ) mais coûteuse pour un essai de 30–60 min. On expose directement la task via assignPublicIp=ENABLED dans un subnet public.

Étape 1 — ECS vs EKS vs Beanstalk : quand Fargate

Approche Quand ça a du sens Limites
Elastic Beanstalk App ZIP / plateforme gérée, peu de concepts Moins de contrôle runtime / multi-services
ECS + Fargate Conteneurs Docker, microservices AWS-native, sans gérer des EC2 Moins « Kubernetes pur » ; écosystème AWS
ECS + EC2 Contrôle des instances, GPU, spot agressif Vous patch / capacity provider
EKS Standard Kubernetes, portabilité, Helm/operators Coût control plane + courbe d’apprentissage

Fargate = launch type serverless pour ECS (et EKS aussi) : vous définissez CPU/mémoire de la task, AWS place les conteneurs. Choisissez Fargate quand vous voulez des conteneurs sans cluster EC2 à entretenir. Passez à EKS si vous avez besoin de l’API Kubernetes (Ingress, CRD, multi-cloud tooling).

Pour l’examen SA : ECS orchestre des tasks ; EKS orchestre des Pods ; Beanstalk abstrait encore plus (PaaS). Fargate ≠ Lambda : facturation continue tant que la task tourne.

Étape 2 — Concepts ECS à maîtriser

Concept Rôle
Cluster Espace logique qui regroupe services / tasks (ex. lab-ecs)
Task definition Blueprint JSON/YAML : image, CPU, mémoire, ports, rôles, logs
Task Instance en cours d’exécution d’une task definition
Service Maintient desiredCount tasks (restart, rolling)
Launch type Fargate AWS gère le compute ; mode réseau awsvpc (ENI dédiée)
Launch type EC2 Vos instances dans le cluster ; plus de knobs capacity

En Fargate, chaque task reçoit une ENI dans votre VPC. Pour joindre Internet en lab : subnet public (route vers IGW) + assignPublicIp ENABLED + SG autorisant le port applicatif.

Étape 3 — VPC, subnet public et Security Group

Réutilisez le VPC default (lab rapide) ou un VPC existant avec subnet public. Créez un SG dédié :

VPC_ID=$(aws ec2 describe-vpcs --filters Name=isDefault,Values=true 
  --query 'Vpcs[0].VpcId' --output text)
SUBNET_ID=$(aws ec2 describe-subnets 
  --filters Name=vpc-id,Values=$VPC_ID Name=default-for-az,Values=true 
  --query 'Subnets[0].SubnetId' --output text)

SG_ID=$(aws ec2 create-security-group 
  --group-name lab-ecs-fargate-sg 
  --description "Lab ECS Fargate HTTP 80" 
  --vpc-id "$VPC_ID" 
  --query GroupId --output text)

# Lab court : 0.0.0.0/0 — ou restreignez à VOTRE_IP/32
aws ec2 authorize-security-group-ingress 
  --group-id "$SG_ID" 
  --protocol tcp --port 80 --cidr 0.0.0.0/0

echo "VPC=$VPC_ID SUBNET=$SUBNET_ID SG=$SG_ID"

En pratique, préférez VOTRE_IP/32 dès que le lab dure plus de quelques minutes. Le SG sortant default (all) suffit pour tirer l’image depuis Docker Hub / ECR Public.

Étape 4 — Rôle d’exécution IAM ecsTaskExecutionRole

Le execution role permet au agent Fargate de tirer l’image et d’écrire les logs. Le task role (app → AWS APIs) n’est pas nécessaire pour nginx statique.

cat > ecs-trust.json << 'EOF'
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"Service": "ecs-tasks.amazonaws.com"},
    "Action": "sts:AssumeRole"
  }]
}
EOF

aws iam create-role --role-name ecsTaskExecutionRole 
  --assume-role-policy-document file://ecs-trust.json 2>/dev/null || true

aws iam attach-role-policy --role-name ecsTaskExecutionRole 
  --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

EXEC_ARN=$(aws iam get-role --role-name ecsTaskExecutionRole 
  --query Role.Arn --output text)
sleep 8
echo "$EXEC_ARN"

Si le rôle existe déjà (console « first run » ECS), réutilisez-le. Aucune clé d’accès dans la task definition.

Étape 5 — Cluster, task definition et service

aws ecs create-cluster --cluster-name lab-ecs

cat > task-nginx.json << EOF
{
  "family": "lab-nginx",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512",
  "executionRoleArn": "$EXEC_ARN",
  "containerDefinitions": [{
    "name": "nginx",
    "image": "public.ecr.aws/nginx/nginx:alpine",
    "portMappings": [{"containerPort": 80, "protocol": "tcp"}],
    "essential": true,
    "logConfiguration": {
      "logDriver": "awslogs",
      "options": {
        "awslogs-group": "/ecs/lab-nginx",
        "awslogs-region": "ca-central-1",
        "awslogs-stream-prefix": "nginx",
        "awslogs-create-group": "true"
      }
    }
  }]
}
EOF

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

aws ecs create-service 
  --cluster lab-ecs 
  --service-name lab-nginx-svc 
  --task-definition lab-nginx 
  --desired-count 1 
  --launch-type FARGATE 
  --network-configuration "awsvpcConfiguration={subnets=[$SUBNET_ID],securityGroups=[$SG_ID],assignPublicIp=ENABLED}"

cpu=256 / memory=512 = taille Fargate minimale courante (très bon marché pour un lab). Image publique ECR Public nginx — pas besoin de push ECR privé. L’option awslogs-create-group crée le log group à la volée (sinon créez /ecs/lab-nginx avant).

Attendez que la task soit RUNNING :

aws ecs wait services-stable --cluster lab-ecs --services lab-nginx-svc

TASK_ARN=$(aws ecs list-tasks --cluster lab-ecs --service-name lab-nginx-svc 
  --query 'taskArns[0]' --output text)

aws ecs describe-tasks --cluster lab-ecs --tasks "$TASK_ARN" 
  --query 'tasks[0].{lastStatus:lastStatus,cpu:cpu,memory:memory,attachments:attachments}'

Étape 6 — IP publique et curl

Récupérez l’ENI puis l’IP publique associée :

ENI_ID=$(aws ecs describe-tasks --cluster lab-ecs --tasks "$TASK_ARN" 
  --query 'tasks[0].attachments[0].details[?name==`networkInterfaceId`].value' 
  --output text)

PUBLIC_IP=$(aws ec2 describe-network-interfaces --network-interface-ids "$ENI_ID" 
  --query 'NetworkInterfaces[0].Association.PublicIp' --output text)

echo "Public IP: $PUBLIC_IP"
curl -sS -o /dev/null -w "%{http_code}n" "http://$PUBLIC_IP/"
curl -sS "http://$PUBLIC_IP/" | head -n 5

HTTP 200 et la page welcome nginx = succès. Sans ALB, l’IP change à chaque remplacement de task : acceptable en lab, pas en prod.

Option ALB (coûteuse) : cible group + listener HTTP/HTTPS + loadBalancers sur le service — utile pour DNS stable et multi-tasks ; pour un lab Free Tier / budget serré, évitez l’ALB (frais horaires + LCU).

Étape 7 — Logs CloudWatch (court)

Avec awslogs dans la task definition :

aws logs tail /ecs/lab-nginx --since 10m --format short

Les access logs nginx apparaissent après quelques requêtes curl. Si le stream est vide : vérifiez executionRoleArn, la policy AmazonECSTaskExecutionRolePolicy, et que le log group existe (awslogs-create-group ou création manuelle).

Vérification

aws ecs describe-services --cluster lab-ecs --services lab-nginx-svc 
  --query 'services[0].{status:status,running:runningCount,desired:desiredCount,launchType:launchType}'
aws ecs list-tasks --cluster lab-ecs --service-name lab-nginx-svc
curl -sS -o /dev/null -w "%{http_code}n" "http://$PUBLIC_IP/"

Checklist : service ACTIVE · runningCount=1 · launch type FARGATE · HTTP 200 · plan de nettoyage prêt.

Nettoyage (obligatoire) — coûts Fargate à l’heure

Fargate facture vCPU-heure + Go-heure tant que la task tourne. Coupez dès la vérif OK :

aws ecs update-service --cluster lab-ecs --service lab-nginx-svc --desired-count 0
aws ecs wait services-stable --cluster lab-ecs --services lab-nginx-svc

aws ecs delete-service --cluster lab-ecs --service lab-nginx-svc --force
aws ecs delete-cluster --cluster lab-ecs

aws ec2 revoke-security-group-ingress --group-id "$SG_ID" 
  --protocol tcp --port 80 --cidr 0.0.0.0/0 2>/dev/null || true
aws ec2 delete-security-group --group-id "$SG_ID"

aws logs delete-log-group --log-group-name /ecs/lab-nginx 2>/dev/null || true
# Optionnel : détacher policy / delete-role ecsTaskExecutionRole si créé uniquement pour ce lab

Ordre important : desired 0 (drain) → delete-service --force → delete-cluster. Un cluster vide ne facture presque rien ; une task oubliée facture à l’heure.

Erreurs fréquentes

Symptôme Cause Correction
Task STOPPED / ResourceInitializationError Subnet sans route Internet / pas d’IP publique Subnet public + assignPublicIp=ENABLED
CannotPullContainerError Pas d’egress / DNS / image privée Image publique ECR/Docker Hub ; SG egress all
curl timeout SG trop fermé / mauvaise IP Ingress tcp/80 ; revérifier PUBLIC_IP ENI
AccessDenied logs Execution role manquant / policy AmazonECSTaskExecutionRolePolicy attachée
Coût surprise Service desired>0 oublié ou ALB desired 0 + delete-service ; pas d’ALB en lab

Debug utile : aws ecs describe-tasks ... --query 'tasks[0].stoppedReason'.

Quiz (3 questions)

1. Pour un lab ECS peu cher sans load balancer, on expose la task Fargate ainsi : – A. Toujours via un ALB multi-AZ
– B. assignPublicIp=ENABLED + SG port 80 sur subnet public
– C. Uniquement via Transit Gateway

2. Le rôle ecsTaskExecutionRole sert surtout à : – A. Donner à nginx un accès S3 admin
– B. Tirer l’image et écrire les logs (agent Fargate)
– C. Remplacer le Security Group

3. Fin de lab correcte côté coûts Fargate : – A. Laisser desiredCount=1 une semaine
– B. update-service --desired-count 0 puis delete-service / delete-cluster
– C. Supprimer seulement le log group

Réponses : 1‑B · 2‑B · 3‑B

Pour aller plus loin

Maillage série AWS (P1)

← Précédent Elastic Beanstalk : déployer une app
→ Suivant EKS : concepts et premier cluster
Aussi Démarrer avec AWS · ALB

Retour parcours AWS — hub de la série et leçons sœurs.

Share your love

Leave a Reply

Your email address will not be published. Required fields are marked *