¿Cómo limpiar las instantáneas huérfanas de AWS EC2?


22

Terminamos con una buena cantidad de instantáneas de AWS EC2 donde el AMI ha sido eliminado, pero la instantánea se ha dejado pudrir. Me gustaría una forma no manual de identificar y eliminar a estos huérfanos para ahorrarnos dinero y espacio.

Idealmente, estoy pensando en un script bash que aproveche la CLI , pero mi AWS-fu es débil. Supongo que alguien ha hecho esto antes, pero no puedo encontrar un script que realmente funcione.

En el mejor de los casos, esto también verificará los volúmenes y los limpiará, pero eso puede ser más adecuado para una segunda pregunta.


Mi versión en python. Cómo usar y enlace
github

Respuestas:


13

En gran parte inspirado por las publicaciones del blog y la esencia ya vinculadas en las otras respuestas, aquí está mi opinión sobre el problema.

Utilicé algunas funciones complicadas de JMESpath para obtener una lista de instantáneas y no es necesario tr.

Descargo de responsabilidad : use bajo su propio riesgo , hice todo lo posible para evitar cualquier problema y mantener los valores predeterminados, pero no me responsabilizaré si le causa problemas.

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

Espero que el script en sí sea lo suficientemente comentado.

El uso predeterminado (sin parámetros) enumerará los comandos de eliminación de instantáneas huérfanas para la cuenta corriente y la región eu-west-1, extraiga:

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

Puede redirigir este resultado a un archivo para su revisión antes de buscarlo para ejecutar todos los comandos.

Si desea que el script ejecute el comando en lugar de imprimirlo, reemplácelo print(cmd)por system(cmd).

El uso es el siguiente con un script llamado snap_cleaner:

para comandos de ejecución en seco en la región us-west-1

./snap_cleaner no us-west-1

para comandos utilizables en eu-central-1

./snap_cleaner IAMSURE eu-central-1 

Se puede usar un tercer parámetro para acceder a otra cuenta (prefiero cambiar el rol a otra cuenta antes).

Versión simplificada de la secuencia de comandos con la secuencia de comandos awk como línea:

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

Magnific! Y excepto por el 'seguimiento' (que la OMI debería ser 'sigue'), creo que esta respuesta debe considerarse como una muestra de publicaciones de alta calidad. Lo único que parece un poco redundante es el descargo de responsabilidad (todo lo que uno usa de algo en un sitio de SE viene con "úselo bajo su propio riesgo"). Sólo puedo pensar en 1 mejora adicional es posible que desee agregar: una indicación de si se hizo prueba de este script y si es así cómo resumir sus resultados de la prueba (algo así como "las obras tal como fue diseñado"?). Obviamente, si ya lo usa usted mismo, es una indicación aún mejor.
Pierre.Vriens

@pierre lo escribió esta mañana, probado parcialmente, probablemente ingresará a nuestra cartera esta tarde, y aunque estoy de acuerdo con la idea general de "tal como está", el nivel de riesgo de eliminar una "copia de seguridad" es alto y siento que debería enfatizarlo aún más.
Tensibai

Hm, para que podamos involucrarte y comenzar un servicio de escritura de código gratuito para este tipo de necesidades de DevOps (con algunas cadenas de exención de responsabilidad adjuntas) ... ¡interesante! Sugiero que más adelante (cuando sea el momento adecuado), agregue una actualización menor (al final) como " mi script ingresó a nuestro canal esta tarde ".
Pierre.Vriens

@ Pierre.Vriens dije que probablemente, no garantizo, podría ser la próxima semana o más tarde también;)
Tensibai

1
Perfecto, gracias por editar! Funciona exactamente como se pretendía.
Alex

5

Utilicé el siguiente script en GitHub de Rodrigue Koffi (bonclay7) y funciona bastante bien.

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

Mando:

amicleaner --check-orphans

Desde la publicación del blog de documentación , hace algunas cosas más:

En realidad, hace un poco más que eso, a partir de hoy permite:

  • Eliminar una lista de imágenes e instantáneas asociadas
  • Mapeo de AMI:
    • Usando nombres
    • Usando etiquetas
  • Filtrado de AMI:
    • utilizado por instancias en ejecución
    • desde grupos de autoescalado (configuraciones de lanzamiento) con una capacidad deseada establecida en 0
    • desde configuraciones de lanzamiento separadas de grupos de escalado automático
  • Especificando cuántas AMI quieres conservar
  • Limpieza de instantáneas huérfanas
  • Un poco de informes

3

Aquí hay un script que puede ayudarlo a encontrar instantáneas huérfanas

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

(desde aquí )

También puedes consultar este artículo desde serverfault

PD: Por supuesto, puedes cambiar la región para reflejar tu

PPS Aquí está el código actualizado:

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

Las explicaciones de muestra de lo que hace el código es:

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

enviar a STDOUT la lista de instantáneas. esta construcción:

<(...)

cree un commcontrolador de archivo temporal virtual para que el comando se lea desde dos "archivos" y compárelos


¿Lo probaste? Encontré el mismo artículo pero no puedo hacerlo funcionar. Si puede, error del usuario por mi parte, pero me temo que puede estar desactualizado en función de la antigüedad del artículo.
Alex

@Alex, puede revisarlo mañana
Romeo Ninov

El comando see ha cambiado, use aws ec2 describe / delete
Tensibai

1
Encontré la misma fuente, pero encadenar al héroe de manera extraña y uniq entristece a mi codificador de shell, publicaré mi versión mañana :)
Tensibai

1
Bien para mí, solo quería brindarle comentarios (constructivos) para hacerle saber que lo que probablemente se parece al inglés regular para un experto (como usted), se parece mucho al chino para mí, ¿de acuerdo? PD: y tampoco suena flamenco ... Mándame un comentario adicional si quieres notificarme después de que hayas terminado (si quieres mis comentarios actualizados entonces).
Pierre.Vriens

2

Aquí hay un fragmento de código GitHub Gist de exactamente lo que está pidiendo Daniil Yaroslavtsev.

Utiliza la lista de todas las imágenes y sus instantáneas y compara las ID con la lista de todas las ID de instantáneas. Lo que queda son los huérfanos. El código funciona con el mismo principio que la respuesta anterior, pero está mejor formateado y es un poco más legible.

El código aprovecha la --query Snapshots[*].SnapshotIdopción JMESPath con (también puede usar la utilidad de línea de comandos jp para eso, si ya está en su distribución. Formatea la salida como texto --output text. Aquí hay un enlace a la referencia de la API y algunos ejemplos. Es un poco más elegante que una larga cadena de tuberías grep / awk / sort / uniq / tr.

Advertencia de Todd Walton : no se confunda con la utilidad 'jq' que utiliza un lenguaje de consulta diferente para analizar documentos json.


Solo para su información, la utilidad de línea de comandos jq no es el mismo lenguaje de consulta JSON que el que usa el comando "aws". El comando "aws" usa JMESPath.
Todd Walton

Gracias por señalar eso. He aprendido algo nuevo hoy.
Jiri Klouda

0

He escrito el script snapshots.py que itera sobre todas las instantáneas (en la lista definida de regiones) y genera report.csv. Este archivo contiene información sobre la instancia, AMI y el volumen al que hacen referencia todas las instantáneas.

También hay un comando para eliminar interactivamente las instantáneas colgantes.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.