AMIやスナップショットを AWS CLI で一気に削除する


# 1.AMIとスナップショットの一覧を取得する
ここはCloudShell で実施している。
## 1-1.AMIの一覧を取得する
`aws ec2 describe-images --owners <対象AWSアカウントID>` を実行すると、以下のようにAMIの詳細がJSON形式でずらずら出てくる。この情報の中から`--query`オプションで必要な情報（今回はImageId）を抜き出す。

```shell_session
$ aws ec2 describe-images --owners <対象AWSアカウントID>
{
    "Images": [
        {
            "Architecture": "x86_64",
            "CreationDate": "2022-05-02T10:24:47.000Z",
            "ImageId": "ami-xxxxxxxxxxxxxxxxx",
            "ImageLocation": "<対象AWSアカウントID>/AMI01_sakujo-test-ec202",
            "ImageType": "machine",
            "Public": false,
            "OwnerId": "<対象AWSアカウントID>",
            "PlatformDetails": "Linux/UNIX",
            "UsageOperation": "RunInstances",
            "State": "available",
            "BlockDeviceMappings": [
                {
                    "DeviceName": "/dev/xvda",
                    "Ebs": {
                        "DeleteOnTermination": true,
                        "SnapshotId": "snap-xxxxxxxxxxxxxxxxx",
                        "VolumeSize": 8,
                        "VolumeType": "gp2",
                        "Encrypted": false
                    }
                }
            ],
            "Description": "AMI01_sakujo-test-ec202",
            "EnaSupport": true,
            "Hypervisor": "xen",
            "Name": "AMI01_sakujo-test-ec202",
            "RootDeviceName": "/dev/xvda",
            "RootDeviceType": "ebs",
            "SriovNetSupport": "simple",
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "AMI01_sakujo-test-ec202"
                }
            ],
            "VirtualizationType": "hvm"
        },
        :
        :
```

### 対象AWSアカウント内のImageIdの一覧

```
aws ec2 describe-images \
  --owners <対象AWSアカウントID>  \
  --query 'Images[].{Id1:ImageId}' \
  --output text
```

実行結果をテキストファイルに保存する。

```:sakujo_AMI_list.txt
ami-xxxxxxxxxxxxxxxxx
ami-xxxxxxxxxxxxxxxxx
ami-xxxxxxxxxxxxxxxxx
ami-xxxxxxxxxxxxxxxxx
ami-xxxxxxxxxxxxxxxxx
ami-xxxxxxxxxxxxxxxxx

```



## 1-2.スナップショットの一覧を取得する
`aws ec2 describe-snapshots --owner-ids <対象AWSアカウントID>` を実行すると、以下のようにスナップショットの詳細がJSON形式でずらずら出てくる。この情報の中から`--query`オプションで必要な情報（今回はSnapshotId）を抜き出す。

```shell_session
$aws ec2 describe-snapshots --owner-ids <対象AWSアカウントID>
{
    "Snapshots": [
        {
            "Description": "Created by CreateImage(i-xxxxxxxxxxxxxxxxx) for ami-xxxxxxxxxxxxxxxxx",
            "Encrypted": false,
            "OwnerId": "<対象AWSアカウントID>",
            "Progress": "100%",
            "SnapshotId": "snap-xxxxxxxxxxxxxxxxx",
            "StartTime": "2022-05-02T10:25:08.349000+00:00",
            "State": "completed",
            "VolumeId": "vol-xxxxxxxxxxxxxxxxx",
            "VolumeSize": 8,
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "AMI02_sakujo-test-ec202"
                }
            ],
            "StorageTier": "standard"
        },
        :
        :
```

### 対象AWSアカウント内のSnapshotIdの一覧

```
aws ec2 describe-snapshots \
    --owner-ids <対象AWSアカウントID> \
    --query 'Snapshots[].{Id1:SnapshotId}' \
    --output text
```

実行結果をテキストファイルに保存する。

```:sakujo_snapshot_list.txt
snap-xxxxxxxxxxxxxxxxx
snap-xxxxxxxxxxxxxxxxx
snap-xxxxxxxxxxxxxxxxx
snap-xxxxxxxxxxxxxxxxx
snap-xxxxxxxxxxxxxxxxx
snap-xxxxxxxxxxxxxxxxx

```


# 2.AMIの削除
以降、Windows 10 にインストールした WSL で実施している。
※削除対象のAMIやスナップショットの数が100個くらいなら、削除権限のあるユーザでログインし CloudShell で削除実施してもよいが、CloudShell には以下のようなセッション制限があるため、長時間の操作に向かない。

- 無操作状態が続いた場合は約20分でセッションが切れる 
- 約12時間連続で実⾏するとセッションが切れる 
- ⻑時間の操作には不向き

AMIを削除する以下シェルスクリプトを作成する。

```shell:sakujo_AMI.sh
#!/bin/bash
# 設定ファイル
ami_list=sakujo_AMI_list.txt
# 日付時刻を文字列にする
jikan=`date +"%Y-%m%d-%H%M-%S"`

# profile
profile_name=<設定したプロファイル名>
# 意図したIAMユーザか確認
aws sts get-caller-identity --profile $profile_name

while read row
do
  echo ":::::::::::::::::::::::::::delete this ami ${row}" >> log/ami_all_log_$jikan.txt 2>&1
  aws ec2 deregister-image --image-id ${row} --profile $profile_name >> log/ami_all_log_$jikan.txt  2>&1
  if [ $? -ne 0 ]; then
    echo ${row} >> log/ami_error_${jikan}.txt
  else
    echo ${row} >> log/ami_ok_${jikan}.txt
  fi
  echo ":::::::::::::::::::::::::::end" >> log/ami_all_log_$jikan.txt  2>&1
sleep 3
done < ${ami_list}
```

AWS CLI でのプロファイル切り替え（スイッチロール）は[AWS CLIでスイッチロール　2.ローカルにインストールしたAWS CLIでスイッチロール](https://qiita.com/emiki/items/2f45f080d77c31613ec5#2%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%AB%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%97%E3%81%9Faws-cli%E3%81%A7%E3%82%B9%E3%82%A4%E3%83%83%E3%83%81%E3%83%AD%E3%83%BC%E3%83%AB)を参照。

同じディレクトリ配下は以下のようになっている。
```
~/sakujo_test$ ls -la
total 28
drwxr-xr-x  3 emi emi 4096 May  3 00:36 .
drwxr-xr-x 10 emi emi 4096 May  3 00:24 ..
drwxr-xr-x  2 emi emi 4096 May  3 00:33 log
-rw-r--r--  1 emi emi  131 May  2 20:24 sakujo_AMI_list.txt
-rw-r--r--  1 emi emi  713 May  3 00:23 sakujo_AMI.sh
-rw-r--r--  1 emi emi  138 May  3 00:35 sakujo_snapshot_list.txt
~/sakujo_test$
```

上記シェルスクリプト実行結果

```
$ bash sakujo_AMI.sh
{
    "UserId": "AROAxxxxxxxxxxxxxxxxx:<ユーザ名>",
    "Account": "<対象AWSアカウントID>",
    "Arn": "arn:aws:sts::<対象AWSアカウントID>:assumed-role/<ロール名>/<ユーザ名>"
}
$
```

logフォルダ配下
```
$ ls -la log/
total 24
drwxr-xr-x 2 emi emi 4096 May  3 00:33 .
drwxr-xr-x 3 emi emi 4096 May  3 00:36 ..
-rw-r--r-- 1 emi emi  480 May  3 00:29 ami_all_log_2022-0503-0029-37.txt
-rw-r--r-- 1 emi emi  110 May  3 00:29 ami_ok_2022-0503-0029-37.txt
$
```

ログ
```:ami_all_log_2022-0503-0029-37.txt
:::::::::::::::::::::::::::delete this ami ami-xxxxxxxxxxxxxxxxx
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this ami ami-xxxxxxxxxxxxxxxxx
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this ami ami-xxxxxxxxxxxxxxxxx
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this ami ami-xxxxxxxxxxxxxxxxx
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this ami ami-xxxxxxxxxxxxxxxxx
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this ami ami-xxxxxxxxxxxxxxxxx
:::::::::::::::::::::::::::end
```

```:ami_ok_2022-0503-0029-37.txt
ami-xxxxxxxxxxxxxxxxx
ami-xxxxxxxxxxxxxxxxx
ami-xxxxxxxxxxxxxxxxx
ami-xxxxxxxxxxxxxxxxx
ami-xxxxxxxxxxxxxxxxx
ami-xxxxxxxxxxxxxxxxx
```

# 3.スナップショットの削除

同様に、スナップショットを削除する以下のシェルスクリプトを作成する。

```shell:sakujo_snapshot.sh
#!/bin/bash
# 設定ファイル
snapshot_list=sakujo_snapshot_list.txt
# 日付時刻を文字列にする
jikan=`date +"%Y-%m%d-%H%M-%S"`

# profile
profile_name=<設定したプロファイル名>
# 意図したIAMユーザか確認
aws sts get-caller-identity --profile $profile_name

while read row
do
  echo ":::::::::::::::::::::::::::delete this snapshot ${row}" >> log/snapshot_all_log_$jikan.txt 2>&1
  aws ec2 delete-snapshot --snapshot-id ${row} --profile $profile_name >> log/snapshot_all_log_$jikan.txt  2>&1
  if [ $? -ne 0 ]; then
    echo ${row} >> log/snapshot_error_${jikan}.txt
  else
    echo ${row} >> log/snapshot_ok_${jikan}.txt
  fi
  echo ":::::::::::::::::::::::::::end" >> log/snapshot_all_log_$jikan.txt  2>&1
sleep 3
done < ${snapshot_list}
```

同じディレクトリ配下は以下のようになっている。
```
~/sakujo_test$ ls -la
total 28
drwxr-xr-x  3 emi emi 4096 May  3 00:36 .
drwxr-xr-x 10 emi emi 4096 May  3 00:24 ..
drwxr-xr-x  2 emi emi 4096 May  3 00:33 log
-rw-r--r--  1 emi emi  131 May  2 20:24 sakujo_AMI_list.txt
-rw-r--r--  1 emi emi  713 May  3 00:23 sakujo_AMI.sh
-rw-r--r--  1 emi emi  138 May  3 00:35 sakujo_snapshot_list.txt
-rw-r--r--  1 emi emi  760 May  3 00:23 sakujo_snapshot.sh
~/sakujo_test$
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/6f05815f-f899-8161-e563-5e7c2113fc5f.png)

上記シェルスクリプト実行結果

```
$ bash sakujo_snapshot.sh
{
    "UserId": "AROAxxxxxxxxxxxxxxxxx:<ユーザ名>",
    "Account": "<対象AWSアカウントID>",
    "Arn": "arn:aws:sts::<対象AWSアカウントID>:assumed-role/<ロール名>/<ユーザ名>"
}
$
```

logフォルダ配下
```
$ ls -la log/
total 24
drwxr-xr-x 2 emi emi 4096 May  3 00:33 .
drwxr-xr-x 4 emi emi 4096 May  3 00:53 ..
-rw-r--r-- 1 emi emi  480 May  3 00:29 ami_all_log_2022-0503-0029-37.txt
-rw-r--r-- 1 emi emi  110 May  3 00:29 ami_ok_2022-0503-0029-37.txt
-rw-r--r-- 1 emi emi  510 May  3 00:33 snapshot_all_log_2022-0503-0033-26.txt
-rw-r--r-- 1 emi emi  115 May  3 00:33 snapshot_ok_2022-0503-0033-26.txt
emi@LAPTOP-AOJR4Q2P:~/sakujo_test$
```

ログ
```:snapshot_all_log_2022-0503-0033-26.txt
:::::::::::::::::::::::::::delete this snapshot snap-xxxxxxxxxxxxxxxxx
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this snapshot snap-xxxxxxxxxxxxxxxxx
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this snapshot snap-xxxxxxxxxxxxxxxxx
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this snapshot snap-xxxxxxxxxxxxxxxxx
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this snapshot snap-xxxxxxxxxxxxxxxxx
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this snapshot snap-xxxxxxxxxxxxxxxxx
:::::::::::::::::::::::::::end
```

```:snapshot_ok_2022-0503-0033-26.txt
snap-xxxxxxxxxxxxxxxxx
snap-xxxxxxxxxxxxxxxxx
snap-xxxxxxxxxxxxxxxxx
snap-xxxxxxxxxxxxxxxxx
snap-xxxxxxxxxxxxxxxxx
snap-xxxxxxxxxxxxxxxxx
```

# 4.参考：`--dry-run` オプション

AWS CLI コマンドに`--dry-run`オプションを付けると、実際にはアクションをしないで、コマンドが実行されるかどうか確かめることができる。

## 4-1.AMI削除コマンドに`--dry-run`オプションをつける

```shell:sakujo_AMI_dry_run.sh
#!/bin/bash
# 設定ファイル
ami_list=sakujo_AMI_list.txt
# 日付時刻を文字列にする
jikan=`date +"%Y-%m%d-%H%M-%S"`

# profile
profile_name=<設定したプロファイル名>
# 意図したIAMユーザか確認
aws sts get-caller-identity --profile $profile_name

while read row
do
  echo ":::::::::::::::::::::::::::delete this ami ${row}" >> log/ami_all_log_$jikan.txt 2>&1
  aws ec2 deregister-image --image-id ${row} --profile $profile_name --dry-run >> log/ami_all_log_$jikan.txt  2>&1
  if [ $? -ne 0 ]; then
    echo ${row} >> log/ami_error_${jikan}.txt
  else
    echo ${row} >> log/ami_ok_${jikan}.txt
  fi
  echo ":::::::::::::::::::::::::::end" >> log/ami_all_log_$jikan.txt  2>&1
sleep 3
done < ${ami_list}
```

上記シェルスクリプト実行結果

```
$ bash sakujo_AMI_dry_run.sh
{
    "UserId": "AROAxxxxxxxxxxxxxxxxx:<ユーザ名>",
    "Account": "<対象AWSアカウントID>",
    "Arn": "arn:aws:sts::<対象AWSアカウントID>:assumed-role/<ロール名>/<ユーザ名>"
}
$
```

ログ
```:ami_all_log_2022-0503-0021-58.txt
:::::::::::::::::::::::::::delete this ami ami-xxxxxxxxxxxxxxxxx

An error occurred (DryRunOperation) when calling the DeregisterImage operation: Request would have succeeded, but DryRun flag is set.
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this ami ami-xxxxxxxxxxxxxxxxx

An error occurred (DryRunOperation) when calling the DeregisterImage operation: Request would have succeeded, but DryRun flag is set.
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this ami ami-xxxxxxxxxxxxxxxxx

An error occurred (DryRunOperation) when calling the DeregisterImage operation: Request would have succeeded, but DryRun flag is set.
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this ami ami-xxxxxxxxxxxxxxxxx

An error occurred (DryRunOperation) when calling the DeregisterImage operation: Request would have succeeded, but DryRun flag is set.
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this ami ami-xxxxxxxxxxxxxxxxx

An error occurred (DryRunOperation) when calling the DeregisterImage operation: Request would have succeeded, but DryRun flag is set.
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this ami ami-xxxxxxxxxxxxxxxxx

An error occurred (DryRunOperation) when calling the DeregisterImage operation: Request would have succeeded, but DryRun flag is set.
:::::::::::::::::::::::::::end
```

```:ami_error_2022-0503-0021-58.txt
ami-xxxxxxxxxxxxxxxxx
ami-xxxxxxxxxxxxxxxxx
ami-xxxxxxxxxxxxxxxxx
ami-xxxxxxxxxxxxxxxxx
ami-xxxxxxxxxxxxxxxxx
ami-xxxxxxxxxxxxxxxxx
```

## 4-2.スナップショット削除コマンドに`--dry-run`オプションをつける

`--dry-run`オプションをつけると、実際にコマンドは実行せず、実行できるかどうかを確認することができる。

```shell:sakujo_snapshot_dry_run.sh
#!/bin/bash
# 設定ファイル
snapshot_list=sakujo_snapshot_list.txt
# 日付時刻を文字列にする
jikan=`date +"%Y-%m%d-%H%M-%S"`

# profile
profile_name=20220326_srtest_emiki_PU
# 意図したIAMユーザか確認
aws sts get-caller-identity --profile $profile_name

while read row
do
  echo ":::::::::::::::::::::::::::delete this snapshot ${row}" >> log/snapshot_all_log_$jikan.txt 2>&1
  aws ec2 delete-snapshot --snapshot-id ${row} --profile $profile_name --dry-run >> log/snapshot_all_log_$jikan.txt  2>&1
  if [ $? -ne 0 ]; then
    echo ${row} >> log/snapshot_error_${jikan}.txt
  else
    echo ${row} >> log/snapshot_ok_${jikan}.txt
  fi
  echo ":::::::::::::::::::::::::::end" >> log/snapshot_all_log_$jikan.txt  2>&1
sleep 3
done < ${snapshot_list}
```

上記シェルスクリプト実行結果

```
$ bash sakujo_snapshot_dry_run.sh
{
    "UserId": "AROA3KKBATVH7Z7JKDWVN:emiki_cli_user",
    "Account": "<対象AWSアカウントID>",
    "Arn": "arn:aws:sts::<対象AWSアカウントID>:assumed-role/<ロール名>/<ユーザ名>"
}
$
```

ログ

```:snapshot_all_log_2022-0503-0018-44.txt
:::::::::::::::::::::::::::delete this snapshot snap-xxxxxxxxxxxxxxxxx

An error occurred (DryRunOperation) when calling the DeleteSnapshot operation: Request would have succeeded, but DryRun flag is set.
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this snapshot snap-xxxxxxxxxxxxxxxxx

An error occurred (DryRunOperation) when calling the DeleteSnapshot operation: Request would have succeeded, but DryRun flag is set.
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this snapshot snap-xxxxxxxxxxxxxxxxx

An error occurred (DryRunOperation) when calling the DeleteSnapshot operation: Request would have succeeded, but DryRun flag is set.
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this snapshot snap-xxxxxxxxxxxxxxxxx

An error occurred (DryRunOperation) when calling the DeleteSnapshot operation: Request would have succeeded, but DryRun flag is set.
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this snapshot snap-xxxxxxxxxxxxxxxxx

An error occurred (DryRunOperation) when calling the DeleteSnapshot operation: Request would have succeeded, but DryRun flag is set.
:::::::::::::::::::::::::::end
:::::::::::::::::::::::::::delete this snapshot snap-xxxxxxxxxxxxxxxxx

An error occurred (DryRunOperation) when calling the DeleteSnapshot operation: Request would have succeeded, but DryRun flag is set.
:::::::::::::::::::::::::::end
```

```:snapshot_error_2022-0503-0018-44.txt
snap-xxxxxxxxxxxxxxxxx
snap-xxxxxxxxxxxxxxxxx
snap-xxxxxxxxxxxxxxxxx
snap-xxxxxxxxxxxxxxxxx
snap-xxxxxxxxxxxxxxxxx
snap-xxxxxxxxxxxxxxxxx
```



# 参考

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/deregister-ami.html

https://blog.serverworks.co.jp/get-ami-snapshot-list

https://dev.classmethod.jp/articles/backup_and_restore_ec2_using_snapshot/

https://qiita.com/r_karotou/items/fa1918c90ebbb462b923

https://zenn.dev/apple_nktn/articles/4982730d1da3dd

https://qiita.com/SoarTec-lab/items/4475ba6de612fba3f163

https://blog.serverworks.co.jp/get-ami-snapshot-list

https://qiita.com/kusokamayarou/items/f6fde4d47a9de8f0b60d

https://dev.classmethod.jp/articles/ami-and-snapshot-delete/

https://qiita.com/tcsh/items/a32dbc8f9cfaa38ec9a0