Bereinigen verwaister AWS EC2-Snapshots


22

Wir haben am Ende eine ganze Reihe von AWS EC2-Snapshots, bei denen der AMI gelöscht wurde, der Snapshot jedoch verrottet. Ich möchte diese Waisenkinder auf nicht manuelle Weise identifizieren und löschen , um Geld und Platz zu sparen.

Idealerweise denke ich an ein Bash-Skript, das die CLI nutzt , aber mein AWS-fu ist schwach. Ich gehe davon aus, dass jemand dies bereits getan hat, aber ich kann kein Skript finden, das tatsächlich funktioniert.

Im besten Fall werden hierdurch auch Volumes überprüft und bereinigt. Dies ist jedoch möglicherweise besser für eine zweite Frage geeignet.


Meine Version auf Python. How-to-Use und Github Link
E. Big

Antworten:


13

Weitgehend inspiriert von den Blog-Beiträgen und dem Inhalt der anderen Antworten, hier ist meine Sicht auf das Problem.

Ich habe einige verschachtelte JMESpath- Funktionen verwendet, um eine Liste von Schnappschüssen zu erhalten, die nicht erforderlich sind tr.

Haftungsausschluss : Die Verwendung erfolgt auf eigenes Risiko . Ich habe mein Bestes getan, um Probleme zu vermeiden und vernünftige Standardeinstellungen beizubehalten. Ich übernehme jedoch keine Schuld, wenn es Ihnen Probleme bereitet.

#!/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"

Ich hoffe, das Skript selbst ist genug kommentiert.

Die Standardverwendung (ohne Parameter) listet Löschbefehle für verwaiste Snapshots für das aktuelle Konto und die Region eu-west-1 auf.

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

Sie können diese Ausgabe zur Überprüfung in eine Datei umleiten, bevor Sie alle Befehle ausführen.

Wenn Sie möchten, dass das Skript den Befehl ausführt, anstatt ihn zu drucken, ersetzen Sie ihn print(cmd)durch system(cmd).

Die Verwendung ist wie folgt mit einem Skript namens snap_cleaner:

für trockenlaufbefehle in der region us-west-1

./snap_cleaner no us-west-1

für verwendbare Befehle in eu-central-1

./snap_cleaner IAMSURE eu-central-1 

Ein dritter Parameter kann verwendet werden, um auf ein anderes Konto zuzugreifen (ich bevorzuge es, die Rolle zu einem anderen Konto zu wechseln).

Reduzierte Version des Skripts mit awk-Skript als 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"

Großartig! Und mit Ausnahme der "Folgen" (die IMO sollte "Folgen" sein), denke ich, dass diese Antwort als Beispiel für qualitativ hochwertige Beiträge zu betrachten ist. Das einzige, was ein bisschen überflüssig erscheint, ist der Haftungsausschluss (alles, was man von etwas auf einer SE-Site verwendet, ist mit "auf eigenes Risiko verwenden" verbunden). Ich kann mir nur eine weitere Verbesserung vorstellen, die Sie vielleicht hinzufügen möchten: einen Hinweis darauf, ob Sie dieses Skript getestet haben und wie Sie die Testergebnisse zusammenfassen können (so etwas wie "funktioniert wie geplant"?). Wenn Sie es bereits selbst verwenden, ist dies natürlich ein noch besserer Hinweis.
Pierre.Vriens

@pierre hat es heute Morgen geschrieben, teilweise getestet, und wird wahrscheinlich heute Nachmittag in unsere Pipeline aufgenommen. Auch wenn ich der allgemeinen Idee zustimme, dass es so ist, wie es ist, ist das Risiko, ein Backup zu entfernen, hoch und ich denke, ich sollte es betonen sogar mehr.
Tensibai

Hm, damit wir Sie dazu bringen können, einen kostenlosen Code-Schreibservice für diese Art von DevOps-Anforderungen zu starten (mit einigen Haftungsausschluss-Strings im Anhang) ... interessant! Ich schlage vor, dass Sie später (wenn die Zeit reif ist) ein kleines Update (am Ende) hinzufügen, wie " Mein Skript ist heute Nachmittag in unsere Pipeline eingegangen ".
Pierre.Vriens

@ Pierre.Vriens Ich sagte wahrscheinlich, keine Garantie, könnte nächste Woche oder später auch sein;)
Tensibai

1
Perfekt, danke für die Bearbeitung! Funktioniert genau wie vorgesehen.
Alex

5

Ich habe das folgende Skript auf GitHub von Rodrigue Koffi (bonclay7) verwendet und es funktioniert ziemlich gut.

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

Befehl:

amicleaner --check-orphans

Aus der Dokumentation Blog - Post es hat einige weitere Dinge:

Tatsächlich macht es ein bisschen mehr als das, bis heute erlaubt es:

  • Entfernen einer Liste von Bildern und zugehörigen Schnappschüssen
  • AMIs zuordnen:
    • Namen verwenden
    • Tags verwenden
  • Filtern von AMIs:
    • Wird zum Ausführen von Instanzen verwendet
    • von Autoscaling-Gruppen (Startkonfigurationen) mit einer gewünschten Kapazität von 0
    • von Startkonfigurationen, die von Autoscaling-Gruppen getrennt sind
  • Angeben, wie viele AMIs Sie behalten möchten
  • Reinigen von verwaisten Schnappschüssen
  • Ein bisschen Berichterstattung

3

Hier ist ein Skript, mit dem Sie verwaiste Schnappschüsse finden können

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' ' '

(von hier )

Sie können diesen Artikel auch von serverfault aus überprüfen

PS Natürlich können Sie die Region ändern, um Ihre

PPS Hier ist der aktualisierte Code:

 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' ' '

Die Beispielerklärungen, was der Code macht, sind:

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

Senden Sie die Liste der Schnappschüsse an STDOUT. diese Konstruktion:

<(...)

Erstellen Sie einen virtuellen temporären Filehandler, damit der commBefehl aus zwei "Dateien" gelesen und diese verglichen werden


Hast du es getestet? Ich habe den gleichen Artikel gefunden, kann ihn aber nicht zum Laufen bringen. Wenn Sie können, Benutzerfehler auf meinem Ende, aber ich fürchte, dass es basierend auf dem Alter des Artikels veraltet sein kann.
Alex

@ Alex, kann es morgen überprüfen
Romeo Ninov

Befehl sehen geändert haben, verwenden Sie aws ec2 beschreiben / löschen
Tensibai

1
Ich habe die gleiche Quelle gefunden, aber die Verkettung von Held awk sort und uniq macht meine Shell-Coder-Seite traurig, ich werde meine Version morgen
posten

1
Gut für mich, ich wollte Ihnen nur ein (konstruktives) Feedback geben, um Ihnen mitzuteilen, dass das, was für einen Experten (wie Sie) wie normales Englisch aussieht, für mich wie Chinesisch aussieht, okay? PS: und es klingt auch nicht flämisch ... Schreibe mir einen zusätzlichen Kommentar, wenn du mich benachrichtigen möchtest, nachdem du fertig bist (wenn du mein aktualisiertes Feedback möchtest, dann).
Pierre.Vriens

2

Hier ist ein GitHub Gist-Code-Snippet von genau dem, was Sie von Daniil Yaroslavtsev verlangen.

Es verwendet die Liste aller Bilder und ihrer Schnappschüsse und vergleicht die IDs mit der Liste aller Schnappschuss-IDs. Was übrig bleibt, sind die Waisen. Der Code funktioniert nach dem gleichen Prinzip wie die obige Antwort, ist jedoch besser formatiert und etwas besser lesbar.

Der Code nutzt die --query Snapshots[*].SnapshotIdOption JMESPath with (Sie können dafür auch das Befehlszeilendienstprogramm jp verwenden, sofern es bereits in Ihrer Distribution enthalten ist. Die Ausgabe wird als Text formatiert --output text. Hier ein Link zur API-Referenz und einige Beispiele. Es ist geringfügig eleganter als eine lange Kette von grep / awk / sort / uniq / tr-Rohren.

Warnung von Todd Walton : Verwechseln Sie nicht das Dienstprogramm 'jq', das zum Parsen von json-Dokumenten eine andere Abfragesprache verwendet.


Nur zu Ihrer Information, das Befehlszeilendienstprogramm jq ist nicht dieselbe JSON-Abfragesprache wie der Befehl "aws". Der Befehl "aws" verwendet JMESPath.
Todd Walton

Danke, dass Sie darauf hingewiesen haben. Ich habe heute etwas Neues gelernt.
Jiri Klouda

0

Ich habe das Skript snapshots.py geschrieben, das alle Snapshots (in einer definierten Liste von Regionen) durchläuft und generiert report.csv. Diese Datei enthält Informationen zu Instanz, AMI und Volume, auf die von allen Snapshots verwiesen wird.

Es gibt auch einen Befehl zum interaktiven Entfernen baumelnder Schnappschüsse.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.