Amazon S3 GlacierのボールトをCLIツールで削除する

我が家ではSynologyNASを利用していますが、GlacierBackupというアプリを利用してSynologyNASのデータをS3 Glacierにバックアップしています。

バックアップの設定を見直した際、昔のボールトを削除することにしたので、削除する方法をまとめておきます。

S3 Glacierのボールトを削除する方法として、SDK・REST API・CLIのいずれかの利用が必要になりますが、今回はCLIツールを利用した削除を行っていきます。

※下記手順はAWSの公式ドキュメントを参考にしています。(Deleting an Archive in Amazon S3 Glacier Using the AWS Command Line Interface

AWS CLIツールのインストール

AWS CLIは公式ドキュメントを参考にインストールします。(参考:AWS CLI の最新バージョンをインストールまたは更新します。

$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install

次にprofileを作成します。profileの作成に必要なアクセスキーとシークレットキーは、事前にAWSコンソールのIAMで作成しておきます。

$ aws configure --profile your-profile-name
...

AWS CloudShellの起動(アーカイブ数が少ない人向け)

AWS CLIツールをインストールしても良いのですが、ボールト内のアーカイブ数が少ない場合、ブラウザで提供されているCloudShellで十分なので、AWSのコンソールにログインしてCloudShellを起動しましょう。

AWSコンソール右上の端末ボタンをクリックするとCloudShellが起動します。

AWSのCloudShellの起動方法

ボールトの削除

ボールトの削除は下記手順で実施します。

  1. ボールト情報(ボールト名)の取得
  2. ボールトイベントリの取得ジョブ実行
  3. アーカイブの削除
  4. ボールトの削除

ボールトは、ボールト内に保存されているアーカイブが存在すると削除できないので、まず全てのアーカイブを削除する必要があります。また、アーカイブIDはボールトイベントリに記載されているので、ボールトイベントリの取得も必要になります。

各手順について、詳細を説明していきます。

ボールト情報の取得

ボールトの情報を取得します。アカウントIDは、AWSコンソールの右上にあるアカウント名からアカウントIDはコピーできます。下記の出力では、123,446件のアーカイブが含まれていることがわかります。

※--profileオプションは、awsコマンドでプロファイルを指定しているだけなので、デフォルトのプロファイルを利用している場合は不要です。

$ export AWS_ACCOUNT_ID=111122223333
$ export AWS_PROFILE=your-profilename
$ aws glacier list-vaults --account-id $AWS_ACCOUNT_ID --profile $AWS_PROFILE
{
    "VaultList": [
        {
            "VaultARN": "arn:...",
            "VaultName": "vault name",
            "CreationDate": "2021-...",
            "LastInventoryDate": "2022-...",
            "NumberOfArchives": 123446,
            "SizeInBytes": 392158741741
        },
     ]
}

削除したいボールト名を環境変数に保存しておきます。

$ export AWS_VAULT_NAME="vault name"

ボールトイベントリのダウンロードジョブの実行

ボールト内のアーカイブIDを取得するため、ボールトイベントリをダウンロードします。この処理には数時間かかるので、途中で出力されるJobIDなどはどこかに保存しておきましょう。

ボールトイベントリとは

公式ドキュメントから引用

あるボールトインベントボールト内のアーカイブのリストを指します。インベントリでは、リスト内の各アーカイブに、アーカイブ ID、作成日、サイズなど、アーカイブに関する情報が記載されています。S3 Glacier はボールトインベントリを毎日 1 回のペースで更新します。

https://docs.aws.amazon.com/ja_jp/amazonglacier/latest/dev/working-with-vaults.html

ジョブを実行します。

# イベントリ取得用Jobの実行
$ aws glacier initiate-job --vault-name $AWS_VAULT_NAME --account-id $AWS_ACCOUNT_ID --profile $AWS_PROFILE --job-parameters "{\"Type\":\"inventory-retrieval\"}"
{
    "location": "...",
    "jobId": "..."
}

ジョブが正常に実行されているか、確認します。

$ export AWS_JOB_ID=...
$ aws glacier describe-job --vault-name $AWS_VAULT_NAME --account-id $AWS_ACCOUNT_ID --job-id $AWS_JOB_ID --profile $AWS_PROFILE
...
    "CreationDate": "2023-04-19T01:25:57.830Z",
    "Completed": false,
    "StatusCode": "InProgress",
...

この処理は数時間かかるので、完了するまで待ちます(※ジョブ完了から24時間以上たつと取得したアーカイブIDが無効になるので、必ず24時間以内に下記の削除を終わらせてください。)。

ちなみに、ジョブが完了すると下記のような出力となります。

$ aws glacier describe-job --vault-name $AWS_VAULT_NAME --account-id $AWS_ACCOUNT_ID --job-id $AWS_JOB_ID  --profile $AWS_PROFILE
...
    "Completed": true,
    "StatusCode": "Succeeded",
    "StatusMessage": "Succeeded",
...

アーカイブの削除

上記で実行したイベントリ取得ジョブの出力にアーカイブIDが含まれているので、JSONファイルに出力します。

$ aws glacier get-job-output --vault-name $AWS_VAULT_NAME --account-id $AWS_ACCOUNT_ID --job-id $AWS_JOB_ID output.json  --profile $AWS_PROFILE
{
    "status": 200,
    "acceptRanges": "bytes",
    "contentType": "application/json"
}

JSONファイルの中身を確認してみます。各アーカイブ毎のIDが取得できているのが確認できます。

$ cat output.json | jq .
{
  "VaultARN": "arn:aws:hoge",
  "InventoryDate": "2022-..",
  "ArchiveList": [
    {
      "ArchiveId": "archive-id",
      "ArchiveDescription": "",
      "CreationDate": "2021-...",
      "Size": 15627,
      "SHA256TreeHash": "hash"
    },
    {..}
 }
]

すべてのアーカイブを一括で削除するために、シェルスクリプト(delete-archives.sh)を作成します。

下記のシェルスクリプトはGitHubのIssueを参考に作成しました(参考:AWS Glacier: Delete vault)。プロセッサー数(nprocコマンド)×2分の同時実行を可能にしています。

#!/usr/bin/env bash

file='./output.json'
id_file='./output-archive-ids.txt'

if [[ -z ${AWS_ACCOUNT_ID} ]] || [[ -z ${AWS_PROFILE} ]] || [[ -z ${AWS_VAULT_NAME} ]]; then
        echo "Please set the following environment variables: "
        echo "AWS_ACCOUNT_ID"
        echo "AWS_VAULT_NAME"
        echo "AWS_PROFILE"
        exit 1
fi

echo "Started at $(date)"

echo -n "Getting archive ids from $file..."
if [[ ! -f $id_file ]]; then
  cat $file | jq -r --stream ". | { (.[0][2]): .[1]} | select(.ArchiveId) | .ArchiveId" > $id_file 2> /dev/null
fi
total=$(wc -l $id_file | awk '{print $1}')
echo "got $total"

num=0
while read -r archive_id; do
  num=$((num+1))
  echo "Deleting archive $num/$total at $(date)"
  aws glacier delete-archive --archive-id=${archive_id} --vault-name ${AWS_VAULT_NAME} --account-id ${AWS_ACCOUNT_ID} &
  [ $( jobs | wc -l ) -ge $(($(nproc)*2)) ] && wait
done < "$id_file"

wait
echo "Finished at $(date)"
echo "Deleted archive ids are in $id_file"

アーカイブを削除します。今回の例ではアーカイブ数が多いのでバックグラウンドで実行するようにnohupを利用していますが、少ない場合nohupは必要ありません。

$ chmod +x delete-archives.sh
$ nohup ./delete-archives.sh > delete-archives.log 2>&1 &
$ tail -f delete-archives.log

削除できたかを確認しますが、アーカイブの削除が反映されるまで半日ー1日程度かかってしまいます。

$ aws glacier describe-job --vault-name $VAULT_NAME --account-id $ACCOUNT_ID 

ボールトの削除

アーカイブを削除したら、ボールトを削除可能になるので、削除します。

$ aws glacier delete-vault --account-id $AWS_ACCOUNT_ID --vault-name $AWS_VAULT_NAME

削除されたかを確認します。

$ aws glacier list-vaults --account-id -
{
    "VaultList": []
}

AWSのポータルからも削除されているはずです。

まとめ

S3 Glacierのボールトを削除する方法を紹介しました。

コンソールから操作できないのが面倒くさいですし、結果が返ってくるまでも結構時間がかかります。データの保存料がやすいので、このあたりはしょうがないかもしれませんね。

  • この記事を書いた人

たかさん

犬と暮らすクラウドエンジニア。GCPが好きだけど良く触るのはAWSとAzureです。

-AWS
-, ,