【コスト削減】全リージョンのスナップショットからAMIとEBSに紐付けのないスナップショットを特定する

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

こんにちは!エンタープライズクラウド部技術2課の日高です。
皆さん不要なスナップショットをきちんと削除していますか??
ついつい面倒になって削除していない方いませんか??(私は削除忘れがとても多いです....)

ということで、すべてのリージョンにあるスナップショットから、「AMIに関連付けられていない」かつ「EC2インスタンスに関連付けられているEBSボリュームIDに紐づいていない」スナップショットIDを抽出するスクリプトを作成してみました。

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

作成スクリプトとその使い方

前提

  • AWS CLIがインストールされている
  • Python3がインストールされている
  • スイッチロールできる設定が済まされている
  • 実行環境のOSがUnix系

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

作成したスクリプト

下記4つのスクリプトを作成しました。
4つではなく1つにまとめることも考えたのですが、手間がかかりそうだったのでそのままにしています.....(いい方法あれば教えていただきたい....)

get_all_snapshots.sh

すべてのリージョンにあるスナップショットIDを取得するスクリプトです。
リージョンとそのリージョンに存在するスナップショットIDが書き込まれた「all_snapshots.txt」が出力されます。

#!/bin/bash  -eu

# AWS CLI のプロファイル名、アカウントIDを指定
PROFILE=<CLIのプロファイル名>
AccountID=<アカウントID>

for region in $(aws ec2 describe-regions --query 'Regions[].{Name:RegionName}' --output text --profile $PROFILE)
do
    echo "Region: $region"
    aws ec2 describe-snapshots --region $region --owner-ids $AccountID --query "Snapshots[*].{ID:SnapshotId}" --output text --profile $PROFILE
done > all_snapshots.txt

get_ami_snapshots.sh

すべてのリージョンにあるAMIに関連付けられているスナップショットIDを取得するスクリプトです。
リージョンとそのリージョンに存在するAMIに関連付けられているスナップショットIDが書き込まれた「ami_snapshots.txt」が出力されます。

#!/bin/bash  -eu

# AWS CLI のプロファイル名、アカウントIDを指定
PROFILE=<CLIのプロファイル名>
AccountID=<アカウントID>

for region in $(aws ec2 describe-regions --query 'Regions[].{Name:RegionName}' --output text --profile $PROFILE)
do
    echo "Region: $region"
    aws ec2 describe-images --region $region --owners $AccountID --query "Images[*].BlockDeviceMappings[*].Ebs.SnapshotId" --output text | tr '\t' '\n'
done > ami_snapshots.txt

get_instance_snapshots.sh

すべてのリージョンにあるEC2のEBSボリュームから作成されているスナップショットIDを取得するスクリプトです。
リージョンとそのリージョンに存在するEC2のEBSボリュームから作成されているスナップショットIDが書き込まれた「instance_snapshots.txt」が出力されます。

#!/bin/bash  -eu

# AWS CLI のプロファイル名を指定
PROFILE=<CLIのプロファイル名>


# すべてのリージョンのリストを取得
AWS_REGIONS=($(aws ec2 describe-regions --query 'Regions[].RegionName' --output text --profile $PROFILE))

# instance_snapshots.txt ファイルをクリア
> instance_snapshots.txt

# 各リージョンについてループ処理
for region in "${AWS_REGIONS[@]}"; do
    echo "Processing region: $region" >> instance_snapshots.txt

    # EC2インスタンスに紐づいているEBSボリュームIDを取得
    VOLUME_IDS=($(aws ec2 describe-instances --region $region --query 'Reservations[].Instances[].BlockDeviceMappings[].Ebs.VolumeId' --output text --profile $PROFILE))

    # 各EBSボリュームについてループ処理
    for volume_id in "${VOLUME_IDS[@]}"; do
        # EBSボリュームに紐づいているスナップショットIDを取得し出力
        aws ec2 describe-snapshots --region $region --filters Name=volume-id,Values="$volume_id" --query 'Snapshots[].SnapshotId' --output text --profile $PROFILE
    done | awk 'NF' >> instance_snapshots.txt

    echo "" >> instance_snapshots.txt
done

find_unused_snapshots.py

all_snapshots(すべての存在するスナップショット)から、ami_snapshots (AMIに関連付くスナップショット)とinstance_snapshots(EC2のEBSボリュームから作成されているスナップショット)を除いた結果を「unused_snapshots.txt」に出力します。

all_snapshots = set(line.strip() for line in open('all_snapshots.txt'))
ami_snapshots = set(line.strip() for line in open('ami_snapshots.txt'))
instance_snapshots = set(line.strip() for line in open('instance_snapshots.txt'))

unused_snapshots = all_snapshots - ami_snapshots - instance_snapshots

# 結果をテキストファイルに書き出す
with open('unused_snapshots.txt', 'w') as f:
    for snapshot in sorted(unused_snapshots):
        f.write("%s\n" % snapshot)

利用方法

準備

  • 上記4つのスクリプトを実行するフォルダ配下に作成する。
    • この際<CLIのプロファイル名><アカウントID>は書き換える。

実行コマンド

  • 下記コマンドを上から順番に実行する。
    • bash get_all_snapshots.sh
    • bash get_ami_snapshots.sh
    • bash get_instance_snapshots.sh
    • python3 find_unused_snapshots.py

コマンドの実行結果

bash get_all_snapshots.sh

リージョンとそのリージョンに存在するAMIに関連付けられているスナップショットIDが書き込まれた「ami_snapshots.txt」が出力されます。

bash get_ami_snapshots.sh

リージョンとそのリージョンに存在するAMIに関連付けられているスナップショットIDが書き込まれた「ami_snapshots.txt」が出力されます。

bash get_instance_snapshots.sh

リージョンとそのリージョンに存在するEC2のEBSボリュームから作成されているスナップショットIDが書き込まれた「instance_snapshots.txt」が出力されます。

python3 find_unused_snapshots.py

all_snapshots(すべての存在するスナップショット)から、ami_snapshots (AMIに関連付くスナップショット)とinstance_snapshots(EC2のEBSボリュームから作成されているスナップショット)を除いた結果を「unused_snapshots.txt」に出力します。

上記のようにAMIにも、EC2のEBSボリュームにも紐づいていない不要なスナップショットIDを取得できました。

スクリプトの詳細

.shがつくスクリプトの詳細は、シェルスクリプトの部分とAWS CLIの部分に分けて解説します。

get_all_snapshots.sh

#!/bin/bash  -eu

# AWS CLI のプロファイル名、アカウントIDを指定
PROFILE=<CLIのプロファイル名>
AccountID=<アカウントID>

for region in $(aws ec2 describe-regions --query 'Regions[].{Name:RegionName}' --output text --profile $PROFILE)
do
    echo "Region: $region"
    aws ec2 describe-snapshots --region $region --owner-ids $AccountID --query "Snapshots[*].{ID:SnapshotId}" --output text --profile $PROFILE
done > all_snapshots.txt

シェルスクリプト

  • #!/bin/bash
    • シェルスクリプトの実行に使用するシェバン(shebang)です。
    • ここではBashを使用していることを示しています。
  • PROFILE=<CLIのプロファイル名>
    • AWS CLIのプロファイル名を指定するための変数です。
    • このスクリプト内で使用するプロファイル名を指定してください。
  • AccountID=<アカウントID>
    • AWSアカウントのIDを指定するための変数です。
    • このスクリプト内で使用するアカウントIDを指定してください。
  • for region in $(...)
    • リージョン情報を取得して、取得したリージョンごとにループ処理を行います。
  • echo "Region: $region"
    • 処理中のリージョンを表示します。
  • aws ec2 describe-snapshots --region $region --owner-ids $AccountID --query "Snapshots[*].{ID:SnapshotId}" --output text --profile $PROFILE
    • AWS CLIの部分で解説します。
  • > all_snapshots.txt
    • スクリプトの出力結果をall_snapshots.txtファイルに保存します。

AWS CLI

  • aws ec2 describe-regions
    • リージョンの情報を取得します。
  • --query 'Regions[].{Name:RegionName}'
    • Regions[].{Name:RegionName}は、取得したリージョン情報の各要素からNameプロパティの値を抽出します。
    • 赤枠のRegions内の青枠のRegion Nameの情報のみが出力されるようにフィルタリングしています 。
  • --output text
    • 出力フォーマットをテキスト形式に指定しています。
  • --profile $PROFILE
    • 使用するAWS CLIのプロファイルを指定し、スイッチロールしています。

※上記のAWS CLIコマンドについて詳しくは以下をご覧ください。

docs.aws.amazon.com

get_ami_snapshots.sh

#!/bin/bash  -eu

# AWS CLI のプロファイル名、アカウントIDを指定
PROFILE=<CLIのプロファイル名>
AccountID=<アカウントID>

for region in $(aws ec2 describe-regions --query 'Regions[].{Name:RegionName}' --output text --profile $PROFILE)
do
    echo "Region: $region"
    aws ec2 describe-images --region $region --owners $AccountID --query "Images[*].BlockDeviceMappings[*].Ebs.SnapshotId" --output text | tr '\t' '\n'
done > ami_snapshots.txt

シェルスクリプト

  • #!/bin/bash
    • シェルスクリプトの実行に使用するシェバン(shebang)です。ここではBashを使用していることを示しています。
  • PROFILE=<CLIのプロファイル名>
    • AWS CLIのプロファイル名を指定するための変数です。
    • このスクリプト内で使用するプロファイル名を指定してください。
  • AccountID=<アカウントID>
    • AWSアカウントのIDを指定するための変数です。
    • このスクリプト内で使用するアカウントIDを指定してください。
  • for region in $(aws ec2 describe-regions --query 'Regions[].{Name:RegionName}' --output text --profile $PROFILE)
    • aws ec2 describe-regionsコマンドを実行し、利用可能なリージョンの一覧を取得してループ処理します。
    • 各ループで$regionに現在のリージョンが代入されます。
  • echo "Region: $region"
    • リージョンを出力します。
  • aws ec2 describe-images --region $region --owners $AccountID --query "Images[*].BlockDeviceMappings[*].Ebs.SnapshotId" --output text | tr '\t' '\n'
    • 指定したリージョンとアカウントIDでaws ec2 describe-imagesコマンドを実行し、スナップショットIDを取得します。
    • tr '\t' '\n'はタブ文字を改行文字に置換するための処理です。
  • done > ami_snapshots.txt
    • ループ処理の結果をami_snapshots.txtというファイルに保存します。

AWS CLI

  • aws ec2 describe-images
    • AMIの情報を取得するAWS CLIコマンドです。
  • --region $region
    • 対象のリージョンを指定します。
    • $regionはシェルスクリプト内でループ変数として設定され、各リージョンごとにコマンドが実行されます。
  • --owners $AccountID
    • イメージの所有者を指定します。
    • $AccountIDはシェルスクリプト内で指定されたアカウントIDです。
    • ここでは指定したアカウントが所有するイメージの情報を取得します。
  • --query "Images[*].BlockDeviceMappings[*].Ebs.SnapshotId"
    • BlockDeviceMappings[*].Ebs.SnapshotIdは、イメージのブロックデバイスマッピングからスナップショットIDを選択します。
    • 赤枠で囲まれている"Images"内の、青枠で囲まれている "BlockDeviceMappings"内の、緑枠で囲まれている"SnapshotId"の情報のみが出力されるようにフィルタリングしています 。
  • --output text
    • 出力フォーマットをテキスト形式に指定しています。

※上記のAWS CLIコマンドについて詳しくは以下をご覧ください docs.aws.amazon.com

get_instance_snapshots.sh

#!/bin/bash  -eu

# AWS CLI のプロファイル名を指定
PROFILE=<CLIのプロファイル名>


# すべてのリージョンのリストを取得
AWS_REGIONS=($(aws ec2 describe-regions --query 'Regions[].RegionName' --output text --profile $PROFILE))

# instance_snapshots.txt ファイルをクリア
> instance_snapshots.txt

# 各リージョンについてループ処理
for region in "${AWS_REGIONS[@]}"; do
    echo "Processing region: $region" >> instance_snapshots.txt

    # EC2インスタンスに紐づいているEBSボリュームIDを取得
    VOLUME_IDS=($(aws ec2 describe-instances --region $region --query 'Reservations[].Instances[].BlockDeviceMappings[].Ebs.VolumeId' --output text --profile $PROFILE))

    # 各EBSボリュームについてループ処理
    for volume_id in "${VOLUME_IDS[@]}"; do
        # EBSボリュームに紐づいているスナップショットIDを取得し出力
        aws ec2 describe-snapshots --region $region --filters Name=volume-id,Values="$volume_id" --query 'Snapshots[].SnapshotId' --output text --profile $PROFILE
    done | awk 'NF' >> instance_snapshots.txt

    echo "" >> instance_snapshots.txt
done

シェルスクリプト

  • #!/bin/bash
    • シェルスクリプトの実行に使用するシェバン(shebang)です。
    • ここではBashを使用していることを示しています。
  • PROFILE=<CLIのプロファイル名>
    • AWS CLIのプロファイル名を指定するための変数です。
    • このスクリプト内で使用するプロファイル名を指定してください。
  • AWS_REGIONS=($(aws ec2 describe-regions --query 'Regions[].RegionName' --output text --profile $PROFILE))
    • AWS CLIコマンドを実行し、利用可能なリージョンの一覧を取得してAWS_REGIONSという配列変数に格納します。
    • $(...)はコマンド置換の構文で、実行結果を変数に割り当てるために使用されます。
  • > instance_snapshots.txt
    • instance_snapshots.txtファイルをクリア(内容を削除)します。
  • for region in "${AWS_REGIONS[@]}"; do
    • AWS_REGIONS配列の要素を1つずつ取り出してループ処理を行います。
    • ${AWS_REGIONS[@]}は配列の全要素を展開する構文です。
  • echo "Processing region: $region" >> instance_snapshots.txt
    • 現在のリージョンをinstance_snapshots.txtファイルに追記します。
    • >>はファイルへの追記を意味します。
  • VOLUME_IDS=($(aws ec2 describe-instances --region $region --query 'Reservations[].Instances[].BlockDeviceMappings[].Ebs.VolumeId' --output text --profile $PROFILE))
    • AWS CLIコマンドを実行し、指定したリージョンのEC2インスタンスに紐づいているEBSボリュームIDを取得してVOLUME_IDSという配列変数に格納します。
  • for volume_id in "${VOLUME_IDS[@]}"; do
    • VOLUME_IDS配列の要素を1つずつ取り出してループ処理を行います。
  • aws ec2 describe-snapshots --region $region --filters Name=volume-id,Values="$volume_id" --query 'Snapshots[].SnapshotId' --output text --profile $PROFILE
    • AWS CLIコマンドを実行し、指定したリージョンとEBSボリュームIDに紐づいているスナップショットIDを取得します。
    • 結果はテキスト形式で出力されます。
  • | awk 'NF'
    • パイプを使用してawkコマンドにパイプします。awk 'NF'は、空でない行のみをフィルタリングするためのAWKコマンドです。
  • >> instance_snapshots.txt
    • フィルタリングされたスナップショットIDをinstance_snapshots.txtファイルに追記します。
  • echo "" >> instance_snapshots.txt
    • 空行をinstance_snapshots.txtファイルに追記します。リージョンごとにスナップショットIDを区切るために使用されます。

AWS CLI

  • aws ec2 describe-instances --region $region --query 'Reservations[].Instances[].BlockDeviceMappings[].Ebs.VolumeId' --output text --profile $PROFILE)
    • aws ec2 describe-instances
      • AWS CLIのec2サービスを使用して、インスタンスの情報を取得します。
    • --region $region
      • 対象のリージョンを指定します。
    • --query 'Reservations[].Instances[].BlockDeviceMappings[].Ebs.VolumeId'
      • 結果のフィルタリングとフォーマット指定を行います
      • Reservations[].Instances[].BlockDeviceMappings[].Ebs.VolumeIdは、取得したインスタンス情報の各要素からブロックデバイスマッピングのEBSボリュームIDを抽出します。
    • --output text
      • 出力フォーマットをテキスト形式に指定します。 *--profile $PROFILE
      • 使用するAWS CLIのプロファイルを指定します。

※上記のAWS CLIコマンドについて詳しくは以下をご覧ください

docs.aws.amazon.com

  • aws ec2 describe-snapshots --region $region --filters Name=volume-id,Values="$volume_id" --query 'Snapshots[].SnapshotId' --output text --profile $PROFILE
    • aws ec2 describe-snapshots
      • AWS CLIのec2サービスを使用して、スナップショットの情報を取得します。
    • --region $region
      • 対象のリージョンを指定します。
    • --filters Name=volume-id,Values="$volume_id
      • :結果をフィルタリングするための条件を指定します。
      • volume-idが指定された$volume_idと一致するスナップショットのみを取得します。
    • --query 'Snapshots[].SnapshotId'
      • 結果のフィルタリングとフォーマット指定を行います。 *Snapshots[].SnapshotIdは、取得したスナップショット情報の各要素からスナップショットIDを抽出します。
    • --output text
      • 出力フォーマットをテキスト形式に指定します。
    • --profile $PROFILE
      • 使用するAWS CLIのプロファイルを指定します。

※上記のAWS CLIコマンドについて詳しくは以下をご覧ください

docs.aws.amazon.com

find_unused_snapshots.py

all_snapshots = set(line.strip() for line in open('all_snapshots.txt'))
ami_snapshots = set(line.strip() for line in open('ami_snapshots.txt'))
instance_snapshots = set(line.strip() for line in open('instance_snapshots.txt'))

unused_snapshots = all_snapshots - ami_snapshots - instance_snapshots

# 結果をテキストファイルに書き出す
with open('unused_snapshots.txt', 'w') as f:
    for snapshot in sorted(unused_snapshots):
        f.write("%s\n" % snapshot)
  • all_snapshots = set(line.strip() for line in open('all_snapshots.txt'))
    • all_snapshots.txtファイルを開き、各行をストリップしてからsetオブジェクトに格納します。
    • setは集合を表すデータ型で、重複を許さず一意の要素のみを保持します。
  • ami_snapshots = set(line.strip() for line in open('ami_snapshots.txt'))
    • 同様に、ami_snapshots.txtファイルを開き、各行をストリップしてからsetオブジェクトに格納します。
  • instance_snapshots = set(line.strip() for line in open('instance_snapshots.txt'))
    • 同様に、instance_snapshots.txtファイルを開き、各行をストリップしてからsetオブジェクトに格納します。
  • unused_snapshots = all_snapshots - ami_snapshots - instance_snapshots
    • 集合演算を使用して、すべてのスナップショットからAMIスナップショットとインスタンススナップショットを除いた未使用のスナップショットを取得します。
  • with open('unused_snapshots.txt', 'w') as f:
    • unused_snapshots.txtファイルを書き込みモードで開きます。
  • with文を使用することで、ファイルを自動的にクローズすることができます。
    • for snapshot in sorted(unused_snapshots):
    • 未使用のスナップショットをソートされた順に取得するループ処理を行います。
  • f.write("%s\n" % snapshot)
    • 未使用のスナップショットをテキストファイルに書き込みます。
    • %sは文字列を表すプレースホルダで、snapshot変数の値で置き換えられます。\nは改行文字を表します。

まとめ

初めてシェルスクリプトとPythonを使ってスクリプトを作った(プログラミング初めてな)ので、かなり時間がかかりましたがとても楽しかったです。
スクリプトを使って不要なスナップショットIDを取得してコスト削減をしてきましょう!!
本記事が誰かの助けになれば幸いです。

追記(2023年6月22日)

下記のリクエストをもらったのでスクリプトを一部修正しました。

  • スクリプト実行する際に、アカウントIDでもループを回せるようにしてほしいです。
  • 1つのコマンドで実行できるようにしてほしいです。

get_all_snapshots.sh

#!/bin/bash  -eu

# AWSから利用可能なすべてのリージョンを取得
# クエリを使用して、各リージョンの名前を出力するように指定
# --output text を指定することで結果をテキスト形式で出力
# --profile を使用してAWSプロファイルを指定
for region in $(aws ec2 describe-regions --query 'Regions[].{Name:RegionName}' --output text --profile $PROFILE)
do
    # 現在処理中のリージョン名を出力
    echo "Region: $region"
    
    # 指定したリージョンと所有者IDでスナップショットを検索
    # クエリを使用して、各スナップショットのIDを出力するように指定
    # --output text を指定することで結果をテキスト形式で出力
    # awk コマンドを使用してリージョン名とスナップショットIDを出力
    aws ec2 describe-snapshots --region $region --owner-ids $AccountID --query "Snapshots[*].{ID:SnapshotId}" --output text --profile $PROFILE | awk -v region=$region '{print region,$0}'
    
# すべてのスナップショット情報をテキストファイルに書き出す
done > all_snapshots_$AccountID.txt

get_ami_snapshots.sh

#!/bin/bash  -eu

# AWSの全リージョンを取得
for region in $(aws ec2 describe-regions --query 'Regions[].{Name:RegionName}' --output text --profile $PROFILE)
do
    # 処理中のリージョンを表示
    echo "Region: $region"
    
    # 特定のアカウントで所有しているAMIからスナップショットIDを取得し、リージョンと一緒に出力
    # "\t"(タブ)で区切られた各行を"\n"(改行)で区切られた各行に変換
    aws ec2 describe-images --region $region --owners $AccountID --query "Images[*].BlockDeviceMappings[*].Ebs.SnapshotId" --output text --profile $PROFILE | tr '\t' '\n' | awk -v region=$region '{print region,$0}'
    
# アカウントIDごとにファイル名を変えてスナップショットIDを出力
done > ami_snapshots_$AccountID.txt

get_instance_snapshots.sh

#!/bin/bash -eu

# AWSのリージョンの一覧を取得し、結果を配列に格納
AWS_REGIONS=($(aws ec2 describe-regions --query 'Regions[].RegionName' --output text --profile $PROFILE))

# インスタンスのスナップショット情報を保存するファイル(アカウントごとに命名)を作成(既に存在する場合は内容を空にする)
> instance_snapshots_$AccountID.txt

# 各AWSリージョンに対して処理を実行
for region in "${AWS_REGIONS[@]}"; do
    echo "処理中のリージョン: $region" >> instance_snapshots_$AccountID.txt

    # リージョン内のEC2インスタンスIDを取得し、結果を配列に格納
    INSTANCE_IDS=($(aws ec2 describe-instances --region $region --query 'Reservations[].Instances[].InstanceId' --output text --profile $PROFILE))

    # 各インスタンスIDに対して処理を実行
    for instance_id in "${INSTANCE_IDS[@]}"; do
        # インスタンスIDに関連するボリュームIDを取得し、結果を配列に格納
        VOLUME_IDS=($(aws ec2 describe-volumes --region $region --filters Name=attachment.instance-id,Values="$instance_id" --query "Volumes[*].VolumeId" --output text --profile $PROFILE))

        # 各ボリュームIDに対して処理を実行
        for volume_id in "${VOLUME_IDS[@]}"; do
            # ボリュームIDに関連するスナップショットを取得し、リージョン、インスタンスID、ボリュームID、スナップショットIDをファイルに追加
            aws ec2 describe-snapshots --region $region --filters Name=volume-id,Values="$volume_id" --query 'Snapshots[].SnapshotId' --output text --profile $PROFILE | awk -v region=$region -v instance_id=$instance_id -v volume_id=$volume_id '{print region,instance_id,volume_id,$0}'
        done
    done | awk 'NF' >> instance_snapshots_$AccountID.txt

    echo "" >> instance_snapshots_$AccountID.txt
done

find_unused_snapshots.py

import sys
import re

# スクリプトの引数を取得
account_id = sys.argv[1]

# 各テキストファイルからスナップショットIDを取り出す関数
def extract_snapshot_ids(filename):
    with open(filename, 'r') as f:
        content = f.read()
    snapshot_ids = re.findall('snap-\w+', content)
    return set(snapshot_ids)  # 重複を除くためにsetを使います

# ファイル名をアカウントIDに基づいて生成
all_snapshots_file = 'all_snapshots_{}.txt'.format(account_id)
ami_snapshots_file = 'ami_snapshots_{}.txt'.format(account_id)
instance_snapshots_file = 'instance_snapshots_{}.txt'.format(account_id)

# スナップショットIDを抽出
all_snapshots = extract_snapshot_ids(all_snapshots_file)
ami_snapshots = extract_snapshot_ids(ami_snapshots_file)
instance_snapshots = extract_snapshot_ids(instance_snapshots_file)

# 'all_snapshots'に存在し、'ami_snapshots'と'instance_snapshots'に存在しないスナップショットIDを探します
unused_snapshots = all_snapshots - ami_snapshots - instance_snapshots

# 新しいテキストファイルに結果を書き込みます
with open('unused_snapshots_{}.txt'.format(account_id), 'w') as f:
    for snapshot in unused_snapshots:
        f.write(snapshot + '\n')

find_unused_in_multiple_accounts.sh(NEW!)

#!/bin/bash  -eu

# アカウントIDのリストを指定
AccountIDS=(アカウント番号① アカウント番号② アカウント番号③...)

# AWS CLIのプロファイル名を指定
PROFILES=(プロファイル名① プロファイル名② プロファイル名③...)

# 各アカウントについてスクリプトを実行
for i in "${!AccountIDS[@]}"; do
    AccountID=${AccountIDS[$i]}
    PROFILE=${PROFILES[$i]}

    echo "Processing Account: $AccountID"

    # スクリプトを実行し、環境変数を渡す
    AccountID=$AccountID PROFILE=$PROFILE ./get_all_snapshots.sh
    AccountID=$AccountID PROFILE=$PROFILE ./get_ami_snapshots.sh
    AccountID=$AccountID PROFILE=$PROFILE ./get_instance_snapshots.sh

    # pythonスクリプトを実行
    python3 find_unused_snapshots.py $AccountID
done

上記のスクリプトのアカウント番号①とプロファイル名①は同一のアカウントを指定してください。
また、アカウント番号とプロファイル名は、不要なスナップショットを取得したいアカウント分記入してください。

実行方法

実行準備

get_all_snapshots.sh、get_ami_snapshots.sh、get_instance_snapshots.sh、find_unused_snapshots.py、find_unused_in_multiple_accounts.shすべてを実行したいフォルダ配下に保存します。

実行コマンド

実行準備で保存したフォルダ配下上でbash find_unused_in_multiple_accounts.shと打つだけです。

実行結果

画像のように指定したアカウントずつ"unused_snapshots_アカウント番号"のテキストファイルが作成され、「AMIに関連付けられていない」かつ「EC2インスタンスに関連付けられているEBSボリュームIDに紐づいていない」スナップショットIDが出力されます。

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

2024 Japan AWS Jr. Champions / 2024 Japan AWS All Certifications Engineers

EC部クラウドコンサルティング課所属。2022年IT未経験でSWXへ新卒入社。
記事に関するお問い合わせや修正依頼⇒ hidaka@serverworks.co.jp