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 :
-
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 -
Lâactiver en amont, dans la dĂ©finition de service ou au moment du dĂ©ploiement (
--enable-execute-commandsurcreate-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:ExecuteCommandsur 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,OpenControlChanneletOpenDataChannel. 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 permissionecs: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-deploymentforce 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 parecs 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.