如何成功刪除 Amazon S3 Glacier 的 Vaults 備份資料 | The Will Will Web

The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

如何成功刪除 Amazon S3 Glacier 的 Vaults 備份資料

我大概在多年前開始把公司重要資料備份到 Amazon S3 Glacier 雲端儲存空間,由於價格真的非常便宜,我大概備份了 500GB 左右的資料在上面,每個月的儲存成本僅僅 2 美元(約 60 新台幣),非常划算的異地備份方案。不過最近由於改變了備份策略,想把儲存庫(Vault)刪除,但卻意外遇到許多阻礙!

無法刪除有資料的 Vault 儲存庫

我原本以為刪除 Vault 很簡單,我資料都不要了,直接刪除不行嗎?沒錯,就是不行!

AWS 的 Vault 可以想像成「保險箱」的概念,把要封存的檔案(archives)鎖在保險箱裡面。

官方文件得知,只要 Vault (保險箱) 還有任何 archives (檔案) 存在,就無法被刪除!

這裡的 inventory (庫存清單) 是告訴你保險箱中有多少檔案明細,預設是沒有庫存清單的,你必須建立一個庫存清單取回作業 (inventory retrieval job),才能得知有多少檔案在裡面,而每次執行一次大約要花 1 ~ 4 小時,看你的檔案數量多寡而定。

這裡判斷可刪除 Vault 的判斷標準,就是最後一次建立的 inventory (庫存清單) 是否還有任何 archives (檔案) 在清單裡面。

如果你試圖刪除 Vault,就會出現以下錯誤:

Vault not empty or recently written to: arn:aws:glacier:us-west-2:111122223333:vaults/MyValutName

如果用 AWS 命令列界面 來執行刪除動作,也會出現以下錯誤:

$ aws glacier delete-vault --vault-name MyValutName --account-id 111122223333

An error occurred (InvalidParameterValueException) when calling the DeleteVault operation: Vault not empty or recently written to: arn:aws:glacier:us-west-2:111122223333:vaults/MyValutName

上述命令的 --account-id (AWS 帳戶 ID) 可以透過 aws s3api list-buckets --query "Owner.ID" 來取得。或是透過 IAM Management Console 中「您的安全登入資料」的「帳戶識別符」頁籤展開後得知。你可以從 AWS 管理控制台 右上角點選姓名、點選「我的安全登入資料」進入查詢。

以下所有 CLI 命令,請將 MyValutName 修改成你的 Vault 名稱,將 111122223333 修改為你的 AWS 帳戶 ID

如何成功刪除還有資料在內的 Vault 儲存庫

要能成功刪除還有資料在內的 Vault 儲存庫,基本上有三個步驟:

  1. 啟動一個庫存清單取回作業 (inventory retrieval job)

    aws glacier initiate-job --vault-name MyValutName --account-id 111122223333 --job-parameters '{"Type": "inventory-retrieval"}'
    

    上述命令會取得一個 Job ID,預期結果如下:

    {
        "location": "/111122223333/vaults/{ValutName}/jobs/{JobId}",
        "jobId": "{JobId}"
    }
    

    取得目前已經有的庫存清單取回作業與狀態 (取得 JobId 欄位)

    aws glacier list-jobs --vault-name MyValutName --account-id 111122223333
    

    取得庫存清單取回作業狀態,如果 StatusCode 出現 InProgress 就代表還沒完成!

    aws glacier describe-job --vault-name MyValutName --account-id 111122223333 --job-id "XOmFI3ySrMXe_SQqul_HQ2IgMNIXhZnBMXolaqI1gm6cHsebFk207hMkdd4im9rLeAzy-_uKhQoBU_WNl9ftEzz1-9xy"
    
    {
        "InventoryRetrievalParameters": {
            "Format": "JSON"
        },
        "VaultARN": "VaultARN",
        "Completed": false,
        "JobId": "JOB_ID",
        "Action": "InventoryRetrieval",
        "CreationDate": "JOB建立日期",
        "StatusCode": "InProgress"
    }
    
  2. 刪除每一個庫存清單中的檔案 (deleting each archive)

    先取得所有檔案清單 (從 output.json 檔案中取得每一個 ArchiveId 欄位)

    aws glacier get-job-output --vault-name MyValutName --account-id 111122223333 --job-id "XOmFI3ySrMXe_SQqul_HQ2IgMNIXhZnBMXolaqI1gm6cHsebFk207hMkdd4im9rLeAzy-_uKhQoBU_WNl9ftEzz1-9xy" output.json
    cat output.json | jq -r '(.ArchiveList[]).ArchiveId' > all_archive_ids.txt
    

    再利用以下命令透過 AWS CLI「逐筆刪除」每個封存檔案

    while read line; do echo "$line" && aws glacier delete-archive --vault-name MyValutName --account-id 111122223333 --archive-id "$line"; done < all_archive_ids.txt
    
  3. 刪除儲存庫 (deleting the vault)

    你必須再次啟動一個庫存清單取回作業 (inventory retrieval job)

    aws glacier initiate-job --vault-name MyValutName --account-id 111122223333 --job-parameters '{"Type": "inventory-retrieval"}'
    

    然後還「不一定」可以刪除,我的經驗是再等個數個小時後,才能真正刪除 Vault 儲存庫!

    aws glacier delete-vault --vault-name MyValutName --account-id 111122223333
    

使用 glacier-vault-remove 工具刪除 Vault 儲存庫

國外有個老兄用 Python 寫了一個小工具叫做 glacier-vault-remove,作者算是十分佛心,把執行檔包成 Docker Image 了,因此你可以很輕易的透過 Docker 來執行,以下我就以 Docker 執行當作範例!

  1. 先到 AWS Console 建立一組 Access Key / Secret Key

    您的安全登入資料

  2. 建立 credentials.json 認證檔,把你在 AWS 的 Access Key / Secret Key 寫成以下 JSON 檔案格式

    {
        "AWSAccessKeyId": "AAAAAAAAAAAAAAAAAAAA",
        "AWSSecretKey":   "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
    }
    
  3. 透過 Windows PowerShell 或 Bash 列出目前有幾個 Valuts

    docker run --rm -v "$(pwd)\credentials.json:/app/credentials.json" leeroyb/glacier-vault-remove us-west-2 LIST
    

    請注意:命令提示字元不支援 $(pwd) 變數語法。

  4. 要能成功刪除還有資料在內的 Vault 儲存庫,一樣也是三個步驟

    1. 啟動一個庫存清單取回作業 (inventory retrieval job)

      預設會先建立一個 Inventory Retrieving Job 取回所有檔案清單(會跑很久)

      docker run --rm -v G:\Projects\credentials.json:/app/credentials.json leeroyb/glacier-vault-remove us-west-2 MyValutName
      

      執行後可以按下 Ctrl-C 結束,因為你需要等待 inventory retrieval job 執行完畢,可能要等上幾個小時!

    2. 刪除每一個儲存庫中的檔案 (deleting each archive)

      設定一次跑 4 個 Process 執行刪除動作 (預設會自動找到最新的取回作業,並接續這份作業進行刪除工作)

      docker run --rm -v G:\Projects\credentials.json:/app/credentials.json leeroyb/glacier-vault-remove us-west-2 MyValutName 4
      

      你也可以先查詢目前正在執行的 Job ID

      docker run --rm -v G:\Projects\credentials.json:/app/credentials.json leeroyb/glacier-vault-remove us-west-2 MyValutName LIST
      

      也可以指定 Jobs ID 執行刪除動作

      docker run --rm -v G:\Projects\credentials.json:/app/credentials.json leeroyb/glacier-vault-remove us-west-2 MyValutName DEBUG 4 MOmFI3ySrMXa_Sqqul_HQ2IgMNIXhZnaMXolaqI1gm6cHsebFk307hMkdd4im9rLeAzy-_uKhQoBU_WNl9ftEzz1-9xy
      
    3. 刪除儲存庫 (deleting the vault)

      你必須再次啟動一個庫存清單取回作業 (inventory retrieval job)

      docker run --rm -v G:\Projects\credentials.json:/app/credentials.json leeroyb/glacier-vault-remove us-west-2 MyValutName NEW
      

      等 inventory retrieval job 完成後,上述命令也「不一定」可以立即刪除 Vault 儲存庫!建議等個半天左右,重新再跑一次,再不行就再等等!

總結

Amazon S3 Glacier 雲端儲存空間確實是一個成本相當低廉的儲存服務,但是除了成本低之外,檔案取得的成本極高,取回的時間越短,成本就越高。因此,只有當你想把這份資料當成「異地備份」用途,而且取回的機會很低,才適合用這個服務來備份檔案。像我從 2014 年開始備份進去,至今沒有取出過一次,因為公司的 NAS 並沒有損毀,所以整體來講,我在「異地儲存」這件事情上,確實省了不少錢。

我最近就是覺得,如果要臨時取出一些重要檔案時,光是取得 inventory (庫存清單) 就要花上 1 ~ 4 小時,這個等待的時間確實讓人蠻焦慮的,所以決定將備份資料移到其他雲端平台(Azure)。

相關連結