Comment nettoyer les instantanés AWS EC2 orphelins?

22

Nous nous retrouvons avec une bonne quantité d'instantanés AWS EC2 où l'AMI a été supprimée, mais l'instantané est laissé pourrir. Je voudrais un moyen non manuel d' identifier et de supprimer ces orphelins pour nous faire économiser de l'argent et de l'espace.

Idéalement, je pense à un script bash exploitant la CLI , mais mon AWS-fu est faible. Je suppose que quelqu'un a déjà fait cela, mais je ne trouve pas de script qui fonctionne réellement.

Dans le meilleur des cas, cela vérifiera également les volumes et les nettoiera également, mais cela peut être mieux adapté à une deuxième question.

Alex
la source
Ma version sur python. Mode d'emploi et lien github
E.Big

Réponses:

13

En grande partie inspiré par les articles de blog et l'essentiel déjà liés dans les autres réponses, voici mon point de vue sur le problème.

J'ai utilisé certaines fonctions JMESpath alambiquées pour obtenir une liste d'instantanés et pas besoin tr.

Avis de non - responsabilité : utilisez à vos risques et périls , j'ai fait de mon mieux pour éviter tout problème et garder les valeurs par défaut saines, mais je ne prendrai aucun blâme s'il vous cause un problème.

#!/bin/sh
# remove x if you don't want to see the commands
set -ex

# Some variable initialisation with sane defaults
DRUN='--dry-run'
DO_DELETE=${1:-'no'}
REGION=${2:-'eu-west-1'}
ACCOUNTID=${3:-'self'}

# Get two temporary files
SNAP_FILE=$(mktemp)
IMAGE_FILE=$(mktemp)

# Get the snapshot list and the volume list
aws --region "$REGION" ec2 describe-snapshots --owner-ids "$ACCOUNTID" --query 'Snapshots[*].[SnapshotId]' --output text > "$SNAP_FILE"
aws --region "$REGION" ec2 describe-images --owners "$ACCOUNTID" --filters Name=state,Values=available --query 'Images[*].BlockDeviceMappings[*].Ebs.[SnapshotId]' --output text > "$IMAGE_FILE"

# Check if the outputed command should be dry-run (default) or not
if [ "$DO_DELETE" = "IAMSURE" ]
then
 DRUN=''
fi

# count each snapshot id, decrease when a volume reference it, print delete command for those with no volumes
awk -v REGION="$REGION" -v DRUN="$DRUN" '
FNR==NR { snap[$1]++; next } # increment snapshots and get to next line in file immediately

{ snap[$1]-- } # we changed file, decrease the snap counter when a volume reference it

END {
 for (s in snap) { # loop over the snapshots
   if (snap[s] > 0) { # if we did not decrese under 1 that means there is no volume referencing this snapshot
    cmd="aws --region " REGION " " DRUN " ec2 delete-snapshot --snapshot-id " s
    print(cmd)
  }
 }
}
' "$SNAP_FILE" "$IMAGE_FILE"
# Clean up the temp files
rm "$SNAP_FILE" "$IMAGE_FILE"

J'espère que le script lui-même est suffisamment commenté.

L'utilisation par défaut (sans paramètres) répertorie les commandes de suppression des instantanés orphelins pour le compte actuel et la région eu-west-1, extrait:

aws --region eu-west-1 --dry-run ec2 delete-snapshot --snapshot-id snap-81e5856a
aws --region eu-west-1 --dry-run ec2 delete-snapshot --snapshot-id snap-95c68c7e
aws --region eu-west-1 --dry-run ec2 delete-snapshot --snapshot-id snap-a3bf50bd

Vous pouvez rediriger cette sortie vers un fichier pour révision avant de la sourcer pour exécuter toutes les commandes.

Si vous souhaitez que le script exécute la commande au lieu de les imprimer, remplacez print(cmd)par system(cmd).

L'utilisation est la suivante avec un script nommé snap_cleaner:

pour les commandes à sec dans la région us-west-1

./snap_cleaner no us-west-1

pour les commandes utilisables dans eu-central-1

./snap_cleaner IAMSURE eu-central-1 

Un troisième paramètre peut être utilisé pour accéder à un autre compte (je préfère changer de rôle vers un autre compte auparavant).

Version dépouillée du script avec un script awk comme oneliner:

#!/bin/sh
set -ex

# Some variable initialisation with sane defaults
DRUN='--dry-run'
DO_DELETE=${1:-'no'}
REGION=${2:-'eu-west-1'}
ACCOUNTID=${3:-'self'}

# Get two temporary files
SNAP_FILE=$(mktemp)
IMAGE_FILE=$(mktemp)

# Get the snapshot list and the volume list
aws --region "$REGION" ec2 describe-snapshots --owner-ids "$ACCOUNTID" --query 'Snapshots[*].[SnapshotId]' --output text > "$SNAP_FILE"
aws --region "$REGION" ec2 describe-images --owners "$ACCOUNTID" --filters Name=state,Values=available --query 'Images[*].BlockDeviceMappings[*].Ebs.[SnapshotId]' --output text > "$IMAGE_FILE"

# Check if the outputed command should be dry-run (default) or not
if [ "$DO_DELETE" = "IAMSURE" ]
then
 DRUN=''
fi

# count each snapshot id, decrease when a volume reference it, print delete command for those with no volumes
awk -v REGION="$REGION" -v DRUN="$DRUN" 'FNR==NR { snap[$1]++; next } { snap[$1]-- } END { for (s in snap) { if (snap[s] > 0) { cmd="aws --region " REGION " " DRUN " ec2 delete-snapshot --snapshot-id " s; print(cmd) } } }' "$SNAP_FILE" "$IMAGE_FILE"
# Clean up the temp files
rm "$SNAP_FILE" "$IMAGE_FILE"
Tensibai
la source
Magnifique! Et à l'exception du «suivi» (que l'OMI devrait être «suit»), je pense que cette réponse doit être considérée comme un échantillon de postes de haute qualité. La seule chose qui semble un peu redondante est la clause de non-responsabilité (tout ce que l'on utilise à partir de quelque chose sur un site SE vient avec "utilisez-le à vos risques et périls"). Je ne peux penser qu'à 1 amélioration supplémentaire que vous voudrez peut-être ajouter: une indication si vous avez testé ce script et si oui, comment résumer ses résultats de test (quelque chose comme "fonctionne comme prévu"?). Évidemment, si vous l'utilisez déjà vous-même, c'est une meilleure indication.
Pierre.Vriens
@pierre l'a écrit ce matin, testé partiellement, entrera probablement dans notre pipeline cet après-midi, et bien que je sois d'accord sur l'idée générale "fourni tel quel", le niveau de risque de suppression d'une "sauvegarde" est élevé et je pense que je devrais le souligner encore plus.
Tensibai
Hm, afin que nous puissions vous impliquer pour démarrer un service gratuit d'écriture de code pour ces types de besoins DevOps (avec quelques chaînes de responsabilité attachées) ... intéressant! Je suggère que plus tard (quand le moment sera venu), vous ajoutiez une mise à jour mineure (à la fin) comme " mon script est entré dans notre pipeline cet après-midi ".
Pierre.Vriens
@ Pierre.Vriens J'ai dit probablement, non garanti, pourrait être la semaine prochaine ou plus tard aussi;)
Tensibai
1
Parfait, merci pour l'édition! Fonctionne exactement comme prévu.
Alex
5

J'ai utilisé le script suivant sur GitHub de Rodrigue Koffi (bonclay7) et cela fonctionne plutôt bien.

https://github.com/bonclay7/aws-amicleaner

Commander:

amicleaner --check-orphans

À partir du blog de documentation, il fait plus de choses:

Il fait en fait un peu plus que cela, il permet aujourd'hui:

  • Suppression d'une liste d'images et de clichés associés
  • Cartographie des AMI:
    • Utiliser des noms
    • Utiliser des balises
  • Filtrage des AMI:
    • utilisé par les instances en cours d'exécution
    • à partir de groupes de mise à l'échelle automatique (configurations de lancement) avec une capacité souhaitée définie sur 0
    • des configurations de lancement détachées des groupes de mise à l'échelle automatique
  • Spécification du nombre d'AMI que vous souhaitez conserver
  • Nettoyage des instantanés orphelins
  • Un peu de reportage
Utilisateur StackOverFlow
la source
3

Voici un script qui peut vous aider à trouver des instantanés orphelins

comm -23 <(echo $(ec2-describe-snapshots --region eu-west-1 | grep SNAPSHOT | awk '{print $2}' | sort | uniq) | tr ' ' '\n') <(echo $(ec2-describe-images --region eu-west-1 | grep BLOCKDEVICEMAPPING | awk '{print $3}' | sort | uniq) | tr ' ' '\n') | tr '\n' ' '

(d' ici )

Vous pouvez également consulter cet article à partir de serverfault

PS Bien sûr, vous pouvez changer la région pour refléter votre

PPS Voici le code mis à jour:

 comm -23 \
<(echo $(aws ec2 describe-snapshots --region eu-west-1 |awk '/SNAPSHOT/ {print $2}' | sort -u) | tr ' ' '\n') \
<(echo $(aws ec2 describe-images --region eu-west-1 |  awk '/BLOCKDEVICEMAPPING/ {print $3}' | sort -u) | tr ' ' '\n') | tr '\n' ' '

Les exemples d'exaplanations du code sont les suivants:

echo $(aws ec2 describe-snapshots --region eu-west-1 | awk '/SNAPSHOT/ {print $2}' | sort -u) | tr ' ' '\n')

envoyer à STDOUT la liste des instantanés. cette construction:

<(...)

créer un gestionnaire de fichiers temporaire virtuel pour faire commlire la commande à partir de deux "fichiers" et les comparer

Roméo Ninov
la source
L'avez-vous testé? J'ai trouvé le même article mais je n'arrive pas à le faire fonctionner. Si vous le pouvez, erreur utilisateur de ma part, mais je crains qu'elle ne soit pas à jour en fonction de l'âge de l'article.
Alex
@Alex, peut le vérifier demain
Romeo Ninov
La commande voir a changé, utilisez aws ec2 description / suppression
Tensibai
1
J'ai trouvé la même source, mais chaîner hero awk sort et uniq rend mon côté codeur shell triste, je
posterai
1
Très bien pour moi, je voulais juste vous fournir des commentaires (constructifs) pour vous faire savoir que ce qui ressemble probablement à un anglais ordinaire à un expert (comme vous), ressemble à peu près au chinois pour moi, d'accord? PS: et ça ne sonne pas flamand non plus ... Envoyez-moi un commentaire supplémentaire si vous voulez m'aviser une fois que vous avez terminé (si vous voulez mes commentaires mis à jour alors).
Pierre.Vriens
2

Voici un extrait de code GitHub Gist d'exactement ce que vous demandez par Daniil Yaroslavtsev.

Il utilise la liste de toutes les images et leurs instantanés et compare les ID à la liste de tous les ID d'instantanés. Ce qui reste, ce sont les orphelins. Le code fonctionne selon le même principe que la réponse ci-dessus, mais il est mieux formaté et légèrement plus lisible.

Le code tire parti de l' --query Snapshots[*].SnapshotIdoption JMESPath with (vous pouvez également utiliser l'utilitaire de ligne de commande jp pour cela, s'il est déjà dans votre distribution. Il formate la sortie sous forme de texte avec --output text. Voici un lien vers la référence de l'API et quelques exemples. Il est légèrement plus élégant qu'une longue chaîne de tuyaux grep / awk / sort / uniq / tr.

Avertissement de Todd Walton : ne vous trompez pas avec l'utilitaire 'jq' qui utilise un langage de requête différent pour analyser les documents json.

Jiri Klouda
la source
Pour info, l'utilitaire de ligne de commande jq n'est pas le même langage de requête JSON que celui utilisé par la commande "aws". La commande "aws" utilise JMESPath.
Todd Walton
Merci d'avoir fait remarquer cela. J'ai appris quelque chose de nouveau aujourd'hui.
Jiri Klouda
0

J'ai écrit un script snapshots.py qui itère sur tous les snapshots (dans une liste définie de régions) et génère report.csv. Ce fichier contient des informations sur l'instance, l'AMI et le volume référencés par tous les instantanés.

Il existe également une commande pour supprimer interactivement les instantanés pendantes.

jazgot
la source