Como limpar os snapshots órfãos do AWS EC2?

22

Acabamos com uma quantidade razoável de instantâneos do AWS EC2 em que a AMI foi excluída, mas o instantâneo é deixado para trás para apodrecer. Eu gostaria de uma maneira não manual de identificar e excluir esses órfãos para economizar dinheiro e espaço.

Idealmente, estou pensando em um script bash aproveitando a CLI , mas meu AWS-fu é fraco. Suponho que alguém tenha feito isso antes, mas não consigo encontrar um script que realmente funcione.

Na melhor das hipóteses, isso também verificará os volumes e os limpará, mas isso pode ser mais adequado para uma segunda pergunta.

Alex
fonte
Minha versão em python. Como usar e link do github
E.Big

Respostas:

13

Em grande parte inspirado pelas postagens do blog e pela essência já vinculada nas outras respostas, aqui está minha opinião sobre o problema.

Eu usei algumas funções complicadas do JMESpath para obter uma lista de instantâneos e não exigir tr.

Isenção de responsabilidade : use por sua conta e risco , fiz o possível para evitar qualquer problema e manter os padrões saudáveis, mas não assumirei nenhuma culpa se isso lhe causar 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 o script em si seja comentado o suficiente.

O uso padrão (sem parâmetros) listará comandos de exclusão de instantâneos órfãos para a conta atual e a região eu-west-1, extrair:

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

Você pode redirecionar essa saída para um arquivo para revisão antes de fornecê-lo para executar todos os comandos.

Se você deseja que o script execute o comando em vez de imprimi-lo, substitua print(cmd)por system(cmd).

O uso é o seguinte com um script chamado snap_cleaner:

para comandos de execução a seco na região us-west-1

./snap_cleaner no us-west-1

para comandos utilizáveis ​​na eu-central-1

./snap_cleaner IAMSURE eu-central-1 

Um terceiro parâmetro pode ser usado para acessar outra conta (eu prefiro mudar de função para outra conta antes).

Versão simplificada do script com o script awk como 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
fonte
Magnific! E, exceto pelo 'follow' (que a IMO deveria ser 'segue'), acho que essa resposta deve ser considerada como uma amostra de postagens de alta qualidade. A única coisa que parece um pouco redundante é o aviso (qualquer coisa que alguém use de algo em um site SE vem com "use-o por sua conta e risco"). Só consigo pensar em uma melhoria adicional que você queira adicionar: uma indicação se você testou esse script e, em caso afirmativo, como resumir os resultados de seus testes (algo como "funciona como projetado"?). Obviamente, se você já o usa, é uma indicação ainda melhor.
Pierre.Vriens
O @pierre escreveu esta manhã, testado parcialmente, provavelmente entrará em nosso pipeline esta tarde e, embora eu concorde com a idéia geral 'fornecida como está', o nível de risco de remover um 'backup' é alto e acho que devo enfatizá-lo ainda mais.
Tensibai 23/03
Hm, para que possamos envolvê-lo para iniciar um serviço gratuito de escrita de código para esse tipo de necessidade do DevOps (com algumas restrições de responsabilidade anexadas) ... interessante! Sugiro que mais tarde (quando for a hora certa), você adicione uma pequena atualização (no final) como " meu script entrou em nosso pipeline esta tarde ".
Pierre.Vriens
@ Pierre.Vriens eu disse, provavelmente, não garantia, poderia ser na próxima semana ou mais tarde também;)
Tensibai
1
Perfeito, obrigado pela edição! Funciona exatamente como pretendido.
23417 Alex
5

Eu usei o seguinte script no GitHub de Rodrigue Koffi (bonclay7) e funciona muito bem.

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

Comando:

amicleaner --check-orphans

Na publicação do blog de documentação, ele faz mais algumas coisas:

Na verdade, faz um pouco mais do que isso, atualmente permite:

  • Removendo uma lista de imagens e instantâneos associados
  • AMIs de mapeamento:
    • Usando nomes
    • Usando tags
  • Filtrando AMIs:
    • usado executando instâncias
    • de grupos de dimensionamento automático (configurações de inicialização) com uma capacidade desejada definida como 0
    • das configurações de ativação desanexadas dos grupos de dimensionamento automático
  • Especificando quantas AMIs você deseja manter
  • Limpando Instantâneos Órfãos
  • Um pouco de relatórios
Usuário StackOverFlow
fonte
3

Aqui está um script que pode ajudá-lo a encontrar instantâneos órfãos

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

( daqui )

Além disso, você pode verificar este artigo em serverfault

PS Claro que você pode mudar a região para refletir sua

PPS Aqui está o código atualizado:

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

A amostra de exemplos do que o código faz é:

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

envie para STDOUT a lista de instantâneos. esta construção:

<(...)

crie manipulador de commarquivos temporário virtual para fazer com que o comando seja lido de dois "arquivos" e compare-os

Romeo Ninov
fonte
Você testou? Encontrei o mesmo artigo, mas não consigo fazê-lo funcionar. Se você puder, erro do usuário do meu lado, mas receio que esteja desatualizado com base na idade do artigo.
22417 Alex
@Alex, pode verificá-lo amanhã
Romeo Ninov
Comando ver mudaram, a AWS uso EC2 descrevem / delete
Tensibai
1
Eu tinha encontrado a mesma fonte, mas o encadeamento herói awk classificar e uniq faz meu codificador lado shell triste, vou postar a minha versão amanhã :)
Tensibai
1
Tudo bem para mim, só queria fornecer um feedback (construtivo) para que você saiba que o que provavelmente parece inglês regular para um especialista (como você), parece muito com o chinês para mim, ok? PS: e também não parece flamengo ... Envie-me um comentário extra se você quiser me avisar depois que terminar (se você quiser meus comentários atualizados).
Pierre.Vriens
2

Aqui está um trecho de código GitHub Gist exatamente do que você está pedindo por Daniil Yaroslavtsev.

Ele usa a lista de todas as imagens e seus snapshots e compara os IDs com a lista de todos os IDs de snapshots. O que resta são os órfãos. O código funciona com o mesmo princípio da resposta acima, mas é melhor formatado e um pouco mais legível.

O código tira proveito do JMESPath com a --query Snapshots[*].SnapshotIdopção (você também pode usar o utilitário de linha de comando jp para isso, se já estiver em sua distribuição. Formata a saída como texto com --output text. Aqui está um link para a referência da API e alguns exemplos. É um pouco mais elegante que uma longa cadeia de tubos grep / awk / sort / uniq / tr.

Aviso de Todd Walton : Não confunda com o utilitário 'jq', que usa uma linguagem de consulta diferente para analisar documentos json.

Jiri Klouda
fonte
Apenas para sua informação, o utilitário de linha de comando jq não é a mesma linguagem de consulta JSON usada pelo comando "aws". O comando "aws" usa JMESPath.
Todd Walton
Obrigado por apontar isso. Eu aprendi algo novo hoje.
Jiri Klouda
0

Eu escrevi o script snapshots.py que itera sobre todos os instantâneos (na lista definida de regiões) e gera report.csv. Este arquivo contém informações sobre instância, AMI e volume referenciados por todos os instantâneos.

Também existe um comando para remover interativamente os instantâneos pendentes.

jazgot
fonte