ECS Exec en pratique : retrouver sa tĂąche, ouvrir la session, passer un script sans se battre avec le quoting

Un guide de référence, indépendant du langage exécuté dans le container

ECS Exec permet d’ouvrir un canal de commande vers un container d’une tĂąche ECS en cours d’exĂ©cution, en s’appuyant sur AWS Systems Manager Session Manager comme transport. Pas de SSH, pas de port ouvert, pas d’agent bastion Ă  maintenir, le canal passe par l’API AWS.

Ce billet rassemble la mĂ©canique complĂšte : retrouver les identifiants d’une tĂąche en partant de zĂ©ro, les prĂ©requis IAM (souvent la partie qui bloque), et le piĂšge du quoting imbriquĂ© qui touche n’importe quel script un peu long, quel que soit le langage exĂ©cutĂ© ensuite.

Étape 0 : retrouver les identifiants de la tñche

Avant mĂȘme de parler d’ECS Exec, encore faut-il savoir quoi cibler : nom du cluster, ID de tĂąche, nom du container. Si on ne les a pas dĂ©jĂ  sous la main (lien depuis la CI/CD, la console, un ticket), voici comment les retrouver en pur CLI, du plus gĂ©nĂ©ral au plus prĂ©cis :

# 1. Identification
aws login

# 2. Lister les clusters disponibles
aws ecs list-clusters

# 3. Lister les services d'un cluster (identifier le bon environnement,
#    ex. "pro-rct" pour une recette, "pro" pour la prod)
aws ecs list-services --cluster <nom-du-cluster>

# 4. Lister les tĂąches en cours pour ce service
aws ecs list-tasks --cluster <nom-du-cluster> --service-name <nom-du-service>

Cette derniĂšre commande renvoie un ou plusieurs taskArn, de la forme :

arn:aws:ecs:eu-west-3:123456789012:task/mon-cluster/abcd1234ef...

L’ID de tĂąche Ă  utiliser dans la suite est le dernier segment de cet ARN (abcd1234ef...). aws ecs execute-command --task accepte indiffĂ©remment l’ARN complet ou juste cet ID. Pas besoin de le dĂ©couper Ă  la main si on prĂ©fĂšre coller l’ARN tel quel.

Avant de s’y connecter, autant confirmer qu’on cible la bonne tĂąche : statut, image dĂ©ployĂ©e, noms des containers.

aws ecs describe-tasks --cluster <nom-du-cluster> --tasks <task-id-ou-arn>

Trois champs à repérer dans la sortie :

  • containers[].name → le nom du container Ă  passer Ă  --container. Une tĂąche peut en contenir plusieurs (le container applicatif, plus un Ă©ventuel sidecar de sĂ©curitĂ© ou de logging).
  • containers[].image → confirme que c’est bien le build attendu (comparer tag ou digest, Ă©ventuellement recoupĂ© avec le SHA du commit vu cĂŽtĂ© CI).
  • enableExecuteCommand → voir la section suivante.

Prérequis cÎté infra

À vĂ©rifier en lecture seule avant toute tentative de connexion.

D’abord, que les credentials locaux pointent bien sur le bon compte AWS, utile pour ne pas se tromper de compte si plusieurs profils sont configurĂ©s (staging vs prod) :

aws sts get-caller-identity --region <REGION>

Ensuite, qu’ECS Exec est bien activĂ© sur la tĂąche ciblĂ©e :

aws ecs describe-tasks \
  --cluster <nom-du-cluster> \
  --tasks <task-id> \
  --query "tasks[0].enableExecuteCommand"

Si la rĂ©ponse est false, ECS Exec n’est pas disponible sur cette tĂąche telle quelle. Deux options, aux implications diffĂ©rentes :

  1. Mettre Ă  jour le service pour l’activer, ce qui force un redĂ©ploiement, et donc redĂ©marre les tĂąches. Pas anodin sur un service qui sert du trafic rĂ©el :

    aws ecs update-service \
      --cluster <nom-du-cluster> \
      --service <nom-du-service> \
      --enable-execute-command \
      --force-new-deployment
    
  2. L’activer en amont, dans la dĂ©finition de service ou au moment du dĂ©ploiement (--enable-execute-command sur create-service / deploy), pour que le flag soit actif par dĂ©faut sur toutes les tĂąches futures. À privilĂ©gier si ce type de diagnostic doit se reproduire rĂ©guliĂšrement, plutĂŽt que de forcer un redĂ©ploiement Ă  chaque fois qu’on en a besoin.

Le flag activĂ© au niveau service ne suffit pas si l’agent managĂ© n’a pas dĂ©marrĂ© sur la tĂąche elle-mĂȘme. Dans la sortie complĂšte de describe-tasks (sans le --query cette fois), chercher dans containers[].managedAgents une entrĂ©e :

{"name": "ExecuteCommandAgent", "lastStatus": "RUNNING"}

Enfin cÎté IAM, deux couches distinctes, et les deux sont nécessaires :

  • les credentials locaux (celles et ceux qui lancent la commande) doivent porter la permission ecs:ExecuteCommand sur le cluster ou la tĂąche.
  • le rĂŽle de tĂąche ECS (task role, pas le rĂŽle d’exĂ©cution, pas l’utilisateur qui se connecte) doit autoriser ssmmessages:CreateControlChannel, CreateDataChannel, OpenControlChannel et OpenDataChannel. C’est SSM Session Manager qui sert de transport sous le capot, donc c’est bien le rĂŽle portĂ© par la tĂąche en cours d’exĂ©cution qui doit l’autoriser, pas seulement le rĂŽle IAM du cĂŽtĂ© client.

Outil client requis : Session Manager Plugin

aws ecs execute-command route systĂ©matiquement via une session SSM Session Manager. Sans le plugin session-manager-plugin installĂ© localement, la commande Ă©choue avec un message explicite qui demande de l’installer.

# Windows (winget)
winget install --id Amazon.SessionManagerPlugin -e

# macOS (Homebrew)
brew install --cask session-manager-plugin

# Linux (Debian/Ubuntu) : télécharger le .deb officiel puis
sudo dpkg -i session-manager-plugin.deb

Lancer une commande ponctuelle

aws ecs execute-command \
  --cluster <nom-du-cluster> \
  --task <task-id> \
  --container <nom-du-conteneur> \
  --region <REGION> \
  --interactive \
  --command "/bin/sh -lc 'pwd && whoami && php -v'"

--interactive est obligatoire : ECS Exec ne propose que des sessions interactives cĂŽtĂ© API, mĂȘme lorsque la commande exĂ©cutĂ©e est un script qui se termine tout seul. Si la commande passĂ©e n’est pas elle-mĂȘme un shell interactif, elle s’exĂ©cute puis la session se termine proprement. Pas besoin d’un vrai TTY cĂŽtĂ© client pour un diagnostic ponctuel.

Le piÚge des quotes imbriquées, et la parade

La commande traverse trois couches de shell/quoting successives : le shell local qui invoque aws ecs execute-command, la chaĂźne passĂ©e Ă  --command, puis /bin/sh -c Ă  l’intĂ©rieur du container. DĂšs qu’on veut exĂ©cuter un script un peu long (plusieurs lignes, guillemets, conditions avec parenthĂšses), les quotes imbriquĂ©es deviennent vite ingĂ©rables.

Exemple concret rencontrĂ© : une commande contenant un $(... || ...) a Ă©chouĂ© avec Syntax error: "(" unexpected, uniquement Ă  cause de l’empilement des couches de quoting, pas d’une erreur de logique shell. Le script Ă©tait syntaxiquement correct : c’est son passage Ă  travers trois interprĂ©tations successives qui l’a cassĂ©.

La parade est gĂ©nĂ©rale et indĂ©pendante du langage cible : encoder le script en base64 cĂŽtĂ© client, puis le dĂ©coder et le piper dans l’interprĂ©teur souhaitĂ© cĂŽtĂ© container. ZĂ©ro problĂšme d’échappement, quel que soit le contenu du script.

B64=$(base64 -w0 mon_script.sh)
aws ecs execute-command \
  --cluster <nom-du-cluster> --task <task-id> --container <nom-du-conteneur> --region <REGION> \
  --interactive \
  --command "/bin/sh -lc 'echo $B64 | base64 -d | sh'"

Remplacer | sh par | php, | python3 ou n’importe quel autre interprĂ©teur prĂ©sent dans le container. La technique est indiffĂ©rente Ă  la cible. C’est ce qui la rend rĂ©utilisable bien au-delĂ  d’un diagnostic PHP : un script Python de vĂ©rification, une requĂȘte SQL passĂ©e Ă  un client en ligne de commande, un test Node, tout ce qui tient dans un fichier peut transiter de cette façon.

Pourquoi c’est sĂ»r, et oĂč sont les limites

Faire tourner une commande dans un container de recette ou de prod fait peur, Ă  raison. Quelques repĂšres.

  • Un script lancĂ© en CLI dĂ©marre un process isolĂ©, distinct du pool de workers qui sert le trafic rĂ©el (php-fpm, un worker Node, un thread Gunicorn selon la stack). Une commande ponctuelle en lecture seule n’affecte aucune requĂȘte en cours.
  • ECS Exec exĂ©cute les commandes dans le container avec les privilĂšges root. C’est une raison supplĂ©mentaire de rĂ©server la technique au diagnostic ponctuel et de restreindre prĂ©cisĂ©ment la permission ecs:ExecuteCommand Ă  qui en a rĂ©ellement besoin, un accĂšs qui dĂ©passe celui d’un utilisateur applicatif normal.
  • Chaque session ECS Exec est tracĂ©e cĂŽtĂ© CloudTrail/SSM, ce qui est utile pour l’audit, mais rappelle aussi que ce n’est pas un canal fait pour de l’automatisation rĂ©guliĂšre (Ă  scripter en boucle ou laisser ouvert).
  • Une nuance Ă  ne pas passer sous silence : ce niveau de sĂ»retĂ© suppose qu’ECS Exec est dĂ©jĂ  actif sur la tĂąche. Si ce n’est pas le cas, l’activer via update-service --force-new-deployment force un redĂ©ploiement complet, ce n’est pas neutre sur un service qui sert du trafic. L’activation elle-mĂȘme est l’étape Ă  traiter avec prudence, Ă  part, et pas dans l’urgence d’un diagnostic.

Outils utilisés

  • AWS CLI v2 (list-clusters, list-services, list-tasks, describe-tasks, execute-command, update-service, sts get-caller-identity).
  • Session Manager Plugin (session-manager-plugin), requis par ecs execute-command.
  • ECS Exec, fonctionnalitĂ© ECS reposant sur AWS Systems Manager Session Manager.
  • base64, pour transporter un script multi-lignes Ă  travers plusieurs couches de shell sans souci de quoting.

Pour un exemple concret d’utilisation (vĂ©rifier un correctif de locale PHP directement dans une tĂąche ECS Fargate rĂ©elle), voir cet article.