Article écrit par Martin Catty
Pour les projets dont nous gérons l’infrastructure de production, nous utilisons depuis longtemps des outils tels que Rancher et Kubernetes.
Avec kubectl on s’habitue vite au confort de pouvoir visualiser la sortie standard de ses conteneurs, exécuter des commandes à l’intérieur, forwarder des ports. Je vous en parlerai un peu plus à l’occasion si vous voulez.
À l’inverse lorsqu’on utilise les solutions maisons (et fermées) de fournisseurs tel qu’AWS, on se retrouve vite démunis et tributaires du bon vouloir du fournisseur pour nous fournir les outils adaptés.
Le cas ECS
ECS est le service de gestion de conteneurs d’Amazon Web Services. Il s’appuie sur le service historique EC2.
Pour faire simple, vous disposez d’instances EC2 pré-configurées avec un démon Docker, ainsi que d’un orchestrateur qui vient organiser et gérer les conteneurs qui seront répartis sur ces instances.
Dans ce mode de fonctionnement, vous n’avez pas la main sur l’orchestrateur mais les nœuds (instances EC2) restent visibles et potentiellement accessibles. On peut donc s’y connecter, notamment en SSH, et interagir avec les conteneurs qui s’y trouvent.
Toutefois cela pose un certain nombre de problèmes :
- obligation d’ouvrir le service SSH, ce qui augmente inutilement la surface d’exposition
- définir au préalable sur quel nœud est exécuté le conteneur avec lequel on souhaite interagir
- pas de possibilité d’interagir avec les conteneurs depuis la console (UI)
Le cas Fargate
Fargate pousse la logique d’ECS un cran plus loin. Cette fois-ci vous n’avez même plus accès aux ressources sous-jacentes.
Évidemment il y a une infrastructure derrière, mais elle est complètement gérée pour vous, avec la promesse de ne pas avoir à gérer le dimensionnement, la sécurisation, etc.
L’inconvénient par rapport à notre besoin d’interaction avec les conteneurs tient au fait que vous n’avez plus du tout de moyen de vous connecter sur les serveurs ni de rentrer dans les conteneurs par ce biais.
Devant cette situation de blocage AWS a mis à jour son CLI pour proposer des commandes permettant d’interagir avec les conteneurs, quel que soit le système utilisé.
AWS CLI à la rescousse
En premier lieu vous aurez besoin du CLI AWS. Je ne vous fais pas l’affront de paraphraser la documentation pour l’installer.
Une fois réalisé vous aurez également besoin d’installer le plugin Session Manager pour le CLI.
On s’assure que tout est installé correctement :
fuse@archibald:~ → aws --version aws-cli/2.6.3 Python/3.9.13 Darwin/21.5.0 source/arm64 prompt/off
fuse@archibald:~ → session-manager-plugin The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.
Pour permettre l’accès au conteneur, AWS utilise son service Systems Manager
(SSM) pour établir la connexion au conteneur et vérifier que l’utilisateur exécutant les commandes a les droits suffisants pour ce faire.
Dans les faits, un agent SSM va être monté et démarré dans le conteneur pour permettre l’exécution de commandes.
Rendre l’agent SSM disponible dans les conteneurs
Création et configuration de la politique
Pour mettre en place cet agent nous allons devoir en premier lieu créer une politique (policy) associée :
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssmmessages:CreateControlChannel", "ssmmessages:CreateDataChannel", "ssmmessages:OpenControlChannel", "ssmmessages:OpenDataChannel" ], "Resource": "*" } ] }
Cette politique devra ensuite être rattachée à un rôle dont dispose l’utilisateur qui doit exécuter les commandes.
Utilisation du rôle par les instances
Par défaut, les conteneurs en cours d’exécution ne seront sûrement pas en capacité d’exécuter des commandes.
Nous allons devoir déployer une nouvelle définition de tâche et activer l’exécution de commandes.
Vous pouvez créer une définition de tâche identique à l’actuelle, simplement pour effectuer la mise à jour. En effet, si vous demandez à ECS de passer de la version N à N il ne fera rien.
Il faut lui dire de passer à la N+1, même si elle est identique.
aws ecs update-service --cluster nom_du_cluster --service nom_du_service --task-definition nom_de_definition_de_tache:version --enable-execute-command
Une fois cette commande lancée, ECS ou Fargate va rouler les conteneurs, en en démarrant de nouveaux puis en stoppant les anciens.
Pour vérifier que tout fonctionne correctement on récupère un identifiant de tâche :
fuse@archibald:~ → aws ecs list-tasks --cluster nom_du_cluster { "taskArns": [ "arn:aws:ecs:eu-west-1:034473609837:task/nom_du_cluster/63832eb11b4641729c376b95bee02f82", "arn:aws:ecs:eu-west-1:034473609837:task/nom_du_cluster/c9b7a91f6cdc43e0a7d6d70835b1db61" ] }
Et on regarde si l’agent est démarré sur cette tâche :
fuse@archibald:~ → aws ecs describe-tasks --tasks c9b7a91f6cdc43e0a7d6d70835b1db61 --cluster nom_du_cluster | jq ".tasks[].containers[].managedAgents" [ { "lastStartedAt": "2022-05-31T17:24:35.002000+02:00", "name": "ExecuteCommandAgent", "lastStatus": "RUNNING" } ]
On voit que l’agent est bien en cours d’exécution, on va pouvoir exécuter nos commandes :
fuse@archibald:~ → aws ecs execute-command --cluster nom_du_cluster --task c9b7a91f6cdc43e0a7d6d70835b1db61 --container nom_du_conteneur --interactive --command "bash" The Session Manager plugin was installed successfully. Use the AWS CLI to start a session. Starting session with SessionId: ecs-execute-command-0ef9e2cdabcb37a0a root@ip-172-23-4-93:/app#
À vous la gloire et la prospérité, vous pouvez maintenant lancer une commande à l’intérieur de votre conteneur !