【コスト削減】不要な複数AMIと、AMIに紐づくスナップショットを一括で削除するスクリプトを作ってみた

記事タイトルとURLをコピーする

こんにちは!
エンタープライズクラウド部技術2課の日高です。

本日は以前公開した「コスト削減】すべてのリージョンに存在する指定した日付以前の、自己所有AMIをスクリプトで特定してみる」に関連するブログになります。

blog.serverworks.co.jp

こちらのブログを見てくれた方から「不要なAMIを特定したはいいものの、AMIを削除してからじゃないとスナップショットが削除できないからマネジメントコンソールでいちいちやるのがめんどくさい」「不要なAMIの量が多ければ多いほど手間がかかる」というお声を頂きました。

ということで、不要な複数AMIと、AMIに紐づくスナップショットを一括で削除するスクリプトを作成してみました。

※スクリプトを利用するだけの場合は「作成スクリプトとその使い方」を、スクリプトの詳細を知りたい方は「スクリプトの詳細」をご覧ください。

前提と作成したスクリプトの解説

前提

  • AWS CLIがインストールされている
  • スイッチロールできる設定が済まされている(AWS CLI の設定 (~/.aws/config ファイル) にて、ロールの情報が設定されている)
  • 実行環境のOSがUnix系

※スイッチロールではなく、デフォルトに設定されているアカウントでスクリプトを実行したい場合は、スクリプトの「profile="指定してください"」と「--profile "$profile"」を削除して利用してください。

作成したスクリプト

指定したリージョンにある、削除したいAMI IDを配列に入れておくことで、そのリージョンに存在するすべてのAMIとそのAMI IDに関連付けられているスナップショットを一括で削除することができます。

#!/bin/bash -eu

# 削除するAMI IDを格納する配列
declare -a ami_ids=(ami-XXXXXXXXX ami-YYYYYYYYYYY ami-ZZZZZZZZZZZ)

# 削除するリージョンを指定
region="指定してください"

# プロファイル名を指定
profile="指定してください"

# 配列に指定されたAMIとAMI IDのすべてのスナップショットを一括で削除
for ami_id in "${ami_ids[@]}"
do
    echo "Deleting associated snapshots for AMI: $ami_id in region $region using profile $profile"
    snapshot_ids=$(aws ec2 describe-images --region "$region" --profile "$profile" --image-ids "$ami_id" --query 'Images[].BlockDeviceMappings[].Ebs.SnapshotId' --output text)
    
    echo "Deleting AMI with ID: $ami_id in region $region using profile $profile"
    aws ec2 deregister-image --image-id "$ami_id" --region "$region" --profile "$profile"
    
    for snapshot_id in $snapshot_ids
    do
        aws --region "$region" --profile "$profile" ec2 delete-snapshot --snapshot-id "$snapshot_id"
        echo "Deleted snapshot: $snapshot_id"
    done
done

利用方法

準備

  • 上記のスクリプトを実行するフォルダ配下に作成する。

※この際ami_idsregionprofileはご自身が実行したいものに書き換えてください。
 ami_idsに記載するものが、前回のブログで特定したAMI IDになります。

実行コマンド

  • 下記コマンドを実行します。
  • bash <保存時のスクリプト名>
    • 私の場合は「delete_AMI.sh」で保存しているのでbash delete_AMI.shが実行コマンドになります。

スクリプトの実行結果

実行する前のマネジメントコンソールの状態

今回削除の対象とするAMIは、下記画像の東京リージョンにある2つのAMI(AMI名がtest、test2)です。 画像から見てもわかる通り、1つのAMIに3つのスナップショットが紐づいています、

スナップショットのコンソール画面は下記です。

スクリプトの実行と実行結果

bash delete_AMI.sh(私の場合は「delete_AMI.sh」でスクリプトを保存しているのでbash delete_AMI.shが実行コマンドになります。)でスクリプトを実行すると下記のような出力結果が得られます。

Deleting associated snapshots for AMI: ami-0c69d8110a1235378 in region ap-northeast-1 using profile bastion
Deleting AMI with ID: ami-0c69d8110a1235378 in region ap-northeast-1 using profile bastion
Deleted snapshot: snap-0f96cbc68fdd3c760
Deleted snapshot: snap-020ddf5e645a4a2db
Deleted snapshot: snap-09435f8b471b55a6e
Deleting associated snapshots for AMI: ami-0f033ccda02c9a044 in region ap-northeast-1 using profile bastion
Deleting AMI with ID: ami-0f033ccda02c9a044 in region ap-northeast-1 using profile bastion
Deleted snapshot: snap-007b079a0a021a30e
Deleted snapshot: snap-07f7122f954dfa64c
Deleted snapshot: snap-0d51d543f723c8b21

無事削除できているかどうかをマネジメントコンソールで確認できました。

スクリプトの詳細

スクリプトの解説をします。

#!/bin/bash -eu

# 削除するAMI IDを格納する配列
declare -a ami_ids=(ami-XXXXXXXXX ami-YYYYYYYYYYY ami-ZZZZZZZZZZZ)

# 削除するリージョンを指定
region="指定してください"

# プロファイル名を指定
profile="指定してください"

# 配列に指定されたAMIとAMI IDのすべてのスナップショットを一括で削除
for ami_id in "${ami_ids[@]}"
do
    echo "Deleting associated snapshots for AMI: $ami_id in region $region using profile $profile"
    snapshot_ids=$(aws ec2 describe-images --region "$region" --profile "$profile" --image-ids "$ami_id" --query 'Images[].BlockDeviceMappings[].Ebs.SnapshotId' --output text)
    
    echo "Deleting AMI with ID: $ami_id in region $region using profile $profile"
    aws ec2 deregister-image --image-id "$ami_id" --region "$region" --profile "$profile"
    
    for snapshot_id in $snapshot_ids
    do
        aws --region "$region" --profile "$profile" ec2 delete-snapshot --snapshot-id "$snapshot_id"
        echo "Deleted snapshot: $snapshot_id"
    done
done
#!/bin/bash -eu

この行はスクリプトのシバン(shebang)として使用されます。
スクリプトをBashシェルで実行することを指定しており、-eオプションはスクリプトがエラーがあれば即座に終了するように、-uオプションは未定義の変数を使用するとエラーになるようにしています。

declare -a ami_ids=(ami-XXXXXXXXX ami-YYYYYYYYYYY ami-ZZZZZZZZZZZ)

ami_idsという名前の配列を宣言し、削除したいAMI IDを含むAMI IDのリストを代入しています。

region="指定してください"

削除したいリージョンを指定するための変数です。
実際のリージョン名(例: "us-west-1")に置き換えてください。

profile="指定してください"

使用したいAWSプロファイルの名前を指定する変数です。
AWS CLIで設定したプロファイル名(例: "my-profile")に置き換えてください。

※スイッチロールではなく、デフォルトに設定されているアカウントでスクリプトを実行したい場合は、スクリプトの「profile="指定してください"」と「--profile "$profile"」を削除して利用してください。

for ami_id in "${ami_ids[@]}"

ami_ids配列内の各AMI IDに対してループ処理を行います。

aws ec2 describe-images ...

aws ec2 describe-imagesコマンドを使用して、指定したAMI IDに関連するスナップショットのIDを取得します。
AMI IDに対応するスナップショットIDが取得され、$snapshot_ids変数に代入されます。

※詳しくは以下をご覧ください。

docs.aws.amazon.com

aws ec2 deregister-image ...

aws ec2 deregister-imageコマンドを使用して、指定したAMI IDを登録解除します。
AMI IDが指定され、対応するAMIが削除されます。

※詳しくは以下をご覧ください。

docs.aws.amazon.com

for snapshot_id in $snapshot_ids

AMIに関連付けられた各スナップショットに対してループ処理を行います。

aws ec2 delete-snapshot ...

aws ec2 delete-snapshotコマンドを使用して、指定したスナップショットを削除します。
AMIに関連付けられたスナップショットIDが指定され、スナップショットが削除されます。

※詳しくは以下をご覧ください。

docs.aws.amazon.com

まとめ

スタンダードのスナップショットの保存料金「0.05USD/1 か月あたりの GB」とみるとそこまで料金がかからないように見えますが、容量が大きいスナップショットが紐づいているAMIがあると無駄なコストが増えてしまいます。

スクリプトを活用して、無駄なコストを削減していきましょう!

本記事が誰かの助けになれば幸いです。

日高 僚太(執筆記事の一覧)

EC部ソリューションアーキテクト2課 / AWS認定資格 12冠

2022年IT未経験で新卒入社しました。
最近はダーツとサウナが気になっています!
記事に関するお問い合わせや修正依頼⇒ hidaka@serverworks.co.jp