Comment supprimer les images AWS ECR non balisées et plus anciennes ?
Amazon ECR s'intègre harmonieusement avec Amazon Elastic Kubernetes Service (Amazon EKS), Amazon Elastic Container Service (Amazon ECS) et AWS Lambda, optimisant ainsi votre parcours de développement jusqu'à la mise en production.
Amazon ECR assure l'hébergement des images dans une infrastructure hautement évolutive et disponible, ce qui garantit un déploiement fiable de conteneurs pour vos applications. Il est essentiel d'éliminer les images obsolètes et sans étiquette afin de maintenir un environnement sain.
Aujourd'hui, les applications sont souvent structurées en microservices. Un microservice est essentiellement un conteneur qui encapsule l'ensemble du code et ses dépendances, permettant à l'application de fonctionner rapidement et avec fiabilité dans n'importe quel environnement informatique. Grâce à leur portabilité, leur taille réduite et leur commodité, les conteneurs sont devenus une méthode privilégiée pour la distribution d'applications modernes.
Les conteneurs sont construits à partir d'un modèle en lecture seule appelé image. Ces images doivent être stockées dans un emplacement centralisé pour permettre à toute machine autorisée de les récupérer.
C'est là qu'intervient un registre de conteneurs. Il n'y a pas si longtemps, DockerHub était largement utilisé pour le stockage de ces images et artefacts. Cependant, si vous utilisez les services cloud AWS, il y a de fortes chances que vous utilisiez déjà AWS ECR, qui constitue une alternative à DockerHub.
AWS ECR est un registre de conteneurs entièrement géré qui fournit un hébergement performant, vous permettant de déployer des images d'applications et des artefacts sous la forme de référentiels publics ou privés.
Chaque jour, de nombreuses applications hébergées sur AWS transfèrent des millions d'images/artefacts d'applications vers et depuis des référentiels ECR spécifiques.
Dans cet article, nous explorerons comment éliminer les images obsolètes et inutiles d'AWS ECR, en veillant à la propreté des référentiels ECR.
Nécessité de supprimer les images anciennes et sans étiquette
La raison principale de nettoyer les référentiels ECR est de maintenir l'hygiène du développement. Il est rare que l'on souhaite conserver des images remontant à plus de dix déploiements. De plus, bien que les retours en arrière soient fréquents dans l'industrie, il est peu probable de revenir sur un changement datant de plus de cinq artefacts.
En termes simples, toute image ou artefact datant de plus de cinq déploiements est généralement considérée comme inutile. Cette politique peut être modifiée dans votre stratégie organisationnelle, mais nous ne la recommandons pas comme pratique optimale.
Dans l'ensemble de l'industrie, l'étiquetage est utilisé pour désigner les images les plus récentes et stables, ou les cinq dernières images les plus récentes. Dans le cycle de vie du développement logiciel, les images sont générées rapidement, et ces étiquettes sont attribuées à de nouvelles images, laissant les anciennes images sans étiquette et donc inutiles.
Dans ce genre de situations, où les images et artefacts sont volumineux, cela peut engendrer des frais de stockage sur ECR. Le coût d'AWS ECR est de "0,10 $ par Go par mois pour les données stockées dans des référentiels privés ou publics".
Ce coût peut sembler insignifiant, mais comme le dit l'adage, les petits ruisseaux font les grandes rivières. Toutes ces images stockées pendant une longue période peuvent alourdir considérablement vos factures AWS.
Par conséquent, il est fortement conseillé de supprimer ces images anciennes et sans étiquette de vos référentiels ECR, car elles ne sont plus nécessaires ! C'est aussi simple que cela ! Pourquoi les conserver et les payer ?
Suppression manuelle d'images AWS ECR
Méthode 1 : Utilisation de l'interface graphique
Étape 1 : Connectez-vous à votre compte Amazon Web Services et accédez au référentiel que vous souhaitez nettoyer.
Étape 2 : Dans ce référentiel, vous remarquerez la dernière étiquette indiquant la version la plus stable. Les autres étiquettes que vous voyez peuvent être considérées comme non étiquetées. Pour supprimer une image, sélectionnez-la et cliquez sur le bouton de suppression.
Étape 3 : Confirmez l'opération de suppression.

Méthode 2 : Utilisation de l'interface de ligne de commande
Pour supprimer une image via l'interface de ligne de commande, vous devez avoir les clés d'accès AWS IAM correctement configurées sur votre machine, ainsi que les autorisations IAM requises pour accéder aux référentiels.
Dans notre cas, cette configuration a déjà été effectuée. Si ce n'est pas votre cas, vous pouvez consulter le guide de configuration AWS pour le faire.
Si vous n'êtes pas certain d'avoir configuré AWS CLI sur votre machine, utilisez la commande suivante pour vérifier :
aws sts get-caller-identity
Une fois confirmé que vous pouvez utiliser AWS CLI, vous pouvez utiliser la commande suivante pour supprimer une image ECR sans étiquette :
aws ecr batch-delete-image --repository-name test-ecr-policy --image-ids imageTag=custom-image-6

Cette commande est similaire à l'opération effectuée via l'interface graphique. Elle supprime l'image étiquetée comme `custom-image-6` située dans le référentiel `test-ecr-policy`.
Méthode 3 : Utilisation de scripts
Le prérequis pour cette méthode est d'avoir une clé d'accès AWS configurée sur la machine où vous exécutez le script.
Voici un script pour supprimer les images sans étiquette :
import boto3
client = boto3.client('ecr')
response = client.list_images(repositoryName="test-ecr-policy")
untaggedImageList = [image for image in response['imageIds'] if image['imageTag'] == 'custom-build-4']
response2 = client.batch_delete_image(repositoryName="aws-test-ecrpolicy", imageIds=untaggedImageList)
print(response2)
La réponse vous fournira une liste des identifiants d'image supprimés, ainsi que les éventuels échecs.
Planification de la suppression d'images ECR
Si vous êtes un ingénieur DevOps ou si vous gérez régulièrement AWS ECR, vous êtes certainement conscient de la complexité de la suppression manuelle de ces images.
Bien que l'exécution de scripts ou de commandes facilite les choses, vous aimeriez probablement avoir une solution automatisée qui éliminerait ces images sans intervention manuelle.
Heureusement, AWS ECR propose une politique de cycle de vie pour vos images, que vous pouvez configurer pour supprimer ces images de manière régulière ou planifiée. Voyons comment procéder.
Méthode 1 : Utilisation de l'interface graphique
Étape 1 : Accédez au référentiel dans lequel vous souhaitez configurer la politique de cycle de vie. Dans le menu de gauche, vous trouverez l'option "Politique de cycle de vie". Cliquez dessus pour commencer.

Étape 2 : Vous pouvez cliquer sur le bouton de création pour définir votre première règle.

Étape 3 : ECR vous permet de supprimer des images selon deux conditions : soit si les images ont dépassé un certain nombre de jours, soit si elles sont étiquetées ou non étiquetées et que vous souhaitez les conserver pendant une période limitée, par exemple X jours.
Explorons ces options. Vous pouvez spécifier que les images non étiquetées doivent être supprimées si elles datent d'un jour ou plus, ou si le nombre d'images non étiquetées dépasse une certaine limite.
Choisissez les paramètres qui correspondent à votre cas d'utilisation. N'oubliez pas que vous pouvez ajuster ces valeurs selon vos besoins. Sauvegardez les modifications pour activer la règle du cycle de vie.

Méthode 2 : Utilisation de l'interface de ligne de commande
La commande AWS CLI pour définir la politique de cycle de vie est `put-lifecycle-policy`.
Voyons comment procéder. Pour cela, vous devez créer un fichier JSON contenant les conditions de la politique. Vous pouvez nommer ce fichier `policy.json`, ou tout autre nom de votre choix.
Avant de commencer, examinons les éléments constitutifs d'une politique de cycle de vie :
rulePriority (Type: integer, Required: yes):
Il s'agit de l'ordre d'application des règles, allant du plus bas au plus élevé. Les règles ayant une priorité de 1 sont appliquées en premier, suivies de 2, et ainsi de suite. Chaque règle de politique de cycle de vie doit avoir une valeur de priorité unique.
Les valeurs de priorité des règles ne doivent pas nécessairement être consécutives. Toutes les règles relatives aux images étiquetées doivent avoir la priorité la plus élevée et être évaluées en dernier.
description (Type: string, Required: no):
Cette option permet de décrire l'objectif d'une règle dans une politique de cycle de vie.
tagStatus (Type: string, Required: yes):
Cette option détermine si la règle de politique de cycle de vie concerne une étiquette d'image. Les valeurs autorisées sont : étiquetée, non étiquetée ou toutes. Si aucune valeur n'est spécifiée, toutes les images sont évaluées. La valeur étiquetée nécessite un `tagPrefixList`, tandis que la valeur non étiquetée implique l'omission de `tagPrefixList`.
tagPrefixList (Type: list[string], Required: yes, only if tagStatus is set to tagged):
Si `tagStatus` est défini sur `tagged`, votre politique de cycle de vie requiert une liste de préfixes d'étiquettes d'image, séparés par des virgules.
En utilisant le préfixe `prod`, vous pouvez spécifier toutes les images étiquetées `prod`, `prod1`, `prod2`, etc. Plusieurs étiquettes permettent de ne sélectionner que les images qui comportent toutes les étiquettes.
countType (Type: string, Required: yes):
Spécifiez `countNumber` si `countType` est défini sur `imageCountMoreThan` pour limiter le nombre d'images dans votre référentiel.
Spécifiez `countUnit` et `countNumber` si `countType` est défini sur `sinceImagePushed` pour limiter la durée de conservation des images dans le référentiel.
countUnit (Type: string, Required: yes, only if countType is set to sinceImagePushed):
Spécifiez une unité de comptage uniquement lorsque `countType` est défini sur `sinceImagePushed` ; dans le cas contraire, une erreur se produira.
countNumber (Type: integer, Required: yes):
Cette option accepte uniquement des entiers positifs (0 n'est pas une valeur valide). Si `countType` est défini sur `imageCountMoreThan`, cette valeur représente le nombre maximal de photos à conserver. L'utilisation de `sinceImagePushed` comme `countType` détermine l'âge maximal de l'image.
type (Type: string, Required: yes):
Choisissez un type d'action. La valeur qui peut être utilisée est `expire`.
Voici mon fichier `policy.json` :
{
"rules": [
{
"rulePriority": 1,
"description": "Expire images older than 10 days",
"selection": {
"tagStatus": "untagged",
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": 14
},
"action": {
"type": "expire"
}
}
]
}
Cette configuration peut être ajustée en fonction des exigences de votre organisation. "sinceImagePushed" peut être remplacé par "imageCountMoreThan".
La commande CLI pour appliquer cette politique est :
aws ecr put-lifecycle-policy --repository-name "test-ecr-polict" --lifecycle-policy-text "file://policy.json"
Méthode 3 : Utilisation de scripts
Nous allons utiliser la commande Boto3 pour parvenir à ce résultat. Nous pouvons utiliser le même fichier `policy.json` pour la configuration. Vous trouverez ci-dessous un exemple de code utilisé :
import boto3
client = boto3.client('ecr')
response = client.put_lifecycle_policy(
registryId='PODES12342',
repositoryName="test-ecr-policy",
lifecyclePolicyText="plicy.json"
)
print(response)
Comment appliquer une politique unique à plusieurs référentiels ECR ?
La question de savoir comment appliquer une même politique à plusieurs référentiels est souvent soulevée.
La définition manuelle des politiques est une tâche répétitive et fastidieuse.
Voici un extrait de code qui peut être utilisé dans un environnement de production pour appliquer une politique à plus de 100 référentiels :
from boto3 import Session,client
from os import getenv
AWS_ACCESS_KEY_ID = getenv("ACCESSKEY")
AWS_SECRET_ACCESS_KEY = getenv("SECRETKEY")
session = Session(
aws_access_key_id=AWS_ACCESS_KEY_ID,
aws_secret_access_key=AWS_SECRET_ACCESS_KEY
)
client = client('ecr')
response = client.describe_repositories()
repositories = response['repositories']
globalLifecyclePolicy = 'put your policy here’’
for repo in repositories:
repoName = repo['repositoryName']
client.put_lifecycle_policy( repositoryName = repoName,lifecyclePolicyText = globalLifecyclePolicy)
Conclusion
Il est facile de configurer une politique de cycle de vie ECR et de supprimer les anciennes images selon les paramètres définis. AWS fournit une documentation complète ainsi que des exemples de politiques de cycle de vie.
Vous pouvez également tester d'autres politiques pour les images étiquetées, par exemple en faisant correspondre les critères avec la date de téléchargement de l'image.
N'hésitez pas à explorer les concepts clés d'AWS pour approfondir vos connaissances.