概要
バックアップ目的でAMI(とそれに紐づくsnapshot)を作ったはいいものの、AMIだけを削除してsnapshotを削除し忘れることはよくあるかと思います。
これらの忘れが積もりに積もって「EC2 その他」として請求が来てから気づくことがあります。
そんなときに使える、AMIに紐づいていないsnapshotをすべて削除するスクリプトです。
コード
import boto3
import datetime
ec2 = boto3.client('ec2')
# AMIに紐づけられているスナップショットを取得
def list_used_snapshot_ids(ec2):
response = ec2.describe_images(Owners=['self'])
res = []
for image in response['Images']:
snapshot_ids = get_snapshot_ids_from_image(image)
res += snapshot_ids
return res
def get_snapshot_ids_from_image(image):
snapshot_ids = []
for device in image['BlockDeviceMappings']:
if 'Ebs' not in device:
continue
id = device['Ebs']['SnapshotId']
snapshot_ids.append(id)
return snapshot_ids
# AMIに紐づけられていないスナップショットを取得
def list_unused_snapshot_ids(ec2,used_snapshot_ids):
all_snapshot_ids = list_all_snapshot_ids(ec2)
res = all_snapshot_ids
for used_snapshot_id in used_snapshot_ids:
if used_snapshot_id in res:
res.remove(used_snapshot_id)
return res
def list_all_snapshot_ids(ec2):
response = ec2.describe_snapshots(OwnerIds=['self'])
snapshot_ids = []
for snapshot in response['Snapshots']:
# 利用されていないかつ、2024年1月1日より前に作成されたスナップショットを削除
# if snapshot['StartTime'] < datetime.datetime(2024, 1, 1, 0, 0, 0, 0, tzinfo=datetime.timezone.utc):
snapshot_ids.append(snapshot['SnapshotId'])
return snapshot_ids
# SNAPSHOTを削除
def remove_unused_ebs_snapshots(ec2,delete_snapshot_ids):
for snapshot_id in delete_snapshot_ids:
time = datetime.datetime.now()
print('delete snapshot: {0}, time: {1}'.format(snapshot_id, time))
ec2.delete_snapshot(SnapshotId=snapshot_id)
def main():
used_snapshot_ids = list_used_snapshot_ids(ec2)
unused_snapshot_ids = list_unused_snapshot_ids(ec2,used_snapshot_ids)
remove_unused_ebs_snapshots(ec2,unused_snapshot_ids)
print("done")
if __name__ == '__main__':
main()
まとめ
AMIを削除しても、snapshotされておらず課金されてしまったので削除するスクリプトを作成してみました。
これとEBS Snapshot のゴミ箱機能を併用すれば安全に削除を進められるかと思います。
一緒に消してくれるフラグがあれば嬉しいなと思いつつ、どなたかの役に立てば幸いです。