Amazon Glacierのボールトはアーカイブが残っていると削除できない

2017.07.25

Amazon GlacierのVaultにアーカイブが残ったまま削除しようとすると、次のようなエラーが発生して削除に失敗します。

aws-glacier-vault-delete-error

CLI から操作しても然りです。

$ aws glacier delete-vault --account-id - --vault-name examplevault

An error occurred (InvalidParameterValueException) when calling the DeleteVault operation: Vault not empty or recently written to: arn:aws:glacier:ap-northeast-1:123456789012:vaults/examplevault

ドキュメントを確認してみましょう

Amazon Glacier deletes a vault only if there are no archives in the vault as of the last inventory it computed and there have been no writes to the vault since the last inventory.

http://docs.aws.amazon.com/amazonglacier/latest/dev/deleting-vaults-console.html

今回は、Vault内のアーカイブを全て削除して(Vaultを空にして)、Vaultを削除する方法を紹介します。

AWS マネジメントコンソールにはアーカイブ削除の機能が提供されていないため、SDK/CLIなどを通じてREST API経由で削除します。

AWS マネジメントコンソールからアーカイブを削除

S3のようにAWSマネジメントコンソールからボールト→アーカイブとドリルダウンして削除出来ると楽なのですが、前述の通りそのような機能は現時点では提供されていません。

You cannot delete an archive using the Amazon Glacier management console. To delete an archive you must use the AWS Command Line Interface (CLI) or write code to make a delete request using either the REST API directly or the AWS SDK for Java and .NET wrapper libraries.

http://docs.aws.amazon.com/amazonglacier/latest/dev/deleting-an-archive.html

CLIからアーカイブを削除

マネジメントコンソールからアーカイブを削除できないため、CLI/SDK経由で REST APIを叩いて削除します。 今回はCLIを利用して削除します。

作業の流れ

アーカイブを削除するにはアーカイブIDが必要です。 アーカイブIDはVaultのインベントリーから参照できます。 Vaultのインベントリーはすぐに取得出来るわけではなく、ジョブでインベントリーの作成依頼をし、数時間すると、取得可能になります。

これらをまとめると、アーカイブを削除してVaultを削除するために、以下の流れで作業します。

  1. Vault の確認
  2. インベントリーを作成するジョブの開始
  3. 数時間するとインベントリーが取得可能状態になる
  4. インベントリーの取得
  5. アーカイブの削除
  6. Vaultの削除

1. Vaultの確認

list-vaults API で Vault 一覧を確認します。

$ aws glacier list-vaults --account-id -
{
    "VaultList": [
        {
            "SizeInBytes": 5505056,
            "VaultARN": "arn:aws:glacier:ap-northeast-1:123456789012:vaults/examplevault",
            "LastInventoryDate": "2015-03-22T07:07:05.124Z",
            "VaultName": "examplevault",
            "NumberOfArchives": 8,
            "CreationDate": "2015-03-19T15:09:31.385Z"
        }
    ]
}

削除したいVaultは examplevault です。 "NumberOfArchives": 8 からこのVaultにはアーカイブが8個あることがわかります。

Vault名を把握している場合、 describe-vault API で特定の Vault の詳細を確認することもできます。

$ aws glacier describe-vault \
  --account-id 123456789012 \
  --vault-name examplevault
{
    "SizeInBytes": 5505056,
    "VaultARN": "arn:aws:glacier:ap-northeast-1:123456789012:vaults/examplevault",
    "LastInventoryDate": "2015-03-22T07:07:05.124Z",
    "NumberOfArchives": 8,
    "CreationDate": "2015-03-19T15:09:31.385Z",
    "VaultName": "examplevault"
}

2. インベントリーを作成するジョブの開始

Vault内のアーカイブはインベントリー経由でしか知るすべがないため、インベントリーを作成するジョブを開始します。

initiate-job API でインベントリーの作成依頼をします。

ジョブは

  • アーカイブ取得
  • インベントリー取得

の2種類があります。

--job-parameters{"Type": "inventory-retrieval"} とすることで、インベントリーの作成依頼になります。

$ aws glacier initiate-job \
  --account-id - \
  --vault-name $VAULT_NAME \
  --job-parameters '{"Type": "inventory-retrieval"}'
{
    "location": "/123456789012/vaults/examplevault/jobs/FOO",
    "jobId": "FOO"
}

開始したジョブを list-jobs API で確認してみます

$ aws glacier list-jobs \
  --account-id - \
  --vault-name $VAULT_NAME
{
    "JobList": [
        {
            "InventoryRetrievalParameters": {
                "Format": "JSON"
            },
            "VaultARN": "arn:aws:glacier:ap-northeast-1:123456789012:vaults/examplevault",
            "Completed": false,
            "JobId": "FOO",
            "Action": "InventoryRetrieval",
            "CreationDate": "2017-07-16T17:18:05.011Z",
            "StatusCode": "InProgress"
        }
    ]
}
  • "Completed": false
  • "Action": "InventoryRetrieval"
  • "StatusCode": "InProgress"

から、インベントリーの取得ジョブが作成され、まだ作業中であることがわかります。

ジョブの完了には数時間を要します。ご注意下さい。 ジョブ処理をシステマティックに行いたい場合は、Vault にSNSを設定し、イベント・ドリブンに行うと良いでしょう。

describe-job API で特定ジョブのステータスを確認することもできます。

ジョブ完了後にステータスを確認した結果が以下です

$ aws glacier describe-job \
  --account-id - \
  --vault-name $VAULT_NAME \
  --job-id "FOO"
{
    "CompletionDate": "2017-07-16T21:05:07.247Z",
    "VaultARN": "arn:aws:glacier:ap-northeast-1:123456789012:vaults/examplevault",
    "InventoryRetrievalParameters": {
        "Format": "JSON"
    },
    "Completed": true,
    "InventorySizeInBytes": 2747,
    "JobId": "FOO",
    "Action": "InventoryRetrieval",
    "CreationDate": "2017-07-16T17:18:05.011Z",
    "StatusMessage": "Succeeded",
    "StatusCode": "Succeeded"
}
  • "Completed": true
  • "Action": "InventoryRetrieval"
  • "StatusMessage": "Succeeded"
  • "StatusCode": "Succeeded"

から、インベントリーの取得ジョブが完了していることがわかります。

3. インベントリーの取得

Vaultのインベントリーはジョブの実行結果として取得できます。 get-job-output API を利用します。

$ aws glacier get-job-output \
  --account-id - \
  --vault-name $VAULT_NAME \
  --job-id "FOO" \
  output.json
{
    "status": 200,
    "acceptRanges": "bytes",
    "contentType": "application/json"
}

ダウンロードした JSON 形式のインベントリーを覗くと、アーカイブ一覧(ArchiveList)と各アーカイブのID(ArchiveId)を確認できます。

$ cat output.json | jq .
{
  "VaultARN": "arn:aws:glacier:ap-northeast-1:123456789012:vaults/examplevault",
  "InventoryDate": "2015-03-22T07:07:05Z",
  "ArchiveList": [
    {
      "ArchiveId": "DUMMY",
      "ArchiveDescription": "The optional description of the archive you are uploading",
      "CreationDate": "2015-03-19T15:16:35Z",
      "Size": 11,
      "SHA256TreeHash": "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
    },
    {
      "ArchiveId": "DUMMY",
      "ArchiveDescription": "test1",
      "CreationDate": "2015-03-19T15:25:09Z",
      "Size": 5,
      "SHA256TreeHash": "1b4f0e9851971998e732078544c96b36c3d01cedf7caa332359d6f1d83567014"
    },
    ...,
    {
      "ArchiveId": "DUMMY",
      "ArchiveDescription": "test2",
      "CreationDate": "2015-03-22T04:43:34Z",
      "Size": 2621440,
      "SHA256TreeHash": "e50b4495edd15ee466d97fec8766204caed6ad724597ef8b0e0a141421f09c48"
    }
  ]
}

4. アーカイブの削除

delete-archive API でアーカイブを削除します。

今回はインベントリーファイルからアーカイブIDをパースしてアーカイブを削除してみました。

#!/bin/sh

for archive in $(cat output.json | jq '.ArchiveList[].ArchiveId')
do
 echo delete $archive
 aws glacier delete-archive --account-id - --vault-name $VAULT_NAME --archive-id $archive
done

アーカイブ削除後のVaultを詳細表示します。

$ aws glacier describe-vault \
  --account-id 123456789012 \
  --vault-name examplevault
{
    "SizeInBytes": 0,
    "VaultARN": "arn:aws:glacier:ap-northeast-1:123456789012:vaults/examplevault",
    "LastInventoryDate": "2017-07-17T01:04:46.981Z",
    "NumberOfArchives": 0,
    "CreationDate": "2015-03-19T15:09:31.385Z",
    "VaultName": "examplevault"
}

"NumberOfArchives": 0 とアーカイブが0件になっていることがわかります。

5. Vaultの削除

delete-vault API でVaultを削除できます。

せっかくなので、この操作も CLI かやってみます。

$ aws glacier delete-vault --account-id - --vault-name $VAULT_NAME
$ aws glacier list-vaults --account-id -
{
    "VaultList": []
}

Vault削除が無事成功し、Vaultが0件になっています。

まとめ

今回はCLIを使ってAmazon GlacierのVaultからアーカイブを削除し、Vaultを削除する方法を紹介しました。

ポイントをまとめます

  • Vaultにアーカイブが残っていると、Vaultを削除できない
  • AWS マネジメントコンソールからはアーカイブを削除できないためCLI/SDKで削除する
  • 削除に必要なアーカイブIDはVaultのインベントリーから取得する
  • インベントリーの作成には数時間かかる

Amazon Glacierのアーカイブ操作はワークフローが特殊なため、一度手順をさらっておくと、安心して運用出来ると思います。

参考