我大概在多年前開始把公司重要資料備份到 Amazon S3 Glacier 雲端儲存空間,由於價格真的非常便宜,我大概備份了 500GB 左右的資料在上面,每個月的儲存成本僅僅 2 美元(約 60 新台幣),非常划算的異地備份方案。不過最近由於改變了備份策略,想把儲存庫(Vault)刪除,但卻意外遇到許多阻礙!
無法刪除有資料的 Vault 儲存庫
我原本以為刪除 Vault 很簡單,我資料都不要了,直接刪除不行嗎?沒錯,就是不行!
AWS 的 Vault
可以想像成「保險箱」的概念,把要封存的檔案(archives)鎖在保險箱裡面。
從官方文件得知,只要 Vault (保險箱) 還有任何 archives (檔案) 存在,就無法被刪除!
這裡的 inventory
(庫存清單) 是告訴你保險箱中有多少檔案明細,預設是沒有庫存清單的,你必須建立一個庫存清單取回作業 (inventory retrieval job),才能得知有多少檔案在裡面,而每次執行一次大約要花 1 ~ 4 小時,看你的檔案數量多寡而定。
這裡判斷可刪除 Vault 的判斷標準,就是最後一次建立的 inventory
(庫存清單) 是否還有任何 archives (檔案) 在清單裡面。
如果你試圖刪除 Vault,就會出現以下錯誤:
如果用 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 儲存庫,基本上有三個步驟:
-
啟動一個庫存清單取回作業 (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"
}
-
刪除每一個庫存清單中的檔案 (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
-
刪除儲存庫 (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
國外有個老兄用 Python 寫了一個小工具叫做 glacier-vault-remove,作者算是十分佛心,把執行檔包成 Docker Image 了,因此你可以很輕易的透過 Docker 來執行,以下我就以 Docker 執行當作範例!
-
先到 AWS Console 建立一組 Access Key / Secret Key
您的安全登入資料
-
建立 credentials.json
認證檔,把你在 AWS 的 Access Key / Secret Key 寫成以下 JSON 檔案格式
{
"AWSAccessKeyId": "AAAAAAAAAAAAAAAAAAAA",
"AWSSecretKey": "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
}
-
透過 Windows PowerShell 或 Bash 列出目前有幾個 Valuts
docker run --rm -v "$(pwd)\credentials.json:/app/credentials.json" leeroyb/glacier-vault-remove us-west-2 LIST
請注意:命令提示字元不支援 $(pwd)
變數語法。
-
要能成功刪除還有資料在內的 Vault 儲存庫,一樣也是三個步驟
-
啟動一個庫存清單取回作業 (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 執行完畢,可能要等上幾個小時!
-
刪除每一個儲存庫中的檔案 (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
-
刪除儲存庫 (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)。
相關連結